5htp 0.2.3 → 0.3.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.
package/src/index.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env -S npx ts-node
2
2
 
3
+ process.traceDeprecation = true;
4
+
3
5
  /*----------------------------------
4
6
  - DEPENDANCES
5
7
  ----------------------------------*/
6
8
 
7
9
  // Npm
8
- import { Logger } from "tslog";
9
10
  import cp from 'child_process';
10
11
 
11
12
  // Libs
@@ -33,15 +34,15 @@ export class CLI {
33
34
 
34
35
  // Context
35
36
  public args: TArgsObject = {};
37
+
38
+ public debug: boolean = false;
36
39
 
37
40
  public constructor(
38
41
  public paths = new Paths( process.cwd() )
39
42
  ) {
40
- console.log(`[cli] 5HTP CLI`, process.env.npm_package_version);
41
- console.log(`[cli] Start debugger ...`);
42
- new Logger({ name: "cli", overwriteConsole: true });
43
+ this.debug && console.log(`[cli] 5HTP CLI`, process.env.npm_package_version);
43
44
 
44
- console.log(`[cli] Apply aliases ...`);
45
+ this.debug && console.log(`[cli] Apply aliases ...`);
45
46
  this.paths.applyAliases();
46
47
 
47
48
  this.start();
@@ -59,7 +60,7 @@ export class CLI {
59
60
  }
60
61
 
61
62
  public start() {
62
-
63
+
63
64
  const [, , commandName, ...argv] = process.argv;
64
65
 
65
66
  if (this.commands[commandName] === undefined)
@@ -107,7 +108,7 @@ export class CLI {
107
108
 
108
109
  this.args = args;
109
110
 
110
- console.info(`Running command ${command}`, this.args);
111
+ this.debug && console.info(`Running command ${command}`, this.args);
111
112
 
112
113
  // Check existance
113
114
  if (this.commands[command] === undefined)
@@ -118,7 +119,7 @@ export class CLI {
118
119
  // Running
119
120
  runner.run().then(() => {
120
121
 
121
- console.info(`Command ${command} finished.`);
122
+ this.debug && console.info(`Command ${command} finished.`);
122
123
 
123
124
  }).catch((e) => {
124
125
 
package/src/paths.ts CHANGED
@@ -14,7 +14,7 @@ import { filenameToImportName } from 'babel-plugin-glob-import';
14
14
  - TYPES
15
15
  ----------------------------------*/
16
16
 
17
- import type App from './app';
17
+ import type { App } from './app';
18
18
  import type { TAppSide } from './app';
19
19
 
20
20
  export type TPathInfosOptions = {
@@ -1,125 +0,0 @@
1
- import app from '@server/app'; // CLI or App
2
- app.configure({
3
-
4
- // Tracking
5
- tracking: {
6
- // https://analytics.google.com/analytics/web/@report-home/a114396550w244235024p227300451
7
- ga: {
8
- pub: 'G-198FW1K066',
9
- // Client ID
10
- prv: '',
11
- // Secret code for GA4 measurement api
12
- // https://analytics.google.com/analytics/web/#/a114396550p308927292/admin/streams/table/3375435279
13
- secret: 'MJWpU7MqSZKth1LJvp2gag'
14
- }
15
- },
16
-
17
- // HTTP
18
- http: {
19
-
20
- port: 3010,
21
- ssl: false,
22
-
23
- upload: {
24
- maxSize: '10mb'
25
- },
26
-
27
- // Protections against bots
28
- security: {
29
- // https://www.google.com/recaptcha/admin/site/346699952
30
- recaptcha: {
31
- pub: '6LewOKoUAAAAAKmaDqpcNaQz31z_AJarSs0sQvft',
32
- prv: '6LewOKoUAAAAAOAj80m9vOJuP9YcR7PnYQ3E-y4o'
33
- },
34
- iphub: "Mzk3MzpLWE84eHhXQ0ZvUlNQODh0M3J0OXpDTGE2WGx5Szl6OA=="
35
- }
36
- /*session: {
37
- duration: 604800, // 7 Jours
38
- secret: 'secret',
39
- name: 'sessionId',
40
- }*/
41
- },
42
-
43
- // Database (SQL)
44
- database: {
45
- list: ['megacharger'],
46
-
47
- dev: {
48
- host: '127.0.0.1',
49
- port: 3306,
50
- login: 'gaetan',
51
- password: "$mdp=MySQL!159753",
52
- },
53
-
54
- prod: {
55
- host: 'mysqldb',
56
- port: 3306,
57
- login: 'gaetan',
58
- password: "$mdp=MySQL!159753",
59
- },
60
-
61
- },
62
-
63
- // Authentication
64
- auth: {
65
- jwt: {
66
- // 2048 bits
67
- key: "D*G-KaPdSgVkYp3s6v9y$B&E(H+MbQeThWmZq4t7w!z%C*F-J@NcRfUjXn2r5u8x/A?D(G+KbPdSgVkYp3s6v9y$B&E)H@McQfThWmZq4t7w!z%C*F-JaNdRgUkXn2r5u8x/A?D(G+KbPeShVmYq3s6v9y$B&E)H@McQfTjWnZr4u7w!z%C*F-JaNdRgUkXp2s5v8y/A?D(G+KbPeShVmYq3t6w9z$C&E)H@McQfTjWnZr4u7x!A%D*G-JaNdRgU",
68
- expiration: "7 days",
69
- },
70
- google: {
71
- web: {
72
- clientId: "186669785739-e760eqsevhi7hd6nii6ha5pk0rip1s86.apps.googleusercontent.com",
73
- secret: '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',
74
- },
75
- android: {
76
- clientId: "186669785739-geqn7egdepda7aqgoob0ce7jot1ko2gh.apps.googleusercontent.com"
77
- }
78
- }
79
- },
80
-
81
- // Router
82
- router: {
83
-
84
- },
85
-
86
- // Socket
87
- socket: {
88
- port: 3011,
89
- },
90
-
91
- // Email
92
- email: {
93
- default: {
94
- transporter: 'mailjet',
95
- from: 'sites@gaetan-legac.fr',
96
- },
97
- transporters: {
98
- local: {
99
- // Réseau
100
- host: 'localhost',
101
- port: 25,
102
- tls: false,
103
- // Auth
104
- login: 'contact',
105
- password: '$mdp=VPS!159753',
106
- },
107
- sendgrid: {
108
- api: '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',
109
- },
110
- mailjet: {
111
- api: '2c24ad3fa9254fe1a50f4d707069d654'
112
- }
113
- }
114
- },
115
-
116
- // Redis
117
- redis: {
118
-
119
- },
120
-
121
- // Cron
122
- cron: {
123
-
124
- }
125
- })
@@ -1,241 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- // Npm
6
- import * as types from '@babel/types'
7
- import type { PluginObj, NodePath } from '@babel/core';
8
- import generate from '@babel/generator';
9
-
10
- // Core
11
- import type { TAppSide } from '@cli/index';
12
-
13
- /*----------------------------------
14
- - WEBPACK RULE
15
- ----------------------------------*/
16
-
17
- type TOptions = {
18
- side: TAppSide
19
- }
20
-
21
- module.exports = (options: TOptions) => ({
22
- test: "**/server/models/**/*.ts",
23
- plugins: [
24
- [Plugin, options]
25
- ]
26
- })
27
-
28
- module.exports.Plugin = Plugin;
29
-
30
- const debug = true;
31
-
32
- const metasKey = 'metadata';
33
-
34
- /*----------------------------------
35
- - PLUGIN
36
- ----------------------------------*/
37
- function Plugin(babel, { }: TOptions) {
38
-
39
- const t = babel.types as typeof types;
40
-
41
- const plugin: PluginObj<{ filename: string }> = {
42
- pre(state) {
43
-
44
- this.filename = state.opts.filename as string;
45
-
46
- },
47
- visitor: {
48
- Program(path) {
49
-
50
- const filename = this.filename;
51
-
52
- // Lorsque les visiteurs sont déclarés à la racine du plugin,
53
- // Impossible d'obtenir les ast des décorateurs car ils ont déjà été compilés ...
54
- // Pourquoi cela fonctionne en passant par Program.traverse ?
55
- path.traverse({
56
- Decorator(path) {
57
-
58
- injectMetadatas(path, filename, t);
59
-
60
- },
61
- });
62
-
63
-
64
- }
65
-
66
- }
67
- };
68
-
69
- return plugin;
70
- }
71
-
72
- /*----------------------------------
73
- - EXTRACTION
74
- ----------------------------------*/
75
- function injectMetadatas( path: NodePath<types.Decorator>, filename: string, t: typeof types ) {
76
-
77
- // @Table( <database>, <table>, <options?> )
78
- const expression = path.node.expression;
79
- if (!(
80
- expression.type === 'CallExpression'
81
- &&
82
- expression.callee.type === 'Identifier'
83
- &&
84
- expression.callee.name === 'Table'
85
- &&
86
- expression.arguments.length >= 2
87
- ))
88
- return;
89
-
90
- // Class
91
- const classe = path.parent;
92
- if (classe.type !== 'ClassDeclaration')
93
- return;
94
-
95
- debug && console.log(`Processing class ${classe.id.name}`);
96
-
97
- // Only process if metadata are not already defined
98
- let [database, table, options] = expression.arguments;
99
- if (options !== undefined) {
100
-
101
- if (options.type !== 'ObjectExpression')
102
- throw new Error(`Error in ${filename}: The 3rd argument of @Table must be an object expression.`);
103
-
104
- const hasMetas = options.properties.some(p =>
105
- p.type === 'ObjectProperty'
106
- &&
107
- p.key.type === 'Identifier'
108
- &&
109
- p.key.name === metasKey
110
- );
111
-
112
- if (hasMetas) {
113
- debug && console.log(`Metadata already provides for class ${classe.id.name} (${filename})`);
114
- return;
115
- }
116
- }
117
-
118
- // Extract metadata
119
- const attributes = extractMetadata(classe, t);
120
- //debug && console.log( generate(attributes).code );
121
- const metasProperty = t.objectProperty(
122
- t.identifier(metasKey),
123
- t.objectExpression(attributes)
124
- )
125
-
126
- // Insert metas in options
127
- if (options === undefined)
128
- options = t.objectExpression([metasProperty]);
129
- else
130
- options = t.objectExpression([...options.properties, metasProperty]);
131
-
132
- // Update decorator
133
- path.replaceWith(t.decorator(
134
- t.callExpression(t.identifier('Table'), [
135
- database,
136
- table,
137
- options
138
- ])
139
- ));
140
- }
141
-
142
- function extractMetadata(classe: types.ClassDeclaration, t: typeof types) {
143
-
144
- const attributes: types.ObjectProperty[] = [];
145
-
146
- // Lecture des propriétés et méthodes de la classe
147
- for (const prop of classe.body.body) {
148
-
149
- if (!(
150
- // non-statique
151
- !prop.static
152
- &&
153
- (
154
- // Propriété simple
155
- prop.type === 'ClassProperty'
156
- ||
157
- // Getter
158
- (prop.type === 'ClassMethod' && prop.kind === 'get')
159
- )
160
- &&
161
- // Publique
162
- prop.accessibility === 'public'
163
- &&
164
- prop.key.type === 'Identifier'
165
- ))
166
- continue;
167
-
168
- const nomProp = prop.key.name;
169
-
170
- // Détermine si la propriété est exposée à l'api
171
- // = possède le décorateur @API()
172
- const exposeToAPI = prop.decorators && prop.decorators.some((decorateur) =>
173
- decorateur.expression.type === 'CallExpression'
174
- &&
175
- decorateur.expression.callee.type === 'Identifier'
176
- &&
177
- decorateur.expression.callee.name === 'API'
178
- );
179
-
180
- if (!exposeToAPI) continue;
181
-
182
- let type: any;
183
- if (prop.type === 'ClassProperty')
184
- type = prop.typeAnnotation;
185
- else
186
- type = prop.returnType;
187
-
188
- // Verif si type spécifié
189
- if (!type)
190
- throw new Error(`Unable to extract type of ${classe.id.name}.${prop.key.name}.`);
191
-
192
- // Sérialisation du type
193
- const typeString = generate(type.typeAnnotation).code;
194
-
195
- debug && console.log( classe.id.name + '.' + nomProp + ': ' + typeString );
196
-
197
- // Sérialisation valeur defaut
198
- const defaut = prop.type === 'ClassProperty' && prop.value && ('value' in prop.value)
199
- ? prop.value
200
- : t.identifier('undefined')
201
-
202
- attributes.push(
203
- t.objectProperty( t.identifier(nomProp), t.objectExpression([
204
-
205
- t.objectProperty(
206
- t.identifier('nom'),
207
- t.stringLiteral(nomProp)
208
- ),
209
-
210
- t.objectProperty(
211
- t.identifier('nomComplet'),
212
- t.stringLiteral(prop.optional ? nomProp + '?' : nomProp)
213
- ),
214
-
215
- t.objectProperty(
216
- t.identifier('type'),
217
- t.stringLiteral(typeString)
218
- ),
219
-
220
- t.objectProperty(
221
- t.identifier('optionnel'),
222
- t.booleanLiteral(prop.optional === true)
223
- ),
224
-
225
- t.objectProperty(
226
- t.identifier('api'),
227
- t.booleanLiteral(exposeToAPI)
228
- ),
229
-
230
- t.objectProperty(
231
- t.identifier('defaut'),
232
- defaut
233
- ),
234
-
235
- ]))
236
- );
237
- }
238
-
239
- return attributes;
240
-
241
- }
@@ -1,152 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- // Npm
6
- import * as types from '@babel/types'
7
- import type { PluginObj, NodePath } from '@babel/core';
8
- import generate from '@babel/generator';
9
-
10
- // Core
11
- import cli from '@cli';
12
- import App, { TAppSide } from '../../../../app';
13
-
14
- /*----------------------------------
15
- - WEBPACK RULE
16
- ----------------------------------*/
17
-
18
- type TOptions = {
19
- side: TAppSide
20
- }
21
-
22
- module.exports = (options: TOptions) => ({
23
- test: "**/client/pages/**/*.tsx",
24
- plugins: [
25
- [Plugin, options]
26
- ]
27
- })
28
-
29
- const debug = false;
30
-
31
- /*----------------------------------
32
- - PLUGIN
33
- ----------------------------------*/
34
- function Plugin(babel, { side }: TOptions) {
35
-
36
- const app = new App();
37
-
38
- const t = babel.types as typeof types;
39
- let program: NodePath<types.Program>;
40
-
41
- const plugin: PluginObj<{
42
- filename: string
43
- }> = {
44
- pre(state) {
45
-
46
- this.filename = state.opts.filename as string;
47
-
48
- },
49
- visitor: {
50
-
51
- Program(path) {
52
- program = path;
53
- },
54
-
55
- CallExpression(path) {
56
-
57
- // route.xxx( <PATH>, ... )
58
- if (!(
59
- path.node.callee.type === 'MemberExpression'
60
- &&
61
- path.node.callee.object.type === "Identifier"
62
- &&
63
- path.node.callee.object.name === "route"
64
- &&
65
- path.node.arguments.length >= 2
66
- ))
67
- return;
68
-
69
- const [routePath, ...routeArgs] = path.node.arguments;
70
- debug && console.log(`[routes]`, this.filename, ...routeArgs.map(n => n.type));
71
-
72
- // Inject chunk id in options (2nd arg)
73
- const status = addChunkId(routeArgs, this.filename);
74
- if (status === 'ALREADY_PROCESSED')
75
- return;
76
-
77
- // Transform 2nd arg of renderer to a useContext spread
78
- addRendererContext(routeArgs, this.filename);
79
-
80
- const replacement = t.callExpression( path.node.callee, [ routePath, ...routeArgs ]);
81
- debug && console.log( generate(replacement).code );
82
-
83
- path.replaceWith( replacement );
84
-
85
- // Force export default
86
- // NOTE: now done by app-import.ts
87
- /*if (path.parent.type === 'ExportDefaultDeclaration')
88
- path.replaceWith( replacement );
89
- else
90
- path.parentPath.replaceWith(
91
- t.exportDefaultDeclaration( replacement )
92
- )*/
93
-
94
- }
95
-
96
- }
97
- };
98
-
99
- function addRendererContext(
100
- routeArgs: types.CallExpression["arguments"],
101
- filename: string
102
- ) {
103
-
104
- // ( <data>, { response, api }) => ....
105
- const renderer = routeArgs[ routeArgs.length - 1 ];
106
- if (!(
107
- renderer.type === 'ArrowFunctionExpression'
108
- &&
109
- renderer.params.length > 1
110
- ))
111
- return;
112
-
113
- // Remove 2nd arg (renderer = react component, so only 1 arg for props)
114
- const declaration = renderer.params.pop() as types.ArrowFunctionExpression["params"][number];
115
- // const <param2> = useContext();
116
- const ctxDeclaration = t.variableDeclaration('const', [t.variableDeclarator(
117
- declaration,
118
- t.callExpression(t.identifier('useContext'), [])
119
- )])
120
-
121
- // Add Declaration
122
- switch (renderer.body.type) {
123
- case 'BlockStatement':
124
- renderer.body.body.unshift(ctxDeclaration);
125
- break;
126
- // TODO: Si type === JSXElement, remplacer par BlockStatement (ctxDeclaration + return JSX)
127
- /*case 'BlockStatement':
128
- renderer.re
129
- break;*/
130
- default:
131
- throw new Error(`Unknown body type for the renderer: ${renderer.body.type}`);
132
- }
133
-
134
- // Add usecontext import if it doesn't exists
135
- if (program.scope.bindings["useContext"] === undefined) {
136
-
137
- debug && console.log(`[routes]`, filename, `Adding useContext import from @context`);
138
-
139
- program.unshiftContainer(
140
- 'body',
141
- t.importDeclaration(
142
- [t.importDefaultSpecifier(t.identifier('useContext'))],
143
- t.stringLiteral('@/client/context')
144
- )
145
- );
146
- }
147
-
148
-
149
- }
150
-
151
- return plugin;
152
- }
@@ -1,46 +0,0 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
-
5
- // Npm
6
- import path from 'path';
7
- import fs from 'fs-extra';
8
-
9
- // App
10
- import type App from '../../../app';
11
-
12
- /*----------------------------------
13
- - TYPES
14
- ----------------------------------*/
15
-
16
- /*----------------------------------
17
- - UTTILS
18
- ----------------------------------*/
19
- export const fixNpmLinkIssues = ( app: App ) => {
20
-
21
- const corePath = path.join(app.paths.root, '/node_modules/5htp-core');
22
- if (!fs.lstatSync( corePath ).isSymbolicLink())
23
- return console.info("Not fixing npm issue because 5htp-core wasn't installed with npm link.");
24
-
25
- console.info(`Fix NPM link issues ...`);
26
-
27
- const appModules = path.join(app.paths.root, 'node_modules');
28
- const coreModules = path.join(corePath, 'node_modules');
29
-
30
- // When the 5htp package is installed from npm link,
31
- // Modules are installed locally and not glbally as with with the 5htp package from NPM.
32
- // So we need to symbilnk the http-core node_modules in one of the parents of server.js.
33
- // It avoids errors like: "Error: Cannot find module 'intl'"
34
- fs.symlinkSync( coreModules, path.join(app.paths.bin, 'node_modules') );
35
-
36
- // Same problem: when 5htp-core is installed via npm link,
37
- // Typescript doesn't detect React and shows mission JSX errors
38
- const preactCoreModule = path.join(coreModules, 'preact');
39
- const preactAppModule = path.join(appModules, 'preact');
40
- const reactAppModule = path.join(appModules, 'react');
41
-
42
- if (!fs.existsSync( preactAppModule ))
43
- fs.symlinkSync( preactCoreModule, preactAppModule );
44
- if (!fs.existsSync( reactAppModule ))
45
- fs.symlinkSync( path.join(preactCoreModule, 'compat'), reactAppModule );
46
- }