proteum 1.0.0-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/.dockerignore +10 -0
- package/Rte.zip +0 -0
- package/cli/app/config.ts +54 -0
- package/cli/app/index.ts +195 -0
- package/cli/bin.js +11 -0
- package/cli/commands/build.ts +34 -0
- package/cli/commands/deploy/app.ts +29 -0
- package/cli/commands/deploy/web.ts +60 -0
- package/cli/commands/dev.ts +109 -0
- package/cli/commands/init.ts +85 -0
- package/cli/compiler/client/identite.ts +72 -0
- package/cli/compiler/client/index.ts +334 -0
- package/cli/compiler/common/babel/index.ts +170 -0
- package/cli/compiler/common/babel/plugins/index.ts +0 -0
- package/cli/compiler/common/babel/plugins/services.ts +579 -0
- package/cli/compiler/common/babel/routes/imports.ts +127 -0
- package/cli/compiler/common/babel/routes/routes.ts +1130 -0
- package/cli/compiler/common/files/autres.ts +39 -0
- package/cli/compiler/common/files/images.ts +35 -0
- package/cli/compiler/common/files/style.ts +78 -0
- package/cli/compiler/common/index.ts +154 -0
- package/cli/compiler/index.ts +532 -0
- package/cli/compiler/server/index.ts +211 -0
- package/cli/index.ts +189 -0
- package/cli/paths.ts +165 -0
- package/cli/print.ts +12 -0
- package/cli/tsconfig.json +38 -0
- package/cli/utils/index.ts +22 -0
- package/cli/utils/keyboard.ts +78 -0
- package/client/app/component.tsx +54 -0
- package/client/app/index.ts +142 -0
- package/client/app/service.ts +34 -0
- package/client/app.tsconfig.json +28 -0
- package/client/components/Button.tsx +298 -0
- package/client/components/Dialog/Manager.tsx +309 -0
- package/client/components/Dialog/card.tsx +208 -0
- package/client/components/Dialog/index.less +151 -0
- package/client/components/Dialog/status.less +176 -0
- package/client/components/Dialog/status.tsx +48 -0
- package/client/components/index.ts +2 -0
- package/client/components/types.d.ts +3 -0
- package/client/data/input.ts +32 -0
- package/client/global.d.ts +5 -0
- package/client/hooks.ts +22 -0
- package/client/index.ts +6 -0
- package/client/pages/_layout/index.less +6 -0
- package/client/pages/_layout/index.tsx +43 -0
- package/client/pages/bug.tsx.old +60 -0
- package/client/pages/useHeader.tsx +50 -0
- package/client/services/captcha/index.ts +67 -0
- package/client/services/router/components/Link.tsx +46 -0
- package/client/services/router/components/Page.tsx +55 -0
- package/client/services/router/components/router.tsx +218 -0
- package/client/services/router/index.tsx +521 -0
- package/client/services/router/request/api.ts +267 -0
- package/client/services/router/request/history.ts +5 -0
- package/client/services/router/request/index.ts +53 -0
- package/client/services/router/request/multipart.ts +147 -0
- package/client/services/router/response/index.tsx +128 -0
- package/client/services/router/response/page.ts +86 -0
- package/client/services/socket/index.ts +147 -0
- package/client/utils/dom.ts +77 -0
- package/common/app/index.ts +9 -0
- package/common/data/chaines/index.ts +54 -0
- package/common/data/dates.ts +179 -0
- package/common/data/markdown.ts +73 -0
- package/common/data/rte/nodes.ts +83 -0
- package/common/data/stats.ts +90 -0
- package/common/errors/index.tsx +326 -0
- package/common/router/index.ts +213 -0
- package/common/router/layouts.ts +93 -0
- package/common/router/register.ts +55 -0
- package/common/router/request/api.ts +77 -0
- package/common/router/request/index.ts +35 -0
- package/common/router/response/index.ts +45 -0
- package/common/router/response/page.ts +128 -0
- package/common/utils/rte.ts +183 -0
- package/common/utils.ts +7 -0
- package/doc/TODO.md +71 -0
- package/doc/front/router.md +27 -0
- package/doc/workspace/workspace.png +0 -0
- package/doc/workspace/workspace2.png +0 -0
- package/doc/workspace/workspace_26.01.22.png +0 -0
- package/package.json +171 -0
- package/server/app/commands.ts +141 -0
- package/server/app/container/config.ts +203 -0
- package/server/app/container/console/index.ts +550 -0
- package/server/app/container/index.ts +137 -0
- package/server/app/index.ts +273 -0
- package/server/app/service/container.ts +88 -0
- package/server/app/service/index.ts +235 -0
- package/server/app.tsconfig.json +28 -0
- package/server/context.ts +4 -0
- package/server/index.ts +4 -0
- package/server/services/auth/index.ts +250 -0
- package/server/services/auth/old.ts +277 -0
- package/server/services/auth/router/index.ts +95 -0
- package/server/services/auth/router/request.ts +54 -0
- package/server/services/auth/router/service.json +6 -0
- package/server/services/auth/service.json +6 -0
- package/server/services/cache/commands.ts +41 -0
- package/server/services/cache/index.ts +297 -0
- package/server/services/cache/service.json +6 -0
- package/server/services/cron/CronTask.ts +86 -0
- package/server/services/cron/index.ts +112 -0
- package/server/services/cron/service.json +6 -0
- package/server/services/disks/driver.ts +103 -0
- package/server/services/disks/drivers/local/index.ts +188 -0
- package/server/services/disks/drivers/local/service.json +6 -0
- package/server/services/disks/drivers/s3/index.ts +301 -0
- package/server/services/disks/drivers/s3/service.json +6 -0
- package/server/services/disks/index.ts +90 -0
- package/server/services/disks/service.json +6 -0
- package/server/services/email/index.ts +188 -0
- package/server/services/email/utils.ts +53 -0
- package/server/services/fetch/index.ts +201 -0
- package/server/services/fetch/service.json +7 -0
- package/server/services/models.7z +0 -0
- package/server/services/prisma/Facet.ts +142 -0
- package/server/services/prisma/index.ts +201 -0
- package/server/services/prisma/service.json +6 -0
- package/server/services/router/http/index.ts +217 -0
- package/server/services/router/http/multipart.ts +102 -0
- package/server/services/router/http/session.ts.old +40 -0
- package/server/services/router/index.ts +801 -0
- package/server/services/router/request/api.ts +87 -0
- package/server/services/router/request/index.ts +184 -0
- package/server/services/router/request/service.ts +21 -0
- package/server/services/router/request/validation/zod.ts +180 -0
- package/server/services/router/response/index.ts +338 -0
- package/server/services/router/response/mask/Filter.ts +323 -0
- package/server/services/router/response/mask/index.ts +60 -0
- package/server/services/router/response/mask/selecteurs.ts +92 -0
- package/server/services/router/response/page/document.tsx +160 -0
- package/server/services/router/response/page/index.tsx +196 -0
- package/server/services/router/service.json +6 -0
- package/server/services/router/service.ts +36 -0
- package/server/services/schema/index.ts +44 -0
- package/server/services/schema/request.ts +49 -0
- package/server/services/schema/router/index.ts +28 -0
- package/server/services/schema/router/service.json +6 -0
- package/server/services/schema/service.json +6 -0
- package/server/services/security/encrypt/aes/index.ts +85 -0
- package/server/services/security/encrypt/aes/service.json +6 -0
- package/server/services/socket/index.ts +162 -0
- package/server/services/socket/scope.ts +226 -0
- package/server/services/socket/service.json +6 -0
- package/server/services_old/SocketClient.ts +92 -0
- package/server/services_old/Token.old.ts +97 -0
- package/server/utils/slug.ts +79 -0
- package/tsconfig.common.json +45 -0
- package/tsconfig.json +3 -0
- package/types/aliases.d.ts +54 -0
- package/types/global/modules.d.ts +49 -0
- package/types/global/utils.d.ts +103 -0
- package/types/icons.d.ts +1 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Npm
|
|
6
|
+
import sizeOf from 'object-sizeof';
|
|
7
|
+
|
|
8
|
+
// Core
|
|
9
|
+
|
|
10
|
+
// Specific
|
|
11
|
+
import type CacheManager from '.';
|
|
12
|
+
|
|
13
|
+
/*----------------------------------
|
|
14
|
+
- TYPES
|
|
15
|
+
----------------------------------*/
|
|
16
|
+
|
|
17
|
+
/*----------------------------------
|
|
18
|
+
- SERVICE
|
|
19
|
+
----------------------------------*/
|
|
20
|
+
export default (cache: CacheManager, app = cache.app) => [
|
|
21
|
+
|
|
22
|
+
app.command('cache', 'Manage the cache service', [
|
|
23
|
+
|
|
24
|
+
app.command('list', 'List cache entries', async () => {
|
|
25
|
+
|
|
26
|
+
return Object.entries(cache.data).map(([ key, entry ]) => ({
|
|
27
|
+
key,
|
|
28
|
+
type: typeof entry?.value,
|
|
29
|
+
size: sizeOf(entry?.value),
|
|
30
|
+
expires: entry?.expiration || 'No expiration'
|
|
31
|
+
}))
|
|
32
|
+
}),
|
|
33
|
+
|
|
34
|
+
app.command('delete', 'List cache entries', async (key?: string) => {
|
|
35
|
+
|
|
36
|
+
await cache.del(key);
|
|
37
|
+
|
|
38
|
+
return true;
|
|
39
|
+
})
|
|
40
|
+
])
|
|
41
|
+
]
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Node
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
// Npm
|
|
9
|
+
import hInterval from 'human-interval';
|
|
10
|
+
|
|
11
|
+
// Core
|
|
12
|
+
import type { Application } from '@server/app';
|
|
13
|
+
import Service, { AnyService, TRegisteredService } from '@server/app/service';
|
|
14
|
+
import type { default as DisksManager, Driver } from '../disks';
|
|
15
|
+
|
|
16
|
+
// Specific
|
|
17
|
+
import registerCommands from './commands';
|
|
18
|
+
|
|
19
|
+
/*----------------------------------
|
|
20
|
+
- CONFIG
|
|
21
|
+
----------------------------------*/
|
|
22
|
+
|
|
23
|
+
const LogPrefix = '[cache]';
|
|
24
|
+
|
|
25
|
+
/*----------------------------------
|
|
26
|
+
- TYPES
|
|
27
|
+
----------------------------------*/
|
|
28
|
+
|
|
29
|
+
type TPrimitiveValue = string | boolean | number | undefined | TPrimitiveValue[] | {
|
|
30
|
+
[key: string]: TPrimitiveValue
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type TExpirationDelay = 'never' | string | number | Date;
|
|
34
|
+
|
|
35
|
+
type CacheEntry<TValue extends TPrimitiveValue =TPrimitiveValue > = {
|
|
36
|
+
// Value
|
|
37
|
+
value: TValue,
|
|
38
|
+
// Expiration Timestamp
|
|
39
|
+
expiration?: number,
|
|
40
|
+
changes: number
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type TCacheGetOrUpdateArgs<TValeur extends TPrimitiveValue> = [
|
|
44
|
+
cle: string,
|
|
45
|
+
func: (() => Promise<TValeur>),
|
|
46
|
+
expiration?: TExpirationDelay,
|
|
47
|
+
avecDetails?: boolean
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
type TCacheGetOnlyArgs = [
|
|
51
|
+
cle: string,
|
|
52
|
+
avecDetails: true
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
/*----------------------------------
|
|
56
|
+
- TYPES
|
|
57
|
+
----------------------------------*/
|
|
58
|
+
|
|
59
|
+
export type Config = {
|
|
60
|
+
debug: boolean,
|
|
61
|
+
disk: string, // TODO: keyof disks
|
|
62
|
+
disks: DisksManager
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type Hooks = {
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/*----------------------------------
|
|
70
|
+
- SERVICE
|
|
71
|
+
----------------------------------*/
|
|
72
|
+
export default class Cache extends Service<Config, Hooks, Application> {
|
|
73
|
+
|
|
74
|
+
public commands = registerCommands(this);
|
|
75
|
+
|
|
76
|
+
public data: {[key: string]: CacheEntry | undefined} = {};
|
|
77
|
+
|
|
78
|
+
private disk: Driver;
|
|
79
|
+
|
|
80
|
+
public constructor(
|
|
81
|
+
parent: AnyService,
|
|
82
|
+
config: Config,
|
|
83
|
+
app: Application,
|
|
84
|
+
) {
|
|
85
|
+
|
|
86
|
+
super(parent, config, app);
|
|
87
|
+
|
|
88
|
+
this.disk = this.config.disks.get(config.disk)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/*----------------------------------
|
|
92
|
+
- LIFECYCLE
|
|
93
|
+
----------------------------------*/
|
|
94
|
+
|
|
95
|
+
public async ready() {
|
|
96
|
+
|
|
97
|
+
setInterval(() => this.cleanMem(), 10000);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public async shutdown() {
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/*----------------------------------
|
|
105
|
+
- ACTIONS
|
|
106
|
+
----------------------------------*/
|
|
107
|
+
private async restore() {
|
|
108
|
+
const files = await this.disk.readDir('data', 'cache')
|
|
109
|
+
for (const file of files) {
|
|
110
|
+
|
|
111
|
+
if (!file.name.endsWith('.json'))
|
|
112
|
+
continue;
|
|
113
|
+
|
|
114
|
+
const entryKey = file.name.substring(0, file.name.length - 5);
|
|
115
|
+
const filePath = path.join('cache', file.name);
|
|
116
|
+
this.data[ entryKey ] = await this.disk.readJSON('data', filePath);
|
|
117
|
+
console.log(LogPrefix, `Restored cache entry ${entryKey}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private cleanMem() {
|
|
122
|
+
|
|
123
|
+
// Remove expired data
|
|
124
|
+
const now = Date.now();
|
|
125
|
+
for (const key in this.data) {
|
|
126
|
+
const entry = this.data[ key ];
|
|
127
|
+
if (entry?.expiration && entry.expiration < now) {
|
|
128
|
+
this.config.debug && console.log(LogPrefix, `Delete expired data: ${key}`);
|
|
129
|
+
this.del(key);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Write changes
|
|
134
|
+
for (const entryKey in this.data) {
|
|
135
|
+
|
|
136
|
+
const entry = this.data[entryKey];
|
|
137
|
+
if (!entry?.changes)
|
|
138
|
+
continue;
|
|
139
|
+
|
|
140
|
+
this.config.debug && console.log(LogPrefix, `Flush ${entry.changes} changes for ${entryKey}`);
|
|
141
|
+
|
|
142
|
+
entry.changes = 0;
|
|
143
|
+
const entryFile = this.getEntryFile(entryKey);
|
|
144
|
+
fs.outputJSONSync(entryFile , this.data[entryKey]);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private getEntryFile( entryKey: string ) {
|
|
149
|
+
return path.join(this.cacheDir, entryKey + '.json');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public get<TValeur extends TPrimitiveValue>(
|
|
153
|
+
cle: string,
|
|
154
|
+
avecDetails?: true
|
|
155
|
+
): Promise<CacheEntry<TValeur> | TValeur | undefined>;
|
|
156
|
+
|
|
157
|
+
// Expiration = Durée de vie en secondes ou date max
|
|
158
|
+
// Retourne null quand pas de valeur
|
|
159
|
+
public get<TValeur extends TPrimitiveValue>(
|
|
160
|
+
cle: string,
|
|
161
|
+
func: (() => Promise<TValeur>),
|
|
162
|
+
expiration: TExpirationDelay,
|
|
163
|
+
avecDetails: true
|
|
164
|
+
): Promise<CacheEntry<TValeur>>;
|
|
165
|
+
|
|
166
|
+
public get<TValeur extends TPrimitiveValue>(
|
|
167
|
+
cle: string,
|
|
168
|
+
func: (() => Promise<TValeur>),
|
|
169
|
+
expiration?: TExpirationDelay,
|
|
170
|
+
avecDetails?: false
|
|
171
|
+
): Promise<TValeur>;
|
|
172
|
+
|
|
173
|
+
public async get<TValeur extends TPrimitiveValue, TArgs extends TCacheGetOnlyArgs | TCacheGetOrUpdateArgs<TValeur> = TCacheGetOnlyArgs | TCacheGetOrUpdateArgs<TValeur>>(
|
|
174
|
+
...args: TArgs
|
|
175
|
+
): Promise< TValeur | CacheEntry<TValeur> | (TArgs extends TCacheGetOnlyArgs ? undefined : TValeur)> {
|
|
176
|
+
|
|
177
|
+
let cle: string;
|
|
178
|
+
let func: (() => Promise<TValeur>) | undefined;
|
|
179
|
+
let expiration: TExpirationDelay | undefined;
|
|
180
|
+
let avecDetails: boolean | undefined = true;
|
|
181
|
+
|
|
182
|
+
if (typeof args[1] === 'function') {
|
|
183
|
+
([ cle, func, expiration, avecDetails ] = args);
|
|
184
|
+
} else {
|
|
185
|
+
([ cle, avecDetails ] = args);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (expiration === undefined)
|
|
189
|
+
expiration = 'never';
|
|
190
|
+
|
|
191
|
+
let entry: CacheEntry<TValeur> | undefined = this.data[cle];
|
|
192
|
+
|
|
193
|
+
// Expired
|
|
194
|
+
if (entry?.expiration && entry.expiration < Date.now()){
|
|
195
|
+
this.config.debug && console.log(LogPrefix, `Key ${cle} expired.`);
|
|
196
|
+
entry = undefined;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Donnée inexistante
|
|
200
|
+
if (entry !== undefined) {
|
|
201
|
+
|
|
202
|
+
this.config.debug && console.log(LogPrefix, `Get "${cle}": restored via cache`);
|
|
203
|
+
|
|
204
|
+
} else if (func !== undefined) {
|
|
205
|
+
|
|
206
|
+
this.config.debug && console.log(LogPrefix, `Get "${cle}": refresh value`);
|
|
207
|
+
|
|
208
|
+
// Rechargement
|
|
209
|
+
entry = {
|
|
210
|
+
value: await func(),
|
|
211
|
+
expiration: this.delayToTimestamp(expiration),
|
|
212
|
+
changes: 0
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (expiration !== 'now')
|
|
216
|
+
await this.set(cle, entry.value, expiration);
|
|
217
|
+
|
|
218
|
+
} else
|
|
219
|
+
return undefined;
|
|
220
|
+
|
|
221
|
+
return avecDetails
|
|
222
|
+
? entry
|
|
223
|
+
: entry.value as TValeur;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Put in cache a JSON value, associated with an unique ID.
|
|
228
|
+
* @param cle Unique identifier for the cache entry. Used to retrieve the value via Cache.set()
|
|
229
|
+
* @param val The value to put in cache
|
|
230
|
+
* @param expiration The interval in which the data is valid.
|
|
231
|
+
* - string: the humain-readable expression. Exemple: 10 minutes
|
|
232
|
+
* - number: time in seconds
|
|
233
|
+
* - Date: the date at which the data expires
|
|
234
|
+
* - null: no expiration (default)
|
|
235
|
+
* @returns A void promise
|
|
236
|
+
*/
|
|
237
|
+
public set( cle: string, val: TPrimitiveValue, expiration: TExpirationDelay = 'never' ): void {
|
|
238
|
+
|
|
239
|
+
// TODO: check is key contains illegal characters
|
|
240
|
+
|
|
241
|
+
this.config.debug && console.log(LogPrefix, "Updating cache " + cle);
|
|
242
|
+
this.data[ cle ] = {
|
|
243
|
+
value: val,
|
|
244
|
+
expiration: this.delayToTimestamp(expiration),
|
|
245
|
+
changes: 1
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
public del( key: string ): void {
|
|
250
|
+
|
|
251
|
+
if (key === undefined) {
|
|
252
|
+
this.data = {};
|
|
253
|
+
console.log(LogPrefix, "Deleting all keys from cache");
|
|
254
|
+
fs.removeSync( this.cacheDir );
|
|
255
|
+
} else {
|
|
256
|
+
this.data[ key ] = undefined;
|
|
257
|
+
console.log(LogPrefix, `Deleting key "${key}" from cache`);
|
|
258
|
+
const entryFile = this.getEntryFile(key);
|
|
259
|
+
fs.removeSync( entryFile );
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
/*----------------------------------
|
|
265
|
+
- UTILS
|
|
266
|
+
----------------------------------*/
|
|
267
|
+
/**
|
|
268
|
+
*
|
|
269
|
+
* @param delay
|
|
270
|
+
* @returns number (timestamp when the data expired) or undefined (never expires)
|
|
271
|
+
*/
|
|
272
|
+
private delayToTimestamp( delay: TExpirationDelay ): number | undefined {
|
|
273
|
+
|
|
274
|
+
if (delay === 'now') {
|
|
275
|
+
|
|
276
|
+
return Date.now();
|
|
277
|
+
|
|
278
|
+
} else if (delay === 'never') {
|
|
279
|
+
|
|
280
|
+
return undefined;
|
|
281
|
+
|
|
282
|
+
// H expression
|
|
283
|
+
} else if (typeof delay === 'string') {
|
|
284
|
+
|
|
285
|
+
const ms = hInterval(delay);
|
|
286
|
+
if (ms === undefined) throw new Error(`Invalid period string: ` + delay);
|
|
287
|
+
return Date.now() + ms;
|
|
288
|
+
|
|
289
|
+
// Lifetime in seconds
|
|
290
|
+
} else if (typeof delay === 'number')
|
|
291
|
+
return Date.now() + delay;
|
|
292
|
+
|
|
293
|
+
// Date limit
|
|
294
|
+
else
|
|
295
|
+
return delay.getTime();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Npm
|
|
6
|
+
import cronParser, { CronExpression } from 'cron-parser';
|
|
7
|
+
|
|
8
|
+
/*----------------------------------
|
|
9
|
+
- TYPES
|
|
10
|
+
----------------------------------*/
|
|
11
|
+
|
|
12
|
+
import type CronManager from '.';
|
|
13
|
+
|
|
14
|
+
export type TFrequence = string | Date;
|
|
15
|
+
export type TRunner = () => Promise<any>
|
|
16
|
+
|
|
17
|
+
/*----------------------------------
|
|
18
|
+
- CLASS
|
|
19
|
+
----------------------------------*/
|
|
20
|
+
export default class CronTask {
|
|
21
|
+
|
|
22
|
+
public cron?: CronExpression
|
|
23
|
+
public nextInvocation?: Date;
|
|
24
|
+
|
|
25
|
+
public constructor(
|
|
26
|
+
private manager: CronManager,
|
|
27
|
+
public nom: string,
|
|
28
|
+
next: TFrequence,
|
|
29
|
+
public runner: TRunner,
|
|
30
|
+
public autoexec?: boolean
|
|
31
|
+
) {
|
|
32
|
+
|
|
33
|
+
this.manager.config.debug && console.info(`[cron][${this.nom}] Enregistrement de la tâche`);
|
|
34
|
+
|
|
35
|
+
this.schedule(next);
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public schedule(next: TFrequence) {
|
|
40
|
+
|
|
41
|
+
this.cron = undefined;
|
|
42
|
+
|
|
43
|
+
// Cron expression
|
|
44
|
+
if (typeof next === 'string') {
|
|
45
|
+
|
|
46
|
+
this.cron = cronParser.parseExpression(next);
|
|
47
|
+
this.nextInvocation = this.cron.next().toDate();
|
|
48
|
+
|
|
49
|
+
this.manager.config.debug &&
|
|
50
|
+
console.info(`[cron][${this.nom}] Planifié pour ${this.nextInvocation.toISOString()} via cron ${next}`);
|
|
51
|
+
|
|
52
|
+
// Date
|
|
53
|
+
} else {
|
|
54
|
+
|
|
55
|
+
this.nextInvocation = next;
|
|
56
|
+
this.manager.config.debug &&
|
|
57
|
+
console.info(`[cron][${this.nom}] Planifié pour ${this.nextInvocation.toISOString()} via date`);
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public scheduleNext() {
|
|
63
|
+
|
|
64
|
+
// Prochaine invocation
|
|
65
|
+
if (this.cron !== undefined)
|
|
66
|
+
this.nextInvocation = this.cron.next().toDate();
|
|
67
|
+
else
|
|
68
|
+
this.nextInvocation = undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public run(now: boolean = false) {
|
|
72
|
+
|
|
73
|
+
// Update invocation date
|
|
74
|
+
const maintenant = new Date
|
|
75
|
+
const runnable = this.nextInvocation !== undefined && this.nextInvocation.valueOf() <= maintenant.valueOf()
|
|
76
|
+
if (runnable)
|
|
77
|
+
this.scheduleNext();
|
|
78
|
+
else if (now === false)
|
|
79
|
+
return;
|
|
80
|
+
|
|
81
|
+
// Execution
|
|
82
|
+
this.runner().then(() => {
|
|
83
|
+
this.manager.config.debug && console.info(`Task runned.`);
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Core
|
|
6
|
+
import type { Application } from '@server/app';
|
|
7
|
+
import Service from '@server/app/service';
|
|
8
|
+
import { NotFound } from '@common/errors';
|
|
9
|
+
import context from '@server/context';
|
|
10
|
+
|
|
11
|
+
/*----------------------------------
|
|
12
|
+
- TYPES
|
|
13
|
+
----------------------------------*/
|
|
14
|
+
|
|
15
|
+
import CronTask, { TRunner, TFrequence } from './CronTask';
|
|
16
|
+
|
|
17
|
+
export { default as CronTask } from './CronTask';
|
|
18
|
+
|
|
19
|
+
/*----------------------------------
|
|
20
|
+
- SERVICE CONFIG
|
|
21
|
+
----------------------------------*/
|
|
22
|
+
|
|
23
|
+
export type Config = {
|
|
24
|
+
debug?: boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type Hooks = {
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type Services = {
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/*----------------------------------
|
|
36
|
+
- CLASSE
|
|
37
|
+
----------------------------------*/
|
|
38
|
+
|
|
39
|
+
export default class CronManager extends Service<Config, Hooks, Application, Application> {
|
|
40
|
+
|
|
41
|
+
public static taches: { [nom: string]: CronTask } = {}
|
|
42
|
+
public static timer: NodeJS.Timeout;
|
|
43
|
+
|
|
44
|
+
/*----------------------------------
|
|
45
|
+
- LIFECICLE
|
|
46
|
+
----------------------------------*/
|
|
47
|
+
|
|
48
|
+
public async ready() {
|
|
49
|
+
|
|
50
|
+
clearInterval(CronManager.timer);
|
|
51
|
+
CronManager.timer = setInterval(() => {
|
|
52
|
+
|
|
53
|
+
for (const id in CronManager.taches)
|
|
54
|
+
CronManager.taches[id].run();
|
|
55
|
+
|
|
56
|
+
}, 10000);
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/*----------------------------------
|
|
61
|
+
- STATIQUE
|
|
62
|
+
----------------------------------*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Create a new Cron task
|
|
66
|
+
* @param nom Unique ID / Label for this task (helpful for tracking & debugging)
|
|
67
|
+
* @param frequence When to execute this task.
|
|
68
|
+
* - Date: The date at which to execute this task (one time execution)
|
|
69
|
+
* - string: Cron expression to define the interval for executing this task
|
|
70
|
+
* @param run Function to run
|
|
71
|
+
* @param autoexec true to execute the task immediatly
|
|
72
|
+
* @returns The CronTask that just have been created
|
|
73
|
+
*/
|
|
74
|
+
public task(nom: string, frequence: TFrequence, run: TRunner, autoexec?: boolean) {
|
|
75
|
+
return new Promise<CronTask>((resolve, reject) => {
|
|
76
|
+
context.run({ channelType: 'cron', channelId: nom }, async () => {
|
|
77
|
+
|
|
78
|
+
CronManager.taches[nom] = new CronTask(this, nom, frequence, run, autoexec);
|
|
79
|
+
|
|
80
|
+
if (autoexec)
|
|
81
|
+
await CronManager.taches[nom].run(true);
|
|
82
|
+
|
|
83
|
+
resolve( CronManager.taches[nom] );
|
|
84
|
+
|
|
85
|
+
})
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public async exec(nom: string) {
|
|
91
|
+
|
|
92
|
+
const tache = CronManager.taches[nom];
|
|
93
|
+
|
|
94
|
+
if (tache === undefined)
|
|
95
|
+
throw new NotFound("Tâche NotFound: " + nom);
|
|
96
|
+
|
|
97
|
+
await tache.run(true);
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
public get(): typeof CronManager.taches;
|
|
101
|
+
public get(name: string): CronTask;
|
|
102
|
+
public get(name?: string): CronTask | typeof CronManager.taches {
|
|
103
|
+
|
|
104
|
+
if (name === undefined)
|
|
105
|
+
return CronManager.taches;
|
|
106
|
+
|
|
107
|
+
const cron = CronManager.taches[name];
|
|
108
|
+
if (cron === undefined)
|
|
109
|
+
throw new Error(`L'instance de la tâche cron ${name} n'a pas été trouvée`);
|
|
110
|
+
return cron;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPS
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Core
|
|
6
|
+
import type { Application } from '@server/app';
|
|
7
|
+
import Service from '@server/app/service';
|
|
8
|
+
|
|
9
|
+
/*----------------------------------
|
|
10
|
+
- CONFIG
|
|
11
|
+
----------------------------------*/
|
|
12
|
+
|
|
13
|
+
export type THooks = {
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type Services = {
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/*----------------------------------
|
|
22
|
+
- TYPE
|
|
23
|
+
----------------------------------*/
|
|
24
|
+
|
|
25
|
+
export type TDrivercnfig = {
|
|
26
|
+
|
|
27
|
+
debug: boolean,
|
|
28
|
+
|
|
29
|
+
rootDir: string,
|
|
30
|
+
buckets: {
|
|
31
|
+
[id: string]: string
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type SourceFile = {
|
|
36
|
+
name: string,
|
|
37
|
+
path: string,
|
|
38
|
+
modified: number,
|
|
39
|
+
parentFolder: string,
|
|
40
|
+
source: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type TOutputFileOptions = {
|
|
44
|
+
encoding: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type TReadFileOptions = {
|
|
48
|
+
encoding?: 'string'|'buffer',
|
|
49
|
+
withMetas?: boolean
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/*----------------------------------
|
|
53
|
+
- CLASS
|
|
54
|
+
----------------------------------*/
|
|
55
|
+
|
|
56
|
+
export default abstract class FsDriver<
|
|
57
|
+
Config extends TDrivercnfig = TDrivercnfig,
|
|
58
|
+
TBucketName = keyof Config["buckets"]
|
|
59
|
+
> extends Service<Config, {}, Application, Application> {
|
|
60
|
+
|
|
61
|
+
public constructor( config: Config, app: Application ) {
|
|
62
|
+
super(app, config, app);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public abstract mount(): Promise<void>;
|
|
66
|
+
|
|
67
|
+
public abstract getFileUrl(
|
|
68
|
+
bucketName: TBucketName,
|
|
69
|
+
filename: string
|
|
70
|
+
): string;
|
|
71
|
+
|
|
72
|
+
public abstract readDir( bucketName: TBucketName, dirname?: string ): Promise<SourceFile[]>;
|
|
73
|
+
|
|
74
|
+
public abstract readFile(
|
|
75
|
+
bucketName: TBucketName,
|
|
76
|
+
filename: string,
|
|
77
|
+
options: TReadFileOptions
|
|
78
|
+
): Promise<Buffer>;
|
|
79
|
+
|
|
80
|
+
public abstract createReadStream( bucketName: TBucketName, filename: string );
|
|
81
|
+
|
|
82
|
+
public abstract exists( bucketName: TBucketName, filename: string ): Promise<boolean>;
|
|
83
|
+
|
|
84
|
+
public abstract move( bucketName: TBucketName, source: string, destination: string, options: { overwrite?: boolean }): Promise<void>;
|
|
85
|
+
|
|
86
|
+
public abstract outputFile(
|
|
87
|
+
bucketName: TBucketName,
|
|
88
|
+
filename: string,
|
|
89
|
+
content: string | Buffer,
|
|
90
|
+
options?: TOutputFileOptions
|
|
91
|
+
): Promise<{
|
|
92
|
+
path: string
|
|
93
|
+
}>;
|
|
94
|
+
|
|
95
|
+
public abstract readJSON( bucketName: TBucketName, filename: string ): Promise<any>;
|
|
96
|
+
|
|
97
|
+
public abstract delete( bucketName: TBucketName, filename: string ): Promise<boolean>;
|
|
98
|
+
|
|
99
|
+
public abstract deleteDir( bucketName: TBucketName, dirname: string ): Promise<boolean>;
|
|
100
|
+
|
|
101
|
+
public abstract unmount(): Promise<void>;
|
|
102
|
+
|
|
103
|
+
}
|