5htp 0.0.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 (35) hide show
  1. package/package.json +94 -0
  2. package/src/commands/build.ts +32 -0
  3. package/src/commands/deploy/app.ts +29 -0
  4. package/src/commands/deploy/web.ts +62 -0
  5. package/src/commands/dev.ts +100 -0
  6. package/src/compiler/client/identite.ts +70 -0
  7. package/src/compiler/client/index.ts +335 -0
  8. package/src/compiler/common/babel/index.ts +261 -0
  9. package/src/compiler/common/babel/plugins/form.ts +191 -0
  10. package/src/compiler/common/babel/plugins/icones-svg.ts +350 -0
  11. package/src/compiler/common/babel/plugins/importations.ts +337 -0
  12. package/src/compiler/common/babel/plugins/injection-dependances/index.ts +223 -0
  13. package/src/compiler/common/babel/plugins/injection-dependances/remplacerFonction.ts +226 -0
  14. package/src/compiler/common/babel/plugins/models.ts +241 -0
  15. package/src/compiler/common/babel/plugins/pages.ts +185 -0
  16. package/src/compiler/common/babel/plugins/queries/index.ts +166 -0
  17. package/src/compiler/common/files/autres.ts +37 -0
  18. package/src/compiler/common/files/images.ts +19 -0
  19. package/src/compiler/common/files/style.ts +64 -0
  20. package/src/compiler/common/index.ts +148 -0
  21. package/src/compiler/common/plugins/indexage/_utils/Stringify.ts +72 -0
  22. package/src/compiler/common/plugins/indexage/_utils/annotations.ts +88 -0
  23. package/src/compiler/common/plugins/indexage/_utils/iterateur.ts +52 -0
  24. package/src/compiler/common/plugins/indexage/icones-svg/index.ts +198 -0
  25. package/src/compiler/common/plugins/indexage/index.ts +132 -0
  26. package/src/compiler/common/plugins/indexage/indexeur.ts +13 -0
  27. package/src/compiler/common/plugins/indexage/injection-dependances/index.ts +68 -0
  28. package/src/compiler/index.ts +86 -0
  29. package/src/compiler/server/index.ts +177 -0
  30. package/src/index.ts +192 -0
  31. package/src/paths.ts +158 -0
  32. package/src/print.ts +12 -0
  33. package/src/utils/index.ts +22 -0
  34. package/src/utils/keyboard.ts +78 -0
  35. package/tsconfig.json +38 -0
@@ -0,0 +1,337 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Node
6
+ import path from 'path';
7
+
8
+ // Npm
9
+ import { PluginObj } from '@babel/core';
10
+ import * as types from '@babel/types'
11
+ import generate from '@babel/generator';
12
+ import micromatch from 'micromatch';
13
+ import fs from 'fs-extra';
14
+
15
+ /*----------------------------------
16
+ - REGEX
17
+ ----------------------------------*/
18
+
19
+ type TRequest = {
20
+ source: string,
21
+ from: string
22
+ } & ({
23
+ type: 'import',
24
+ default?: string,
25
+ specifiers: string[]
26
+ } | {
27
+ type: 'require'
28
+ })
29
+
30
+ type TUnresolvedRequest = {
31
+ source: string,
32
+ from: string,
33
+ type: 'import' | 'require',
34
+ }
35
+
36
+ type FileMatch = { filename: string, matches: string[] };
37
+
38
+ type TTransformer = (
39
+ request: TRequest,
40
+ matches: FileMatch[],
41
+ t: typeof types
42
+ ) => types.Node[] | void
43
+
44
+ type TTransformRule = {
45
+ test: (request: TUnresolvedRequest) => boolean,
46
+ replace: TTransformer
47
+ }
48
+
49
+ type TOptions = {
50
+ debug?: boolean,
51
+ removeAliases?: (source: string) => string
52
+ }
53
+
54
+ /*----------------------------------
55
+ - WEBPACK RULE
56
+ ----------------------------------*/
57
+
58
+ const ruleBuilder = (options: TOptions, rules: TTransformRule[]) => [Plugin, { ...options, rules }];
59
+ export default ruleBuilder;
60
+
61
+ /*----------------------------------
62
+ - PLUGIN
63
+ ----------------------------------*/
64
+
65
+ function getFiles( dir: string ) {
66
+ const files: string[] = [];
67
+ const dirents = fs.readdirSync(dir, { withFileTypes: true });
68
+ for (const dirent of dirents) {
69
+ const res = path.resolve(dir, dirent.name);
70
+ if (dirent.isDirectory()) {
71
+ files.push(...getFiles(res));
72
+ } else {
73
+ files.push(res);
74
+ }
75
+ }
76
+ return files;
77
+ }
78
+
79
+ function Plugin (babel, { rules, debug, removeAliases }: TOptions & { rules: TTransformRule[] }) {
80
+
81
+ //debug = true;
82
+
83
+ const t = babel.types as typeof types;
84
+
85
+ const findFiles = (request: TUnresolvedRequest): {
86
+ files: FileMatch[],
87
+ replace: TTransformer | undefined
88
+ } | null => {
89
+
90
+ const matchingRule = rules.find(({ test }) => test(request));
91
+ if (!request.source.includes('*'))
92
+ return null;
93
+
94
+ let cheminGlob: string = request.source;
95
+
96
+ // Chemin relatif => Transformation en absolu
97
+ if (cheminGlob[0] === '.')
98
+ cheminGlob = path.resolve( path.dirname(request.from), request.source );
99
+ // Chemin absolu => Remplacement alias
100
+ else if (removeAliases !== undefined)
101
+ cheminGlob = removeAliases(request.source);
102
+
103
+ // List files in the search directory
104
+ const wildcardPos = cheminGlob.indexOf('*');
105
+ const rootDir = cheminGlob.substring(0, wildcardPos);
106
+ const allfiles = getFiles(rootDir);
107
+
108
+ // Find matches + keep captured groups
109
+ debug && console.log(`Searching for files matching ${request.source} in directory ${rootDir}`);
110
+ const regex = micromatch.makeRe(cheminGlob, { capture: true });
111
+ const matchedFiles: FileMatch[] = [];
112
+ for (const file of allfiles) {
113
+ const matches = file.match(regex);
114
+ if (matches)
115
+ matchedFiles.push({ filename: file, matches: matches.slice(1) });
116
+ }
117
+ debug && console.log('IMPORT GLOB', request.source, '=>', cheminGlob, matchingRule ? 'from rule' : '', matchedFiles)
118
+
119
+ return { files: matchedFiles, replace: matchingRule?.replace };
120
+ }
121
+
122
+ const plugin: PluginObj<{ fichier: string }> = {
123
+ pre(state) {
124
+ this.fichier = state.opts.filename as string;
125
+ },
126
+ visitor: {
127
+
128
+ // require("path")
129
+ CallExpression(instruction) {
130
+
131
+ const { callee, arguments: args } = instruction.node;
132
+ if (!(
133
+ callee.type === "Identifier" && callee.name === 'require'
134
+ &&
135
+ args.length === 1 && args[0].type === "StringLiteral"
136
+ ))
137
+ return;
138
+
139
+ const chemin = args[0].value;
140
+
141
+ // Glob
142
+ const unresolvedRequest: TUnresolvedRequest = {
143
+ type: 'require',
144
+ source: chemin,
145
+ from: this.fichier
146
+ };
147
+ const result = findFiles(unresolvedRequest);
148
+ if (result === null) return;
149
+ const { replace, files } = result
150
+
151
+ let remplacement: types.Node[] | void;
152
+ if (replace !== undefined)
153
+ remplacement = replace(unresolvedRequest, files, t);
154
+
155
+ if (remplacement === undefined) {
156
+
157
+ remplacement = files.map(fichier => t.callExpression(
158
+ t.identifier('require'),
159
+ [t.stringLiteral(fichier.filename)]
160
+ ))
161
+
162
+ }
163
+
164
+ /*debug && console.log(
165
+ generate(instruction.node).code,
166
+ '=>',
167
+ generate(t.program(remplacement)).code,
168
+ );*/
169
+
170
+ instruction.replaceWithMultiple(remplacement);
171
+
172
+ },
173
+
174
+ ImportDeclaration(instruction) {
175
+
176
+ const chemin = instruction.node.source.value;
177
+ const unresolvedRequest: TUnresolvedRequest = {
178
+ type: 'import',
179
+ source: chemin,
180
+ from: this.fichier
181
+ };
182
+ const result = findFiles(unresolvedRequest);
183
+ if (result === null) return;
184
+ const { replace, files } = result
185
+
186
+ // Référe,ncement des noms à importer
187
+ let importDefault: string | undefined = undefined;
188
+ let importClassique: string[] = []
189
+ let importAll: boolean = false;
190
+ for (const specifier of instruction.node.specifiers) {
191
+
192
+ console.log("specifier.type", specifier.type);
193
+
194
+ /*
195
+ import templates from '@/earn/serveur/emails/*.hbs';
196
+ =>
197
+ import templates_notifications from '@/earn/serveur/emails/notifications.hbs';
198
+ import templates_inscription from '@/earn/serveur/emails/inscription.hbs';
199
+ const templates = {
200
+ notifications: templates_notifications,
201
+ inscription: templates_inscription,
202
+ }
203
+ */
204
+ if (specifier.type === 'ImportDefaultSpecifier') {
205
+
206
+ importDefault = specifier.local.name;
207
+
208
+ /*
209
+ import { notifications, inscription } from '@/earn/serveur/emails/*.hbs';
210
+ =>
211
+ import notifications from '@/earn/serveur/emails/notifications.hbs';
212
+ import inscription from '@/earn/serveur/emails/inscription.hbs';
213
+ */
214
+ } else if (specifier.type === 'ImportSpecifier') {
215
+
216
+ importClassique.push( specifier.local.name );
217
+
218
+ /*
219
+ import * as templates from '@/earn/serveur/emails/*.hbs';
220
+ =>
221
+ import * as templates_notifications from '@/earn/serveur/emails/notifications.hbs';
222
+ import * as templates_inscription from '@/earn/serveur/emails/inscription.hbs';
223
+ const templates = {
224
+ notifications: templates_notifications,
225
+ inscription: templates_inscription,
226
+ }
227
+ */
228
+ } else if (specifier.type === 'ImportNamespaceSpecifier') {
229
+
230
+ importDefault = specifier.local.name;
231
+ importAll = true;
232
+
233
+ }
234
+
235
+ }
236
+
237
+ let remplacement: types.Node[] | void;
238
+ if (replace !== undefined)
239
+ remplacement = replace({
240
+ ...unresolvedRequest,
241
+ default: importDefault,
242
+ specifiers: importClassique
243
+ }, files, t);
244
+
245
+ if (remplacement === undefined) {
246
+
247
+ // Recup liste files disponibles et création des importations
248
+ let nomImports: [string, string][] = []
249
+ remplacement = [];
250
+
251
+ for (const fichier of files) {
252
+
253
+ /// Exclusion du fichier actuel
254
+ if (fichier.filename === this.fichier)
255
+ continue;
256
+
257
+ // import <chemin>
258
+ if (instruction.node.specifiers.length === 0) {
259
+
260
+ remplacement.push(
261
+ t.importDeclaration(
262
+ [],
263
+ t.stringLiteral(fichier.filename)
264
+ )
265
+ );
266
+
267
+ } else {
268
+
269
+ // Création nom d'importation via le nom du fichier
270
+ const posSlash = fichier.filename.lastIndexOf('/') + 1;
271
+ const posExt = fichier.filename.lastIndexOf('.');
272
+ const nomFichier = fichier.filename.substring(
273
+ posSlash,
274
+ posExt > posSlash ? posExt : undefined
275
+ )
276
+ const nomFichierPourImport = fichier.matches.join('_')
277
+
278
+ //console.log({ posSlash, posExt, length: fichier.length, nomFichier });
279
+
280
+ let nomImport: string;
281
+ // import <nom> from <chemin>
282
+ if (importClassique.includes( nomFichier ))
283
+ nomImport = nomFichierPourImport;
284
+ // import <prefixe>_<nom> from <chemin>
285
+ else if (importDefault !== undefined) {
286
+ nomImport = importDefault + '_' + nomFichierPourImport.replace(
287
+ /[ \/]/g, '_'
288
+ );
289
+ nomImports.push([nomImport, nomFichierPourImport])
290
+ } else
291
+ continue;
292
+
293
+ // Création de l'importation
294
+ remplacement.push(
295
+ t.importDeclaration(
296
+ [ importAll
297
+ ? t.importNamespaceSpecifier( t.identifier(nomImport) )
298
+ : t.importDefaultSpecifier( t.identifier(nomImport) )
299
+ ],
300
+ t.stringLiteral(fichier.filename)
301
+ )
302
+ );
303
+
304
+ }
305
+
306
+ }
307
+
308
+ // Import default
309
+ if (importDefault !== undefined)
310
+ remplacement.push(
311
+ t.variableDeclaration('const', [
312
+ t.variableDeclarator(
313
+ t.identifier(importDefault),
314
+ t.objectExpression(
315
+ nomImports.map(([nomImport, nomFichier]) => t.objectProperty(
316
+ t.stringLiteral(nomFichier),
317
+ t.identifier(nomImport),
318
+ ))
319
+ )
320
+ )
321
+ ])
322
+ )
323
+ }
324
+
325
+ debug && console.log(
326
+ generate(instruction.node).code,
327
+ '=>',
328
+ generate( t.program(remplacement) ).code,
329
+ );
330
+
331
+ instruction.replaceWithMultiple(remplacement);
332
+ }
333
+ }
334
+ };
335
+
336
+ return plugin;
337
+ }
@@ -0,0 +1,223 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import { PluginObj } from '@babel/core';
7
+ import * as types from '@babel/types'
8
+ var minimatch = require("minimatch")
9
+
10
+ import cli from '@cli';
11
+
12
+ /*----------------------------------
13
+ - WEBPACK RULE
14
+ ----------------------------------*/
15
+ const globServices = cli.paths.app.root + '/src/server/services/**/*.ts';
16
+ const globModuleService = '@app/server/services/**';
17
+ const globRoutes = cli.paths.app.root + '/src/server/routes/**/*.ts';
18
+
19
+ module.exports = {
20
+ test: [globRoutes, globServices],
21
+ plugins: [
22
+ [Plugin]
23
+ ]
24
+ }
25
+
26
+ /*----------------------------------
27
+ - PLUGIN
28
+ ----------------------------------*/
29
+ function Plugin (babel) {
30
+
31
+ const t = babel.types as typeof types;
32
+
33
+ const remplacerFonction = require('./remplacerFonction').default(t);
34
+
35
+ const plugin: PluginObj<{
36
+ fichier: string,
37
+ cheminApi: string | undefined,
38
+ dependances: {[fichier: string]: { }}
39
+ nbDependances: number,
40
+ servicesImportes: {[nom: string]: string}
41
+ }> = {
42
+ pre(state) {
43
+
44
+ this.fichier = state.opts.filename as string;
45
+
46
+ this.cheminApi = getCheminControleur(this.fichier);
47
+
48
+ //console.log('fichier', fichier);
49
+
50
+ this.dependances = {}; // fichier service => { classe, dependances }
51
+ this.nbDependances = 0;
52
+
53
+ // Permet d'identifier le chemin du module associé à un nom de type
54
+ this.servicesImportes = {};
55
+
56
+ for (const nomBinding in state.scope.bindings) {
57
+ const binding = state.scope.bindings[nomBinding].path;
58
+ // Les services doitvent être importés via un import default
59
+ if (binding.type === 'ImportDefaultSpecifier' && binding.parent.type === 'ImportDeclaration') {
60
+
61
+ const fichier = binding.parent.source.value;
62
+
63
+ if (!minimatch(fichier, globModuleService))
64
+ continue;
65
+
66
+ this.servicesImportes[nomBinding] = fichier;
67
+
68
+ }
69
+ }
70
+
71
+ },
72
+ visitor: {
73
+
74
+ // Typescript vire les imports quand ils sont utilisés uniquement comme des types
75
+ // Etant donné que ces derniers sont encore visibles dans pre(state) mais qu'ils le sont plus ici,
76
+ // On les rajoute
77
+ Program(path) {
78
+ for (const nomService in this.servicesImportes) {
79
+ if (!( nomService in path.scope.bindings )) {
80
+
81
+ console.log('Importation forcée de ' + nomService + ' dans ' + this.fichier);
82
+
83
+ path.unshiftContainer(
84
+ 'body',
85
+ t.importDeclaration(
86
+ [t.importDefaultSpecifier( t.identifier(nomService) )],
87
+ t.stringLiteral( this.servicesImportes[ nomService ] )
88
+ )
89
+ )
90
+ }
91
+ }
92
+ },
93
+
94
+ // Classe service
95
+ ClassMethod(i) {
96
+ try {
97
+
98
+ const constructeurService = (
99
+ i.node.kind === 'constructor'
100
+ &&
101
+ i.node.params.length !== 0
102
+ );
103
+ if (!constructeurService) return;
104
+
105
+ const classeParent = i.findParent(p => p.node.type === 'ClassDeclaration');
106
+ const parentService = (
107
+ classeParent !== undefined
108
+ &&
109
+ (classeParent.node as types.ClassDeclaration).id.name.endsWith('Service')
110
+ )
111
+ if (!parentService) return;
112
+
113
+ // Extraction de la liste des dépendances
114
+ const remplacement = remplacerFonction.bind(this)(i.node)
115
+ if (remplacement !== null)
116
+ i.replaceWith(remplacement);
117
+
118
+ } catch (e) {
119
+ console.error("[plugin injection-dependances] Erreur traitement constructeur classe", e);
120
+ throw e;
121
+ }
122
+ },
123
+
124
+ // Route
125
+ CallExpression(i) {
126
+ try {
127
+
128
+ if (i.node.loc === undefined) return; // Pas de loc = nouvellement créé = Pas besoin de retraiter
129
+
130
+ // xxx.get('/', ...)
131
+ if (
132
+ i.node.callee.type === 'MemberExpression'
133
+ &&
134
+ i.node.callee.property.type === 'Identifier'
135
+ &&
136
+ ['get', 'post', 'put', 'delete'].includes(i.node.callee.property.name)
137
+ &&
138
+ i.node.arguments.length >= 2 // url + au moins 1 middleware
139
+ &&
140
+ i.node.arguments[0].type === 'StringLiteral'
141
+ ) {
142
+
143
+ i.replaceWith(
144
+ t.callExpression(
145
+ i.node.callee,
146
+ i.node.arguments.map((arg) => (
147
+ // async ( ... ) => { ... }
148
+ arg.type === 'ArrowFunctionExpression'
149
+ &&
150
+ arg.async === true
151
+ &&
152
+ arg.params.length !== 0
153
+ ) ? remplacerFonction.bind(this)(arg) || arg : arg)
154
+ )
155
+ );
156
+
157
+ }
158
+
159
+ } catch (e) {
160
+ console.error("[plugin injection-dependances] Erreur traitement controleur route", e);
161
+ throw e;
162
+ }
163
+
164
+ },
165
+
166
+ // Injection chemin fichier dans la définition des requetes api
167
+ ExportDefaultDeclaration(instruction) {
168
+
169
+ if (this.cheminApi === undefined)
170
+ return;
171
+
172
+ const declaration = instruction.node.declaration;
173
+
174
+ // Avant: export default Route.api({ ... });
175
+ // Après: export default Route.api({ ... }, 'Earn.Tasks.Missions.Get');
176
+ if (
177
+ declaration.type === 'CallExpression'
178
+ &&
179
+ declaration.callee.type === 'MemberExpression'
180
+ &&
181
+ declaration.callee.object.type === 'Identifier'
182
+ &&
183
+ declaration.callee.object.name === 'Route'
184
+ &&
185
+ declaration.callee.property.type === 'Identifier'
186
+ &&
187
+ declaration.callee.property.name === 'api'
188
+ &&
189
+ declaration.arguments.length === 1
190
+ &&
191
+ declaration.arguments[0].type === 'ObjectExpression'
192
+ ) {
193
+
194
+ //console.log('METHODES API', this.cheminApi);
195
+
196
+ const chemin = this.cheminApi;
197
+
198
+ instruction.replaceWith(
199
+ t.exportDefaultDeclaration(
200
+ t.callExpression(
201
+ declaration.callee,
202
+ [
203
+ declaration.arguments[0],
204
+ t.stringLiteral(chemin)
205
+ ]
206
+ )
207
+ )
208
+ )
209
+
210
+ }
211
+
212
+ }
213
+ },
214
+ post(state) {
215
+
216
+ if (this.nbDependances !== 0)
217
+ state.metadata['injection-dependances'] = this.dependances;
218
+
219
+ }
220
+ };
221
+
222
+ return plugin;
223
+ }