@@ -10,40 +10,43 @@ import * as singletonChecks from './singleton-checks'
10
10
11
11
const log = Logger . create ( { name : 'app' } )
12
12
13
- /**
14
- * The available server options to configure how your app runs its server.
15
- */
16
- type ServerOptions = Partial <
17
- Pick < Server . Options , 'port' | 'playground' | 'startMessage' >
18
- >
19
-
20
13
type Request = HTTP . IncomingMessage & { log : Logger . Logger }
21
14
22
- // TODO plugins could augment the request
15
+ // todo the jsdoc below is lost on the destructured object exports later on...
16
+ // todo plugins could augment the request
23
17
// plugins will be able to use typegen to signal this fact
24
18
// all places in the framework where the req object is referenced should be
25
19
// actually referencing the typegen version, so that it reflects the req +
26
20
// plugin augmentations type
27
21
type ContextContributor < T extends { } > = ( req : Request ) => T
28
22
29
23
export type App = {
30
- use : ( plugin : Plugin . Driver ) => App
31
24
/**
32
25
* [API Reference](https://nexus-future.now.sh/#/references/api?id=logger) ⌁ [Guide](https://nexus-future.now.sh/#/guides/logging)
33
26
*
34
27
* ### todo
35
28
*/
36
- log : Logger . RootLogger
29
+ log : Logger . Logger
37
30
/**
38
31
* [API Reference](https://nexus-future.now.sh/#/references/api?id=server) ⌁ [Guide](todo)
39
32
*
40
33
* ### todo
41
34
*
42
35
*/
43
36
server : {
44
- start : ( config ?: ServerOptions ) => Promise < void >
37
+ /**
38
+ * todo
39
+ */
40
+ start : ( ) => Promise < void >
41
+ /**
42
+ * todo
43
+ */
45
44
stop : ( ) => Promise < void >
46
45
}
46
+ /**
47
+ * todo
48
+ */
49
+ settings : Settings
47
50
/**
48
51
* [API Reference](https://nexus-future.now.sh/#/references/api?id=appschema) // [Guide](todo)
49
52
*
@@ -62,56 +65,93 @@ export type App = {
62
65
}
63
66
}
64
67
68
+ type SettingsInput = {
69
+ logger ?: Logger . SettingsInput
70
+ schema ?: Schema . SettingsInput
71
+ server ?: Server . ExtraSettingsInput
72
+ }
73
+
74
+ type SettingsData = Readonly < {
75
+ logger : Logger . SettingsData
76
+ schema : Schema . SettingsData
77
+ server : Server . ExtraSettingsData
78
+ } >
79
+
80
+ /**
81
+ * todo
82
+ */
83
+ type Settings = {
84
+ /**
85
+ * todo
86
+ */
87
+ original : SettingsData
88
+ /**
89
+ * todo
90
+ */
91
+ current : SettingsData
92
+ /**
93
+ * todo
94
+ */
95
+ change ( newSetting : SettingsInput ) : void
96
+ }
97
+
65
98
/**
66
99
* Crate an app instance
67
100
* TODO extract and improve config type
68
101
*/
69
102
export function create ( appConfig ?: { types ?: any } ) : App {
70
103
const plugins : Plugin . RuntimeContributions [ ] = [ ]
71
-
72
104
// Automatically use all installed plugins
73
105
// TODO during build step we should turn this into static imports, not unlike
74
106
// the schema module imports system.
75
107
plugins . push ( ...Plugin . loadAllRuntimePluginsFromPackageJsonSync ( ) )
76
108
77
109
const contextContributors : ContextContributor < any > [ ] = [ ]
78
110
79
- /**
80
- * Auto-use all runtime plugins that are installed in the project
81
- */
82
-
83
111
let server : Server . Server
112
+
84
113
const schema = Schema . create ( )
85
- const api : App = {
86
- log,
87
- // TODO bring this back pending future discussion
88
- // installGlobally() {
89
- // installGlobally(api)
90
- // return api
91
- // },
92
- // TODO think hard about this api... When/why would it be used with auto-use
93
- // import system? "Inproject" plugins? What is the right place to expose
94
- // this? app.plugins.use() ?
95
- use ( pluginDriver ) {
96
- const plugin = pluginDriver . loadRuntimePlugin ( )
97
- if ( plugin ) {
98
- plugins . push ( plugin )
114
+
115
+ const settings : Settings = {
116
+ change ( newSettings ) {
117
+ if ( newSettings . logger ) {
118
+ log . settings ( newSettings . logger )
119
+ }
120
+ if ( newSettings . schema ) {
121
+ schema . private . settings . change ( newSettings . schema )
99
122
}
100
- return api
123
+ if ( newSettings . server ) {
124
+ Object . assign ( settings . current . server , newSettings . server )
125
+ }
126
+ } ,
127
+ current : {
128
+ logger : log . settings ,
129
+ schema : schema . private . settings . data ,
130
+ server : { ...Server . defaultExtraSettings } ,
101
131
} ,
132
+ original : Lo . cloneDeep ( {
133
+ logger : log . settings ,
134
+ schema : schema . private . settings . data ,
135
+ server : { ...Server . defaultExtraSettings } ,
136
+ } ) ,
137
+ }
138
+
139
+ const api : App = {
140
+ log,
141
+ settings,
102
142
schema : {
103
143
addToContext ( contextContributor ) {
104
144
contextContributors . push ( contextContributor )
105
145
return api
106
146
} ,
107
- ...schema . external ,
147
+ ...schema . public ,
108
148
} ,
109
149
server : {
110
150
/**
111
151
* Start the server. If you do not call this explicitly then nexus will
112
152
* for you. You should not normally need to call this function yourself.
113
153
*/
114
- async start ( opts : ServerOptions = { } ) : Promise < void > {
154
+ async start ( ) : Promise < void > {
115
155
// Track the start call so that we can know in entrypoint whether to run
116
156
// or not start for the user.
117
157
singletonChecks . state . is_was_server_start_called = true
@@ -237,17 +277,17 @@ export function create(appConfig?: { types?: any }): App {
237
277
nexusConfig . types . push ( ...appConfig . types )
238
278
}
239
279
240
- if ( schema . internal . types . length === 0 ) {
280
+ if ( schema . private . types . length === 0 ) {
241
281
log . warn (
242
282
'Your GraphQL schema is empty. Make sure your GraphQL schema lives in a `schema.ts` file or some `schema/` directories'
243
283
)
244
284
}
245
285
246
286
return Server . create ( {
247
- schema : await schema . internal . compile ( nexusConfig ) ,
287
+ schema : await schema . private . compile ( nexusConfig ) ,
248
288
plugins,
249
289
contextContributors,
250
- ...opts ,
290
+ ...settings . current . server ,
251
291
} ) . start ( )
252
292
} ,
253
293
async stop ( ) {
0 commit comments