5htp-core 0.3.0 → 0.3.1
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/package.json +2 -2
- package/src/client/components/Select/index.tsx +4 -2
- package/src/client/services/router/index.tsx +22 -1
- package/src/client/services/router/response/index.tsx +1 -1
- package/src/common/errors/index.ts +20 -0
- package/src/common/validation/validators.ts +12 -1
- package/src/server/app/commands.ts +21 -1
- package/src/server/app/container/config.ts +1 -0
- package/src/server/app/container/index.ts +6 -3
- package/src/server/app/index.ts +30 -15
- package/src/server/app/service/container.ts +13 -24
- package/src/server/app/service/index.ts +100 -54
- package/src/server/app.tsconfig.json +2 -0
- package/src/server/index.ts +2 -1
- package/src/server/services/cache/index.ts +6 -4
- package/src/server/services/console/index.ts +7 -24
- package/src/server/services/cron/index.ts +5 -1
- package/src/server/services/database/index.ts +67 -41
- package/src/server/services/disks/driver.ts +5 -1
- package/src/server/services/disks/drivers/s3/index.ts +1 -1
- package/src/server/services/disks/index.ts +16 -12
- package/src/server/services/email/index.ts +5 -1
- package/src/server/services/fetch/index.ts +3 -5
- package/src/server/services/router/index.ts +4 -4
- package/src/server/services/router/service.ts +9 -3
- package/src/server/services/security/encrypt/aes/index.ts +9 -6
- package/src/server/services/socket/index.ts +16 -17
- package/src/server/services/users/index.ts +5 -1
- package/src/server/services/users/router/index.ts +2 -2
- package/src/server/app/instance.ts +0 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "5htp-core",
|
|
3
3
|
"description": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.1",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -97,6 +97,6 @@
|
|
|
97
97
|
"babel-plugin-glob-import": "^0.0.7"
|
|
98
98
|
},
|
|
99
99
|
"peerDependencies": {
|
|
100
|
-
"5htp": "0.3.
|
|
100
|
+
"5htp": "0.3.1"
|
|
101
101
|
}
|
|
102
102
|
}
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
8
|
// Core
|
|
9
|
-
import
|
|
9
|
+
import { Props as DropdownProps } from '@client/components/dropdown';
|
|
10
10
|
import Input from '@client/components/inputv3';
|
|
11
11
|
|
|
12
12
|
// Specific
|
|
13
|
-
import
|
|
13
|
+
import {
|
|
14
14
|
Props as SelectorProps,
|
|
15
15
|
Choice,
|
|
16
16
|
} from './ChoiceSelector';
|
|
@@ -24,6 +24,8 @@ export type Props = DropdownProps & SelectorProps & {
|
|
|
24
24
|
errors?: string[],
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
export type { Choice } from './ChoiceSelector';
|
|
28
|
+
|
|
27
29
|
const ChoiceElement = ({ choice, currentList, onChange, multiple, includeCurrent }: {
|
|
28
30
|
choice: Choice,
|
|
29
31
|
currentList: Choice[],
|
|
@@ -40,7 +40,7 @@ import * as appRoutes from '@/client/pages/**/*.tsx';
|
|
|
40
40
|
- CONFIG
|
|
41
41
|
----------------------------------*/
|
|
42
42
|
|
|
43
|
-
const debug =
|
|
43
|
+
const debug = false;
|
|
44
44
|
const LogPrefix = '[router]'
|
|
45
45
|
|
|
46
46
|
/*----------------------------------
|
|
@@ -61,6 +61,8 @@ export type Response = ClientResponse<ClientRouter> | ServerResponse<ServerRoute
|
|
|
61
61
|
- TYPES: ROUTES LOADING
|
|
62
62
|
----------------------------------*/
|
|
63
63
|
|
|
64
|
+
// WARN: To be updated with the mplemenations list of Router.page
|
|
65
|
+
// (both server and client side)
|
|
64
66
|
export type TRegisterPageArgs<TProvidedData extends TFetcherList = {}, TRouter extends Router = Router> = ([
|
|
65
67
|
path: string,
|
|
66
68
|
controller: TDataProvider<TProvidedData> | null,
|
|
@@ -219,6 +221,25 @@ export default class ClientRouter<
|
|
|
219
221
|
return currentRoute;
|
|
220
222
|
}
|
|
221
223
|
|
|
224
|
+
public page(
|
|
225
|
+
path: string,
|
|
226
|
+
controller: TDataProvider<{}> | null,
|
|
227
|
+
renderer: TFrontRenderer<{}>
|
|
228
|
+
): TRoute;
|
|
229
|
+
|
|
230
|
+
public page(
|
|
231
|
+
path: string,
|
|
232
|
+
options: Partial<TRoute["options"]>,
|
|
233
|
+
renderer: TFrontRenderer<{}>
|
|
234
|
+
): TRoute;
|
|
235
|
+
|
|
236
|
+
public page(
|
|
237
|
+
path: string,
|
|
238
|
+
options: Partial<TRoute["options"]>,
|
|
239
|
+
controller: TDataProvider<{}> | null,
|
|
240
|
+
renderer: TFrontRenderer<{}>
|
|
241
|
+
): TRoute;
|
|
242
|
+
|
|
222
243
|
public page(...args: TRegisterPageArgs): TRoute {
|
|
223
244
|
|
|
224
245
|
const { path, options, controller, renderer, layout } = getRegisterPageArgs(...args);
|
|
@@ -16,6 +16,26 @@ type TDetailsErreur = {
|
|
|
16
16
|
urlRequete?: string,
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/*----------------------------------
|
|
20
|
+
- TYPES: BUG REPORT
|
|
21
|
+
----------------------------------*/
|
|
22
|
+
|
|
23
|
+
export type ServerBug = {
|
|
24
|
+
// Context
|
|
25
|
+
hash: string,
|
|
26
|
+
date: Date, // Timestamp
|
|
27
|
+
channelType?: string,
|
|
28
|
+
channelId?: string,
|
|
29
|
+
|
|
30
|
+
user: string | null | undefined,
|
|
31
|
+
ip: string | null | undefined,
|
|
32
|
+
|
|
33
|
+
// Error
|
|
34
|
+
error: Error,
|
|
35
|
+
stacktrace: string,
|
|
36
|
+
logs: string,
|
|
37
|
+
}
|
|
38
|
+
|
|
19
39
|
/*----------------------------------
|
|
20
40
|
- ERREURS
|
|
21
41
|
----------------------------------*/
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
isURL
|
|
11
11
|
} from 'validator';
|
|
12
12
|
|
|
13
|
+
import normalizeUrl, { Options as NormalizeUrlOptions } from 'normalize-url';
|
|
14
|
+
|
|
13
15
|
// Core
|
|
14
16
|
import { InputError } from '@common/errors';
|
|
15
17
|
import FileToUpload from '@client/components/inputv3/file/FileToUpload';
|
|
@@ -157,16 +159,25 @@ export default class SchemaValidators {
|
|
|
157
159
|
|
|
158
160
|
}, opts)
|
|
159
161
|
|
|
160
|
-
public url = (opts: TValidator<string> & {
|
|
162
|
+
public url = (opts: TValidator<string> & {
|
|
163
|
+
normalize?: NormalizeUrlOptions
|
|
164
|
+
} = {}) =>
|
|
161
165
|
new Validator<string>('url', (inputVal, input, output, corriger?) => {
|
|
162
166
|
|
|
163
167
|
let val = this.string(opts).validate(inputVal, input, output, corriger);
|
|
164
168
|
|
|
169
|
+
// Check if URL
|
|
165
170
|
if (!isURL(val, {
|
|
166
171
|
// https://www.npmjs.com/package/validator
|
|
167
172
|
}))
|
|
168
173
|
throw new InputError(`Please provide a valid URL.`);
|
|
169
174
|
|
|
175
|
+
// Normalize
|
|
176
|
+
if (opts.normalize !== undefined)
|
|
177
|
+
val = normalizeUrl(val, opts.normalize);
|
|
178
|
+
|
|
179
|
+
console.log("@@@@@@@@@@@@@NORMALISZE URL", opts.normalize, val);
|
|
180
|
+
|
|
170
181
|
return val;
|
|
171
182
|
}, opts)
|
|
172
183
|
|
|
@@ -41,15 +41,35 @@ export type Hooks = {
|
|
|
41
41
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
export type Services = {
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
44
48
|
/*----------------------------------
|
|
45
49
|
- SERVICE
|
|
46
50
|
----------------------------------*/
|
|
47
|
-
export default class CommandsManager extends Service<Config, Hooks, Application> {
|
|
51
|
+
export default class CommandsManager extends Service<Config, Hooks, Application, Services> {
|
|
48
52
|
|
|
49
53
|
public priority = 2 as 2;
|
|
50
54
|
|
|
51
55
|
public commandsIndex: CommandsList = {}
|
|
52
56
|
|
|
57
|
+
/*----------------------------------
|
|
58
|
+
- LIFECYCLE
|
|
59
|
+
----------------------------------*/
|
|
60
|
+
|
|
61
|
+
protected async start() {
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
protected async ready() {
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
protected async shutdown() {
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
53
73
|
/*----------------------------------
|
|
54
74
|
- DEFINITIONS
|
|
55
75
|
----------------------------------*/
|
|
@@ -8,19 +8,22 @@ import './patch';
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
|
|
10
10
|
// Core
|
|
11
|
-
import
|
|
11
|
+
import type { StartedServicesIndex } from '../service';
|
|
12
|
+
import Services, { ServicesContainer } from '../service/container';
|
|
12
13
|
import ConfigParser, { TEnvConfig } from './config';
|
|
13
14
|
|
|
14
15
|
/*----------------------------------
|
|
15
16
|
- CLASS
|
|
16
17
|
----------------------------------*/
|
|
17
|
-
export class ApplicationContainer
|
|
18
|
+
export class ApplicationContainer<
|
|
19
|
+
TServicesIndex extends StartedServicesIndex = StartedServicesIndex
|
|
20
|
+
> {
|
|
18
21
|
|
|
19
22
|
/*----------------------------------
|
|
20
23
|
- INIT
|
|
21
24
|
----------------------------------*/
|
|
22
25
|
|
|
23
|
-
public Services = Services
|
|
26
|
+
public Services = Services as ServicesContainer<TServicesIndex>;
|
|
24
27
|
public Environment: TEnvConfig;
|
|
25
28
|
public Identity: Config.Identity;
|
|
26
29
|
|
package/src/server/app/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import AppContainer from './container';
|
|
|
7
7
|
import ApplicationService, { AnyService } from './service';
|
|
8
8
|
import CommandsManager from './commands';
|
|
9
9
|
import ServicesContainer, { TRegisteredService, TServiceMetas } from './service/container';
|
|
10
|
+
import type { ServerBug } from '../services/console';
|
|
10
11
|
|
|
11
12
|
// Built-in
|
|
12
13
|
import type { default as Router, Request as ServerRequest } from '@server/services/router';
|
|
@@ -48,7 +49,7 @@ export const Service = ServicesContainer;
|
|
|
48
49
|
/*----------------------------------
|
|
49
50
|
- FUNCTIONS
|
|
50
51
|
----------------------------------*/
|
|
51
|
-
export class Application extends ApplicationService<Config, Hooks, /* TODO: this ? */Application> {
|
|
52
|
+
export class Application extends ApplicationService<Config, Hooks, /* TODO: this ? */Application, {}> {
|
|
52
53
|
|
|
53
54
|
/*----------------------------------
|
|
54
55
|
- PROPERTIES
|
|
@@ -72,8 +73,8 @@ export class Application extends ApplicationService<Config, Hooks, /* TODO: this
|
|
|
72
73
|
public debug: boolean = false;
|
|
73
74
|
public launched: boolean = false;
|
|
74
75
|
|
|
75
|
-
//
|
|
76
|
-
public
|
|
76
|
+
// Mandatory services
|
|
77
|
+
public Console = this.use('Core/Console');
|
|
77
78
|
|
|
78
79
|
/*----------------------------------
|
|
79
80
|
- INIT
|
|
@@ -81,10 +82,14 @@ export class Application extends ApplicationService<Config, Hooks, /* TODO: this
|
|
|
81
82
|
|
|
82
83
|
public constructor() {
|
|
83
84
|
|
|
85
|
+
const self = 'self' as unknown as Application;
|
|
86
|
+
|
|
84
87
|
// Application itself doesnt have configuration
|
|
85
88
|
// Configuration must be handled by application services
|
|
86
|
-
super(
|
|
89
|
+
super(self, {}, {}, self);
|
|
87
90
|
|
|
91
|
+
// We can't pass this in super so we assign here
|
|
92
|
+
this.parent = this;
|
|
88
93
|
this.app = this;
|
|
89
94
|
|
|
90
95
|
// Gestion crash
|
|
@@ -113,9 +118,9 @@ export class Application extends ApplicationService<Config, Hooks, /* TODO: this
|
|
|
113
118
|
console.log(`5HTP Core`, process.env.npm_package_version);
|
|
114
119
|
|
|
115
120
|
// Handle errors & crashs
|
|
116
|
-
this.on('error', this.
|
|
121
|
+
this.on('error', e => this.Console.createBugReport(e))
|
|
117
122
|
|
|
118
|
-
|
|
123
|
+
console.info(`[boot] Start services`);
|
|
119
124
|
await this.startServices();
|
|
120
125
|
|
|
121
126
|
this.debug && console.info(`[boot] App ready`);
|
|
@@ -132,8 +137,10 @@ export class Application extends ApplicationService<Config, Hooks, /* TODO: this
|
|
|
132
137
|
}
|
|
133
138
|
|
|
134
139
|
// Default error handler
|
|
135
|
-
public async
|
|
136
|
-
|
|
140
|
+
public async reportBug( bug: ServerBug ) {
|
|
141
|
+
|
|
142
|
+
console.error( bug.error );
|
|
143
|
+
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
public async shutdown() {
|
|
@@ -150,30 +157,38 @@ export class Application extends ApplicationService<Config, Hooks, /* TODO: this
|
|
|
150
157
|
|
|
151
158
|
// Don't check services prop as it will trigger an error (it's a proxy)
|
|
152
159
|
// TODO: exclude all properties coming from the Service class itself
|
|
153
|
-
if (propName === 'services' ||
|
|
160
|
+
if (propName === 'services' || this[ propName ] === undefined)
|
|
154
161
|
continue;
|
|
155
162
|
|
|
156
163
|
// Check if this property is a service registration
|
|
157
|
-
const
|
|
158
|
-
|
|
164
|
+
const service = this[ propName ] as TRegisteredService;
|
|
165
|
+
const isService = (
|
|
166
|
+
service instanceof ApplicationService
|
|
167
|
+
||
|
|
168
|
+
(
|
|
169
|
+
typeof service === 'function'
|
|
170
|
+
&&
|
|
171
|
+
service.serviceInstance instanceof ApplicationService
|
|
172
|
+
)
|
|
173
|
+
)
|
|
174
|
+
if (!isService)
|
|
159
175
|
continue;
|
|
160
176
|
|
|
161
177
|
// Instanciate the service
|
|
162
|
-
|
|
163
|
-
this[ propName ] = service;
|
|
178
|
+
this.bindService( propName, service );
|
|
164
179
|
|
|
165
180
|
// Register commands
|
|
166
181
|
if (service.commands)
|
|
167
182
|
this.commandsManager.fromList( service.commands );
|
|
168
183
|
|
|
169
184
|
// Start service
|
|
170
|
-
await this.startService( service );
|
|
185
|
+
await this.startService( propName, service );
|
|
171
186
|
}
|
|
172
187
|
|
|
173
188
|
// Check if any setup service has not been used
|
|
174
189
|
const unused: string[] = []
|
|
175
190
|
for (const serviceNS in ServicesContainer.registered)
|
|
176
|
-
if (
|
|
191
|
+
if (ServicesContainer.allServices[ serviceNS ] === undefined)
|
|
177
192
|
unused.push(serviceNS);
|
|
178
193
|
|
|
179
194
|
if (unused.length !== 0)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// Specific
|
|
6
6
|
import type {
|
|
7
|
-
AnyService,
|
|
7
|
+
AnyService, StartedServicesIndex,
|
|
8
8
|
// Hooks
|
|
9
9
|
THookCallback, THooksIndex
|
|
10
10
|
} from ".";
|
|
@@ -46,13 +46,18 @@ const LogPrefix = '[service]';
|
|
|
46
46
|
/*----------------------------------
|
|
47
47
|
- CLASS
|
|
48
48
|
----------------------------------*/
|
|
49
|
-
export class ServicesContainer
|
|
49
|
+
export class ServicesContainer<
|
|
50
|
+
TServicesIndex extends StartedServicesIndex = StartedServicesIndex
|
|
51
|
+
> {
|
|
50
52
|
|
|
51
53
|
public registered: TRegisteredServicesIndex = {}
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
// All service instances by service id
|
|
56
|
+
public allServices: {[serviceId: string]: AnyService} = {}
|
|
57
|
+
|
|
58
|
+
public setup<TServiceId extends keyof TServicesIndex>(
|
|
59
|
+
serviceId: keyof TServicesIndex,
|
|
60
|
+
serviceConfig: TServicesIndex[TServiceId]["config"]
|
|
56
61
|
): TRegisteredService {
|
|
57
62
|
|
|
58
63
|
// Check if the service is installed & has been indexed
|
|
@@ -86,25 +91,6 @@ export class ServicesContainer {
|
|
|
86
91
|
return service;
|
|
87
92
|
}
|
|
88
93
|
|
|
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
94
|
public callableInstance = <TInstance extends object, TCallableName extends keyof TInstance>(
|
|
109
95
|
instance: TInstance,
|
|
110
96
|
funcName: TCallableName
|
|
@@ -129,6 +115,9 @@ export class ServicesContainer {
|
|
|
129
115
|
? instance[ method ].bind( instance )
|
|
130
116
|
: instance[ method ];
|
|
131
117
|
|
|
118
|
+
// Allow us to recognize a callable as a service
|
|
119
|
+
callable.serviceInstance = instance;
|
|
120
|
+
|
|
132
121
|
return callable as TInstance[TCallableName] & TInstance;
|
|
133
122
|
}
|
|
134
123
|
}
|
|
@@ -6,12 +6,13 @@
|
|
|
6
6
|
import type { Application } from "..";
|
|
7
7
|
import type { Command } from "../commands";
|
|
8
8
|
import type { TServiceMetas, TRegisteredServicesIndex, TRegisteredService } from './container';
|
|
9
|
+
import ServicesContainer from './container';
|
|
9
10
|
|
|
10
11
|
/*----------------------------------
|
|
11
12
|
- TYPES: OPTIONS
|
|
12
13
|
----------------------------------*/
|
|
13
14
|
|
|
14
|
-
export type AnyService = Service<{}, {}, Application,
|
|
15
|
+
export type AnyService = Service<{}, {}, Application, {}>
|
|
15
16
|
|
|
16
17
|
type TServiceConfig = {
|
|
17
18
|
debug?: boolean
|
|
@@ -52,7 +53,7 @@ export default abstract class Service<
|
|
|
52
53
|
TConfig extends TServiceConfig,
|
|
53
54
|
THooks extends THooksList,
|
|
54
55
|
TApplication extends Application,
|
|
55
|
-
TServicesIndex extends StartedServicesIndex
|
|
56
|
+
TServicesIndex extends StartedServicesIndex
|
|
56
57
|
> {
|
|
57
58
|
|
|
58
59
|
public started?: Promise<void>;
|
|
@@ -62,26 +63,34 @@ export default abstract class Service<
|
|
|
62
63
|
public metas!: TServiceMetas;
|
|
63
64
|
public bindings: string[] = []
|
|
64
65
|
|
|
65
|
-
public
|
|
66
|
-
parent: AnyService,
|
|
67
|
-
config: TServiceConfig,
|
|
68
|
-
services: TRegisteredServicesIndex,
|
|
69
|
-
app: Application
|
|
70
|
-
) => Service<TServiceConfig, THooksList, Application, StartedServicesIndex>;
|
|
66
|
+
public app: TApplication;
|
|
71
67
|
|
|
72
68
|
public constructor(
|
|
73
|
-
public parent: AnyService,
|
|
69
|
+
public parent: AnyService | 'self',
|
|
74
70
|
public config: TConfig,
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
// Make this argument appear as instanciated sercices index
|
|
72
|
+
// But actually, Setup.use returns a registered service, not yet launched
|
|
73
|
+
services: TServicesIndex,
|
|
74
|
+
app: TApplication | 'self'
|
|
77
75
|
) {
|
|
78
76
|
|
|
77
|
+
if (this.parent === 'self')
|
|
78
|
+
this.parent = this;
|
|
79
|
+
|
|
80
|
+
this.app = app === 'self'
|
|
81
|
+
? this as unknown as TApplication
|
|
82
|
+
: app
|
|
83
|
+
|
|
79
84
|
// Instanciate subservices
|
|
80
85
|
for (const localName in services)
|
|
81
|
-
this.
|
|
86
|
+
this.bindService( localName, services[localName] as unknown as TRegisteredService );
|
|
82
87
|
|
|
83
88
|
}
|
|
84
89
|
|
|
90
|
+
public getServiceInstance() {
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
/*----------------------------------
|
|
86
95
|
- LIFECYCLE
|
|
87
96
|
----------------------------------*/
|
|
@@ -90,7 +99,7 @@ export default abstract class Service<
|
|
|
90
99
|
|
|
91
100
|
// Instanciate subservices
|
|
92
101
|
for (const localName in this.services)
|
|
93
|
-
await this.startService( this.services[localName] );
|
|
102
|
+
await this.startService( localName, this.services[localName] );
|
|
94
103
|
|
|
95
104
|
// Start service
|
|
96
105
|
if (this.start)
|
|
@@ -112,66 +121,103 @@ export default abstract class Service<
|
|
|
112
121
|
- SUBSERVICES
|
|
113
122
|
----------------------------------*/
|
|
114
123
|
|
|
115
|
-
public
|
|
124
|
+
public registered: TRegisteredServicesIndex = {} as TRegisteredServicesIndex;
|
|
125
|
+
|
|
126
|
+
public services: TServicesIndex = {} as TServicesIndex;
|
|
127
|
+
|
|
128
|
+
/*new Proxy({}, {
|
|
116
129
|
get: (target, prop, recever) => {
|
|
117
130
|
if (!( prop in target )) {
|
|
118
131
|
|
|
119
|
-
throw new Error(`You made reference to the "${prop}" service, but this one hasn't been loaded
|
|
132
|
+
throw new Error(`You made reference to the "${prop}" service, but this one hasn't been loaded or started yet.
|
|
133
|
+
Registered services: ${Object.keys(this.services).join(', ')} ;
|
|
134
|
+
Loaded services: ${Object.keys(this.services).join(', ')}
|
|
135
|
+
`);
|
|
120
136
|
}
|
|
121
137
|
}
|
|
122
138
|
}) as TRegisteredServicesIndex*/
|
|
123
139
|
|
|
124
|
-
|
|
140
|
+
// this.use immediatly instanciate the subservice for few reasons:
|
|
141
|
+
// - The subservice instance can be accesses from another service in the constructor, no matter the order of loading of the services
|
|
142
|
+
// - Consistency: the subserviuce proprties shouldn't be assogned to two different values according depending on the app lifecycle
|
|
143
|
+
public use<TServiceId extends keyof TServicesIndex>(
|
|
144
|
+
serviceId: TServiceId,
|
|
145
|
+
// TODO: Only subservices types supported by the parent service
|
|
146
|
+
subServices: TServicesIndex[TServiceId]["services"] = {}
|
|
147
|
+
) {
|
|
125
148
|
|
|
126
|
-
//
|
|
127
|
-
|
|
149
|
+
// Check of the service has been configurated
|
|
150
|
+
const registered = ServicesContainer.registered[ serviceId ];
|
|
151
|
+
if (registered === undefined)
|
|
152
|
+
throw new Error(`Unable to use service "${serviceId}": This one hasn't been setup.`);
|
|
128
153
|
|
|
129
|
-
//
|
|
130
|
-
|
|
154
|
+
// Bind subservices
|
|
155
|
+
registered.subServices = subServices;
|
|
131
156
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
: new ServiceClass(this, registered.config, registered.subServices, this.app);
|
|
157
|
+
// Check if not already instanciated
|
|
158
|
+
const existing = ServicesContainer.allServices[ serviceId ];
|
|
159
|
+
if (existing !== undefined) {
|
|
160
|
+
console.info("Service", serviceId, "already instanciated through another service.");
|
|
161
|
+
return existing;
|
|
162
|
+
}
|
|
139
163
|
|
|
140
|
-
|
|
164
|
+
// Instanciate
|
|
165
|
+
console.log(`[app] Load service`, registered.metas.id);
|
|
166
|
+
const ServiceClass = registered.metas.class().default;
|
|
141
167
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
168
|
+
// Create class instance
|
|
169
|
+
const service = new ServiceClass(this, registered.config, registered.subServices, this.app || this)
|
|
170
|
+
.getServiceInstance()
|
|
145
171
|
|
|
146
|
-
// Bind
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.app.allServices[ registered.metas.id ] = service;
|
|
172
|
+
// Bind his own metas
|
|
173
|
+
service.metas = registered.metas;
|
|
174
|
+
ServicesContainer.allServices[ registered.metas.id ] = service;
|
|
150
175
|
|
|
151
176
|
return service;
|
|
152
|
-
|
|
153
177
|
}
|
|
154
178
|
|
|
155
|
-
protected
|
|
179
|
+
protected bindService( localName: string, service: AnyService ) {
|
|
156
180
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
service.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
process.exit();
|
|
169
|
-
else
|
|
170
|
-
throw e;
|
|
171
|
-
})
|
|
181
|
+
const serviceScope = this.constructor.name + '.' + localName;
|
|
182
|
+
|
|
183
|
+
// Fix the parent service (the app could be provided as parent because the dev called this.use() in the app class definition)
|
|
184
|
+
service.parent = this;
|
|
185
|
+
|
|
186
|
+
// Bind subservice to service
|
|
187
|
+
//console.log(`Binding service ${serviceScope}`);
|
|
188
|
+
service.bindings.push(serviceScope);
|
|
189
|
+
|
|
190
|
+
// Since now we have the localname, we can bind the service in this.service too
|
|
191
|
+
this.services[localName] = service;
|
|
172
192
|
|
|
173
|
-
|
|
174
|
-
|
|
193
|
+
// For serices that have been passed through this.use
|
|
194
|
+
if ((localName in this) && this[localName] === undefined)
|
|
195
|
+
this[ localName ] = service;
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
protected async startService( localName: string, service: AnyService ) {
|
|
200
|
+
// Service already started
|
|
201
|
+
if (!service.started) {
|
|
202
|
+
|
|
203
|
+
const serviceScope = this.constructor.name + '.' + localName;
|
|
204
|
+
|
|
205
|
+
// Start servuce & eventually his subservices
|
|
206
|
+
console.log(`[app] Start service`, serviceScope);
|
|
207
|
+
service.status = 'starting';
|
|
208
|
+
service.started = service.launch();
|
|
209
|
+
await service.started.catch(e => {
|
|
210
|
+
console.error("Catched error while starting service " + serviceScope, e);
|
|
211
|
+
if (this.app.env.profile === 'prod')
|
|
212
|
+
process.exit();
|
|
213
|
+
else
|
|
214
|
+
throw e;
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
// Bind to app
|
|
218
|
+
console.log(`[app] Service`, serviceScope, 'started (bound to:', service.bindings.join(', '),')');
|
|
219
|
+
service.status = 'running';
|
|
220
|
+
}
|
|
175
221
|
}
|
|
176
222
|
|
|
177
223
|
/*----------------------------------
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
"baseUrl": "..",
|
|
6
6
|
"paths": {
|
|
7
7
|
|
|
8
|
+
"@/server/models": ["./server/.generated/models"],
|
|
9
|
+
|
|
8
10
|
"@client/*": ["../node_modules/5htp-core/src/client/*"],
|
|
9
11
|
"@common/*": ["../node_modules/5htp-core/src/common/*"],
|
|
10
12
|
"@server/*": ["../node_modules/5htp-core/src/server/*"],
|
package/src/server/index.ts
CHANGED
|
@@ -65,10 +65,14 @@ export type Hooks = {
|
|
|
65
65
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
export type Services = {
|
|
69
|
+
disks: DisksManager,
|
|
70
|
+
}
|
|
71
|
+
|
|
68
72
|
/*----------------------------------
|
|
69
73
|
- SERVICE
|
|
70
74
|
----------------------------------*/
|
|
71
|
-
export default class Cache extends Service<Config, Hooks, Application> {
|
|
75
|
+
export default class Cache extends Service<Config, Hooks, Application, Services> {
|
|
72
76
|
|
|
73
77
|
public commands = registerCommands(this);
|
|
74
78
|
|
|
@@ -79,9 +83,7 @@ export default class Cache extends Service<Config, Hooks, Application> {
|
|
|
79
83
|
public constructor(
|
|
80
84
|
parent: AnyService,
|
|
81
85
|
config: Config,
|
|
82
|
-
services:
|
|
83
|
-
disks: TRegisteredService< DisksManager >,
|
|
84
|
-
},
|
|
86
|
+
services: Services,
|
|
85
87
|
app: Application,
|
|
86
88
|
) {
|
|
87
89
|
|
|
@@ -11,6 +11,7 @@ import highlight from 'cli-highlight';
|
|
|
11
11
|
import type { Application } from '@server/app';
|
|
12
12
|
import Service from '@server/app/service';
|
|
13
13
|
import context from '@server/context';
|
|
14
|
+
import type { ServerBug } from '@common/errors';
|
|
14
15
|
import type ServerRequest from '@server/services/router/request';
|
|
15
16
|
import { SqlError } from '@server/services/database/debug';
|
|
16
17
|
|
|
@@ -38,6 +39,10 @@ export type Hooks = {
|
|
|
38
39
|
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
export type Services = {
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
/*----------------------------------
|
|
42
47
|
- TYPES
|
|
43
48
|
----------------------------------*/
|
|
@@ -82,25 +87,6 @@ export type TDbQueryLog = ChannelInfos & {
|
|
|
82
87
|
|
|
83
88
|
export type TLog = ILogObject & ChannelInfos
|
|
84
89
|
|
|
85
|
-
/*----------------------------------
|
|
86
|
-
- TYPES: BUG REPORT
|
|
87
|
-
----------------------------------*/
|
|
88
|
-
|
|
89
|
-
export type ServerBug = {
|
|
90
|
-
// Context
|
|
91
|
-
hash: string,
|
|
92
|
-
date: Date, // Timestamp
|
|
93
|
-
channelType?: string,
|
|
94
|
-
channelId?: string,
|
|
95
|
-
|
|
96
|
-
user: string | null | undefined,
|
|
97
|
-
ip: string | null | undefined,
|
|
98
|
-
|
|
99
|
-
// Error
|
|
100
|
-
error: Error,
|
|
101
|
-
stacktrace: string,
|
|
102
|
-
logs: string,
|
|
103
|
-
}
|
|
104
90
|
|
|
105
91
|
/*----------------------------------
|
|
106
92
|
- CONST
|
|
@@ -129,7 +115,7 @@ const logFields = [
|
|
|
129
115
|
/*----------------------------------
|
|
130
116
|
- LOGGER
|
|
131
117
|
----------------------------------*/
|
|
132
|
-
export default class Console extends Service<Config, Hooks, Application> {
|
|
118
|
+
export default class Console extends Service<Config, Hooks, Application, Services> {
|
|
133
119
|
|
|
134
120
|
// Services
|
|
135
121
|
public logger!: Logger;
|
|
@@ -184,9 +170,6 @@ export default class Console extends Service<Config, Hooks, Application> {
|
|
|
184
170
|
}, envConfig.level);*/
|
|
185
171
|
|
|
186
172
|
setInterval(() => this.clean(), 10000);
|
|
187
|
-
|
|
188
|
-
// Send email report
|
|
189
|
-
this.app.on('error', this.createBugReport.bind(this));
|
|
190
173
|
}
|
|
191
174
|
|
|
192
175
|
public async ready() {
|
|
@@ -259,7 +242,7 @@ export default class Console extends Service<Config, Hooks, Application> {
|
|
|
259
242
|
logs: logsHtml
|
|
260
243
|
}
|
|
261
244
|
|
|
262
|
-
await this.
|
|
245
|
+
await this.app.reportBug( bugReport );
|
|
263
246
|
}
|
|
264
247
|
|
|
265
248
|
public getChannel() {
|
|
@@ -28,11 +28,15 @@ export type Hooks = {
|
|
|
28
28
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export type Services = {
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
31
35
|
/*----------------------------------
|
|
32
36
|
- CLASSE
|
|
33
37
|
----------------------------------*/
|
|
34
38
|
|
|
35
|
-
export default class CronManager extends Service<Config, Hooks, Application> {
|
|
39
|
+
export default class CronManager extends Service<Config, Hooks, Application, Services> {
|
|
36
40
|
|
|
37
41
|
public static taches: { [nom: string]: CronTask } = {}
|
|
38
42
|
public static timer: NodeJS.Timeout;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// Npm
|
|
6
6
|
import mysql from 'mysql2/promise';
|
|
7
|
-
import type {
|
|
7
|
+
import type { OkPacket } from 'mysql2';
|
|
8
8
|
import dottie from 'dottie';
|
|
9
9
|
const safeStringify = require('fast-safe-stringify'); // remplace les références circulairs par un [Circular]
|
|
10
10
|
|
|
@@ -29,6 +29,10 @@ export type Hooks = {
|
|
|
29
29
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
export type Services = {
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
/*----------------------------------
|
|
33
37
|
- DEFINITIONS TYPES
|
|
34
38
|
----------------------------------*/
|
|
@@ -42,6 +46,7 @@ export type TSelectQueryOptions = TQueryOptions & {
|
|
|
42
46
|
export type TUpdateQueryOptions<TData extends TObjetDonnees = TObjetDonnees> = TQueryOptions;
|
|
43
47
|
|
|
44
48
|
export type TInsertQueryOptions<TData extends TObjetDonnees = TObjetDonnees> = TQueryOptions & {
|
|
49
|
+
bulk?: boolean,
|
|
45
50
|
upsert?: TColsToUpsert<TData>, // When "*", we use table.upsertableColumns
|
|
46
51
|
upsertMode?: 'increment'
|
|
47
52
|
try?: boolean
|
|
@@ -66,13 +71,27 @@ type TColsToUpsert<TData extends TObjetDonnees> = (
|
|
|
66
71
|
|
|
67
72
|
const LogPrefix = '[database]'
|
|
68
73
|
|
|
74
|
+
const emptyOkPacket = {
|
|
75
|
+
constructor: {
|
|
76
|
+
name: 'OkPacket'
|
|
77
|
+
},
|
|
78
|
+
fieldCount: 0,
|
|
79
|
+
affectedRows: 0,
|
|
80
|
+
changedRows: 0,
|
|
81
|
+
insertId: 0,
|
|
82
|
+
serverStatus: 0,
|
|
83
|
+
warningCount: 0,
|
|
84
|
+
message: '',
|
|
85
|
+
procotol41: true,
|
|
86
|
+
} as OkPacket
|
|
87
|
+
|
|
69
88
|
/*----------------------------------
|
|
70
89
|
- CORE
|
|
71
90
|
----------------------------------*/
|
|
72
91
|
|
|
73
92
|
// TODO: build callable instance sithut instanciating the service
|
|
74
93
|
|
|
75
|
-
export default class SQL extends Service<Config, Hooks, Application> {
|
|
94
|
+
export default class SQL extends Service<Config, Hooks, Application, Services> {
|
|
76
95
|
|
|
77
96
|
public database: Database;
|
|
78
97
|
|
|
@@ -88,16 +107,8 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
88
107
|
this.database = new Database(this, config);
|
|
89
108
|
}
|
|
90
109
|
|
|
91
|
-
public
|
|
92
|
-
|
|
93
|
-
config: Config,
|
|
94
|
-
services: TRegisteredServicesIndex,
|
|
95
|
-
app: Application
|
|
96
|
-
) {
|
|
97
|
-
return Services.callableInstance(
|
|
98
|
-
new SQL(parent, config, services, app),
|
|
99
|
-
'sql'
|
|
100
|
-
)
|
|
110
|
+
public getServiceInstance() {
|
|
111
|
+
return Services.callableInstance(this, 'sql')
|
|
101
112
|
}
|
|
102
113
|
|
|
103
114
|
/*----------------------------------
|
|
@@ -321,7 +332,7 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
321
332
|
data: TData,
|
|
322
333
|
where?: (keyof TData)[] | TObjetDonnees,
|
|
323
334
|
opts?: TUpdateQueryOptions<TData>
|
|
324
|
-
]): Promise<
|
|
335
|
+
]): Promise<OkPacket> {
|
|
325
336
|
|
|
326
337
|
let [tableName, data, where, opts] = args;
|
|
327
338
|
|
|
@@ -389,7 +400,7 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
389
400
|
path: string,
|
|
390
401
|
data: TData | TData[],
|
|
391
402
|
opts: TInsertQueryOptions<TData> = {}
|
|
392
|
-
): Promise<
|
|
403
|
+
): Promise<OkPacket> {
|
|
393
404
|
|
|
394
405
|
const table = this.database.getTable(path);
|
|
395
406
|
|
|
@@ -398,39 +409,54 @@ export default class SQL extends Service<Config, Hooks, Application> {
|
|
|
398
409
|
data = [data];
|
|
399
410
|
else if (data.length === 0) {
|
|
400
411
|
console.warn(LogPrefix, `Insert nothing in ${path}. Cancelled.`);
|
|
401
|
-
return
|
|
402
|
-
fieldCount: 0,
|
|
403
|
-
affectedRows: 0,
|
|
404
|
-
changedRows: 0,
|
|
405
|
-
insertId: 0,
|
|
406
|
-
serverStatus: 0,
|
|
407
|
-
warningStatus: 0,
|
|
408
|
-
info: undefined
|
|
409
|
-
};
|
|
412
|
+
return emptyOkPacket;
|
|
410
413
|
}
|
|
411
414
|
|
|
412
|
-
let querySuffix: string = '';
|
|
413
|
-
|
|
414
415
|
// Upsert
|
|
416
|
+
let upsertStatement: string = '';
|
|
415
417
|
if (opts.upsert !== undefined)
|
|
416
|
-
|
|
418
|
+
upsertStatement = ' ' + this.buildUpsertStatement<TData>(table, opts as With<TInsertQueryOptions<TData>, 'upsert'>);
|
|
417
419
|
|
|
418
420
|
// Create basic insert query
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
421
|
+
if (opts.bulk === false) {
|
|
422
|
+
|
|
423
|
+
const okPacket = { ...emptyOkPacket }
|
|
424
|
+
|
|
425
|
+
for (const row of data) {
|
|
426
|
+
|
|
427
|
+
const query = this.buildInsertStatement(table, [row], opts) + upsertStatement;
|
|
428
|
+
|
|
429
|
+
const queryResult = await this.database.query<mysql.OkPacket>(query + ';', opts)
|
|
430
|
+
|
|
431
|
+
okPacket.fieldCount += queryResult.fieldCount;
|
|
432
|
+
okPacket.affectedRows += queryResult.affectedRows;
|
|
433
|
+
okPacket.changedRows += queryResult.changedRows;
|
|
434
|
+
okPacket.insertId = queryResult.insertId;
|
|
435
|
+
okPacket.serverStatus += queryResult.serverStatus;
|
|
436
|
+
okPacket.warningCount += queryResult.warningCount;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return okPacket;
|
|
440
|
+
|
|
441
|
+
} else {
|
|
442
|
+
const query = this.buildInsertStatement(table, data, opts) + upsertStatement;
|
|
443
|
+
|
|
444
|
+
const queryResult = await this.database.query<mysql.OkPacket>(query + ';', opts);
|
|
445
|
+
|
|
446
|
+
return {
|
|
447
|
+
constructor: {
|
|
448
|
+
name: 'OkPacket'
|
|
449
|
+
},
|
|
450
|
+
fieldCount: queryResult.fieldCount,
|
|
451
|
+
affectedRows: queryResult.affectedRows,
|
|
452
|
+
changedRows: queryResult.changedRows,
|
|
453
|
+
insertId: queryResult.insertId,
|
|
454
|
+
serverStatus: queryResult.serverStatus,
|
|
455
|
+
warningCount: queryResult.warningCount,
|
|
456
|
+
message: queryResult.message,
|
|
457
|
+
procotol41: queryResult.procotol41,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
434
460
|
// OLD: return [data, queryResult?.insertId, queryResult];
|
|
435
461
|
}
|
|
436
462
|
|
|
@@ -14,6 +14,10 @@ export type THooks = {
|
|
|
14
14
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export type Services = {
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
/*----------------------------------
|
|
18
22
|
- TYPE
|
|
19
23
|
----------------------------------*/
|
|
@@ -52,7 +56,7 @@ export type TReadFileOptions = {
|
|
|
52
56
|
export default abstract class FsDriver<
|
|
53
57
|
Config extends TDrivercnfig = TDrivercnfig,
|
|
54
58
|
TBucketName = keyof Config["buckets"]
|
|
55
|
-
> extends Service<Config, {}, Application> {
|
|
59
|
+
> extends Service<Config, {}, Application, Services> {
|
|
56
60
|
|
|
57
61
|
public abstract mount(): Promise<void>;
|
|
58
62
|
|
|
@@ -24,25 +24,27 @@ export type Hooks = {
|
|
|
24
24
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
type
|
|
27
|
+
export type Services = {
|
|
28
|
+
|
|
29
|
+
}
|
|
28
30
|
|
|
29
31
|
/*----------------------------------
|
|
30
32
|
- SERVICE
|
|
31
33
|
----------------------------------*/
|
|
32
34
|
export default class DisksManager<
|
|
33
|
-
MountpointList extends
|
|
35
|
+
MountpointList extends Services = {},
|
|
34
36
|
TConfig extends Config = Config,
|
|
35
37
|
TApplication extends Application = Application
|
|
36
|
-
> extends Service<TConfig, Hooks, TApplication> {
|
|
38
|
+
> extends Service<TConfig, Hooks, TApplication, MountpointList> {
|
|
37
39
|
|
|
38
|
-
public default
|
|
40
|
+
public default!: Driver;
|
|
39
41
|
|
|
40
|
-
public mounted:
|
|
42
|
+
public mounted: MountpointList = this.services;
|
|
41
43
|
|
|
42
44
|
public constructor(
|
|
43
45
|
parent: AnyService,
|
|
44
46
|
config: TConfig,
|
|
45
|
-
drivers:
|
|
47
|
+
drivers: MountpointList,
|
|
46
48
|
app: TApplication,
|
|
47
49
|
) {
|
|
48
50
|
|
|
@@ -51,6 +53,14 @@ export default class DisksManager<
|
|
|
51
53
|
if (Object.keys( drivers ).length === 0)
|
|
52
54
|
throw new Error("At least one disk driver should be mounted.");
|
|
53
55
|
|
|
56
|
+
console.log('start disks service', Object.keys( drivers ), Object.keys( this.mounted ), Object.keys( this.services ));
|
|
57
|
+
|
|
58
|
+
const defaultDisk = drivers[ this.config.default ];
|
|
59
|
+
if (defaultDisk === undefined)
|
|
60
|
+
console.log(`Default disk "${this.config.default as string}" not mounted.`);
|
|
61
|
+
|
|
62
|
+
this.default = defaultDisk;
|
|
63
|
+
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
/*----------------------------------
|
|
@@ -58,12 +68,6 @@ export default class DisksManager<
|
|
|
58
68
|
----------------------------------*/
|
|
59
69
|
|
|
60
70
|
public async start() {
|
|
61
|
-
|
|
62
|
-
const defaultDisk = this.mounted[ this.config.default ];
|
|
63
|
-
if (defaultDisk === undefined)
|
|
64
|
-
console.log(`Default disk "${this.config.default as string}" not mounted.`);
|
|
65
|
-
|
|
66
|
-
this.default = defaultDisk;
|
|
67
71
|
|
|
68
72
|
}
|
|
69
73
|
|
|
@@ -41,6 +41,10 @@ export type Hooks = {
|
|
|
41
41
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
export type Services = {
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
44
48
|
/*----------------------------------
|
|
45
49
|
- TYPES: EMAILS
|
|
46
50
|
----------------------------------*/
|
|
@@ -105,7 +109,7 @@ type TOptions = {
|
|
|
105
109
|
/*----------------------------------
|
|
106
110
|
- FONCTIONS
|
|
107
111
|
----------------------------------*/
|
|
108
|
-
export default class Email extends Service<Config, Hooks, Application> {
|
|
112
|
+
export default class Email extends Service<Config, Hooks, Application, Services> {
|
|
109
113
|
|
|
110
114
|
private transporters = this.config.transporters;
|
|
111
115
|
|
|
@@ -65,9 +65,6 @@ export default class FetchService extends Service<Config, Hooks, Application, Se
|
|
|
65
65
|
) {
|
|
66
66
|
|
|
67
67
|
super(parent, config, services, app);
|
|
68
|
-
|
|
69
|
-
if (this.services.disks)
|
|
70
|
-
this.disk = this.services.disks.get( config.disk );
|
|
71
68
|
|
|
72
69
|
}
|
|
73
70
|
|
|
@@ -77,7 +74,8 @@ export default class FetchService extends Service<Config, Hooks, Application, Se
|
|
|
77
74
|
|
|
78
75
|
public async start() {
|
|
79
76
|
|
|
80
|
-
|
|
77
|
+
if (this.services.disks)
|
|
78
|
+
this.disk = this.services.disks.get( this.config.disk );
|
|
81
79
|
|
|
82
80
|
|
|
83
81
|
}
|
|
@@ -114,7 +112,7 @@ export default class FetchService extends Service<Config, Hooks, Application, Se
|
|
|
114
112
|
{ width, height, fit, quality }: TImageConfig,
|
|
115
113
|
saveToBucket: string,
|
|
116
114
|
saveToPath?: string,
|
|
117
|
-
disk?:
|
|
115
|
+
disk?: string
|
|
118
116
|
): Promise<Buffer | null> {
|
|
119
117
|
|
|
120
118
|
// Define target disk
|
|
@@ -96,7 +96,9 @@ export type Config<
|
|
|
96
96
|
|
|
97
97
|
export type Services = {
|
|
98
98
|
disks?: DisksManager
|
|
99
|
-
} &
|
|
99
|
+
} & {
|
|
100
|
+
[routerServiceId: string]: RouterService
|
|
101
|
+
}
|
|
100
102
|
|
|
101
103
|
// Set it as a function, so when we instanciate the services, we can callthis.router to pass the router instance in roiuter services
|
|
102
104
|
type TRouterServicesList = {
|
|
@@ -132,7 +134,7 @@ export default class ServerRouter<
|
|
|
132
134
|
public constructor(
|
|
133
135
|
parent: AnyService,
|
|
134
136
|
config: TConfig,
|
|
135
|
-
services:
|
|
137
|
+
services: Services,
|
|
136
138
|
app: TApplication,
|
|
137
139
|
) {
|
|
138
140
|
|
|
@@ -156,8 +158,6 @@ export default class ServerRouter<
|
|
|
156
158
|
if (routerService instanceof RouterService)
|
|
157
159
|
this.routerServices[ serviceName ] = routerService;
|
|
158
160
|
}
|
|
159
|
-
|
|
160
|
-
console.log("this.routerServices", Object.keys( this.routerServices ));
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
public async ready() {
|
|
@@ -11,16 +11,22 @@ import type { default as Router } from '.';
|
|
|
11
11
|
import type ServerRequest from './request';
|
|
12
12
|
import type RequestService from './request/service';
|
|
13
13
|
|
|
14
|
+
export type Services = {
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
/*----------------------------------
|
|
15
19
|
- SERVICE
|
|
16
20
|
----------------------------------*/
|
|
17
21
|
export default abstract class RouterService<
|
|
18
22
|
TConfig extends {} = {}
|
|
19
|
-
> extends Service<TConfig, {}, Application> {
|
|
23
|
+
> extends Service<TConfig, {}, Application, Services> {
|
|
20
24
|
|
|
21
25
|
public constructor(
|
|
22
26
|
// Parent is always a router in RouterService
|
|
23
|
-
|
|
27
|
+
// Warning: for now, it's possible that router is actually the app
|
|
28
|
+
// It's fixed with a not very clean way in Service.bindService
|
|
29
|
+
router: Router,
|
|
24
30
|
config: TConfig,
|
|
25
31
|
services: TRegisteredServicesIndex,
|
|
26
32
|
app: Application
|
|
@@ -30,6 +36,6 @@ export default abstract class RouterService<
|
|
|
30
36
|
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
public abstract requestService( request: ServerRequest<
|
|
39
|
+
public abstract requestService( request: ServerRequest<Router> ): RequestService | null;
|
|
34
40
|
|
|
35
41
|
}
|
|
@@ -10,11 +10,6 @@ import type { Application } from '@server/app';
|
|
|
10
10
|
import Service from '@server/app/service';
|
|
11
11
|
import { Forbidden } from '@common/errors';
|
|
12
12
|
|
|
13
|
-
/*----------------------------------
|
|
14
|
-
- CONFIG
|
|
15
|
-
----------------------------------*/
|
|
16
|
-
|
|
17
|
-
|
|
18
13
|
/*----------------------------------
|
|
19
14
|
- SERVICE CONFIG
|
|
20
15
|
----------------------------------*/
|
|
@@ -33,6 +28,14 @@ export type Hooks = {
|
|
|
33
28
|
|
|
34
29
|
}
|
|
35
30
|
|
|
31
|
+
export type Services = {
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/*----------------------------------
|
|
36
|
+
- TYPES
|
|
37
|
+
----------------------------------*/
|
|
38
|
+
|
|
36
39
|
type TEncryptOptions = {
|
|
37
40
|
encoding: Encoding
|
|
38
41
|
}
|
|
@@ -44,7 +47,7 @@ type TDecryptOptions = {
|
|
|
44
47
|
/*----------------------------------
|
|
45
48
|
- SERVICE
|
|
46
49
|
----------------------------------*/
|
|
47
|
-
export default class AES<TConfig extends Config = Config> extends Service<TConfig, Hooks, Application> {
|
|
50
|
+
export default class AES<TConfig extends Config = Config> extends Service<TConfig, Hooks, Application, Services> {
|
|
48
51
|
|
|
49
52
|
/*----------------------------------
|
|
50
53
|
- LIFECYCLE
|
|
@@ -32,36 +32,39 @@ export type Hooks = {
|
|
|
32
32
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
export type Services<TUser extends {}> = {
|
|
36
|
+
users: UsersManagementService<TUser, Application>,
|
|
37
|
+
router: Router
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
/*----------------------------------
|
|
36
41
|
- MANAGER
|
|
37
42
|
----------------------------------*/
|
|
38
43
|
export default class WebSocketCommander<
|
|
39
44
|
TUser extends {},
|
|
40
|
-
TConfig extends Config<TUser>= Config<TUser
|
|
41
|
-
|
|
45
|
+
TConfig extends Config<TUser>= Config<TUser>,
|
|
46
|
+
TServices extends Services<TUser> = Services<TUser>
|
|
47
|
+
> extends Service<TConfig, Hooks, Application, TServices> {
|
|
42
48
|
|
|
43
49
|
// Services
|
|
44
50
|
public ws!: WebSocketServer;
|
|
45
|
-
public users
|
|
46
|
-
public router
|
|
51
|
+
public users!: TServices["users"];
|
|
52
|
+
public router!: Router;
|
|
47
53
|
|
|
48
54
|
// Context
|
|
49
55
|
public scopes: {[path: string]: SocketScope<TUser>} = {}
|
|
50
56
|
|
|
51
|
-
public constructor(
|
|
57
|
+
public constructor(
|
|
52
58
|
parent: AnyService,
|
|
53
59
|
config: TConfig,
|
|
54
|
-
services:
|
|
55
|
-
|
|
56
|
-
router: Router
|
|
57
|
-
},
|
|
58
|
-
app: Application,
|
|
60
|
+
services: Services,
|
|
61
|
+
app: TApplication,
|
|
59
62
|
) {
|
|
60
|
-
|
|
61
63
|
super(parent, config, services, app);
|
|
62
|
-
|
|
64
|
+
|
|
63
65
|
this.users = this.services.users;
|
|
64
66
|
this.router = this.services.router;
|
|
67
|
+
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
/*----------------------------------
|
|
@@ -71,10 +74,6 @@ export default class WebSocketCommander<
|
|
|
71
74
|
public loading: Promise<void> | undefined = undefined;
|
|
72
75
|
protected async start() {
|
|
73
76
|
|
|
74
|
-
this.app.on('cleanup', async () => {
|
|
75
|
-
this.closeAll();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
77
|
this.users.on('disconnect', async (userId: string) => {
|
|
79
78
|
this.disconnect(userId, 'Logout');
|
|
80
79
|
});
|
|
@@ -126,7 +125,7 @@ export default class WebSocketCommander<
|
|
|
126
125
|
}
|
|
127
126
|
|
|
128
127
|
public async shutdown() {
|
|
129
|
-
|
|
128
|
+
this.closeAll();
|
|
130
129
|
}
|
|
131
130
|
|
|
132
131
|
/*----------------------------------
|
|
@@ -58,6 +58,10 @@ export type THooks = {
|
|
|
58
58
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
export type TServices = {
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
/*----------------------------------
|
|
62
66
|
- SERVICE
|
|
63
67
|
----------------------------------*/
|
|
@@ -66,7 +70,7 @@ export default abstract class UsersManagementService<
|
|
|
66
70
|
TApplication extends Application,
|
|
67
71
|
TJwtSession extends {} = {},
|
|
68
72
|
TRequest extends ServerRequest<Router> = ServerRequest<Router>,
|
|
69
|
-
> extends Service<TConfig, THooks, TApplication> {
|
|
73
|
+
> extends Service<TConfig, THooks, TApplication, TServices> {
|
|
70
74
|
|
|
71
75
|
/*----------------------------------
|
|
72
76
|
- LIFECYCLE
|
|
@@ -42,7 +42,7 @@ export default class AuthenticationRouterService<
|
|
|
42
42
|
protected async start() {
|
|
43
43
|
|
|
44
44
|
// Decode current user
|
|
45
|
-
this.
|
|
45
|
+
this.parent.on('request', async (request: TRequest) => {
|
|
46
46
|
|
|
47
47
|
// TODO: Typings. (context.user ?)
|
|
48
48
|
const decoded = await this.services.users.decode( request.req, true);
|
|
@@ -51,7 +51,7 @@ export default class AuthenticationRouterService<
|
|
|
51
51
|
})
|
|
52
52
|
|
|
53
53
|
// Check route permissions
|
|
54
|
-
this.
|
|
54
|
+
this.parent.on('resolved', async (route: TAnyRoute, request: TRequest) => {
|
|
55
55
|
|
|
56
56
|
if (route.options.auth !== undefined)
|
|
57
57
|
// TODO: How to pas the router type to router config ? Circular rfeerence ?
|