5htp 0.4.6 → 0.5.9-2

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.
Files changed (41) hide show
  1. package/{src/app → app}/config.ts +7 -7
  2. package/app/index.ts +210 -0
  3. package/{src/commands → commands}/dev.ts +2 -2
  4. package/{src/commands → commands}/init.ts +1 -1
  5. package/{src/compiler → compiler}/client/identite.ts +1 -1
  6. package/{src/compiler → compiler}/client/index.ts +6 -6
  7. package/{src/compiler → compiler}/common/babel/index.ts +20 -2
  8. package/{src/compiler → compiler}/common/babel/plugins/injection-dependances/index.ts +5 -3
  9. package/{src/compiler → compiler}/common/babel/plugins/queries/index.ts +1 -1
  10. package/compiler/common/babel/plugins/services.ts +245 -0
  11. package/{src/compiler → compiler}/common/babel/routes/imports.ts +3 -3
  12. package/{src/compiler → compiler}/common/babel/routes/routes.ts +218 -70
  13. package/{src/compiler → compiler}/common/files/style.ts +3 -3
  14. package/{src/compiler → compiler}/common/plugins/indexage/icones-svg/index.ts +2 -2
  15. package/{src/compiler → compiler}/index.ts +175 -48
  16. package/{src/compiler → compiler}/server/index.ts +18 -11
  17. package/package.json +7 -5
  18. package/{src/paths.ts → paths.ts} +3 -4
  19. package/tsconfig.json +3 -2
  20. package/src/app/index.ts +0 -111
  21. package/src/compiler/common/babel/plugins/services.ts +0 -209
  22. /package/{src/commands → commands}/build.ts +0 -0
  23. /package/{src/commands → commands}/deploy/app.ts +0 -0
  24. /package/{src/commands → commands}/deploy/web.ts +0 -0
  25. /package/{src/compiler → compiler}/common/babel/plugins/form.ts +0 -0
  26. /package/{src/compiler → compiler}/common/babel/plugins/icones-svg.ts +0 -0
  27. /package/{src/compiler → compiler}/common/babel/plugins/index.ts +0 -0
  28. /package/{src/compiler → compiler}/common/babel/plugins/injection-dependances/remplacerFonction.ts +0 -0
  29. /package/{src/compiler → compiler}/common/files/autres.ts +0 -0
  30. /package/{src/compiler → compiler}/common/files/images.ts +0 -0
  31. /package/{src/compiler → compiler}/common/index.ts +0 -0
  32. /package/{src/compiler → compiler}/common/plugins/indexage/_utils/Stringify.ts +0 -0
  33. /package/{src/compiler → compiler}/common/plugins/indexage/_utils/annotations.ts +0 -0
  34. /package/{src/compiler → compiler}/common/plugins/indexage/_utils/iterateur.ts +0 -0
  35. /package/{src/compiler → compiler}/common/plugins/indexage/index.ts +0 -0
  36. /package/{src/compiler → compiler}/common/plugins/indexage/indexeur.ts +0 -0
  37. /package/{src/compiler → compiler}/common/plugins/indexage/injection-dependances/index.ts +0 -0
  38. /package/{src/index.ts → index.ts} +0 -0
  39. /package/{src/print.ts → print.ts} +0 -0
  40. /package/{src/utils → utils}/index.ts +0 -0
  41. /package/{src/utils → utils}/keyboard.ts +0 -0
@@ -39,17 +39,24 @@ module.exports = (options: TOptions) => (
39
39
  [Plugin, options]
40
40
  )
41
41
 
42
+ const clientServices = ['Router'];
43
+ // Others will be called via app.<Service> (backend) or api.post(<path>, <params>) (frontend)
44
+
45
+ const routerMethods = ['get', 'post', 'put', 'delete', 'patch'];
46
+
42
47
  /*----------------------------------
43
48
  - PLUGIN
44
49
  ----------------------------------*/
45
50
  function Plugin(babel, { app, side, debug }: TOptions) {
46
51
 
52
+ //debug = true;
53
+
47
54
  const t = babel.types as typeof types;
48
55
 
49
56
  /*
50
57
  - Wrap route.get(...) with (app: Application) => { }
51
58
  - Inject chunk ID into client route options
52
- - Transform aoi.fetch:
59
+ - Transform api.fetch:
53
60
 
54
61
  Input:
55
62
  const { stats } = api.fetch({
@@ -78,7 +85,8 @@ function Plugin(babel, { app, side, debug }: TOptions) {
78
85
  // Replace by: nothing
79
86
  ImportDeclaration(path) {
80
87
 
81
- if (!this.file.process)
88
+ const shouldTransformImports = this.file.process;
89
+ if (!shouldTransformImports)
82
90
  return;
83
91
 
84
92
  if (path.node.source.value !== '@app')
@@ -92,7 +100,12 @@ function Plugin(babel, { app, side, debug }: TOptions) {
92
100
  if (specifier.imported.type !== 'Identifier')
93
101
  continue;
94
102
 
95
- this.file.importedServices[ specifier.local.name ] = specifier.imported.name;
103
+ const serviceName = specifier.imported.name;
104
+
105
+ if (clientServices.includes(serviceName))
106
+ this.file.importedServices[ specifier.local.name ] = serviceName;
107
+ else
108
+ this.file.importedServices[ specifier.local.name ] = 'app';
96
109
  }
97
110
 
98
111
  // Remove this import
@@ -100,9 +113,7 @@ function Plugin(babel, { app, side, debug }: TOptions) {
100
113
 
101
114
  },
102
115
 
103
- // Find Router definitions
104
- // Test: Router.xxx()
105
- // Replace by: nothing
116
+ // Transform services service calls
106
117
  CallExpression(path) {
107
118
 
108
119
  if (!this.file.process)
@@ -112,36 +123,121 @@ function Plugin(babel, { app, side, debug }: TOptions) {
112
123
  const callee = path.node.callee
113
124
  if (!(
114
125
  callee.type === 'MemberExpression'
115
- &&
116
- callee.object.type === 'Identifier'
117
- &&
118
- callee.property.type === 'Identifier'
119
- &&
120
- // Should be at the root of the document
121
- path.parent.type === 'ExpressionStatement'
122
- &&
123
- path.parentPath.parent.type === 'Program'
124
- // And make reference to a service
125
- &&
126
- (callee.object.name in this.file.importedServices)
127
126
  ))
128
127
  return;
129
128
 
130
- const routeDef: TRouteDefinition = {
131
- definition: path.node,
132
- dataFetchers: []
133
- }
129
+ // Create full path
130
+ const completePath: string[] = [];
131
+ let currCallee: types.MemberExpression = callee;
132
+ while (1) {
134
133
 
135
- // Adjust
136
- if (this.file.side === 'front') {
137
- transformDataFetchers(path, this, routeDef);
134
+ if (currCallee.property.type === 'Identifier')
135
+ completePath.unshift(currCallee.property.name);
136
+
137
+ if (currCallee.object.type === 'MemberExpression')
138
+ currCallee = currCallee.object;
139
+ else {
140
+
141
+ if (currCallee.object.type === 'Identifier')
142
+ completePath.unshift(currCallee.object.name);
143
+
144
+ break;
145
+ }
138
146
  }
147
+
148
+ // If we actually call a service
149
+ const serviceName = completePath[0];
150
+
151
+ /*
152
+ Router.page: wrap with export const __register = ({ Router }) => Router.page(...)
153
+ */
154
+ if (
155
+ serviceName === 'Router'
156
+ &&
157
+ callee.property.type === 'Identifier'
158
+ &&
159
+ ['page', 'error', ...routerMethods].includes(callee.property.name)
160
+ ) {
161
+
162
+ // Should be at the root of the document
163
+ if (!(
164
+ path.parent.type === 'ExpressionStatement'
165
+ &&
166
+ path.parentPath.parent.type === 'Program'
167
+ ))
168
+ return;
169
+
170
+ const routeDef: TRouteDefinition = {
171
+ definition: path.node,
172
+ dataFetchers: []
173
+ }
174
+
175
+ // Adjust
176
+ if (this.file.side === 'front') {
177
+ transformDataFetchers(path, this, routeDef);
178
+ }
179
+
180
+ // Add to the list of route definitons to wrap
181
+ this.file.routeDefinitions.push(routeDef);
182
+
183
+ // Delete the route def since it will be replaced by a wrapper
184
+ path.replaceWithMultiple([]);
185
+
186
+ /* [client] Backend Service calls: Transform to api.post( <method path>, <params> )
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
+ */
192
+ } else if (this.file.side === 'front') {
139
193
 
140
- // Add to the list of route definitons to wrap
141
- this.file.routeDefinitions.push(routeDef);
194
+ const isAService = (
195
+ serviceName in this.file.importedServices
196
+ &&
197
+ serviceName[0] === serviceName[0].toUpperCase()
198
+ );
199
+ if(!isAService)
200
+ return;
201
+
202
+ if (side === 'client') {
142
203
 
143
- // Delete the route def since it will be replaced by a wrapper
144
- path.replaceWithMultiple([]);
204
+ // Get complete call path
205
+ const apiPath = '/api/' + completePath.join('/');
206
+
207
+ // Replace by api.post( <method path>, <params> )
208
+ const apiPostArgs: types.CallExpression["arguments"] = [t.stringLiteral(apiPath)];
209
+ if (path.node.arguments.length === 1)
210
+ apiPostArgs.push( path.node.arguments[0] );
211
+
212
+ path.replaceWith(
213
+ t.callExpression(
214
+ t.memberExpression(
215
+ t.identifier('api'), t.identifier('post')
216
+ ), apiPostArgs
217
+ )
218
+ )
219
+ } else {
220
+
221
+ // Rebuild member expression from completePath, adding a api prefix
222
+ let newCallee = t.memberExpression(
223
+ t.identifier('app'),
224
+ t.identifier(completePath[0])
225
+ );
226
+ for (let i = 1; i < completePath.length; i++) {
227
+ newCallee = t.memberExpression(
228
+ newCallee,
229
+ t.identifier(completePath[i])
230
+ );
231
+ }
232
+
233
+ // Replace by app.<service>.<method>(...)
234
+ path.replaceWith(
235
+ t.callExpression(
236
+ newCallee, [...path.node.arguments]
237
+ )
238
+ )
239
+ }
240
+ }
145
241
 
146
242
  },
147
243
  Program: {
@@ -153,7 +249,6 @@ function Plugin(babel, { app, side, debug }: TOptions) {
153
249
  const wrappedrouteDefs = wrapRouteDefs( this.file );
154
250
  if (wrappedrouteDefs)
155
251
  path.pushContainer('body', [wrappedrouteDefs])
156
-
157
252
  }
158
253
  }
159
254
  }
@@ -175,8 +270,8 @@ function Plugin(babel, { app, side, debug }: TOptions) {
175
270
  relativeFileName = filename.substring( cli.paths.appRoot.length );
176
271
  if (filename.startsWith( cli.paths.coreRoot ))
177
272
  relativeFileName = filename.substring( cli.paths.coreRoot.length );
178
- if (filename.startsWith('/node_modules/5htp-core/'))
179
- relativeFileName = filename.substring( '/node_modules/5htp-core/'.length );
273
+ /*if (filename.startsWith('/node_modules/5htp-core/'))
274
+ relativeFileName = filename.substring( '/node_modules/5htp-core/'.length );*/
180
275
 
181
276
  // The file isn't a route definition
182
277
  if (relativeFileName === undefined) {
@@ -185,9 +280,9 @@ function Plugin(babel, { app, side, debug }: TOptions) {
185
280
  }
186
281
 
187
282
  // Differenciate back / front
188
- if (relativeFileName.startsWith('/src/client/pages')) {
283
+ if (relativeFileName.startsWith('/client/pages')) {
189
284
  file.side = 'front';
190
- } else if (relativeFileName.startsWith('/src/server/routes')) {
285
+ } else if (relativeFileName.startsWith('/server/routes')) {
191
286
  file.side = 'back';
192
287
  } else
193
288
  file.process = false;
@@ -201,12 +296,13 @@ function Plugin(babel, { app, side, debug }: TOptions) {
201
296
  routeDef: TRouteDefinition
202
297
  ) {
203
298
  path.traverse({
299
+ // api.load => move data fetchers to route.options.data
300
+ // So the router is able to load data before rendering the component
204
301
  CallExpression(path) {
205
302
 
206
303
  const callee = path.node.callee
207
304
 
208
- // api.load => move data fetchers to route.options.data
209
- // So the router is able to load data before rendering the component
305
+ // Detect api.fetch
210
306
  if (!(
211
307
  callee.type === 'MemberExpression'
212
308
  &&
@@ -220,11 +316,23 @@ function Plugin(babel, { app, side, debug }: TOptions) {
220
316
  ))
221
317
  return;
222
318
 
319
+ /* Reference data fetchers
320
+ {
321
+ stats: api.get(...)
322
+ }
323
+ */
223
324
  routeDef.dataFetchers.push(
224
325
  ...path.node.arguments[0].properties
225
326
  );
226
327
 
227
- // Delete routerDefContext node
328
+ /* Replace the:
329
+ const { stats } = api.fetch({
330
+ stats: api.get(...)
331
+ })
332
+
333
+ by:
334
+ const { stats } = context.data.stats;
335
+ */
228
336
  path.replaceWith(
229
337
  t.memberExpression(
230
338
  t.identifier( routeDef.contextName || 'context' ),
@@ -235,7 +343,7 @@ function Plugin(babel, { app, side, debug }: TOptions) {
235
343
  }, routerDefContext);
236
344
  }
237
345
 
238
- function injectOptions(
346
+ function enrichRouteOptions(
239
347
  routeDef: TRouteDefinition,
240
348
  routeArgs: types.CallExpression["arguments"],
241
349
  filename: string
@@ -251,7 +359,7 @@ function Plugin(babel, { app, side, debug }: TOptions) {
251
359
 
252
360
  // Generate page chunk id
253
361
  const { filepath, chunkId } = cli.paths.getPageChunk(app, filename);
254
- debug && console.log(`[routes]`, filename, '=>', chunkId);
362
+ debug && console.log(`[routes]`, filename.replace(cli.paths.appRoot + '/client/pages', ''));
255
363
 
256
364
  // Create new options to add in route.options
257
365
  const newProperties = [
@@ -361,12 +469,14 @@ function Plugin(babel, { app, side, debug }: TOptions) {
361
469
  if (importedServicesList.length === 0)
362
470
  return;
363
471
 
364
- let exportValue: types.Expression | types.BlockStatement;
472
+ const definitions: types.BlockStatement["body"] = [];
365
473
  if (file.side === 'front') {
366
474
 
367
475
  // Limit to one route def per file
368
476
  const routesDefCount = file.routeDefinitions.length;
369
- if (routesDefCount !== 1)
477
+ if (routesDefCount === 0)
478
+ return;
479
+ else if (routesDefCount > 1)
370
480
  throw new Error(`Frontend route definition files (/client/pages/**/**.ts) can contain only one route definition.
371
481
  ${routesDefCount} were given in ${file.path}.`);
372
482
 
@@ -379,7 +489,7 @@ function Plugin(babel, { app, side, debug }: TOptions) {
379
489
  if (callee.object.name === 'Router') {
380
490
 
381
491
  // Inject chunk id in options (2nd arg)
382
- const newRouteArgs = injectOptions(routeDef, routeArgs, file.path);
492
+ const newRouteArgs = enrichRouteOptions(routeDef, routeArgs, file.path);
383
493
  if (newRouteArgs === 'ALREADY_PROCESSED')
384
494
  return;
385
495
 
@@ -388,47 +498,85 @@ function Plugin(babel, { app, side, debug }: TOptions) {
388
498
 
389
499
  // Force babel to create new fresh nodes
390
500
  // If we directy use statementParent, it will not be included in the final compiler code
391
- exportValue = t.callExpression(
392
- t.memberExpression(
393
- t.identifier( callee.object.name ),
394
- callee.property,
395
- ),
396
- [routePath, ...routeArgs]
501
+ definitions.push(
502
+ t.returnStatement(
503
+ t.callExpression(
504
+ t.memberExpression(
505
+ t.identifier( callee.object.name ),
506
+ callee.property,
507
+ ),
508
+ [routePath, ...routeArgs]
509
+ )
510
+ )
397
511
  )
398
512
 
399
513
  } else {
400
514
 
401
- exportValue = t.blockStatement([
515
+ definitions.push(
402
516
  // Without spread = react jxx need additionnal loader
403
517
  ...file.routeDefinitions.map( def =>
404
518
  t.expressionStatement(def.definition)
405
519
  ),
406
- ])
520
+ )
407
521
  }
408
522
 
409
- const exportDeclaration = t.exportNamedDeclaration(
410
- t.variableDeclaration('const', [
411
- t.variableDeclarator(
412
- t.identifier('__register'),
413
- t.arrowFunctionExpression(
414
- [
415
- t.objectPattern(
416
- importedServicesList.map(([ local, imported ]) =>
417
- t.objectProperty(
418
- t.identifier( local ),
419
- t.identifier( imported ),
523
+ /*
524
+ ({ Router, app: { Events } }}) => {
525
+ ...
526
+ }
527
+ */
528
+ const appSpread: types.ObjectProperty[] = []
529
+ const servicesSpread: types.ObjectProperty[] = [
530
+ t.objectProperty(
531
+ t.identifier('app'),
532
+ t.identifier('app'),
533
+ )
534
+ ]
535
+ for (const [local, imported] of importedServicesList) {
536
+ if (imported === 'app')
537
+ appSpread.push(
538
+ t.objectProperty(
539
+ t.identifier(local),
540
+ t.identifier(local),
541
+ )
542
+ )
543
+ else
544
+ servicesSpread.push(
545
+ t.objectProperty(
546
+ t.identifier(local),
547
+ t.identifier(imported),
548
+ )
549
+ )
550
+ }
551
+
552
+ // export const __register = ({ Router, app }) => { ... }
553
+ const exportDeclaration = t.exportNamedDeclaration(
554
+ t.variableDeclaration('const', [
555
+ t.variableDeclarator(
556
+ t.identifier('__register'),
557
+ t.arrowFunctionExpression(
558
+ [
559
+ t.objectPattern(servicesSpread)
560
+ ],
561
+ t.blockStatement([
562
+ // const { Events } = app;
563
+ t.variableDeclaration('const', [
564
+ t.variableDeclarator(
565
+ t.objectPattern(appSpread),
566
+ t.identifier('app')
420
567
  )
421
- )
422
- )
423
- ],
424
- exportValue
568
+ ]),
569
+ // Router.post(....)
570
+ ...definitions,
571
+ ])
572
+ )
425
573
  )
426
- )
427
- ])
428
- );
574
+ ])
575
+ );
576
+
429
577
 
430
- /*(file.side === 'front' && file.path.includes('/headhunter/talents/index.tsx'))
431
- && console.log( file.path, generate(exportDeclaration).code );*/
578
+ /*(file.path.includes('client/pages/convert/auth/login.tsx'))
579
+ && console.log( file.path, generate(exportDeclaration).code );*/
432
580
 
433
581
  return exportDeclaration;
434
582
  }
@@ -18,16 +18,16 @@ module.exports = (app: App, dev: Boolean, client: boolean) => {
18
18
 
19
19
  // Process external/third-party styles
20
20
  {
21
- exclude: [/*process.env.framework + '/kernel', */app.paths.src],
21
+ exclude: [app.paths.root],
22
22
  loader: 'css-loader',
23
23
  options: {
24
24
  sourceMap: dev
25
25
  },
26
26
  },
27
27
 
28
- // Process internal/project styles (from src folder)
28
+ // Process internal/project styles (from root folder)
29
29
  {
30
- include: [/*process.env.framework + '/kernel', */app.paths.src],
30
+ include: [app.paths.root],
31
31
  loader: 'css-loader',
32
32
  options: {
33
33
  // CSS Loader https://github.com/webpack/css-loader
@@ -38,10 +38,10 @@ export default class IconesSVG extends Indexeur {
38
38
  super();
39
39
 
40
40
  this.formats = ['woff2'];
41
- this.dossierIcones = cli.paths.core.src + '/client/assets/icons/';
41
+ this.dossierIcones = cli.paths.core.root + '/client/assets/icons/';
42
42
  this.dossierSortie = app.paths.bin + '/public/';
43
43
 
44
- this.cacheTypes = cli.paths.core.src + '/types/icons.d.ts';
44
+ this.cacheTypes = cli.paths.core.root + '/types/icons.d.ts';
45
45
  this.cacheIndex = this.dossierIcones + 'index.json';
46
46
 
47
47
  if (fs.existsSync(this.cacheIndex)) {