5htp-core 0.2.9 → 0.3.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.
Files changed (75) hide show
  1. package/package.json +7 -5
  2. package/src/client/app/component.tsx +2 -2
  3. package/src/client/assets/css/text/titres.less +4 -0
  4. package/src/client/components/Dialog/card.tsx +1 -1
  5. package/src/client/components/Dialog/index.less +3 -3
  6. package/src/client/components/inputv3/date/index.tsx +1 -1
  7. package/src/client/components/inputv3/index.tsx +14 -4
  8. package/src/client/pages/_layout/index.tsx +3 -3
  9. package/src/client/pages/_messages/400.tsx +2 -2
  10. package/src/client/pages/_messages/401.tsx +2 -2
  11. package/src/client/pages/_messages/403.tsx +2 -2
  12. package/src/client/pages/_messages/404.tsx +2 -2
  13. package/src/client/pages/_messages/500.tsx +2 -2
  14. package/src/client/pages/useHeader.tsx +2 -1
  15. package/src/client/services/router/components/router.tsx +1 -1
  16. package/src/client/services/router/index.tsx +5 -1
  17. package/src/client/services/router/response/index.tsx +5 -2
  18. package/src/common/data/objets.ts +0 -25
  19. package/src/common/router/index.ts +8 -12
  20. package/src/common/router/layouts.ts +3 -1
  21. package/src/common/router/register.ts +5 -3
  22. package/src/common/router/response/index.ts +3 -3
  23. package/src/server/app/commands.ts +2 -11
  24. package/src/server/app/{config.ts → container/config.ts} +4 -1
  25. package/src/server/app/container/index.ts +84 -0
  26. package/src/server/app/index.ts +73 -136
  27. package/src/server/app/instance.ts +3 -0
  28. package/src/server/app/service/container.ts +136 -0
  29. package/src/server/app/service/index.ts +219 -0
  30. package/src/server/index.ts +9 -3
  31. package/src/server/services/cache/index.ts +42 -16
  32. package/src/server/services/cache/service.json +6 -0
  33. package/src/server/services/console/index.ts +35 -22
  34. package/src/server/services/console/service.json +6 -0
  35. package/src/server/services/cron/index.ts +11 -11
  36. package/src/server/services/cron/service.json +6 -0
  37. package/src/server/services/database/connection.ts +26 -34
  38. package/src/server/services/database/index.ts +41 -21
  39. package/src/server/services/database/metas.ts +12 -7
  40. package/src/server/services/database/repository.ts +0 -9
  41. package/src/server/services/database/service.json +6 -0
  42. package/src/server/services/database/stats.ts +3 -3
  43. package/src/server/services/disks/driver.ts +9 -7
  44. package/src/server/services/disks/drivers/local/index.ts +199 -0
  45. package/src/server/services/disks/drivers/local/service.json +6 -0
  46. package/src/server/services/disks/drivers/s3/index.ts +282 -0
  47. package/src/server/services/disks/drivers/s3/service.json +6 -0
  48. package/src/server/services/disks/index.ts +47 -16
  49. package/src/server/services/disks/service.json +6 -0
  50. package/src/server/services/email/index.ts +16 -4
  51. package/src/server/services/email/service.json +6 -0
  52. package/src/server/services/fetch/index.ts +52 -8
  53. package/src/server/services/fetch/service.json +6 -0
  54. package/src/server/services/router/http/index.ts +12 -9
  55. package/src/server/services/router/index.ts +95 -68
  56. package/src/server/services/router/request/api.ts +1 -1
  57. package/src/server/services/router/response/index.ts +13 -19
  58. package/src/server/services/router/service.json +6 -0
  59. package/src/server/services/router/service.ts +16 -29
  60. package/src/server/services/schema/{router.ts → router/index.ts} +19 -7
  61. package/src/server/services/schema/router/service.json +6 -0
  62. package/src/server/services/schema/service.json +6 -0
  63. package/src/server/services/security/encrypt/{aes.ts → aes/index.ts} +16 -3
  64. package/src/server/services/security/encrypt/aes/service.json +6 -0
  65. package/src/server/services/socket/index.ts +39 -13
  66. package/src/server/services/socket/service.json +6 -0
  67. package/src/server/services/users/index.ts +16 -4
  68. package/src/server/services/users/old.ts +1 -1
  69. package/src/server/services/users/router/index.ts +21 -14
  70. package/src/server/services/users/router/service.json +6 -0
  71. package/src/server/services/users/service.json +6 -0
  72. package/src/types/aliases.d.ts +5 -0
  73. package/tsconfig.common.json +2 -0
  74. package/src/server/app/service.ts +0 -109
  75. /package/src/server/{patch.ts → app/container/patch.ts} +0 -0
@@ -2,26 +2,20 @@
2
2
  - DEPENDANCES
3
3
  ----------------------------------*/
4
4
 
5
- import '../patch';
6
-
7
- // Npm
8
- import fs from 'fs-extra';
9
-
10
5
  // Core
11
- import ConfigParser, { TEnvConfig } from './config';
12
- import { default as Service, AnyService } from './service';
6
+ import AppContainer from './container';
7
+ import ApplicationService, { AnyService } from './service';
13
8
  import CommandsManager from './commands';
9
+ import ServicesContainer, { TRegisteredService, TServiceMetas } from './service/container';
14
10
 
15
11
  // Built-in
16
12
  import type { default as Router, Request as ServerRequest } from '@server/services/router';
13
+ export { default as Services } from './service/container';
17
14
 
18
15
  /*----------------------------------
19
16
  - TYPES
20
17
  ----------------------------------*/
21
18
 
22
- export { default as Service } from './service';
23
- export type { TPriority } from './service';
24
-
25
19
  type Config = {
26
20
 
27
21
  }
@@ -49,80 +43,62 @@ declare global {
49
43
  interface User { }
50
44
  }
51
45
 
46
+ export const Service = ServicesContainer;
47
+
52
48
  /*----------------------------------
53
49
  - FUNCTIONS
54
50
  ----------------------------------*/
55
- export default abstract class Application extends Service<Config, Hooks, /* TODO: this ? */Application> {
51
+ export class Application extends ApplicationService<Config, Hooks, /* TODO: this ? */Application> {
56
52
 
57
53
  /*----------------------------------
58
54
  - PROPERTIES
59
55
  ----------------------------------*/
60
56
 
61
57
  public side = 'server' as 'server';
62
-
63
- // Context
64
- public hmr: __WebpackModuleApi.Hot | undefined = module.hot;
65
-
66
- public path = {
67
- root: process.cwd(),
68
- public: process.cwd() + '/public',
69
-
70
- // TODO: move to disk
71
- var: process.cwd() + '/var',
72
- typings: process.cwd() + '/var/typings',
73
- cache: process.cwd() + '/var/cache',
74
- data: process.cwd() + '/var/data',
75
- log: process.cwd() + '/var/log',
58
+ public metas: TServiceMetas = {
59
+ id: 'application',
60
+ name: 'Application',
61
+ parent: 'root',
62
+ dependences: [],
63
+ class: () => ({ 'default': Application })
76
64
  }
77
65
 
78
- public pkg = fs.readJSONSync(this.path.root + '/package.json');
66
+ // Shortcuts to ApplicationContainer
67
+ public container = AppContainer;
68
+ public env = AppContainer.Environment;
69
+ public identity = AppContainer.Identity;
79
70
 
80
71
  // Status
72
+ public debug: boolean = false;
81
73
  public launched: boolean = false;
82
- public status = {
83
- services: false
84
- }
85
74
 
86
- private servicesList: AnyService[] = []
75
+ // All service instances by service id
76
+ public allServices: {[serviceId: string]: AnyService} = {}
87
77
 
88
78
  /*----------------------------------
89
79
  - INIT
90
80
  ----------------------------------*/
91
81
 
92
- public env: TEnvConfig;
93
- public identity: Config.Identity;
94
-
95
82
  public constructor() {
96
83
 
97
- super({}, {});
84
+ // Application itself doesnt have configuration
85
+ // Configuration must be handled by application services
86
+ super({}, {}, {}, {});
87
+
88
+ this.app = this;
98
89
 
99
90
  // Gestion crash
100
91
  process.on('unhandledRejection', (error: any, promise: any) => {
101
92
  // We don't log the error here because it's the role of the app to decidehiw to log errors
102
93
  this.runHook('error', error);
103
94
  });
104
-
105
- // Load config files
106
- const configParser = new ConfigParser( this.path.root );
107
- this.env = configParser.env();
108
- this.identity = configParser.identity();
109
- }
110
-
111
- /*----------------------------------
112
- - REGISTER
113
- ----------------------------------*/
114
-
115
- // Require a service at file scope
116
- // Only use in files where a service is strictly required
117
- public use<ServiceType extends Service<{}, {}, this>>( serviceName: string ): ServiceType | undefined {
118
- return this[ serviceName ];
119
95
  }
120
96
 
121
97
  /*----------------------------------
122
98
  - COMMANDS
123
99
  ----------------------------------*/
124
100
 
125
- private commandsManager = new CommandsManager(this, { debug: true });
101
+ private commandsManager = new CommandsManager(this, { debug: true }, {}, this);
126
102
 
127
103
  public command( ...args: Parameters<CommandsManager["command"]> ) {
128
104
  return this.commandsManager.command(...args);
@@ -131,119 +107,80 @@ export default abstract class Application extends Service<Config, Hooks, /* TODO
131
107
  /*----------------------------------
132
108
  - LAUNCH
133
109
  ----------------------------------*/
134
-
135
- public async register() {
136
-
137
- }
138
110
 
139
- public async start() {
111
+ protected async start() {
140
112
 
141
113
  console.log(`5HTP Core`, process.env.npm_package_version);
142
114
 
143
- console.info(`[boot] Connect disk`);
144
- await this.initDisk();
115
+ // Handle errors & crashs
116
+ this.on('error', this.error.bind(this))
145
117
 
146
- console.info(`[boot] Start services`);
147
- await this.startServices()
118
+ this.debug && console.info(`[boot] Start services`);
119
+ await this.startServices();
148
120
 
149
- console.info(`[boot] App ready`);
121
+ this.debug && console.info(`[boot] App ready`);
122
+ await this.ready();
150
123
  await this.runHook('ready');
151
124
 
152
- console.info(`[boot] Run application-specific boot instructions ...`);
153
- await this.boot();
154
-
155
- console.info(`[boot] Application is ready.`);
125
+ this.debug && console.info(`[boot] Application is ready.`);
156
126
  this.launched = true;
127
+ }
128
+
129
+ public async ready() {
130
+
157
131
 
158
132
  }
159
133
 
160
- private async initDisk() {
161
- console.info(`[boot] Ensure runtime dirs ...`);
162
- await Promise.all([
163
- fs.ensureDir( this.path.cache ),
164
- fs.ensureDir( this.path.log ),
165
- fs.ensureDir( this.path.data ),
166
- ]);
134
+ // Default error handler
135
+ public async error( e: Error ) {
136
+ console.error( e );
167
137
  }
168
138
 
169
- public registerService( service: AnyService ) {
170
- console.log(`[app] Register service`, service.constructor?.name);
171
- this.servicesList.push(service);
139
+ public async shutdown() {
140
+
172
141
  }
173
142
 
143
+ // TODO: move to servie class
144
+ // So we can do public myService = Services.use() inside service class ded
174
145
  public async startServices() {
175
146
 
176
- console.log(`[app] Sorting ${this.servicesList.length} services by priority`);
177
- this.servicesList.sort((s1, s2) => s2.priority - s1.priority);
147
+ const propsNames = Object.getOwnPropertyNames(this);
148
+
149
+ for (const propName of propsNames) {
150
+
151
+ // Don't check services prop as it will trigger an error (it's a proxy)
152
+ // TODO: exclude all properties coming from the Service class itself
153
+ if (propName === 'services' || typeof this[ propName ] !== 'object')
154
+ continue;
178
155
 
179
- console.log(`[app] Starting ${this.servicesList.length} services.`);
180
- for (const service of this.servicesList) {
181
- const serviceClassName = service.constructor?.name;
182
- console.log(`[app] Start service`, serviceClassName);
183
- service.status = 'starting';
156
+ // Check if this property is a service registration
157
+ const registered = this[ propName ] as TRegisteredService;
158
+ if (registered?.type !== 'service')
159
+ continue;
184
160
 
185
- if (service.register)
186
- await service.register();
161
+ // Instanciate the service
162
+ const service = this.registerService( propName, registered );
163
+ this[ propName ] = service;
187
164
 
188
165
  // Register commands
189
166
  if (service.commands)
190
- this.commandsManager.fromList(service.commands);
167
+ this.commandsManager.fromList( service.commands );
191
168
 
192
169
  // Start service
193
- if (service.start) {
194
- service.started = service.start();
195
- await service.started.catch(e => {
196
- console.error("Catched error while starting service " + serviceClassName + '. Exiting process if mode production.', e);
197
- if (this.env.profile === 'prod')
198
- process.exit();
199
- else
200
- throw e;
201
- })
202
- }
203
-
204
- service.status = 'running';
170
+ await this.startService( service );
205
171
  }
206
172
 
207
- console.log(`[app] All ${this.servicesList.length} services were started.`);
173
+ // Check if any setup service has not been used
174
+ const unused: string[] = []
175
+ for (const serviceNS in ServicesContainer.registered)
176
+ if (this.allServices[ serviceNS ] === undefined)
177
+ unused.push(serviceNS);
178
+
179
+ if (unused.length !== 0)
180
+ console.warn(`${unused.length} services were setup, but are not used anywhere:`,
181
+ unused.join(', '));
208
182
  }
209
183
 
210
- public abstract boot(): Promise<void>;
211
-
212
- // TODO: make it work
213
- private activateHMR() {
214
-
215
- if (!module.hot) return;
216
-
217
- console.info(`Activating HMR ...`);
218
-
219
- module.hot.accept();
220
- module.hot.accept( this.path.root + '/.cache/commun/routes.ts' );
221
-
222
- module.hot.addDisposeHandler((data) => {
223
-
224
- console.info(`Cleaning application ...`);
225
-
226
- // Services hooks
227
- /*for (const id in this.services) {
228
- const service = this.services[id]
229
- if (service.cleanup) {
230
- console.info(`Cleaning ${id} service ...`);
231
- service.cleanup();
232
- }
233
- }*/
234
-
235
- // Application specific hooks
236
- this.runHook('cleanup');
237
-
238
- /*
239
- console.log("[nettoyage] Arrêt serveur socket ...");
240
- if (socket !== undefined)
241
- socket.serveur.close()
242
-
243
- console.log("[nettoyage] Reset du cache requêtes JSQL ...");
244
- QueryParser.clearCache();*/
245
-
246
- });
247
- }
184
+ }
248
185
 
249
- }
186
+ export default Application
@@ -0,0 +1,3 @@
1
+ import Application from '@/server';
2
+
3
+ export default new Application
@@ -0,0 +1,136 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Specific
6
+ import type {
7
+ AnyService,
8
+ // Hooks
9
+ THookCallback, THooksIndex
10
+ } from ".";
11
+
12
+ import ServicesIndex from '@/server/.generated/services';
13
+
14
+ /*----------------------------------
15
+ - TYPES: REGISTRATION
16
+ ----------------------------------*/
17
+
18
+ // From service/service.json
19
+ export type TServiceMetas<TServiceClass extends AnyService = AnyService> = {
20
+ id: string,
21
+ name: string,
22
+ parent: string,
23
+ dependences: string[],
24
+ class: () => { default: ClassType<TServiceClass> }
25
+ }
26
+
27
+ export type TRegisteredService<TServiceClass extends AnyService = AnyService> = {
28
+ type: 'service', // Used to recognize if an object is a registered service
29
+ config?: {},
30
+ metas: TServiceMetas<TServiceClass>,
31
+ hooks: THooksIndex<{}>,
32
+ on: (hookName: string, hookFunc: THookCallback<any>) => void,
33
+ subServices: TRegisteredServicesIndex
34
+ }
35
+
36
+ export type TRegisteredServicesIndex<TServiceClass extends AnyService = AnyService> = {
37
+ [serviceId: string]: TRegisteredService<TServiceClass>
38
+ }
39
+
40
+ /*----------------------------------
41
+ - CONFIG
42
+ ----------------------------------*/
43
+
44
+ const LogPrefix = '[service]';
45
+
46
+ /*----------------------------------
47
+ - CLASS
48
+ ----------------------------------*/
49
+ export class ServicesContainer {
50
+
51
+ public registered: TRegisteredServicesIndex = {}
52
+
53
+ public setup(
54
+ serviceId: string,
55
+ serviceConfig: {}
56
+ ): TRegisteredService {
57
+
58
+ // Check if the service is installed & has been indexed
59
+ const installedService = ServicesIndex[ serviceId ];
60
+ if (installedService === undefined)
61
+ throw new Error(`Unable to setup service "${serviceId}": This one doesn't seems to be installed.`);
62
+
63
+ // Service already registered & setup
64
+ const registered = this.registered[ serviceId ];
65
+ if (registered !== undefined)
66
+ throw new Error(`Service ${serviceId} has been setup multiple times. One service can only be setup one time.`);
67
+
68
+ // Create & register metas
69
+ const service: TRegisteredService = {
70
+ type: 'service',
71
+ config: serviceConfig,
72
+ metas: installedService,
73
+ hooks: {},
74
+ on: (hookName: string, hookFunc: THookCallback<any>) => {
75
+ const callbacks = service.hooks[ hookName ];
76
+ if (callbacks)
77
+ callbacks.push( hookFunc );
78
+ else
79
+ service.hooks[ hookName ] = [hookFunc]
80
+ },
81
+ subServices: {}
82
+ };
83
+
84
+ this.registered[ serviceId ] = service;
85
+
86
+ return service;
87
+ }
88
+
89
+ public use(
90
+ serviceId: string,
91
+ // TODO: Only subservices types supported by the parent service
92
+ subServices: TRegisteredServicesIndex = {}
93
+ ): TRegisteredService {
94
+
95
+ // Check of the service has been configurated
96
+ const registered = this.registered[ serviceId ];
97
+ if (registered === undefined)
98
+ throw new Error(`Unable to use service "${serviceId}": This one hasn't been setup.`);
99
+
100
+ // Bind subservices
101
+ registered.subServices = subServices;
102
+
103
+ // Return the service metas
104
+ // The parent service will take care of instanciating & starting it
105
+ return registered;
106
+ }
107
+
108
+ public callableInstance = <TInstance extends object, TCallableName extends keyof TInstance>(
109
+ instance: TInstance,
110
+ funcName: TCallableName
111
+ ): TInstance[TCallableName] & TInstance => {
112
+
113
+ const callableFunc = instance[funcName];
114
+ if (typeof callableFunc !== 'function')
115
+ throw new Error(`instance[funcName] isn't callable.`);
116
+
117
+ const callable = callableFunc.bind(instance);
118
+
119
+ const methods = [
120
+ ...Object.getOwnPropertyNames( Object.getPrototypeOf( instance )),
121
+ ...Object.getOwnPropertyNames( instance ),
122
+ // service.launch() isn't included, maybe because parent abstract class
123
+ 'launch'
124
+ ];
125
+
126
+ for (const method of methods)
127
+ if (method !== 'constructor')
128
+ callable[ method ] = typeof instance[ method ] === 'function'
129
+ ? instance[ method ].bind( instance )
130
+ : instance[ method ];
131
+
132
+ return callable as TInstance[TCallableName] & TInstance;
133
+ }
134
+ }
135
+
136
+ export default new ServicesContainer
@@ -0,0 +1,219 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Specific
6
+ import type { Application } from "..";
7
+ import type { Command } from "../commands";
8
+ import type { TServiceMetas, TRegisteredServicesIndex, TRegisteredService } from './container';
9
+
10
+ /*----------------------------------
11
+ - TYPES: OPTIONS
12
+ ----------------------------------*/
13
+
14
+ export type AnyService = Service<{}, {}, Application, TStartedServicesIndex>
15
+
16
+ type TServiceConfig = {
17
+ debug?: boolean
18
+ }
19
+
20
+ export type { TRegisteredServicesIndex, TRegisteredService } from './container';
21
+
22
+ /*----------------------------------
23
+ - TYPES: HOOKS
24
+ ----------------------------------*/
25
+
26
+ export type THookCallback<THookArgs extends THookOptions> = (...args: THookArgs["args"]) => Promise<void>;
27
+
28
+ type THooksList = {
29
+ [hookName: string]: THookOptions
30
+ }
31
+
32
+ type THookOptions = {
33
+ args: any[]
34
+ }
35
+
36
+ export type THooksIndex<THooks extends THooksList> = {[name in keyof THooks]?: THookCallback< THooks[name] >[]}
37
+
38
+ export type StartedServicesIndex = {
39
+ [serviceId: string]: AnyService
40
+ }
41
+
42
+ /*----------------------------------
43
+ - CONFIG
44
+ ----------------------------------*/
45
+
46
+ const LogPrefix = '[service]';
47
+
48
+ /*----------------------------------
49
+ - CLASS
50
+ ----------------------------------*/
51
+ export default abstract class Service<
52
+ TConfig extends TServiceConfig,
53
+ THooks extends THooksList,
54
+ TApplication extends Application,
55
+ TServicesIndex extends StartedServicesIndex = StartedServicesIndex
56
+ > {
57
+
58
+ public started?: Promise<void>;
59
+ public status: 'stopped' | 'starting' | 'running' | 'paused' = 'stopped';
60
+
61
+ public commands?: Command[];
62
+ public metas!: TServiceMetas;
63
+ public bindings: string[] = []
64
+
65
+ public static createInstance?: (
66
+ parent: AnyService,
67
+ config: TServiceConfig,
68
+ services: TRegisteredServicesIndex,
69
+ app: Application
70
+ ) => Service<TServiceConfig, THooksList, Application, StartedServicesIndex>;
71
+
72
+ public constructor(
73
+ public parent: AnyService,
74
+ public config: TConfig,
75
+ services: TRegisteredServicesIndex,
76
+ public app: TApplication
77
+ ) {
78
+
79
+ // Instanciate subservices
80
+ for (const localName in services)
81
+ this.registerService( localName, services[localName] );
82
+
83
+ }
84
+
85
+ /*----------------------------------
86
+ - LIFECYCLE
87
+ ----------------------------------*/
88
+
89
+ public async launch() {
90
+
91
+ // Instanciate subservices
92
+ for (const localName in this.services)
93
+ await this.startService( this.services[localName] );
94
+
95
+ // Start service
96
+ if (this.start)
97
+ await this.start();
98
+
99
+ // Bind app events
100
+ this.app.on('ready', this.ready.bind(this))
101
+ this.app.on('shutdown', this.shutdown.bind(this))
102
+
103
+ }
104
+
105
+ protected abstract start(): Promise<void>;
106
+
107
+ protected abstract ready(): Promise<void>;
108
+
109
+ protected abstract shutdown(): Promise<void>;
110
+
111
+ /*----------------------------------
112
+ - SUBSERVICES
113
+ ----------------------------------*/
114
+
115
+ public services: TRegisteredServicesIndex = {} as TRegisteredServicesIndex/*new Proxy({}, {
116
+ get: (target, prop, recever) => {
117
+ if (!( prop in target )) {
118
+
119
+ throw new Error(`You made reference to the "${prop}" service, but this one hasn't been loaded yet. Loaded services: ` + Object.keys(this.services).join(', '));
120
+ }
121
+ }
122
+ }) as TRegisteredServicesIndex*/
123
+
124
+ protected registerService( localName: string, registered: TRegisteredService ): AnyService {
125
+
126
+ // Service already instabciates on the app scope
127
+ let service = this.app.allServices[ registered.metas.id ];
128
+
129
+ // Service not yet instanciated
130
+ if (service === undefined) {
131
+
132
+ // Instanciate
133
+ console.log(`[app] Load service`, registered.metas.id);
134
+ const ServiceClass = registered.metas.class().default;
135
+ // Create class instance
136
+ service = ServiceClass.createInstance !== undefined
137
+ ? ServiceClass.createInstance(this, registered.config, registered.subServices, this.app)
138
+ : new ServiceClass(this, registered.config, registered.subServices, this.app);
139
+
140
+ service.metas = registered.metas;
141
+
142
+ } else {
143
+ console.warn(`[app] Service`, registered.metas.id, 'already instanciated in this app.');
144
+ }
145
+
146
+ // Bind to app
147
+ this.services[ localName ] = service;
148
+ service.bindings.push(this.constructor.name + '.' + localName);
149
+ this.app.allServices[ registered.metas.id ] = service;
150
+
151
+ return service;
152
+
153
+ }
154
+
155
+ protected async startService( service: AnyService ) {
156
+
157
+ // Service already started
158
+ if (service.started)
159
+ return;
160
+
161
+ // Start servuce & eventually his subservices
162
+ console.log(`[app] Start service`, service.metas.id);
163
+ service.status = 'starting';
164
+ service.started = service.launch();
165
+ await service.started.catch(e => {
166
+ console.error("Catched error while starting service " + service.metas.id, e);
167
+ if (this.app.env.profile === 'prod')
168
+ process.exit();
169
+ else
170
+ throw e;
171
+ })
172
+
173
+ console.log(`[app] Service`, service.metas.id, 'started (bound to:', service.bindings.join(', '),')');
174
+ service.status = 'running';
175
+ }
176
+
177
+ /*----------------------------------
178
+ - HOOKS
179
+ ----------------------------------*/
180
+ public hooks: THooksIndex<THooks> = {}
181
+
182
+ public on<THookName extends keyof THooksList>(
183
+ name: THookName,
184
+ callback: THookCallback<THooksList[THookName]>
185
+ ) {
186
+
187
+ const callbacks = this.hooks[ name ];
188
+ if (callbacks)
189
+ callbacks.push( callback );
190
+ else
191
+ this.hooks[ name ] = [callback]
192
+
193
+ return this;
194
+ }
195
+
196
+ public runHook<THookName extends keyof THooksList>(
197
+ name: THookName,
198
+ ...args: THooksList[THookName]["args"]
199
+ ) {
200
+
201
+ const callbacks = this.hooks[name];
202
+ if (!callbacks)
203
+ return;// console.info(LogPrefix, `No ${name} hook defined in the current service instance.`);
204
+
205
+ this.config.debug && console.info(`[hook] Run all ${name} hook (${callbacks.length}).`);
206
+ return Promise.all(
207
+ callbacks.map(
208
+ cb => cb(...args).catch(e => {
209
+ console.error(`[hook] Error while executing hook ${name}:`, e);
210
+ if (name !== 'error')
211
+ this.runHook('error', e);
212
+ })
213
+ )
214
+ ).then(() => {
215
+ this.config.debug && console.info(`[hook] Hooks ${name} executed with success.`);
216
+ })
217
+ }
218
+
219
+ }
@@ -1,5 +1,11 @@
1
- import Application from '@/server';
1
+ // Load Application container
2
+ import './app/container';
2
3
 
3
- const app = new Application();
4
+ // Load services setup
5
+ import '@/server/config/*.ts';
4
6
 
5
- app.start();
7
+ // Load Application
8
+ import application from './app/instance';
9
+
10
+ // Start application
11
+ application.start();