proteum 1.0.2 → 2.0.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 (185) hide show
  1. package/AGENTS.md +101 -0
  2. package/agents/codex/AGENTS.md +95 -0
  3. package/agents/codex/CODING_STYLE.md +71 -0
  4. package/agents/codex/agents.md.zip +0 -0
  5. package/agents/codex/client/AGENTS.md +102 -0
  6. package/agents/codex/client/pages/AGENTS.md +35 -0
  7. package/agents/codex/server/routes/AGENTS.md +12 -0
  8. package/agents/codex/server/services/AGENTS.md +137 -0
  9. package/agents/codex/tests/AGENTS.md +8 -0
  10. package/cli/app/config.ts +13 -11
  11. package/cli/app/index.ts +74 -82
  12. package/cli/bin.js +1 -1
  13. package/cli/commands/build.ts +51 -14
  14. package/cli/commands/check.ts +19 -0
  15. package/cli/commands/deploy/app.ts +4 -8
  16. package/cli/commands/deploy/web.ts +16 -20
  17. package/cli/commands/dev.ts +189 -64
  18. package/cli/commands/devEvents.ts +106 -0
  19. package/cli/commands/init.ts +63 -57
  20. package/cli/commands/lint.ts +21 -0
  21. package/cli/commands/refresh.ts +18 -0
  22. package/cli/commands/typecheck.ts +18 -0
  23. package/cli/compiler/client/identite.ts +80 -53
  24. package/cli/compiler/client/index.ts +139 -213
  25. package/cli/compiler/common/bundleAnalysis.ts +94 -0
  26. package/cli/compiler/common/clientManifest.ts +67 -0
  27. package/cli/compiler/common/controllers.ts +288 -0
  28. package/cli/compiler/common/files/autres.ts +7 -18
  29. package/cli/compiler/common/files/images.ts +40 -37
  30. package/cli/compiler/common/files/style.ts +11 -22
  31. package/cli/compiler/common/generatedRouteModules.ts +368 -0
  32. package/cli/compiler/common/index.ts +31 -65
  33. package/cli/compiler/common/loaders/forbid-ssr-import.js +13 -0
  34. package/cli/compiler/common/rspackAliases.ts +13 -0
  35. package/cli/compiler/common/scripts.ts +37 -0
  36. package/cli/compiler/index.ts +781 -230
  37. package/cli/compiler/server/index.ts +59 -75
  38. package/cli/compiler/writeIfChanged.ts +21 -0
  39. package/cli/index.ts +71 -72
  40. package/cli/paths.ts +51 -57
  41. package/cli/print.ts +17 -11
  42. package/cli/tsconfig.json +5 -4
  43. package/cli/utils/agents.ts +100 -0
  44. package/cli/utils/check.ts +71 -0
  45. package/cli/utils/index.ts +1 -3
  46. package/cli/utils/keyboard.ts +8 -25
  47. package/cli/utils/runProcess.ts +30 -0
  48. package/client/app/component.tsx +29 -29
  49. package/client/app/index.ts +36 -57
  50. package/client/app/service.ts +7 -12
  51. package/client/app.tsconfig.json +2 -2
  52. package/client/components/Dialog/Manager.ssr.tsx +40 -0
  53. package/client/components/Dialog/Manager.tsx +119 -150
  54. package/client/components/Dialog/status.tsx +3 -3
  55. package/client/components/index.ts +1 -1
  56. package/client/components/types.d.ts +1 -3
  57. package/client/dev/hmr.ts +65 -0
  58. package/client/global.d.ts +2 -2
  59. package/client/hooks.ts +6 -9
  60. package/client/index.ts +2 -1
  61. package/client/islands/index.ts +7 -0
  62. package/client/islands/useDeferredModule.ts +199 -0
  63. package/client/pages/_layout/index.tsx +4 -12
  64. package/client/pages/useHeader.tsx +14 -21
  65. package/client/router.ts +27 -0
  66. package/client/services/router/components/Link.tsx +34 -27
  67. package/client/services/router/components/Page.tsx +6 -14
  68. package/client/services/router/components/router.ssr.tsx +36 -0
  69. package/client/services/router/components/router.tsx +63 -83
  70. package/client/services/router/index.tsx +185 -220
  71. package/client/services/router/request/api.ts +97 -119
  72. package/client/services/router/request/history.ts +2 -2
  73. package/client/services/router/request/index.ts +13 -12
  74. package/client/services/router/request/multipart.ts +72 -62
  75. package/client/services/router/response/index.tsx +68 -61
  76. package/client/services/router/response/page.ts +28 -32
  77. package/client/utils/dom.ts +17 -33
  78. package/common/app/index.ts +3 -3
  79. package/common/data/chaines/index.ts +22 -23
  80. package/common/data/dates.ts +35 -70
  81. package/common/data/markdown.ts +42 -39
  82. package/common/dev/serverHotReload.ts +26 -0
  83. package/common/errors/index.tsx +110 -142
  84. package/common/router/contracts.ts +29 -0
  85. package/common/router/index.ts +89 -108
  86. package/common/router/layouts.ts +34 -47
  87. package/common/router/pageSetup.ts +50 -0
  88. package/common/router/register.ts +53 -24
  89. package/common/router/request/api.ts +30 -36
  90. package/common/router/request/index.ts +2 -8
  91. package/common/router/response/index.ts +8 -15
  92. package/common/router/response/page.ts +70 -58
  93. package/common/utils.ts +1 -1
  94. package/doc/TODO.md +1 -1
  95. package/eslint.js +62 -0
  96. package/package.json +12 -47
  97. package/prettier.config.cjs +9 -0
  98. package/scripts/cleanup-generated-controllers.ts +62 -0
  99. package/scripts/fix-reference-app-typing.ts +490 -0
  100. package/scripts/refactor-client-app-imports.ts +244 -0
  101. package/scripts/refactor-client-pages.ts +587 -0
  102. package/scripts/refactor-server-controllers.ts +470 -0
  103. package/scripts/refactor-server-runtime-aliases.ts +360 -0
  104. package/scripts/restore-client-app-import-files.ts +41 -0
  105. package/scripts/restore-files-from-git-head.ts +20 -0
  106. package/scripts/update-codex-agents.ts +35 -0
  107. package/server/app/commands.ts +35 -64
  108. package/server/app/container/config.ts +48 -59
  109. package/server/app/container/console/index.ts +202 -248
  110. package/server/app/container/index.ts +33 -71
  111. package/server/app/controller/index.ts +61 -0
  112. package/server/app/index.ts +39 -105
  113. package/server/app/service/container.ts +41 -42
  114. package/server/app/service/index.ts +120 -147
  115. package/server/context.ts +1 -1
  116. package/server/index.ts +25 -1
  117. package/server/services/auth/index.ts +75 -115
  118. package/server/services/auth/router/index.ts +31 -32
  119. package/server/services/auth/router/request.ts +14 -16
  120. package/server/services/cron/CronTask.ts +13 -26
  121. package/server/services/cron/index.ts +14 -36
  122. package/server/services/disks/driver.ts +40 -58
  123. package/server/services/disks/drivers/local/index.ts +79 -90
  124. package/server/services/disks/drivers/s3/index.ts +116 -163
  125. package/server/services/disks/index.ts +23 -38
  126. package/server/services/email/index.ts +45 -104
  127. package/server/services/email/utils.ts +14 -27
  128. package/server/services/fetch/index.ts +53 -85
  129. package/server/services/prisma/Facet.ts +39 -91
  130. package/server/services/prisma/index.ts +74 -110
  131. package/server/services/router/generatedRuntime.ts +29 -0
  132. package/server/services/router/http/index.ts +78 -73
  133. package/server/services/router/http/multipart.ts +19 -42
  134. package/server/services/router/index.ts +378 -365
  135. package/server/services/router/request/api.ts +26 -25
  136. package/server/services/router/request/index.ts +44 -51
  137. package/server/services/router/request/service.ts +7 -11
  138. package/server/services/router/request/validation/zod.ts +111 -148
  139. package/server/services/router/response/index.ts +110 -125
  140. package/server/services/router/response/mask/Filter.ts +31 -72
  141. package/server/services/router/response/mask/index.ts +8 -15
  142. package/server/services/router/response/mask/selecteurs.ts +11 -25
  143. package/server/services/router/response/page/clientManifest.ts +25 -0
  144. package/server/services/router/response/page/document.tsx +199 -127
  145. package/server/services/router/response/page/index.tsx +89 -94
  146. package/server/services/router/service.ts +13 -15
  147. package/server/services/schema/index.ts +17 -26
  148. package/server/services/schema/request.ts +19 -33
  149. package/server/services/schema/router/index.ts +8 -11
  150. package/server/services/security/encrypt/aes/index.ts +15 -35
  151. package/server/utils/slug.ts +29 -35
  152. package/skills/clean-project-code/SKILL.md +63 -0
  153. package/skills/clean-project-code/agents/openai.yaml +4 -0
  154. package/tsconfig.common.json +4 -3
  155. package/tsconfig.json +4 -1
  156. package/types/aliases.d.ts +17 -21
  157. package/types/controller-input.test.ts +48 -0
  158. package/types/express-extra.d.ts +6 -0
  159. package/types/global/constants.d.ts +13 -0
  160. package/types/global/express-extra.d.ts +6 -0
  161. package/types/global/modules.d.ts +13 -16
  162. package/types/global/utils.d.ts +17 -49
  163. package/types/global/vendors.d.ts +62 -0
  164. package/types/icons.d.ts +65 -1
  165. package/types/uuid.d.ts +3 -0
  166. package/types/vendors.d.ts +62 -0
  167. package/cli/compiler/common/babel/index.ts +0 -170
  168. package/cli/compiler/common/babel/plugins/index.ts +0 -0
  169. package/cli/compiler/common/babel/plugins/services.ts +0 -586
  170. package/cli/compiler/common/babel/routes/imports.ts +0 -127
  171. package/cli/compiler/common/babel/routes/routes.ts +0 -1130
  172. package/client/services/captcha/index.ts +0 -67
  173. package/client/services/socket/index.ts +0 -147
  174. package/common/data/rte/nodes.ts +0 -83
  175. package/common/data/stats.ts +0 -90
  176. package/common/utils/rte.ts +0 -183
  177. package/server/services/auth/old.ts +0 -277
  178. package/server/services/cache/commands.ts +0 -41
  179. package/server/services/cache/index.ts +0 -297
  180. package/server/services/cache/service.json +0 -6
  181. package/server/services/socket/index.ts +0 -162
  182. package/server/services/socket/scope.ts +0 -226
  183. package/server/services/socket/service.json +0 -6
  184. package/server/services_old/SocketClient.ts +0 -92
  185. package/server/services_old/Token.old.ts +0 -97
@@ -1,277 +0,0 @@
1
-
2
- import md5 from 'md5';
3
- import { OAuth2Client, LoginTicket } from 'google-auth-library';
4
-
5
-
6
-
7
- type AuthResponse = {
8
- token: string,
9
- redirect: string,
10
- user: User
11
- }
12
-
13
- export default class {
14
-
15
-
16
- protected async ready() {
17
-
18
- // Google auth client
19
- if (this.config.google) {
20
-
21
- const httpConfig = this.app.http.publicUrl;
22
-
23
- this.googleClient = new OAuth2Client(
24
- this.config.google.web.clientId, // Google Client ID
25
- this.config.google.web.secret, // Private key
26
- httpConfig + "/auth/google/response" // Redirect url
27
- );
28
- }
29
- }
30
-
31
-
32
- private googleClient: OAuth2Client | undefined;
33
-
34
- public async FromGoogle(request: ServerRequest): Promise<string> {
35
-
36
- if (!this.googleClient)
37
- throw new Forbidden(`Authentication method disabled.`);
38
-
39
- // Register start time, so we can determine the signup time to display
40
- request.response?.cookie('signupstart', Date.now());
41
-
42
- // Google auth doesn't support local env
43
- // So we simulate that google sent a response with the user email
44
- if (app.env.name === 'local') {
45
- const { redirect } = await this.Auth("tbsoftwares23@gmail.com", request, true);
46
- return redirect;
47
- }
48
-
49
- return this.googleClient.generateAuthUrl({
50
- access_type: 'offline',
51
- scope: [
52
- "email", "profile"
53
- ]
54
- });
55
-
56
- }
57
-
58
- public async GoogleResponse(
59
- type: 'code' | 'token',
60
- codeOrToken: string | undefined,
61
- request: ServerRequest,
62
- ): Promise<AuthResponse> {
63
-
64
- const googleConfig = this.config.google;
65
- if (!this.googleClient || !googleConfig)
66
- throw new Forbidden(`Authentication method disabled.`);
67
-
68
- if (codeOrToken === undefined)
69
- throw new Forbidden("Bad code / token");
70
-
71
- if (type === 'code') {
72
- const r = await this.googleClient.getToken(codeOrToken);
73
- return this.GoogleResponse('token', r.tokens.id_token, request);
74
- }
75
-
76
- this.config.debug && console.log(LogPrefix, "Auth via google", googleConfig);
77
-
78
- let ticket: LoginTicket;
79
- try {
80
- ticket = await this.googleClient.verifyIdToken({
81
- idToken: codeOrToken,
82
- audience: [
83
- googleConfig.web.clientId,
84
- googleConfig.android.clientId,
85
- ]
86
- });
87
- } catch (error) {
88
- throw new Forbidden(`Google denied your login attempt: ` + error.message + `. If you don't think it's normal, please contact us.`);
89
- }
90
-
91
- const payload = ticket.getPayload();
92
- if (payload === undefined)
93
- throw new Forbidden("Invalid payload");
94
- const { email, sub: google_id } = payload;
95
-
96
- if (email === undefined)
97
- throw new Forbidden("Unable to get your email address from the Google sign-in.");
98
-
99
- return await this.Auth(email, request, true);
100
-
101
- }
102
-
103
- /**
104
- * Login u
105
- * @param email Email that identifies the account to log in
106
- * @param request Used to call security-related features
107
- * @param canPass true when from 3rd party auth, we're sure the email is owned bu the current user
108
- * @param userInfo User field to update (eg: lastLogin)
109
- * @returns
110
- */
111
- public async Auth(
112
- email: string,
113
- request: ServerRequest,
114
- canPass: boolean = false,
115
- userInfo: Partial<User> = {}
116
- ): Promise<AuthResponse> {
117
-
118
- let user = await this.getData('email = ' + this.sql.esc(email));
119
- let ip: IP;
120
- let redirect: string;
121
- if (!user) { // Signup
122
-
123
- ip = await request.detect.botsAndMultiaccount();
124
-
125
- // Create user
126
- ({ user, redirect } = await this.Signup(email, request));
127
-
128
- } else if (!canPass) { // Send login email
129
-
130
- throw new Forbidden("This option is not available");
131
-
132
- // If the current IP was used to connect to another account that the current
133
- ip = await request.detect.botsAndMultiaccount(user.email);
134
-
135
- // Send email with link to /auth/token (expiration 5 min)
136
-
137
- // Route /auth/:token: check si même ip, même device
138
-
139
- } else { // Login
140
-
141
- redirect = config.logoutUrl;
142
-
143
- }
144
-
145
- /*await this.sql`
146
- INSERT INTO UserLogin SET
147
- user = ${user.email},
148
- date = NOW(),
149
- ip = ${request.ip},
150
- device = ${request.deviceString()}
151
- `.run();*/
152
-
153
- const token = request.auth.login(user.email);
154
-
155
- return { token, user, redirect };
156
-
157
- }
158
-
159
- public async Signup(email: string, request: ServerRequest, moreInfos: Partial<User> = {}) {
160
-
161
- let username = email.split('@')[0];
162
-
163
- // Prefix username if alreasy existing
164
- const duplicates = await this.sql`
165
- FROM User
166
- WHERE name REGEXP CONCAT('^', ${username}, '[0-9]*$');
167
- `.count();
168
-
169
- if (duplicates !== 0)
170
- username += duplicates;
171
-
172
- const user: Partial<User> = {
173
- email,
174
- emailHash: md5(email),
175
- name: username,
176
- referrer: request.cookies.r,
177
- utm: request.cookies.utm,
178
- ...moreInfos
179
- }
180
-
181
- // Hook
182
- if (this.beforeSignup !== undefined)
183
- await this.beforeSignup( user );
184
-
185
- // Referrer
186
- if (user.referrer !== undefined) {
187
-
188
- const refExists = await this.sql`FROM User WHERE name = ${user.referrer}`.exists();
189
- if (!refExists)
190
- user.referrer = undefined;
191
- else {
192
-
193
- await this.sql.upsert('UserStats', {
194
- user: user.referrer,
195
- date: new Date,
196
- refSignups: 1
197
- }, ['refSignups'], {
198
- upsertMode: 'increment'
199
- });
200
- }
201
- }
202
-
203
- // Create user
204
- await this.sql.insert('User', user);
205
- await this.sql.update('logs.IP', { user_name: username }, { address: request.ip });
206
-
207
- // Hook
208
- let redirect: string = '/';
209
- if (this.afterSignup !== undefined)
210
- ({ redirect } = await this.afterSignup(user));
211
-
212
- // TODO: download user avatar from gravatar
213
- // remove user.emailHash
214
-
215
- // Notif email
216
- await this.email.send({
217
- to: app.identity.author.email,
218
- subject: app.identity.name + ": New User",
219
- html: JSON.stringify(user)
220
- });
221
-
222
- // TODO
223
- // this.hook.signup(user);
224
- //Achievements.activity(user, 'just signed up', null);
225
-
226
- // Instanciation
227
- return { user, redirect };
228
-
229
- }
230
-
231
- public async setReferrer( referrer: unknown, { user, response, cookies, req, detect, request }: ServerRequest) {
232
-
233
- if (!response || user)
234
- return;
235
-
236
- // Source tracking
237
- if (!cookies.utm) {
238
-
239
- const data = req.query;
240
-
241
- const utm = [data.utm_medium, data.utm_source, data.utm_campaign]
242
- .filter(a => a !== undefined);
243
-
244
- response.cookie('utm', utm.join(','));
245
- }
246
-
247
- // Referral program
248
- if (cookies.r === undefined && typeof referrer === "string") {
249
-
250
- const conflict = await detect.conflictOfInterest( referrer, request );
251
- if (conflict)
252
- return;
253
-
254
- // Check if user exists
255
- const referrerExists = await this.sql`FROM User WHERE name = ${referrer}`.count();
256
- if (referrerExists === 0)
257
- return;
258
-
259
- // await secutity.detectCheatAttempts();
260
- // => Check IP (reprendre code existant)
261
- // => Check si IP pas déjà utilisée par un autre membre (1 compte par IP)
262
-
263
- // Tracking cookie for signup
264
- response.cookie('r', referrer);
265
-
266
- // Count the clic
267
- await this.sql.upsert('UserStats', {
268
- user: referrer,
269
- date: new Date,
270
- refClics: 1
271
- }, ['refClics'], {
272
- upsertMode: 'increment'
273
- });
274
- }
275
-
276
- }
277
- }
@@ -1,41 +0,0 @@
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
- ]
@@ -1,297 +0,0 @@
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
- }
@@ -1,6 +0,0 @@
1
- {
2
- "id": "Core/Cache",
3
- "name": "Cache",
4
- "parent": "app",
5
- "dependences": []
6
- }