5htp 0.5.9-42 → 0.5.9-7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
// Npm
|
|
6
6
|
import * as types from '@babel/types'
|
|
7
|
-
import type { PluginObj } from '@babel/core';
|
|
7
|
+
import type { NodePath, PluginObj } from '@babel/core';
|
|
8
|
+
import generate from '@babel/generator';
|
|
8
9
|
|
|
9
10
|
// Core
|
|
10
11
|
import cli from '@cli';
|
|
@@ -24,12 +25,19 @@ type TOptions = {
|
|
|
24
25
|
* Extended source type: now includes "models"
|
|
25
26
|
* so we can differentiate how we rewrite references.
|
|
26
27
|
*/
|
|
27
|
-
type TImportSource = 'container' | '
|
|
28
|
+
type TImportSource = 'container' | 'services' | 'models' | 'request';
|
|
28
29
|
|
|
29
30
|
module.exports = (options: TOptions) => (
|
|
30
31
|
[Plugin, options]
|
|
31
32
|
)
|
|
32
33
|
|
|
34
|
+
type TImportedIndex = {
|
|
35
|
+
local: string,
|
|
36
|
+
imported: string, // The original “imported” name
|
|
37
|
+
references: NodePath<types.Node>[], // reference paths
|
|
38
|
+
source: TImportSource // container | application | models
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
/*----------------------------------
|
|
34
42
|
- PLUGIN
|
|
35
43
|
----------------------------------*/
|
|
@@ -54,8 +62,6 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
54
62
|
this.app.Models.client.MyModel.someCall();
|
|
55
63
|
|
|
56
64
|
Processed files:
|
|
57
|
-
@/server/config
|
|
58
|
-
@/server/routes
|
|
59
65
|
@/server/services
|
|
60
66
|
*/
|
|
61
67
|
|
|
@@ -68,40 +74,65 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
68
74
|
|
|
69
75
|
// Count how many total imports we transform
|
|
70
76
|
importedCount: number,
|
|
77
|
+
routeMethods: string[],
|
|
71
78
|
|
|
72
79
|
// For every local identifier, store info about how it should be rewritten
|
|
73
|
-
|
|
74
|
-
[localName: string]:
|
|
75
|
-
imported: string, // The original “imported” name
|
|
76
|
-
bindings: any, // reference paths
|
|
77
|
-
source: TImportSource // container | application | models
|
|
78
|
-
}
|
|
80
|
+
imported: {
|
|
81
|
+
[localName: string]: TImportedIndex
|
|
79
82
|
}
|
|
80
|
-
|
|
81
|
-
// Tally how many references per kind
|
|
82
|
-
bySource: { [s in TImportSource]: number }
|
|
83
83
|
}> = {
|
|
84
84
|
|
|
85
85
|
pre(state) {
|
|
86
86
|
this.filename = state.opts.filename as string;
|
|
87
|
-
this.processFile = (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
this.importedReferences = {};
|
|
94
|
-
this.bySource = {
|
|
95
|
-
container: 0,
|
|
96
|
-
application: 0,
|
|
97
|
-
models: 0
|
|
98
|
-
};
|
|
87
|
+
this.processFile = this.filename.startsWith(cli.paths.appRoot + '/server/services');
|
|
88
|
+
|
|
89
|
+
this.imported = {};
|
|
90
|
+
|
|
99
91
|
this.importedCount = 0;
|
|
100
92
|
this.debug = debug || false;
|
|
93
|
+
|
|
94
|
+
this.routeMethods = [];
|
|
101
95
|
},
|
|
102
96
|
|
|
103
97
|
visitor: {
|
|
104
98
|
|
|
99
|
+
// Detect decored methods before other plugins remove decorators
|
|
100
|
+
Program(path) {
|
|
101
|
+
|
|
102
|
+
if (!this.processFile) return;
|
|
103
|
+
|
|
104
|
+
// Traverse the AST within the Program node
|
|
105
|
+
path.traverse({
|
|
106
|
+
ClassMethod: (subPath) => {
|
|
107
|
+
const { node } = subPath;
|
|
108
|
+
if (!node.decorators || node.key.type !== 'Identifier') return;
|
|
109
|
+
|
|
110
|
+
for (const decorator of node.decorators) {
|
|
111
|
+
|
|
112
|
+
const isRoute = (
|
|
113
|
+
// Handles the case of @Route without parameters
|
|
114
|
+
(
|
|
115
|
+
t.isIdentifier(decorator.expression) && decorator.expression.name === 'Route'
|
|
116
|
+
)
|
|
117
|
+
||
|
|
118
|
+
// Handles the case of @Route() with parameters
|
|
119
|
+
(
|
|
120
|
+
t.isCallExpression(decorator.expression) &&
|
|
121
|
+
t.isIdentifier(decorator.expression.callee) &&
|
|
122
|
+
decorator.expression.callee.name === 'Route'
|
|
123
|
+
)
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
if (!isRoute) continue;
|
|
127
|
+
|
|
128
|
+
const methodName = node.key.name;
|
|
129
|
+
this.routeMethods.push( methodName );
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
|
|
105
136
|
/**
|
|
106
137
|
* Detect import statements from '@app' or '@models'
|
|
107
138
|
*/
|
|
@@ -109,7 +140,7 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
109
140
|
if (!this.processFile) return;
|
|
110
141
|
|
|
111
142
|
const source = path.node.source.value;
|
|
112
|
-
if (source !== '@app' && source !== '@models') {
|
|
143
|
+
if (source !== '@app' && source !== '@models' && source !== '@request') {
|
|
113
144
|
return;
|
|
114
145
|
}
|
|
115
146
|
|
|
@@ -121,25 +152,32 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
121
152
|
this.importedCount++;
|
|
122
153
|
|
|
123
154
|
let importSource: TImportSource;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
155
|
+
switch (source) {
|
|
156
|
+
case '@app':
|
|
157
|
+
// Distinguish whether it's a container service or an application service
|
|
158
|
+
if (app.containerServices.includes(specifier.imported.name)) {
|
|
159
|
+
importSource = 'container';
|
|
160
|
+
} else {
|
|
161
|
+
importSource = 'services';
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
case '@request':
|
|
165
|
+
importSource = 'request';
|
|
166
|
+
break;
|
|
167
|
+
case '@models':
|
|
168
|
+
// source === '@models'
|
|
169
|
+
importSource = 'models';
|
|
170
|
+
break;
|
|
171
|
+
default:
|
|
172
|
+
throw new Error(`Unknown import source: ${source}`);
|
|
134
173
|
}
|
|
135
174
|
|
|
136
|
-
this.
|
|
175
|
+
this.imported[specifier.local.name] = {
|
|
176
|
+
local: specifier.local.name,
|
|
137
177
|
imported: specifier.imported.name,
|
|
138
|
-
|
|
178
|
+
references: path.scope.bindings[specifier.local.name].referencePaths,
|
|
139
179
|
source: importSource
|
|
140
180
|
};
|
|
141
|
-
|
|
142
|
-
this.bySource[importSource]++;
|
|
143
181
|
}
|
|
144
182
|
|
|
145
183
|
// Remove the original import line(s) and replace with any needed new import
|
|
@@ -149,7 +187,7 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
149
187
|
|
|
150
188
|
// If this line had container references, add a default import for container
|
|
151
189
|
// Example: import container from '<root>/server/app/container'
|
|
152
|
-
if (source === '@app'
|
|
190
|
+
if (source === '@app') {
|
|
153
191
|
replaceWith.push(
|
|
154
192
|
t.importDeclaration(
|
|
155
193
|
[t.importDefaultSpecifier(t.identifier('container'))],
|
|
@@ -165,78 +203,124 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
165
203
|
path.replaceWithMultiple(replaceWith);
|
|
166
204
|
},
|
|
167
205
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
*/
|
|
171
|
-
Identifier(path) {
|
|
172
|
-
if (!this.processFile || this.importedCount === 0) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
206
|
+
// This visitor fires for every class method.
|
|
207
|
+
ClassMethod(path) {
|
|
175
208
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (!ref || !ref.bindings) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
209
|
+
// Must be a server service
|
|
210
|
+
if (!this.processFile || path.replaced) return;
|
|
181
211
|
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
212
|
+
// Must have a method name
|
|
213
|
+
if (path.node.key.type !== 'Identifier') return;
|
|
214
|
+
|
|
215
|
+
// Init context
|
|
216
|
+
const methodName = path.node.key.name;
|
|
217
|
+
let params = path.node.params;
|
|
218
|
+
|
|
219
|
+
// Prefix references
|
|
220
|
+
path.traverse({ Identifier: (subPath) => {
|
|
221
|
+
|
|
222
|
+
const { node } = subPath;
|
|
223
|
+
const name = node.name;
|
|
224
|
+
const ref = this.imported[name];
|
|
225
|
+
if (!ref || !ref.references) {
|
|
226
|
+
return;
|
|
188
227
|
}
|
|
189
|
-
}
|
|
190
|
-
if (!foundBinding) {
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
228
|
|
|
194
|
-
|
|
195
|
-
|
|
229
|
+
// Find a specific binding that hasn't been replaced yet
|
|
230
|
+
const foundBinding = ref.references.find(binding => {
|
|
231
|
+
return subPath.getPathLocation() === binding.getPathLocation();
|
|
232
|
+
});
|
|
196
233
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
else if (ref.source === 'application') {
|
|
209
|
-
// this.app.[identifier]
|
|
210
|
-
// e.g. this.app.MyService
|
|
211
|
-
path.replaceWith(
|
|
212
|
-
t.memberExpression(
|
|
234
|
+
if (!foundBinding || foundBinding.replaced)
|
|
235
|
+
return;
|
|
236
|
+
|
|
237
|
+
// Mark as replaced to avoid loops
|
|
238
|
+
foundBinding.replaced = true;
|
|
239
|
+
|
|
240
|
+
// Based on the source, replace the identifier with the proper MemberExpression
|
|
241
|
+
if (ref.source === 'container') {
|
|
242
|
+
// container.[identifier]
|
|
243
|
+
// e.g. container.Environment
|
|
244
|
+
subPath.replaceWith(
|
|
213
245
|
t.memberExpression(
|
|
214
|
-
t.
|
|
215
|
-
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
246
|
+
t.identifier('container'),
|
|
247
|
+
subPath.node
|
|
248
|
+
)
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
else if (ref.source === 'services') {
|
|
252
|
+
// this.app.[identifier]
|
|
253
|
+
// e.g. this.app.MyService
|
|
254
|
+
subPath.replaceWith(
|
|
255
|
+
t.memberExpression(
|
|
256
|
+
t.memberExpression(
|
|
257
|
+
t.thisExpression(),
|
|
258
|
+
t.identifier('app')
|
|
259
|
+
),
|
|
260
|
+
subPath.node
|
|
261
|
+
)
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
else if (ref.source === 'models') {
|
|
265
|
+
// this.app.Models.client.[identifier]
|
|
266
|
+
// e.g. this.app.Models.client.MyModel
|
|
267
|
+
subPath.replaceWith(
|
|
226
268
|
t.memberExpression(
|
|
227
269
|
t.memberExpression(
|
|
228
270
|
t.memberExpression(
|
|
229
|
-
t.
|
|
230
|
-
|
|
271
|
+
t.memberExpression(
|
|
272
|
+
t.thisExpression(),
|
|
273
|
+
t.identifier('app')
|
|
274
|
+
),
|
|
275
|
+
t.identifier('Models')
|
|
231
276
|
),
|
|
232
|
-
t.identifier('
|
|
277
|
+
t.identifier('client')
|
|
233
278
|
),
|
|
234
|
-
|
|
235
|
-
)
|
|
236
|
-
|
|
279
|
+
subPath.node
|
|
280
|
+
)
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
else if (ref.source === 'request') {
|
|
284
|
+
// this.app.Models.client.[identifier]
|
|
285
|
+
// e.g. this.app.Models.client.MyModel
|
|
286
|
+
subPath.replaceWith(
|
|
287
|
+
t.memberExpression(
|
|
288
|
+
t.identifier('context'),
|
|
289
|
+
subPath.node
|
|
290
|
+
)
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
} });
|
|
295
|
+
|
|
296
|
+
if (
|
|
297
|
+
this.routeMethods.includes(methodName)
|
|
298
|
+
&&
|
|
299
|
+
path.node.params.length < 2
|
|
300
|
+
) {
|
|
301
|
+
|
|
302
|
+
// Expose router context variable via the second parameter
|
|
303
|
+
params = [
|
|
304
|
+
path.node.params[0] || t.objectPattern([]),
|
|
305
|
+
t.identifier('context'),
|
|
306
|
+
];
|
|
307
|
+
|
|
308
|
+
// Apply changes
|
|
309
|
+
path.replaceWith(
|
|
310
|
+
t.classMethod(
|
|
311
|
+
path.node.kind,
|
|
312
|
+
path.node.key,
|
|
313
|
+
params,
|
|
314
|
+
path.node.body,
|
|
315
|
+
false,
|
|
316
|
+
false,
|
|
317
|
+
false,
|
|
318
|
+
path.node.async
|
|
237
319
|
)
|
|
238
320
|
);
|
|
239
321
|
}
|
|
322
|
+
|
|
323
|
+
//console.log("ROUTE METHOD", this.filename, methodName, generate(path.node).code);
|
|
240
324
|
}
|
|
241
325
|
}
|
|
242
326
|
};
|
|
@@ -173,6 +173,7 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
// Adjust
|
|
176
|
+
// /client/pages/*
|
|
176
177
|
if (this.file.side === 'front') {
|
|
177
178
|
transformDataFetchers(path, this, routeDef);
|
|
178
179
|
}
|
|
@@ -183,12 +184,7 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
183
184
|
// Delete the route def since it will be replaced by a wrapper
|
|
184
185
|
path.replaceWithMultiple([]);
|
|
185
186
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Events.Create( form.data ).then(res => toast.success(res.message))
|
|
189
|
-
=>
|
|
190
|
-
api.post( '/api/events/create', form.data ).then(res => toast.success(res.message))
|
|
191
|
-
*/
|
|
187
|
+
|
|
192
188
|
} else if (this.file.side === 'front') {
|
|
193
189
|
|
|
194
190
|
const isAService = (
|
|
@@ -199,14 +195,20 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
199
195
|
if(!isAService)
|
|
200
196
|
return;
|
|
201
197
|
|
|
202
|
-
|
|
198
|
+
/* [client] Backend Service calls: Transform to api.post( <method path>, <params> )
|
|
199
|
+
|
|
200
|
+
Events.Create( form.data ).then(res => toast.success(res.message))
|
|
201
|
+
=>
|
|
202
|
+
api.post( '/api/events/create', form.data ).then(res => toast.success(res.message))
|
|
203
|
+
*/
|
|
204
|
+
if (side === 'client' && !clientServices.includes(serviceName)) {
|
|
203
205
|
|
|
204
206
|
// Get complete call path
|
|
205
207
|
const apiPath = '/api/' + completePath.join('/');
|
|
206
208
|
|
|
207
209
|
// Replace by api.post( <method path>, <params> )
|
|
208
210
|
const apiPostArgs: types.CallExpression["arguments"] = [t.stringLiteral(apiPath)];
|
|
209
|
-
if (path.node.arguments.length
|
|
211
|
+
if (path.node.arguments.length >= 1)
|
|
210
212
|
apiPostArgs.push( path.node.arguments[0] );
|
|
211
213
|
|
|
212
214
|
path.replaceWith(
|
|
@@ -216,6 +218,13 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
216
218
|
), apiPostArgs
|
|
217
219
|
)
|
|
218
220
|
)
|
|
221
|
+
|
|
222
|
+
/* [server] Backend Service calls
|
|
223
|
+
|
|
224
|
+
Events.Create( form.data ).then(res => toast.success(res.message))
|
|
225
|
+
=>
|
|
226
|
+
app.Events.Create( form.data, context ).then(res => toast.success(res.message))
|
|
227
|
+
*/
|
|
219
228
|
} else {
|
|
220
229
|
|
|
221
230
|
// Rebuild member expression from completePath, adding a api prefix
|
|
@@ -233,7 +242,8 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
233
242
|
// Replace by app.<service>.<method>(...)
|
|
234
243
|
path.replaceWith(
|
|
235
244
|
t.callExpression(
|
|
236
|
-
newCallee,
|
|
245
|
+
newCallee,
|
|
246
|
+
[...path.node.arguments]
|
|
237
247
|
)
|
|
238
248
|
)
|
|
239
249
|
}
|
|
@@ -322,7 +332,39 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
322
332
|
}
|
|
323
333
|
*/
|
|
324
334
|
routeDef.dataFetchers.push(
|
|
325
|
-
...path.node.arguments[0].properties
|
|
335
|
+
...path.node.arguments[0].properties.map(p => {
|
|
336
|
+
|
|
337
|
+
// Server side: Pass request context as 2nd argument
|
|
338
|
+
// companies: Companies.create( <params>, context )
|
|
339
|
+
if (
|
|
340
|
+
side === 'server'
|
|
341
|
+
&&
|
|
342
|
+
p.type === 'ObjectProperty'
|
|
343
|
+
&&
|
|
344
|
+
p.key.type === 'Identifier'
|
|
345
|
+
&&
|
|
346
|
+
p.value.type === 'CallExpression'
|
|
347
|
+
&&
|
|
348
|
+
// TODO: reliable way to know if it's a service
|
|
349
|
+
!(
|
|
350
|
+
p.value.callee.type === 'MemberExpression'
|
|
351
|
+
&&
|
|
352
|
+
p.value.callee.object.type === 'Identifier'
|
|
353
|
+
&&
|
|
354
|
+
p.value.callee.object.name === 'api'
|
|
355
|
+
)
|
|
356
|
+
) {
|
|
357
|
+
|
|
358
|
+
// Pass request context as 2nd argument
|
|
359
|
+
p.value.arguments = p.value.arguments.length === 0
|
|
360
|
+
? [ t.objectExpression([]), t.identifier('context') ]
|
|
361
|
+
: [ p.value.arguments[0], t.identifier('context') ];
|
|
362
|
+
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return p;
|
|
366
|
+
|
|
367
|
+
})
|
|
326
368
|
);
|
|
327
369
|
|
|
328
370
|
/* Replace the:
|
|
@@ -376,9 +418,19 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
376
418
|
// Add data fetchers
|
|
377
419
|
if (routeDef.dataFetchers.length !== 0) {
|
|
378
420
|
|
|
421
|
+
const rendererContext = t.cloneNode( renderer.params[0] );
|
|
422
|
+
// If not already present, add context to the 1st argument (a object spread)
|
|
423
|
+
if (!rendererContext.properties.some( p => p.key.name === 'context' ))
|
|
424
|
+
rendererContext.properties.push(
|
|
425
|
+
t.objectProperty(
|
|
426
|
+
t.identifier('context'),
|
|
427
|
+
t.identifier('context')
|
|
428
|
+
)
|
|
429
|
+
)
|
|
430
|
+
|
|
379
431
|
// (contollerParams) => { stats: api.get(...) }
|
|
380
432
|
const dataFetchersFunc = t.arrowFunctionExpression(
|
|
381
|
-
|
|
433
|
+
[rendererContext],
|
|
382
434
|
t.objectExpression(
|
|
383
435
|
routeDef.dataFetchers.map( df => t.cloneNode( df ))
|
|
384
436
|
)
|
|
@@ -530,6 +582,10 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
530
582
|
t.objectProperty(
|
|
531
583
|
t.identifier('app'),
|
|
532
584
|
t.identifier('app'),
|
|
585
|
+
),
|
|
586
|
+
t.objectProperty(
|
|
587
|
+
t.identifier('context'),
|
|
588
|
+
t.identifier('context'),
|
|
533
589
|
)
|
|
534
590
|
]
|
|
535
591
|
for (const [local, imported] of importedServicesList) {
|
|
@@ -575,8 +631,8 @@ function Plugin(babel, { app, side, debug }: TOptions) {
|
|
|
575
631
|
);
|
|
576
632
|
|
|
577
633
|
|
|
578
|
-
|
|
579
|
-
&& console.log( file.path, generate(exportDeclaration).code )
|
|
634
|
+
// (file.path.includes('clients/prospect/search') && side === 'client')
|
|
635
|
+
// && console.log( file.path, generate(exportDeclaration).code );
|
|
580
636
|
|
|
581
637
|
return exportDeclaration;
|
|
582
638
|
}
|
package/compiler/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ import cli from '..';
|
|
|
17
17
|
import createServerConfig from './server';
|
|
18
18
|
import createClientConfig from './client';
|
|
19
19
|
import { TCompileMode } from './common';
|
|
20
|
+
import { routerServices } from './common/babel/plugins/services';
|
|
20
21
|
|
|
21
22
|
type TCompilerCallback = (compiler: webpack.Compiler) => void
|
|
22
23
|
|
|
@@ -32,6 +33,7 @@ type TServiceMetas = {
|
|
|
32
33
|
type TRegisteredService = {
|
|
33
34
|
id?: string,
|
|
34
35
|
name: string,
|
|
36
|
+
className: string,
|
|
35
37
|
instanciation: (parentRef: string) => string,
|
|
36
38
|
priority: number,
|
|
37
39
|
}
|
|
@@ -253,6 +255,7 @@ export default class Compiler {
|
|
|
253
255
|
id: serviceConfig.id,
|
|
254
256
|
name: serviceName,
|
|
255
257
|
instanciation,
|
|
258
|
+
className: serviceMetas.name,
|
|
256
259
|
priority: serviceConfig.config?.priority || serviceMetas.priority || 0,
|
|
257
260
|
};
|
|
258
261
|
}
|
|
@@ -269,43 +272,67 @@ export default class Compiler {
|
|
|
269
272
|
path.join( app.paths.client.generated, 'services.d.ts'),
|
|
270
273
|
`declare module "@app" {
|
|
271
274
|
|
|
272
|
-
import {
|
|
273
|
-
import
|
|
275
|
+
import { ${appClassIdentifier} as ${appClassIdentifier}Client } from "@/client";
|
|
276
|
+
import ${appClassIdentifier}Server from "@/server/.generated/app";
|
|
274
277
|
|
|
275
278
|
import { ApplicationProperties as ClientApplicationProperties } from "@client/app";
|
|
276
279
|
import { ApplicationProperties as ServerApplicationProperties } from "@server/app";
|
|
277
280
|
|
|
278
|
-
type ClientServices = Omit
|
|
279
|
-
type ServerServices = Omit
|
|
281
|
+
type ClientServices = Omit<${appClassIdentifier}Client, ClientApplicationProperties>;
|
|
282
|
+
type ServerServices = Omit<${appClassIdentifier}Server, ServerApplicationProperties | keyof ClientServices>;
|
|
280
283
|
|
|
281
284
|
type CombinedServices = ClientServices & ServerServices;
|
|
282
285
|
|
|
283
286
|
const appClass: CombinedServices;
|
|
284
287
|
export = appClass;
|
|
285
288
|
}
|
|
289
|
+
|
|
290
|
+
declare module '@models/types' {
|
|
291
|
+
export * from '@/var/prisma/index';
|
|
292
|
+
}
|
|
286
293
|
|
|
294
|
+
declare module '@request' {
|
|
295
|
+
|
|
296
|
+
}
|
|
287
297
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
declare module '@models' {
|
|
294
|
-
import { Prisma, PrismaClient } from '@/var/prisma/index';
|
|
295
|
-
|
|
296
|
-
type ModelNames = Prisma.ModelName;
|
|
297
|
-
|
|
298
|
-
type ModelDelegates = {
|
|
299
|
-
[K in ModelNames]: PrismaClient[Uncapitalize<K>];
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
const models: ModelDelegates;
|
|
303
|
-
|
|
304
|
-
export = models;
|
|
298
|
+
declare namespace preact.JSX {
|
|
299
|
+
interface HTMLAttributes {
|
|
300
|
+
src?: string;
|
|
301
|
+
}
|
|
305
302
|
}
|
|
306
|
-
|
|
303
|
+
`
|
|
307
304
|
);
|
|
308
305
|
|
|
306
|
+
fs.outputFileSync(
|
|
307
|
+
path.join( app.paths.client.generated, 'context.ts'),
|
|
308
|
+
`// TODO: move it into core (but how to make sure usecontext returns ${appClassIdentifier}'s context ?)
|
|
309
|
+
import React from 'react';
|
|
310
|
+
|
|
311
|
+
import type ${appClassIdentifier}Server from '@/server/.generated/app';
|
|
312
|
+
import type { TRouterContext as TServerRouterRequestContext } from '@server/services/router/response';
|
|
313
|
+
import type { TRouterContext as TClientRouterRequestContext } from '@client/services/router/response';
|
|
314
|
+
import type ${appClassIdentifier}Client from '.';
|
|
315
|
+
|
|
316
|
+
// TO Fix: TClientRouterRequestContext is unable to get the right type of ${appClassIdentifier}Client["router"]
|
|
317
|
+
// (it gets ClientApplication instead of ${appClassIdentifier}Client)
|
|
318
|
+
type ClientRequestContext = TClientRouterRequestContext<${appClassIdentifier}Client["Router"], ${appClassIdentifier}Client>;
|
|
319
|
+
type ServerRequestContext = TServerRouterRequestContext<${appClassIdentifier}Server["Router"]>
|
|
320
|
+
type UniversalServices = ClientRequestContext | ServerRequestContext
|
|
321
|
+
|
|
322
|
+
// Non-universla services are flagged as potentially undefined
|
|
323
|
+
export type ClientContext = (
|
|
324
|
+
UniversalServices
|
|
325
|
+
&
|
|
326
|
+
Partial<Omit<ClientRequestContext, keyof UniversalServices>>
|
|
327
|
+
&
|
|
328
|
+
{
|
|
329
|
+
Router: ${appClassIdentifier}Client["Router"],
|
|
330
|
+
}
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
export const ReactClientContext = React.createContext<ClientContext>({} as ClientContext);
|
|
334
|
+
export default (): ClientContext => React.useContext<ClientContext>(ReactClientContext);`);
|
|
335
|
+
|
|
309
336
|
fs.outputFileSync(
|
|
310
337
|
path.join( app.paths.server.generated, 'app.ts'),
|
|
311
338
|
`import { Application } from '@server/app/index';
|
|
@@ -315,7 +342,7 @@ ${imported.join('\n')}
|
|
|
315
342
|
export default class ${appClassIdentifier} extends Application {
|
|
316
343
|
|
|
317
344
|
${sortedServices.map(service =>
|
|
318
|
-
`public ${service.name}!:
|
|
345
|
+
`public ${service.name}!: ${service.className};`
|
|
319
346
|
).join('\n')}
|
|
320
347
|
|
|
321
348
|
protected registered = {
|
|
@@ -373,6 +400,12 @@ declare module '@server/app' {
|
|
|
373
400
|
|
|
374
401
|
export = foo;
|
|
375
402
|
}
|
|
403
|
+
|
|
404
|
+
declare module '@request' {
|
|
405
|
+
import type { TRouterContext } from '@server/services/router/response';
|
|
406
|
+
const routerContext: TRouterContext<CrossPath["Router"]>;
|
|
407
|
+
export = routerContext;
|
|
408
|
+
}
|
|
376
409
|
|
|
377
410
|
declare module '@models' {
|
|
378
411
|
import { Prisma, PrismaClient } from '@/var/prisma/index';
|
|
@@ -386,6 +419,10 @@ declare module '@models' {
|
|
|
386
419
|
const models: ModelDelegates;
|
|
387
420
|
|
|
388
421
|
export = models;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
declare module '@models/types' {
|
|
425
|
+
export * from '@/var/prisma/index';
|
|
389
426
|
}`
|
|
390
427
|
);
|
|
391
428
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "5htp",
|
|
3
3
|
"description": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "0.5.9-
|
|
4
|
+
"version": "0.5.9-7",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp.git",
|
|
7
7
|
"license": "MIT",
|