@zintrust/core 0.1.12 → 0.1.14
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 +1 -1
- package/src/boot/Application.d.ts.map +1 -1
- package/src/boot/Application.js +142 -11
- package/src/cache/Cache.d.ts +13 -0
- package/src/cache/Cache.d.ts.map +1 -1
- package/src/cache/Cache.js +48 -6
- package/src/cache/CacheRuntimeRegistration.d.ts +11 -0
- package/src/cache/CacheRuntimeRegistration.d.ts.map +1 -0
- package/src/cache/CacheRuntimeRegistration.js +21 -0
- package/src/config/broadcast.d.ts +18 -4
- package/src/config/broadcast.d.ts.map +1 -1
- package/src/config/broadcast.js +60 -12
- package/src/config/cache.d.ts +1 -1
- package/src/config/cache.d.ts.map +1 -1
- package/src/config/cache.js +19 -8
- package/src/config/database.d.ts +1 -1
- package/src/config/database.d.ts.map +1 -1
- package/src/config/database.js +59 -43
- package/src/config/index.d.ts +23 -2
- package/src/config/index.d.ts.map +1 -1
- package/src/config/index.js +6 -0
- package/src/config/mail.d.ts +3 -3
- package/src/config/mail.d.ts.map +1 -1
- package/src/config/mail.js +24 -9
- package/src/config/notification.d.ts +25 -29
- package/src/config/notification.d.ts.map +1 -1
- package/src/config/notification.js +75 -20
- package/src/config/storage.d.ts +8 -0
- package/src/config/storage.d.ts.map +1 -1
- package/src/config/storage.js +29 -7
- package/src/config/type.d.ts +32 -31
- package/src/config/type.d.ts.map +1 -1
- package/src/index.d.ts +16 -3
- package/src/index.d.ts.map +1 -1
- package/src/index.js +16 -3
- package/src/node.d.ts +6 -4
- package/src/node.d.ts.map +1 -1
- package/src/node.js +6 -4
- package/src/orm/Database.d.ts.map +1 -1
- package/src/orm/Database.js +4 -0
- package/src/orm/DatabaseRuntimeRegistration.d.ts +17 -0
- package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -0
- package/src/orm/DatabaseRuntimeRegistration.js +55 -0
- package/src/orm/Model.d.ts +3 -9
- package/src/orm/Model.d.ts.map +1 -1
- package/src/orm/Model.js +9 -7
- package/src/templates/project/basic/config/broadcast.ts.tpl +79 -11
- package/src/templates/project/basic/config/cache.ts.tpl +21 -9
- package/src/templates/project/basic/config/database.ts.tpl +67 -50
- package/src/templates/project/basic/config/index.ts.tpl +6 -0
- package/src/templates/project/basic/config/mail.ts.tpl +24 -11
- package/src/templates/project/basic/config/notification.ts.tpl +98 -25
- package/src/templates/project/basic/config/storage.ts.tpl +33 -17
- package/src/templates/project/basic/config/type.ts.tpl +46 -33
- package/src/templates/project/basic/routes/health.ts.tpl +21 -11
- package/src/tools/broadcast/Broadcast.d.ts +5 -3
- package/src/tools/broadcast/Broadcast.d.ts.map +1 -1
- package/src/tools/broadcast/Broadcast.js +48 -24
- package/src/tools/broadcast/BroadcastRegistry.d.ts +15 -0
- package/src/tools/broadcast/BroadcastRegistry.d.ts.map +1 -0
- package/src/tools/broadcast/BroadcastRegistry.js +29 -0
- package/src/tools/broadcast/BroadcastRuntimeRegistration.d.ts +11 -0
- package/src/tools/broadcast/BroadcastRuntimeRegistration.d.ts.map +1 -0
- package/src/tools/broadcast/BroadcastRuntimeRegistration.js +20 -0
- package/src/tools/broadcast/index.d.ts +2 -0
- package/src/tools/broadcast/index.d.ts.map +1 -1
- package/src/tools/broadcast/index.js +2 -0
- package/src/tools/mail/Mail.d.ts +8 -0
- package/src/tools/mail/Mail.d.ts.map +1 -1
- package/src/tools/mail/Mail.js +15 -2
- package/src/tools/mail/MailDriverRegistry.d.ts +2 -0
- package/src/tools/mail/MailDriverRegistry.d.ts.map +1 -1
- package/src/tools/mail/MailDriverRegistry.js +4 -0
- package/src/tools/notification/Notification.d.ts +3 -0
- package/src/tools/notification/Notification.d.ts.map +1 -1
- package/src/tools/notification/Notification.js +3 -0
- package/src/tools/notification/NotificationChannelRegistry.d.ts +15 -0
- package/src/tools/notification/NotificationChannelRegistry.d.ts.map +1 -0
- package/src/tools/notification/NotificationChannelRegistry.js +36 -0
- package/src/tools/notification/NotificationRuntimeRegistration.d.ts +13 -0
- package/src/tools/notification/NotificationRuntimeRegistration.d.ts.map +1 -0
- package/src/tools/notification/NotificationRuntimeRegistration.js +22 -0
- package/src/tools/notification/Registry.d.ts.map +1 -1
- package/src/tools/notification/Registry.js +4 -0
- package/src/tools/notification/Service.d.ts +1 -0
- package/src/tools/notification/Service.d.ts.map +1 -1
- package/src/tools/notification/Service.js +77 -4
- package/src/tools/notification/drivers/SlackNotification.d.ts +8 -0
- package/src/tools/notification/drivers/SlackNotification.d.ts.map +1 -0
- package/src/tools/notification/drivers/SlackNotification.js +13 -0
- package/src/tools/notification/drivers/TwilioNotification.d.ts +8 -0
- package/src/tools/notification/drivers/TwilioNotification.d.ts.map +1 -0
- package/src/tools/notification/drivers/TwilioNotification.js +13 -0
- package/src/tools/queue/Queue.d.ts +1 -0
- package/src/tools/queue/Queue.d.ts.map +1 -1
- package/src/tools/queue/Queue.js +3 -0
- package/src/tools/queue/QueueRuntimeRegistration.d.ts +11 -0
- package/src/tools/queue/QueueRuntimeRegistration.d.ts.map +1 -0
- package/src/tools/queue/QueueRuntimeRegistration.js +28 -0
- package/src/tools/storage/StorageDiskRegistry.d.ts +14 -0
- package/src/tools/storage/StorageDiskRegistry.d.ts.map +1 -0
- package/src/tools/storage/StorageDiskRegistry.js +36 -0
- package/src/tools/storage/StorageRuntimeRegistration.d.ts +10 -0
- package/src/tools/storage/StorageRuntimeRegistration.d.ts.map +1 -0
- package/src/tools/storage/StorageRuntimeRegistration.js +23 -0
- package/src/tools/storage/index.d.ts +1 -0
- package/src/tools/storage/index.d.ts.map +1 -1
- package/src/tools/storage/index.js +40 -6
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../../src/boot/Application.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAmB,MAAM,8BAA8B,CAAC;AACjF,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../../../src/boot/Application.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAmB,MAAM,8BAA8B,CAAC;AACjF,OAAO,EAAE,KAAK,OAAO,EAAU,MAAM,kBAAkB,CAAC;AASxD,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,IAAI,OAAO,CAAC;IACpB,aAAa,IAAI,OAAO,CAAC;IACzB,YAAY,IAAI,OAAO,CAAC;IACxB,SAAS,IAAI,OAAO,CAAC;IACrB,cAAc,IAAI,MAAM,CAAC;IACzB,SAAS,IAAI,OAAO,CAAC;IACrB,YAAY,IAAI,iBAAiB,CAAC;IAClC,kBAAkB,IAAI,gBAAgB,CAAC;IACvC,WAAW,IAAI,MAAM,CAAC;CACvB;AAkVD;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;sBACe,MAAM,GAAG,YAAY;EA0CvC,CAAC;AAEH,eAAe,WAAW,CAAC"}
|
package/src/boot/Application.js
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* Application - Framework core entry point
|
|
3
3
|
* Handles application lifecycle, booting, and environment
|
|
4
4
|
*/
|
|
5
|
-
import { appConfig } from '../config/index.js';
|
|
5
|
+
import { appConfig, cacheConfig, databaseConfig, queueConfig, storageConfig } from '../config/index.js';
|
|
6
6
|
import { ServiceContainer } from '../container/ServiceContainer.js';
|
|
7
7
|
import { StartupHealthChecks } from '../health/StartupHealthChecks.js';
|
|
8
8
|
import { MiddlewareStack } from '../middleware/MiddlewareStack.js';
|
|
9
9
|
import { Router } from '../routing/Router.js';
|
|
10
|
+
import broadcastConfig from '../config/broadcast.js';
|
|
10
11
|
import { FeatureFlags } from '../config/features.js';
|
|
11
12
|
import { Logger } from '../config/logger.js';
|
|
13
|
+
import notificationConfig from '../config/notification.js';
|
|
12
14
|
import { StartupConfigValidator } from '../config/StartupConfigValidator.js';
|
|
13
15
|
import * as path from '../node-singletons/path.js';
|
|
14
16
|
import { pathToFileURL } from '../node-singletons/url.js';
|
|
@@ -55,6 +57,83 @@ const registerCoreInstances = (params) => {
|
|
|
55
57
|
params.container.singleton('container', params.container);
|
|
56
58
|
params.container.singleton('shutdownManager', params.shutdownManager);
|
|
57
59
|
};
|
|
60
|
+
const registerFrameworkShutdownHooks = (shutdownManager) => {
|
|
61
|
+
// Register framework-level shutdown hooks for long-lived resources
|
|
62
|
+
// ConnectionManager may not be initialized; shutdownIfInitialized is safe
|
|
63
|
+
// Use dynamic import without top-level await to avoid transforming the module into an async module
|
|
64
|
+
import('../orm/ConnectionManager.js')
|
|
65
|
+
.then((mod) => {
|
|
66
|
+
shutdownManager.add(async () => mod.ConnectionManager.shutdownIfInitialized());
|
|
67
|
+
})
|
|
68
|
+
/* c8 ignore start */
|
|
69
|
+
.catch(() => {
|
|
70
|
+
/* ignore import failures in restrictive runtimes */
|
|
71
|
+
});
|
|
72
|
+
/* c8 ignore stop */
|
|
73
|
+
import('../orm/Database.js')
|
|
74
|
+
.then((mod) => {
|
|
75
|
+
shutdownManager.add(() => mod.resetDatabase());
|
|
76
|
+
})
|
|
77
|
+
/* c8 ignore start */
|
|
78
|
+
.catch(() => {
|
|
79
|
+
/* ignore import failures in restrictive runtimes */
|
|
80
|
+
});
|
|
81
|
+
/* c8 ignore stop */
|
|
82
|
+
import('../cache/Cache.js')
|
|
83
|
+
.then((mod) => {
|
|
84
|
+
shutdownManager.add(() => mod.Cache.reset());
|
|
85
|
+
})
|
|
86
|
+
/* c8 ignore start */
|
|
87
|
+
.catch(() => {
|
|
88
|
+
/* ignore import failures in restrictive runtimes */
|
|
89
|
+
});
|
|
90
|
+
/* c8 ignore stop */
|
|
91
|
+
import('../tools/broadcast/BroadcastRegistry.js')
|
|
92
|
+
.then((mod) => {
|
|
93
|
+
shutdownManager.add(() => mod.BroadcastRegistry.reset());
|
|
94
|
+
})
|
|
95
|
+
/* c8 ignore start */
|
|
96
|
+
.catch(() => {
|
|
97
|
+
/* ignore import failures in restrictive runtimes */
|
|
98
|
+
});
|
|
99
|
+
/* c8 ignore stop */
|
|
100
|
+
import('../tools/storage/StorageDiskRegistry.js')
|
|
101
|
+
.then((mod) => {
|
|
102
|
+
shutdownManager.add(() => mod.StorageDiskRegistry.reset());
|
|
103
|
+
})
|
|
104
|
+
/* c8 ignore start */
|
|
105
|
+
.catch(() => {
|
|
106
|
+
/* ignore import failures in restrictive runtimes */
|
|
107
|
+
});
|
|
108
|
+
/* c8 ignore stop */
|
|
109
|
+
import('../tools/notification/NotificationChannelRegistry.js')
|
|
110
|
+
.then((mod) => {
|
|
111
|
+
shutdownManager.add(() => mod.NotificationChannelRegistry.reset());
|
|
112
|
+
})
|
|
113
|
+
/* c8 ignore start */
|
|
114
|
+
.catch(() => {
|
|
115
|
+
/* ignore import failures in restrictive runtimes */
|
|
116
|
+
});
|
|
117
|
+
/* c8 ignore stop */
|
|
118
|
+
import('../tools/mail/MailDriverRegistry.js')
|
|
119
|
+
.then((mod) => {
|
|
120
|
+
shutdownManager.add(() => mod.MailDriverRegistry.reset());
|
|
121
|
+
})
|
|
122
|
+
/* c8 ignore start */
|
|
123
|
+
.catch(() => {
|
|
124
|
+
/* ignore import failures in restrictive runtimes */
|
|
125
|
+
});
|
|
126
|
+
/* c8 ignore stop */
|
|
127
|
+
import('../tools/queue/Queue.js')
|
|
128
|
+
.then((mod) => {
|
|
129
|
+
shutdownManager.add(() => mod.Queue.reset());
|
|
130
|
+
})
|
|
131
|
+
/* c8 ignore start */
|
|
132
|
+
.catch(() => {
|
|
133
|
+
/* ignore import failures in restrictive runtimes */
|
|
134
|
+
});
|
|
135
|
+
/* c8 ignore stop */
|
|
136
|
+
};
|
|
58
137
|
const tryImportRoutesFromAppBase = async (resolvedBasePath) => {
|
|
59
138
|
if (resolvedBasePath === '')
|
|
60
139
|
return undefined;
|
|
@@ -126,6 +205,67 @@ const createLifecycle = (params) => {
|
|
|
126
205
|
StartupConfigValidator.assertValid();
|
|
127
206
|
FeatureFlags.initialize();
|
|
128
207
|
await StartupHealthChecks.assertHealthy();
|
|
208
|
+
// Register ORM database connections from runtime config.
|
|
209
|
+
// This makes every `databaseConfig.connections[name]` available via `useDatabase(undefined, name)`.
|
|
210
|
+
// The configured default is also registered as 'default'.
|
|
211
|
+
try {
|
|
212
|
+
const { registerDatabasesFromRuntimeConfig } = await import('../orm/DatabaseRuntimeRegistration.js');
|
|
213
|
+
registerDatabasesFromRuntimeConfig(databaseConfig);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// best-effort: ignore in restrictive runtimes
|
|
217
|
+
}
|
|
218
|
+
// Register queue drivers from runtime config.
|
|
219
|
+
// Ensures default drivers like `sync` are available without manual registration.
|
|
220
|
+
try {
|
|
221
|
+
const { registerQueuesFromRuntimeConfig } = await import('../tools/queue/QueueRuntimeRegistration.js');
|
|
222
|
+
registerQueuesFromRuntimeConfig(queueConfig);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// best-effort: ignore in restrictive runtimes
|
|
226
|
+
}
|
|
227
|
+
// Register cache driver factories from runtime config.
|
|
228
|
+
// Ensures built-in drivers are available via the driver registry.
|
|
229
|
+
try {
|
|
230
|
+
const { registerCachesFromRuntimeConfig } = await import('../cache/CacheRuntimeRegistration.js');
|
|
231
|
+
registerCachesFromRuntimeConfig(cacheConfig);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// best-effort: ignore in restrictive runtimes
|
|
235
|
+
}
|
|
236
|
+
// Register broadcasters from runtime config.
|
|
237
|
+
// Ensures named broadcasters are available and unknown names throw when selected.
|
|
238
|
+
try {
|
|
239
|
+
const { registerBroadcastersFromRuntimeConfig } = await import('../tools/broadcast/BroadcastRuntimeRegistration.js');
|
|
240
|
+
registerBroadcastersFromRuntimeConfig({
|
|
241
|
+
default: broadcastConfig.default,
|
|
242
|
+
drivers: broadcastConfig.drivers,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// best-effort: ignore in restrictive runtimes
|
|
247
|
+
}
|
|
248
|
+
// Register storage disks from runtime config.
|
|
249
|
+
// Ensures named disks are available and 'default' is a reserved alias.
|
|
250
|
+
try {
|
|
251
|
+
const { registerDisksFromRuntimeConfig } = await import('../tools/storage/StorageRuntimeRegistration.js');
|
|
252
|
+
registerDisksFromRuntimeConfig(storageConfig);
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// best-effort: ignore in restrictive runtimes
|
|
256
|
+
}
|
|
257
|
+
// Register notification channels from runtime config.
|
|
258
|
+
// Enables selecting named channels and reserves the `default` alias.
|
|
259
|
+
try {
|
|
260
|
+
const { registerNotificationChannelsFromRuntimeConfig } = await import('../tools/notification/NotificationRuntimeRegistration.js');
|
|
261
|
+
registerNotificationChannelsFromRuntimeConfig({
|
|
262
|
+
default: notificationConfig.default,
|
|
263
|
+
drivers: notificationConfig.drivers,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// best-effort: ignore in restrictive runtimes
|
|
268
|
+
}
|
|
129
269
|
await initializeArtifactDirectories(params.resolvedBasePath);
|
|
130
270
|
await registerRoutes(params.resolvedBasePath, params.router);
|
|
131
271
|
// Register service providers
|
|
@@ -164,16 +304,7 @@ export const Application = Object.freeze({
|
|
|
164
304
|
let booted = false;
|
|
165
305
|
registerCorePaths(container, resolvedBasePath, joinFromBase);
|
|
166
306
|
registerCoreInstances({ container, environment, router, middlewareStack, shutdownManager });
|
|
167
|
-
|
|
168
|
-
// ConnectionManager may not be initialized; shutdownIfInitialized is safe
|
|
169
|
-
// Use dynamic import without top-level await to avoid transforming the module into an async module
|
|
170
|
-
import('../orm/ConnectionManager.js')
|
|
171
|
-
.then(({ ConnectionManager }) => {
|
|
172
|
-
shutdownManager.add(async () => ConnectionManager.shutdownIfInitialized());
|
|
173
|
-
})
|
|
174
|
-
.catch(() => {
|
|
175
|
-
/* ignore import failures in restrictive runtimes */
|
|
176
|
-
});
|
|
307
|
+
registerFrameworkShutdownHooks(shutdownManager);
|
|
177
308
|
const { boot, shutdown } = createLifecycle({
|
|
178
309
|
environment,
|
|
179
310
|
resolvedBasePath,
|
package/src/cache/Cache.d.ts
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
* Sealed namespace pattern - all exports through Cache namespace
|
|
5
5
|
*/
|
|
6
6
|
import { CacheDriver } from './CacheDriver';
|
|
7
|
+
type CacheStore = Readonly<{
|
|
8
|
+
get: <T>(key: string) => Promise<T | null>;
|
|
9
|
+
set: <T>(key: string, value: T, ttl?: number) => Promise<void>;
|
|
10
|
+
delete: (key: string) => Promise<void>;
|
|
11
|
+
clear: () => Promise<void>;
|
|
12
|
+
has: (key: string) => Promise<boolean>;
|
|
13
|
+
getDriver: () => CacheDriver;
|
|
14
|
+
}>;
|
|
7
15
|
export declare const Cache: Readonly<{
|
|
8
16
|
get: <T>(key: string) => Promise<T | null>;
|
|
9
17
|
set: <T>(key: string, value: T, ttl?: number) => Promise<void>;
|
|
@@ -11,6 +19,8 @@ export declare const Cache: Readonly<{
|
|
|
11
19
|
clear: () => Promise<void>;
|
|
12
20
|
has: (key: string) => Promise<boolean>;
|
|
13
21
|
getDriver: () => CacheDriver;
|
|
22
|
+
store: (name?: string) => CacheStore;
|
|
23
|
+
reset: () => void;
|
|
14
24
|
}>;
|
|
15
25
|
/**
|
|
16
26
|
* Helper alias for cache
|
|
@@ -22,5 +32,8 @@ export declare const cache: Readonly<{
|
|
|
22
32
|
clear: () => Promise<void>;
|
|
23
33
|
has: (key: string) => Promise<boolean>;
|
|
24
34
|
getDriver: () => CacheDriver;
|
|
35
|
+
store: (name?: string) => CacheStore;
|
|
36
|
+
reset: () => void;
|
|
25
37
|
}>;
|
|
38
|
+
export {};
|
|
26
39
|
//# sourceMappingURL=Cache.d.ts.map
|
package/src/cache/Cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Cache.d.ts","sourceRoot":"","sources":["../../../src/cache/Cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Cache.d.ts","sourceRoot":"","sources":["../../../src/cache/Cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAmHjD,KAAK,UAAU,GAAG,QAAQ,CAAC;IACzB,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3C,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,SAAS,EAAE,MAAM,WAAW,CAAC;CAC9B,CAAC,CAAC;AA0CH,eAAO,MAAM,KAAK;UA1FC,CAAC,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;UAQlC,CAAC,OAAO,MAAM,SAAS,CAAC,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;kBAOjD,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;iBAOtB,OAAO,CAAC,IAAI,CAAC;eAOb,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;qBAQ3B,WAAW;mBAaX,MAAM,KAAG,UAAU;iBAmCvB,IAAI;EAcpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,KAAK;UAxGC,CAAC,OAAO,MAAM,KAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;UAQlC,CAAC,OAAO,MAAM,SAAS,CAAC,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;kBAOjD,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;iBAOtB,OAAO,CAAC,IAAI,CAAC;eAOb,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;qBAQ3B,WAAW;mBAaX,MAAM,KAAG,UAAU;iBAmCvB,IAAI;EAmBI,CAAC"}
|
package/src/cache/Cache.js
CHANGED
|
@@ -11,7 +11,7 @@ import { MongoDriver } from './drivers/MongoDriver.js';
|
|
|
11
11
|
import { RedisDriver } from './drivers/RedisDriver.js';
|
|
12
12
|
import { cacheConfig } from '../config/cache.js';
|
|
13
13
|
import { ErrorFactory } from '../exceptions/ZintrustError.js';
|
|
14
|
-
|
|
14
|
+
const instances = new Map();
|
|
15
15
|
function buildDriver(driver) {
|
|
16
16
|
const maybeCreate = driver.create;
|
|
17
17
|
if (typeof maybeCreate === 'function') {
|
|
@@ -22,8 +22,8 @@ function buildDriver(driver) {
|
|
|
22
22
|
}
|
|
23
23
|
throw ErrorFactory.createGeneralError('Invalid cache driver export');
|
|
24
24
|
}
|
|
25
|
-
function resolveDriver() {
|
|
26
|
-
const driverConfig = cacheConfig.getDriver();
|
|
25
|
+
function resolveDriver(storeName) {
|
|
26
|
+
const driverConfig = cacheConfig.getDriver(storeName);
|
|
27
27
|
const externalFactory = CacheDriverRegistry.get(driverConfig.driver);
|
|
28
28
|
if (externalFactory !== undefined) {
|
|
29
29
|
return externalFactory(driverConfig);
|
|
@@ -43,9 +43,18 @@ function resolveDriver() {
|
|
|
43
43
|
return buildDriver(MemoryDriver);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
function getDriverInstance() {
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
function getDriverInstance(storeName) {
|
|
47
|
+
const normalizedSelection = String(storeName ?? '')
|
|
48
|
+
.trim()
|
|
49
|
+
.toLowerCase();
|
|
50
|
+
const resolvedKey = normalizedSelection.length > 0 ? normalizedSelection : 'default';
|
|
51
|
+
const existing = instances.get(resolvedKey);
|
|
52
|
+
if (existing !== undefined)
|
|
53
|
+
return existing;
|
|
54
|
+
const selector = resolvedKey === 'default' ? undefined : resolvedKey;
|
|
55
|
+
const created = resolveDriver(selector);
|
|
56
|
+
instances.set(resolvedKey, created);
|
|
57
|
+
return created;
|
|
49
58
|
}
|
|
50
59
|
/**
|
|
51
60
|
* Get an item from the cache
|
|
@@ -85,6 +94,37 @@ const has = async (key) => {
|
|
|
85
94
|
const getDriver = () => {
|
|
86
95
|
return getDriverInstance();
|
|
87
96
|
};
|
|
97
|
+
const store = (name) => {
|
|
98
|
+
const getFromStore = async (key) => {
|
|
99
|
+
return getDriverInstance(name).get(key);
|
|
100
|
+
};
|
|
101
|
+
const setInStore = async (key, value, ttl) => {
|
|
102
|
+
await getDriverInstance(name).set(key, value, ttl);
|
|
103
|
+
};
|
|
104
|
+
const delFromStore = async (key) => {
|
|
105
|
+
await getDriverInstance(name).delete(key);
|
|
106
|
+
};
|
|
107
|
+
const clearStore = async () => {
|
|
108
|
+
await getDriverInstance(name).clear();
|
|
109
|
+
};
|
|
110
|
+
const hasInStore = async (key) => {
|
|
111
|
+
return getDriverInstance(name).has(key);
|
|
112
|
+
};
|
|
113
|
+
const getStoreDriver = () => {
|
|
114
|
+
return getDriverInstance(name);
|
|
115
|
+
};
|
|
116
|
+
return Object.freeze({
|
|
117
|
+
get: getFromStore,
|
|
118
|
+
set: setInStore,
|
|
119
|
+
delete: delFromStore,
|
|
120
|
+
clear: clearStore,
|
|
121
|
+
has: hasInStore,
|
|
122
|
+
getDriver: getStoreDriver,
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
const reset = () => {
|
|
126
|
+
instances.clear();
|
|
127
|
+
};
|
|
88
128
|
// Sealed namespace with cache functionality
|
|
89
129
|
export const Cache = Object.freeze({
|
|
90
130
|
get,
|
|
@@ -93,6 +133,8 @@ export const Cache = Object.freeze({
|
|
|
93
133
|
clear,
|
|
94
134
|
has,
|
|
95
135
|
getDriver,
|
|
136
|
+
store,
|
|
137
|
+
reset,
|
|
96
138
|
});
|
|
97
139
|
/**
|
|
98
140
|
* Helper alias for cache
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CacheConfig } from '../config/cache';
|
|
2
|
+
/**
|
|
3
|
+
* Register cache drivers from runtime config.
|
|
4
|
+
*
|
|
5
|
+
* This follows the framework's config-driven availability pattern:
|
|
6
|
+
* - Built-in driver factories are registered so config entries can reference them.
|
|
7
|
+
* - Named cache stores are still resolved from `cacheConfig.drivers[storeName]`.
|
|
8
|
+
* - Unknown store names throw when explicitly selected via `cacheConfig.getDriver(name)`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerCachesFromRuntimeConfig(_config: CacheConfig): void;
|
|
11
|
+
//# sourceMappingURL=CacheRuntimeRegistration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CacheRuntimeRegistration.d.ts","sourceRoot":"","sources":["../../../src/cache/CacheRuntimeRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AASjD;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAM1E"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CacheDriverRegistry } from './CacheDriverRegistry.js';
|
|
2
|
+
import { KVDriver } from './drivers/KVDriver.js';
|
|
3
|
+
import { KVRemoteDriver } from './drivers/KVRemoteDriver.js';
|
|
4
|
+
import { MemoryDriver } from './drivers/MemoryDriver.js';
|
|
5
|
+
import { MongoDriver } from './drivers/MongoDriver.js';
|
|
6
|
+
import { RedisDriver } from './drivers/RedisDriver.js';
|
|
7
|
+
/**
|
|
8
|
+
* Register cache drivers from runtime config.
|
|
9
|
+
*
|
|
10
|
+
* This follows the framework's config-driven availability pattern:
|
|
11
|
+
* - Built-in driver factories are registered so config entries can reference them.
|
|
12
|
+
* - Named cache stores are still resolved from `cacheConfig.drivers[storeName]`.
|
|
13
|
+
* - Unknown store names throw when explicitly selected via `cacheConfig.getDriver(name)`.
|
|
14
|
+
*/
|
|
15
|
+
export function registerCachesFromRuntimeConfig(_config) {
|
|
16
|
+
CacheDriverRegistry.register('memory', () => MemoryDriver.create());
|
|
17
|
+
CacheDriverRegistry.register('redis', () => RedisDriver.create());
|
|
18
|
+
CacheDriverRegistry.register('mongodb', () => MongoDriver.create());
|
|
19
|
+
CacheDriverRegistry.register('kv', () => KVDriver.create());
|
|
20
|
+
CacheDriverRegistry.register('kv-remote', () => KVRemoteDriver.create());
|
|
21
|
+
}
|
|
@@ -4,19 +4,33 @@
|
|
|
4
4
|
* Centralizes broadcast driver selection and provider env mappings.
|
|
5
5
|
* Driver selection must be dynamic (tests may mutate process.env).
|
|
6
6
|
*/
|
|
7
|
-
import { KnownBroadcastDriverConfig } from './type';
|
|
7
|
+
import { InMemoryBroadcastDriverConfig, KnownBroadcastDriverConfig, PusherBroadcastDriverConfig, RedisBroadcastDriverConfig, RedisHttpsBroadcastDriverConfig } from './type';
|
|
8
8
|
declare const _default: Readonly<{
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Default broadcaster name (normalized).
|
|
11
|
+
*/
|
|
12
|
+
readonly default: string;
|
|
13
|
+
/**
|
|
14
|
+
* Broadcast drivers.
|
|
11
15
|
*
|
|
12
|
-
*
|
|
16
|
+
* You may add custom named broadcasters (e.g. `ops`, `billing`) that point to any
|
|
17
|
+
* known driver config.
|
|
18
|
+
*/
|
|
19
|
+
readonly drivers: {
|
|
20
|
+
readonly inmemory: InMemoryBroadcastDriverConfig;
|
|
21
|
+
readonly pusher: PusherBroadcastDriverConfig;
|
|
22
|
+
readonly redis: RedisBroadcastDriverConfig;
|
|
23
|
+
readonly redishttps: RedisHttpsBroadcastDriverConfig;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Normalized broadcast driver name for the default broadcaster.
|
|
13
27
|
*/
|
|
14
28
|
readonly getDriverName: () => string;
|
|
15
29
|
/**
|
|
16
30
|
* Get a config object for the currently selected driver.
|
|
17
31
|
* Defaults to inmemory for unknown/unsupported names.
|
|
18
32
|
*/
|
|
19
|
-
readonly getDriverConfig: () => KnownBroadcastDriverConfig;
|
|
33
|
+
readonly getDriverConfig: (name?: string) => KnownBroadcastDriverConfig;
|
|
20
34
|
}>;
|
|
21
35
|
export default _default;
|
|
22
36
|
//# sourceMappingURL=broadcast.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../../src/config/broadcast.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../../src/config/broadcast.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAGL,6BAA6B,EAC7B,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC1B,+BAA+B,EAChC,MAAM,cAAc,CAAC;;IA0EpB;;OAEG;sBACY,MAAM;IAIrB;;;;;OAKG;;2BAEe,6BAA6B;;;;;IAc/C;;OAEG;kCACc,MAAM;IAIvB;;;OAGG;sCACoB,MAAM,KAAG,0BAA0B;;AAK5D,wBAAiD"}
|
package/src/config/broadcast.js
CHANGED
|
@@ -5,7 +5,19 @@
|
|
|
5
5
|
* Driver selection must be dynamic (tests may mutate process.env).
|
|
6
6
|
*/
|
|
7
7
|
import { Env } from './env.js';
|
|
8
|
+
import { ErrorFactory } from '../exceptions/ZintrustError.js';
|
|
8
9
|
const normalizeDriverName = (value) => value.trim().toLowerCase();
|
|
10
|
+
const hasOwn = (obj, key) => {
|
|
11
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
12
|
+
};
|
|
13
|
+
const getDefaultBroadcaster = (drivers) => {
|
|
14
|
+
const value = normalizeDriverName(Env.get('BROADCAST_DRIVER', 'inmemory'));
|
|
15
|
+
if (value.length > 0 && hasOwn(drivers, value)) {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
// Backwards-compatible default.
|
|
19
|
+
return hasOwn(drivers, 'inmemory') ? 'inmemory' : (Object.keys(drivers)[0] ?? 'inmemory');
|
|
20
|
+
};
|
|
9
21
|
const getPusherConfig = () => ({
|
|
10
22
|
driver: 'pusher',
|
|
11
23
|
appId: Env.get('PUSHER_APP_ID', ''),
|
|
@@ -27,28 +39,64 @@ const getRedisHttpsConfig = () => ({
|
|
|
27
39
|
token: Env.get('REDIS_HTTPS_TOKEN', ''),
|
|
28
40
|
channelPrefix: Env.get('BROADCAST_CHANNEL_PREFIX', 'broadcast:'),
|
|
29
41
|
});
|
|
42
|
+
const getBroadcastDriver = (config, name) => {
|
|
43
|
+
const selected = normalizeDriverName(String(name ?? config.default));
|
|
44
|
+
const broadcasterName = selected === 'default' ? normalizeDriverName(config.default) : selected;
|
|
45
|
+
const isExplicitSelection = name !== undefined &&
|
|
46
|
+
String(name).trim().length > 0 &&
|
|
47
|
+
normalizeDriverName(String(name)) !== 'default';
|
|
48
|
+
if (broadcasterName.length > 0 && hasOwn(config.drivers, broadcasterName)) {
|
|
49
|
+
const resolved = config.drivers[broadcasterName];
|
|
50
|
+
if (resolved !== undefined)
|
|
51
|
+
return resolved;
|
|
52
|
+
}
|
|
53
|
+
if (isExplicitSelection) {
|
|
54
|
+
throw ErrorFactory.createConfigError(`Broadcast driver not configured: ${broadcasterName}`);
|
|
55
|
+
}
|
|
56
|
+
const fallback = config.drivers['inmemory'] ?? Object.values(config.drivers)[0];
|
|
57
|
+
if (fallback !== undefined)
|
|
58
|
+
return fallback;
|
|
59
|
+
throw ErrorFactory.createConfigError('No broadcast drivers are configured');
|
|
60
|
+
};
|
|
30
61
|
const broadcastConfigObj = {
|
|
31
62
|
/**
|
|
32
|
-
*
|
|
63
|
+
* Default broadcaster name (normalized).
|
|
64
|
+
*/
|
|
65
|
+
get default() {
|
|
66
|
+
return getDefaultBroadcaster(this.drivers);
|
|
67
|
+
},
|
|
68
|
+
/**
|
|
69
|
+
* Broadcast drivers.
|
|
33
70
|
*
|
|
34
|
-
*
|
|
71
|
+
* You may add custom named broadcasters (e.g. `ops`, `billing`) that point to any
|
|
72
|
+
* known driver config.
|
|
73
|
+
*/
|
|
74
|
+
drivers: {
|
|
75
|
+
get inmemory() {
|
|
76
|
+
return { driver: 'inmemory' };
|
|
77
|
+
},
|
|
78
|
+
get pusher() {
|
|
79
|
+
return getPusherConfig();
|
|
80
|
+
},
|
|
81
|
+
get redis() {
|
|
82
|
+
return getRedisConfig();
|
|
83
|
+
},
|
|
84
|
+
get redishttps() {
|
|
85
|
+
return getRedisHttpsConfig();
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
/**
|
|
89
|
+
* Normalized broadcast driver name for the default broadcaster.
|
|
35
90
|
*/
|
|
36
91
|
getDriverName() {
|
|
37
|
-
return normalizeDriverName(
|
|
92
|
+
return normalizeDriverName(this.default);
|
|
38
93
|
},
|
|
39
94
|
/**
|
|
40
95
|
* Get a config object for the currently selected driver.
|
|
41
96
|
* Defaults to inmemory for unknown/unsupported names.
|
|
42
97
|
*/
|
|
43
|
-
getDriverConfig() {
|
|
44
|
-
|
|
45
|
-
if (driver === 'pusher')
|
|
46
|
-
return getPusherConfig();
|
|
47
|
-
if (driver === 'redis')
|
|
48
|
-
return getRedisConfig();
|
|
49
|
-
if (driver === 'redishttps')
|
|
50
|
-
return getRedisHttpsConfig();
|
|
51
|
-
return { driver: 'inmemory' };
|
|
98
|
+
getDriverConfig(name) {
|
|
99
|
+
return getBroadcastDriver(this, name);
|
|
52
100
|
},
|
|
53
101
|
};
|
|
54
102
|
export default Object.freeze(broadcastConfigObj);
|
package/src/config/cache.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAoB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAoB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AA+EnE,eAAO,MAAM,WAAW;IArDtB;;OAEG;;IAGH;;OAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4BH;;OAEG;qBACc,MAAM,GAAG,iBAAiB;IAI3C;;OAEG;;IAGH;;OAEG;;EAImD,CAAC;AACzD,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC"}
|
package/src/config/cache.js
CHANGED
|
@@ -4,13 +4,24 @@
|
|
|
4
4
|
* Sealed namespace for immutability
|
|
5
5
|
*/
|
|
6
6
|
import { Env } from './env.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
import { ErrorFactory } from '../exceptions/ZintrustError.js';
|
|
8
|
+
const getCacheDriver = (config, name) => {
|
|
9
|
+
const selected = String(name ?? config.default).trim();
|
|
10
|
+
const storeName = selected === 'default' ? String(config.default).trim() : selected;
|
|
11
|
+
const isExplicitSelection = name !== undefined && String(name).trim().length > 0 && String(name).trim() !== 'default';
|
|
12
|
+
if (storeName.length > 0 && Object.hasOwn(config.drivers, storeName)) {
|
|
13
|
+
const resolved = config.drivers[storeName];
|
|
14
|
+
if (resolved !== undefined)
|
|
15
|
+
return resolved;
|
|
12
16
|
}
|
|
13
|
-
|
|
17
|
+
if (isExplicitSelection) {
|
|
18
|
+
throw ErrorFactory.createConfigError(`Cache store not configured: ${storeName}`);
|
|
19
|
+
}
|
|
20
|
+
// Backwards-compatible fallback.
|
|
21
|
+
const fallback = config.drivers['memory'] ?? Object.values(config.drivers)[0];
|
|
22
|
+
if (fallback !== undefined)
|
|
23
|
+
return fallback;
|
|
24
|
+
throw ErrorFactory.createConfigError('No cache stores are configured');
|
|
14
25
|
};
|
|
15
26
|
const cacheConfigObj = {
|
|
16
27
|
/**
|
|
@@ -49,8 +60,8 @@ const cacheConfigObj = {
|
|
|
49
60
|
/**
|
|
50
61
|
* Get cache driver config
|
|
51
62
|
*/
|
|
52
|
-
getDriver() {
|
|
53
|
-
return getCacheDriver(this);
|
|
63
|
+
getDriver(name) {
|
|
64
|
+
return getCacheDriver(this, name);
|
|
54
65
|
},
|
|
55
66
|
/**
|
|
56
67
|
* Key prefix for all cache keys
|
package/src/config/database.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/config/database.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/config/database.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAuB,MAAM,cAAc,CAAC;AAkHlG,eAAO,MAAM,cAAc;IAzCzB;;OAEG;;IAGH;;OAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGH;;OAEG;wBACiB,mBAAmB,GAAG,wBAAwB;IAIlE;;OAEG;;;;;IAMH;;OAEG;;;;;IAMH;;OAEG;;;;EAMyD,CAAC;AAC/D,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC"}
|