proteum 1.0.0-1 → 1.0.0
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.
- package/changelog.md +5 -0
- package/client/components/Dialog/index.less +1 -3
- package/package.json +3 -69
- package/server/app/container/console/index.ts +1 -1
- package/templates/composant.tsx +40 -0
- package/templates/form.ts +30 -0
- package/templates/modal.tsx +47 -0
- package/templates/modele.ts +56 -0
- package/templates/page.tsx +74 -0
- package/templates/route.ts +43 -0
- package/templates/service.ts +75 -0
- package/tsconfig.common.json +1 -2
- package/vscode/copyimportationpath/.eslintrc.json +24 -0
- package/vscode/copyimportationpath/.vscodeignore +12 -0
- package/vscode/copyimportationpath/CHANGELOG.md +9 -0
- package/vscode/copyimportationpath/README.md +3 -0
- package/vscode/copyimportationpath/copyimportationpath-0.0.1.vsix +0 -0
- package/vscode/copyimportationpath/out/extension.js +206 -0
- package/vscode/copyimportationpath/out/extension.js.map +1 -0
- package/vscode/copyimportationpath/package-lock.json +4536 -0
- package/vscode/copyimportationpath/package.json +86 -0
- package/vscode/copyimportationpath/src/extension.ts +300 -0
- package/vscode/copyimportationpath/tsconfig.json +22 -0
- package/vscode/copyimportationpath/vsc-extension-quickstart.md +42 -0
- package/cli/app/config.ts +0 -54
- package/cli/app/index.ts +0 -195
- package/cli/bin.js +0 -11
- package/cli/commands/build.ts +0 -34
- package/cli/commands/deploy/app.ts +0 -29
- package/cli/commands/deploy/web.ts +0 -60
- package/cli/commands/dev.ts +0 -109
- package/cli/commands/init.ts +0 -85
- package/cli/compiler/client/identite.ts +0 -72
- package/cli/compiler/client/index.ts +0 -334
- package/cli/compiler/common/babel/index.ts +0 -170
- package/cli/compiler/common/babel/plugins/index.ts +0 -0
- package/cli/compiler/common/babel/plugins/services.ts +0 -579
- package/cli/compiler/common/babel/routes/imports.ts +0 -127
- package/cli/compiler/common/babel/routes/routes.ts +0 -1130
- package/cli/compiler/common/files/autres.ts +0 -39
- package/cli/compiler/common/files/images.ts +0 -35
- package/cli/compiler/common/files/style.ts +0 -78
- package/cli/compiler/common/index.ts +0 -154
- package/cli/compiler/index.ts +0 -532
- package/cli/compiler/server/index.ts +0 -211
- package/cli/index.ts +0 -189
- package/cli/paths.ts +0 -165
- package/cli/print.ts +0 -12
- package/cli/tsconfig.json +0 -38
- package/cli/utils/index.ts +0 -22
- package/cli/utils/keyboard.ts +0 -78
|
@@ -1,579 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import * as types from '@babel/types'
|
|
7
|
-
import type { NodePath, PluginObj } from '@babel/core';
|
|
8
|
-
import generate from '@babel/generator';
|
|
9
|
-
import fs from 'fs';
|
|
10
|
-
import path from 'path';
|
|
11
|
-
import { parse } from '@babel/parser';
|
|
12
|
-
import traverse from '@babel/traverse';
|
|
13
|
-
|
|
14
|
-
// Core
|
|
15
|
-
import cli from '@cli';
|
|
16
|
-
import { App, TAppSide } from '../../../../app';
|
|
17
|
-
|
|
18
|
-
/*----------------------------------
|
|
19
|
-
- WEBPACK RULE
|
|
20
|
-
----------------------------------*/
|
|
21
|
-
|
|
22
|
-
type TOptions = {
|
|
23
|
-
side: TAppSide,
|
|
24
|
-
app: App,
|
|
25
|
-
debug?: boolean
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Extended source type: now includes "models"
|
|
30
|
-
* so we can differentiate how we rewrite references.
|
|
31
|
-
*/
|
|
32
|
-
type TImportSource = 'container' | 'services' | 'models' | 'request';
|
|
33
|
-
|
|
34
|
-
module.exports = (options: TOptions) => (
|
|
35
|
-
[Plugin, options]
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
type TImportedIndex = {
|
|
39
|
-
local: string,
|
|
40
|
-
imported: string, // The original “imported” name
|
|
41
|
-
references: NodePath<types.Node>[], // reference paths
|
|
42
|
-
source: TImportSource // container | application | models
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
type TRoutesIndex = {
|
|
46
|
-
byFile: Map<string, Set<string>>,
|
|
47
|
-
all: Set<string>,
|
|
48
|
-
initialized: boolean
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const routesIndexByAppRoot = new Map<string, TRoutesIndex>();
|
|
52
|
-
|
|
53
|
-
function isRouteDecoratorExpression(expression: types.Expression): boolean {
|
|
54
|
-
return (
|
|
55
|
-
// Handles the case of @Route without parameters
|
|
56
|
-
(types.isIdentifier(expression) && expression.name === 'Route')
|
|
57
|
-
||
|
|
58
|
-
// Handles the case of @Route() with parameters
|
|
59
|
-
(
|
|
60
|
-
types.isCallExpression(expression)
|
|
61
|
-
&&
|
|
62
|
-
types.isIdentifier(expression.callee)
|
|
63
|
-
&&
|
|
64
|
-
expression.callee.name === 'Route'
|
|
65
|
-
)
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function getRoutePathFromDecoratorExpression(expression: types.Expression): string | undefined {
|
|
70
|
-
if (
|
|
71
|
-
!types.isCallExpression(expression)
|
|
72
|
-
||
|
|
73
|
-
!types.isIdentifier(expression.callee)
|
|
74
|
-
||
|
|
75
|
-
expression.callee.name !== 'Route'
|
|
76
|
-
)
|
|
77
|
-
return;
|
|
78
|
-
|
|
79
|
-
const firstArg = expression.arguments[0];
|
|
80
|
-
if (!types.isStringLiteral(firstArg))
|
|
81
|
-
return;
|
|
82
|
-
|
|
83
|
-
return firstArg.value;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function extractRoutePathsFromCode(code: string, filename: string): Set<string> {
|
|
87
|
-
const routePaths = new Set<string>();
|
|
88
|
-
|
|
89
|
-
let ast: ReturnType<typeof parse> | undefined;
|
|
90
|
-
try {
|
|
91
|
-
ast = parse(code, {
|
|
92
|
-
sourceType: 'module',
|
|
93
|
-
sourceFilename: filename,
|
|
94
|
-
plugins: [
|
|
95
|
-
'typescript',
|
|
96
|
-
'decorators-legacy',
|
|
97
|
-
'jsx',
|
|
98
|
-
'classProperties',
|
|
99
|
-
'classPrivateProperties',
|
|
100
|
-
'classPrivateMethods',
|
|
101
|
-
'dynamicImport',
|
|
102
|
-
'importMeta',
|
|
103
|
-
'optionalChaining',
|
|
104
|
-
'nullishCoalescingOperator',
|
|
105
|
-
'topLevelAwait',
|
|
106
|
-
],
|
|
107
|
-
});
|
|
108
|
-
} catch {
|
|
109
|
-
return routePaths;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
traverse(ast, {
|
|
113
|
-
ClassMethod(path) {
|
|
114
|
-
const { node } = path;
|
|
115
|
-
if (!node.decorators || node.key.type !== 'Identifier')
|
|
116
|
-
return;
|
|
117
|
-
|
|
118
|
-
for (const decorator of node.decorators) {
|
|
119
|
-
if (!isRouteDecoratorExpression(decorator.expression))
|
|
120
|
-
continue;
|
|
121
|
-
|
|
122
|
-
const routePath = getRoutePathFromDecoratorExpression(decorator.expression);
|
|
123
|
-
if (routePath)
|
|
124
|
-
routePaths.add(routePath);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
return routePaths;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function listTsFiles(dirPath: string): string[] {
|
|
133
|
-
let entries: fs.Dirent[];
|
|
134
|
-
try {
|
|
135
|
-
entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
136
|
-
} catch {
|
|
137
|
-
return [];
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const files: string[] = [];
|
|
141
|
-
for (const entry of entries) {
|
|
142
|
-
const fullPath = path.join(dirPath, entry.name);
|
|
143
|
-
if (entry.isDirectory()) {
|
|
144
|
-
files.push(...listTsFiles(fullPath));
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const isTs = fullPath.endsWith('.ts') || fullPath.endsWith('.tsx');
|
|
149
|
-
if (!isTs || fullPath.endsWith('.d.ts'))
|
|
150
|
-
continue;
|
|
151
|
-
|
|
152
|
-
files.push(fullPath);
|
|
153
|
-
}
|
|
154
|
-
return files;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function initializeRoutesIndex(appRoot: string, index: TRoutesIndex) {
|
|
158
|
-
const servicesDir = path.join(appRoot, 'server', 'services');
|
|
159
|
-
const files = listTsFiles(servicesDir);
|
|
160
|
-
|
|
161
|
-
for (const file of files) {
|
|
162
|
-
let code: string;
|
|
163
|
-
try {
|
|
164
|
-
code = fs.readFileSync(file, 'utf8');
|
|
165
|
-
} catch {
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const routes = extractRoutePathsFromCode(code, file);
|
|
170
|
-
index.byFile.set(file, routes);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
index.all.clear();
|
|
174
|
-
for (const routes of index.byFile.values()) {
|
|
175
|
-
for (const route of routes)
|
|
176
|
-
index.all.add(route);
|
|
177
|
-
}
|
|
178
|
-
index.initialized = true;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function getRoutesIndex(appRoot: string): TRoutesIndex {
|
|
182
|
-
let index = routesIndexByAppRoot.get(appRoot);
|
|
183
|
-
if (!index) {
|
|
184
|
-
index = {
|
|
185
|
-
byFile: new Map(),
|
|
186
|
-
all: new Set(),
|
|
187
|
-
initialized: false
|
|
188
|
-
};
|
|
189
|
-
routesIndexByAppRoot.set(appRoot, index);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (!index.initialized) {
|
|
193
|
-
initializeRoutesIndex(appRoot, index);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return index;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function updateRoutesIndexForFile(index: TRoutesIndex, filename: string, routePaths: Set<string>) {
|
|
200
|
-
index.byFile.set(filename, routePaths);
|
|
201
|
-
|
|
202
|
-
index.all.clear();
|
|
203
|
-
for (const routes of index.byFile.values()) {
|
|
204
|
-
for (const route of routes)
|
|
205
|
-
index.all.add(route);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/*----------------------------------
|
|
210
|
-
- PLUGIN
|
|
211
|
-
----------------------------------*/
|
|
212
|
-
function Plugin(babel, { app, side, debug }: TOptions) {
|
|
213
|
-
|
|
214
|
-
const t = babel.types as typeof types;
|
|
215
|
-
|
|
216
|
-
/*
|
|
217
|
-
Transforms:
|
|
218
|
-
import { MyService, Environment } from '@app';
|
|
219
|
-
import { MyModel } from '@models';
|
|
220
|
-
...
|
|
221
|
-
MyService.method();
|
|
222
|
-
Environment.name;
|
|
223
|
-
MyModel.someCall();
|
|
224
|
-
|
|
225
|
-
To:
|
|
226
|
-
import container from '<path>/server/app/container';
|
|
227
|
-
...
|
|
228
|
-
container.Environment.name;
|
|
229
|
-
this.app.MyService.method();
|
|
230
|
-
this.app.Models.client.MyModel.someCall();
|
|
231
|
-
|
|
232
|
-
Processed files:
|
|
233
|
-
@/server/services
|
|
234
|
-
*/
|
|
235
|
-
|
|
236
|
-
const plugin: PluginObj<{
|
|
237
|
-
|
|
238
|
-
debug: boolean,
|
|
239
|
-
|
|
240
|
-
filename: string,
|
|
241
|
-
processFile: boolean,
|
|
242
|
-
|
|
243
|
-
// Count how many total imports we transform
|
|
244
|
-
importedCount: number,
|
|
245
|
-
routeMethods: string[],
|
|
246
|
-
routePaths: Set<string>,
|
|
247
|
-
routesIndex: TRoutesIndex,
|
|
248
|
-
contextGuardedClassMethods: WeakSet<types.ClassMethod>,
|
|
249
|
-
|
|
250
|
-
// For every local identifier, store info about how it should be rewritten
|
|
251
|
-
imported: {
|
|
252
|
-
[localName: string]: TImportedIndex
|
|
253
|
-
}
|
|
254
|
-
}> = {
|
|
255
|
-
|
|
256
|
-
pre(state) {
|
|
257
|
-
this.filename = state.opts.filename as string;
|
|
258
|
-
this.processFile = this.filename.startsWith(cli.paths.appRoot + '/server/services');
|
|
259
|
-
|
|
260
|
-
this.imported = {};
|
|
261
|
-
|
|
262
|
-
this.importedCount = 0;
|
|
263
|
-
this.debug = debug || false;
|
|
264
|
-
|
|
265
|
-
this.routeMethods = [];
|
|
266
|
-
this.routePaths = new Set();
|
|
267
|
-
|
|
268
|
-
this.routesIndex = getRoutesIndex(app.paths.root);
|
|
269
|
-
this.contextGuardedClassMethods = new WeakSet();
|
|
270
|
-
},
|
|
271
|
-
|
|
272
|
-
visitor: {
|
|
273
|
-
|
|
274
|
-
// Detect decored methods before other plugins remove decorators
|
|
275
|
-
Program(path) {
|
|
276
|
-
|
|
277
|
-
if (!this.processFile) return;
|
|
278
|
-
|
|
279
|
-
// Traverse the AST within the Program node
|
|
280
|
-
path.traverse({
|
|
281
|
-
ClassMethod: (subPath) => {
|
|
282
|
-
const { node } = subPath;
|
|
283
|
-
if (!node.decorators || node.key.type !== 'Identifier') return;
|
|
284
|
-
|
|
285
|
-
for (const decorator of node.decorators) {
|
|
286
|
-
|
|
287
|
-
const isRoute = isRouteDecoratorExpression(decorator.expression);
|
|
288
|
-
|
|
289
|
-
if (!isRoute) continue;
|
|
290
|
-
|
|
291
|
-
const methodName = node.key.name;
|
|
292
|
-
this.routeMethods.push( methodName );
|
|
293
|
-
|
|
294
|
-
const routePath = getRoutePathFromDecoratorExpression(decorator.expression);
|
|
295
|
-
if (routePath)
|
|
296
|
-
this.routePaths.add(routePath);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
updateRoutesIndexForFile(this.routesIndex, this.filename, this.routePaths);
|
|
302
|
-
},
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Detect import statements from '@app' or '@models'
|
|
306
|
-
*/
|
|
307
|
-
ImportDeclaration(path) {
|
|
308
|
-
if (!this.processFile) return;
|
|
309
|
-
|
|
310
|
-
const source = path.node.source.value;
|
|
311
|
-
if (source !== '@app' && source !== '@models' && source !== '@request') {
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// For '@app' and '@models', gather imported symbols
|
|
316
|
-
for (const specifier of path.node.specifiers) {
|
|
317
|
-
if (specifier.type !== 'ImportSpecifier') continue;
|
|
318
|
-
if (specifier.imported.type !== 'Identifier') continue;
|
|
319
|
-
|
|
320
|
-
this.importedCount++;
|
|
321
|
-
|
|
322
|
-
let importSource: TImportSource;
|
|
323
|
-
switch (source) {
|
|
324
|
-
case '@app':
|
|
325
|
-
// Distinguish whether it's a container service or an application service
|
|
326
|
-
if (app.containerServices.includes(specifier.imported.name)) {
|
|
327
|
-
importSource = 'container';
|
|
328
|
-
} else {
|
|
329
|
-
importSource = 'services';
|
|
330
|
-
}
|
|
331
|
-
break;
|
|
332
|
-
case '@request':
|
|
333
|
-
importSource = 'request';
|
|
334
|
-
break;
|
|
335
|
-
case '@models':
|
|
336
|
-
// source === '@models'
|
|
337
|
-
importSource = 'models';
|
|
338
|
-
break;
|
|
339
|
-
default:
|
|
340
|
-
throw new Error(`Unknown import source: ${source}`);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
this.imported[specifier.local.name] = {
|
|
344
|
-
local: specifier.local.name,
|
|
345
|
-
imported: specifier.imported.name,
|
|
346
|
-
references: path.scope.bindings[specifier.local.name].referencePaths,
|
|
347
|
-
source: importSource
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Remove the original import line(s) and replace with any needed new import
|
|
352
|
-
// For @app imports, we might import "container" if needed
|
|
353
|
-
// For @models, we don’t import anything
|
|
354
|
-
const replaceWith: any[] = [];
|
|
355
|
-
|
|
356
|
-
// If this line had container references, add a default import for container
|
|
357
|
-
// Example: import container from '<root>/server/app/container'
|
|
358
|
-
if (source === '@app') {
|
|
359
|
-
replaceWith.push(
|
|
360
|
-
t.importDeclaration(
|
|
361
|
-
[t.importDefaultSpecifier(t.identifier('container'))],
|
|
362
|
-
t.stringLiteral(
|
|
363
|
-
cli.paths.core.root + '/server/app/container'
|
|
364
|
-
)
|
|
365
|
-
)
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// Replace the original import statement with our new import(s) if any
|
|
370
|
-
// or remove it entirely if no container references exist.
|
|
371
|
-
path.replaceWithMultiple(replaceWith);
|
|
372
|
-
},
|
|
373
|
-
|
|
374
|
-
CallExpression(path) {
|
|
375
|
-
if (!this.processFile)
|
|
376
|
-
return;
|
|
377
|
-
|
|
378
|
-
const classMethodPath = path.findParent(p => p.isClassMethod()) as NodePath<types.ClassMethod> | null;
|
|
379
|
-
if (!classMethodPath)
|
|
380
|
-
return;
|
|
381
|
-
|
|
382
|
-
// Ignore constructors
|
|
383
|
-
if (classMethodPath.node.kind === 'constructor')
|
|
384
|
-
return;
|
|
385
|
-
|
|
386
|
-
const callee = path.node.callee;
|
|
387
|
-
if (!t.isMemberExpression(callee) && !(t as any).isOptionalMemberExpression?.(callee))
|
|
388
|
-
return;
|
|
389
|
-
|
|
390
|
-
// Build member chain segments: this.app.<Service>.<...>
|
|
391
|
-
const segments: string[] = [];
|
|
392
|
-
let current: any = callee;
|
|
393
|
-
while (t.isMemberExpression(current) || (t as any).isOptionalMemberExpression?.(current)) {
|
|
394
|
-
const prop = current.property;
|
|
395
|
-
if (t.isIdentifier(prop)) {
|
|
396
|
-
segments.unshift(prop.name);
|
|
397
|
-
} else if (t.isStringLiteral(prop)) {
|
|
398
|
-
segments.unshift(prop.value);
|
|
399
|
-
} else {
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
current = current.object;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
if (!t.isThisExpression(current))
|
|
406
|
-
return;
|
|
407
|
-
|
|
408
|
-
// Expect: this.app.<Service>.<method>
|
|
409
|
-
if (segments.length < 3 || segments[0] !== 'app')
|
|
410
|
-
return;
|
|
411
|
-
|
|
412
|
-
const serviceLocalName = segments[1];
|
|
413
|
-
const importedRef = this.imported[serviceLocalName];
|
|
414
|
-
if (!importedRef || importedRef.source !== 'services')
|
|
415
|
-
return;
|
|
416
|
-
|
|
417
|
-
const routePath = [
|
|
418
|
-
importedRef.imported || serviceLocalName,
|
|
419
|
-
...segments.slice(2)
|
|
420
|
-
].join('/');
|
|
421
|
-
|
|
422
|
-
if (!this.routesIndex.all.has(routePath))
|
|
423
|
-
return;
|
|
424
|
-
|
|
425
|
-
// Ensure the parent function checks that `context` exists
|
|
426
|
-
if (!this.contextGuardedClassMethods.has(classMethodPath.node)) {
|
|
427
|
-
const guard = t.ifStatement(
|
|
428
|
-
t.binaryExpression(
|
|
429
|
-
'===',
|
|
430
|
-
t.unaryExpression('typeof', t.identifier('context')),
|
|
431
|
-
t.stringLiteral('undefined')
|
|
432
|
-
),
|
|
433
|
-
t.blockStatement([
|
|
434
|
-
t.throwStatement(
|
|
435
|
-
t.newExpression(t.identifier('Error'), [
|
|
436
|
-
t.stringLiteral('context variable should be passed in this function')
|
|
437
|
-
])
|
|
438
|
-
)
|
|
439
|
-
])
|
|
440
|
-
);
|
|
441
|
-
classMethodPath.get('body').unshiftContainer('body', guard);
|
|
442
|
-
this.contextGuardedClassMethods.add(classMethodPath.node);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Ensure call arguments: second argument is `context`
|
|
446
|
-
const args = path.node.arguments;
|
|
447
|
-
if (args.length === 0) {
|
|
448
|
-
args.push(t.identifier('undefined'), t.identifier('context'));
|
|
449
|
-
} else if (args.length === 1) {
|
|
450
|
-
args.push(t.identifier('context'));
|
|
451
|
-
} else {
|
|
452
|
-
args[1] = t.identifier('context') as any;
|
|
453
|
-
}
|
|
454
|
-
},
|
|
455
|
-
|
|
456
|
-
// This visitor fires for every class method.
|
|
457
|
-
ClassMethod(path) {
|
|
458
|
-
|
|
459
|
-
// Must be a server service
|
|
460
|
-
if (!this.processFile || path.replaced) return;
|
|
461
|
-
|
|
462
|
-
// Must have a method name
|
|
463
|
-
if (path.node.key.type !== 'Identifier') return;
|
|
464
|
-
|
|
465
|
-
// Init context
|
|
466
|
-
const methodName = path.node.key.name;
|
|
467
|
-
let params = path.node.params;
|
|
468
|
-
|
|
469
|
-
// Prefix references
|
|
470
|
-
path.traverse({ Identifier: (subPath) => {
|
|
471
|
-
|
|
472
|
-
const { node } = subPath;
|
|
473
|
-
const name = node.name;
|
|
474
|
-
const ref = this.imported[name];
|
|
475
|
-
if (!ref || !ref.references) {
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// Find a specific binding that hasn't been replaced yet
|
|
480
|
-
const foundBinding = ref.references.find(binding => {
|
|
481
|
-
return subPath.getPathLocation() === binding.getPathLocation();
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
if (!foundBinding || foundBinding.replaced)
|
|
485
|
-
return;
|
|
486
|
-
|
|
487
|
-
// Mark as replaced to avoid loops
|
|
488
|
-
foundBinding.replaced = true;
|
|
489
|
-
|
|
490
|
-
// Based on the source, replace the identifier with the proper MemberExpression
|
|
491
|
-
if (ref.source === 'container') {
|
|
492
|
-
// container.[identifier]
|
|
493
|
-
// e.g. container.Environment
|
|
494
|
-
subPath.replaceWith(
|
|
495
|
-
t.memberExpression(
|
|
496
|
-
t.identifier('container'),
|
|
497
|
-
subPath.node
|
|
498
|
-
)
|
|
499
|
-
);
|
|
500
|
-
}
|
|
501
|
-
else if (ref.source === 'services') {
|
|
502
|
-
// this.app.[identifier]
|
|
503
|
-
// e.g. this.app.MyService
|
|
504
|
-
subPath.replaceWith(
|
|
505
|
-
t.memberExpression(
|
|
506
|
-
t.memberExpression(
|
|
507
|
-
t.thisExpression(),
|
|
508
|
-
t.identifier('app')
|
|
509
|
-
),
|
|
510
|
-
subPath.node
|
|
511
|
-
)
|
|
512
|
-
);
|
|
513
|
-
}
|
|
514
|
-
else if (ref.source === 'models') {
|
|
515
|
-
// this.app.Models.client.[identifier]
|
|
516
|
-
// e.g. this.app.Models.client.MyModel
|
|
517
|
-
subPath.replaceWith(
|
|
518
|
-
t.memberExpression(
|
|
519
|
-
t.memberExpression(
|
|
520
|
-
t.memberExpression(
|
|
521
|
-
t.memberExpression(
|
|
522
|
-
t.thisExpression(),
|
|
523
|
-
t.identifier('app')
|
|
524
|
-
),
|
|
525
|
-
t.identifier('Models')
|
|
526
|
-
),
|
|
527
|
-
t.identifier('client')
|
|
528
|
-
),
|
|
529
|
-
subPath.node
|
|
530
|
-
)
|
|
531
|
-
);
|
|
532
|
-
}
|
|
533
|
-
else if (ref.source === 'request') {
|
|
534
|
-
// this.app.Models.client.[identifier]
|
|
535
|
-
// e.g. this.app.Models.client.MyModel
|
|
536
|
-
subPath.replaceWith(
|
|
537
|
-
t.memberExpression(
|
|
538
|
-
t.identifier('context'),
|
|
539
|
-
subPath.node
|
|
540
|
-
)
|
|
541
|
-
);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
} });
|
|
545
|
-
|
|
546
|
-
if (
|
|
547
|
-
this.routeMethods.includes(methodName)
|
|
548
|
-
&&
|
|
549
|
-
path.node.params.length < 2
|
|
550
|
-
) {
|
|
551
|
-
|
|
552
|
-
// Expose router context variable via the second parameter
|
|
553
|
-
params = [
|
|
554
|
-
path.node.params[0] || t.objectPattern([]),
|
|
555
|
-
t.identifier('context'),
|
|
556
|
-
];
|
|
557
|
-
|
|
558
|
-
// Apply changes
|
|
559
|
-
path.replaceWith(
|
|
560
|
-
t.classMethod(
|
|
561
|
-
path.node.kind,
|
|
562
|
-
path.node.key,
|
|
563
|
-
params,
|
|
564
|
-
path.node.body,
|
|
565
|
-
false,
|
|
566
|
-
false,
|
|
567
|
-
false,
|
|
568
|
-
path.node.async
|
|
569
|
-
)
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
//console.log("ROUTE METHOD", this.filename, methodName, generate(path.node).code);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
};
|
|
577
|
-
|
|
578
|
-
return plugin;
|
|
579
|
-
}
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/*----------------------------------
|
|
2
|
-
- DEPENDANCES
|
|
3
|
-
----------------------------------*/
|
|
4
|
-
|
|
5
|
-
// Npm
|
|
6
|
-
import type { ImportTransformer } from 'babel-plugin-glob-import';
|
|
7
|
-
import * as types from '@babel/types'
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import generate from '@babel/generator';
|
|
10
|
-
|
|
11
|
-
// Core
|
|
12
|
-
import cli from '@cli';
|
|
13
|
-
import type { TAppSide, default as App } from '@cli/app';
|
|
14
|
-
|
|
15
|
-
// Resources
|
|
16
|
-
const routesToPreload = require( cli.paths.appRoot + '/client/pages/preload.json' );
|
|
17
|
-
|
|
18
|
-
/*----------------------------------
|
|
19
|
-
- CONFIG
|
|
20
|
-
----------------------------------*/
|
|
21
|
-
|
|
22
|
-
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
23
|
-
|
|
24
|
-
/*----------------------------------
|
|
25
|
-
- TRANSFORMER
|
|
26
|
-
----------------------------------*/
|
|
27
|
-
|
|
28
|
-
module.exports = (app: App, side: TAppSide, dev: boolean): ImportTransformer => ({
|
|
29
|
-
|
|
30
|
-
debug: false,
|
|
31
|
-
|
|
32
|
-
test: (request) => (
|
|
33
|
-
side === 'client'
|
|
34
|
-
&&
|
|
35
|
-
(
|
|
36
|
-
request.source === '@client/pages/**/([a-z0-9]*).tsx'
|
|
37
|
-
||
|
|
38
|
-
request.source === '@/client/pages/**/([a-z0-9]*).tsx'
|
|
39
|
-
)
|
|
40
|
-
&&
|
|
41
|
-
request.type === 'import'
|
|
42
|
-
),
|
|
43
|
-
replace: (request, matches, t) => {
|
|
44
|
-
|
|
45
|
-
if (request.imported.type !== 'all')
|
|
46
|
-
return;
|
|
47
|
-
|
|
48
|
-
const imports: types.ImportDeclaration[] = [];
|
|
49
|
-
|
|
50
|
-
// const routes = {
|
|
51
|
-
// <chunkId1>: () => import(/* webpackChunkName: '<chunkId>' */ "<file>"),
|
|
52
|
-
// <chunkId2>: () => require("<file>").default,
|
|
53
|
-
// }
|
|
54
|
-
|
|
55
|
-
const pageLoaders: types.ObjectProperty[] = [];
|
|
56
|
-
for (const file of matches) {
|
|
57
|
-
|
|
58
|
-
// Exclude layouts
|
|
59
|
-
if (file.filename.includes("/_layout/")) {
|
|
60
|
-
//console.log("Exclude", file, 'from pages loaders (its a layout)');
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Page config
|
|
65
|
-
const { chunkId } = cli.paths.getPageChunk(app, file.filename);
|
|
66
|
-
const preloadPage = routesToPreload.includes(chunkId);
|
|
67
|
-
|
|
68
|
-
// Preload = use sync import
|
|
69
|
-
if (preloadPage) {
|
|
70
|
-
|
|
71
|
-
// import <chunkId> from "<file>";
|
|
72
|
-
imports.push(
|
|
73
|
-
t.importDeclaration(
|
|
74
|
-
[t.importSpecifier(
|
|
75
|
-
t.identifier(chunkId),
|
|
76
|
-
t.identifier('__register'),
|
|
77
|
-
)],
|
|
78
|
-
t.stringLiteral(file.filename)
|
|
79
|
-
)
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
// { <chunkId>: <chunkId> }
|
|
83
|
-
pageLoaders.push(
|
|
84
|
-
t.objectProperty(
|
|
85
|
-
t.stringLiteral(chunkId),
|
|
86
|
-
t.identifier(chunkId)
|
|
87
|
-
)
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
// Otherwise, use async import + chunk name
|
|
91
|
-
} else {
|
|
92
|
-
|
|
93
|
-
// <chunkId>: () => ...
|
|
94
|
-
pageLoaders.push(
|
|
95
|
-
t.objectProperty(
|
|
96
|
-
|
|
97
|
-
t.stringLiteral(chunkId),
|
|
98
|
-
// () => import(/* webpackChunkName: '<chunkId>' */ "<file>")
|
|
99
|
-
t.arrowFunctionExpression([], t.callExpression(
|
|
100
|
-
|
|
101
|
-
t.import(), [t.addComment(
|
|
102
|
-
t.stringLiteral(file.filename),
|
|
103
|
-
"leading",
|
|
104
|
-
"webpackChunkName: '" + chunkId + "'"
|
|
105
|
-
)]
|
|
106
|
-
))
|
|
107
|
-
)
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/*console.log( generate(t.variableDeclaration("const", [t.variableDeclarator(
|
|
113
|
-
t.identifier(request.imported.name),
|
|
114
|
-
t.objectExpression(pageLoaders)
|
|
115
|
-
)])).code );*/
|
|
116
|
-
|
|
117
|
-
return [
|
|
118
|
-
...imports,
|
|
119
|
-
// const routes = { ... }
|
|
120
|
-
t.variableDeclaration("const", [t.variableDeclarator(
|
|
121
|
-
t.identifier(request.imported.name),
|
|
122
|
-
t.objectExpression(pageLoaders)
|
|
123
|
-
)])
|
|
124
|
-
]
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
})
|