@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.
Files changed (108) hide show
  1. package/package.json +1 -1
  2. package/src/boot/Application.d.ts.map +1 -1
  3. package/src/boot/Application.js +142 -11
  4. package/src/cache/Cache.d.ts +13 -0
  5. package/src/cache/Cache.d.ts.map +1 -1
  6. package/src/cache/Cache.js +48 -6
  7. package/src/cache/CacheRuntimeRegistration.d.ts +11 -0
  8. package/src/cache/CacheRuntimeRegistration.d.ts.map +1 -0
  9. package/src/cache/CacheRuntimeRegistration.js +21 -0
  10. package/src/config/broadcast.d.ts +18 -4
  11. package/src/config/broadcast.d.ts.map +1 -1
  12. package/src/config/broadcast.js +60 -12
  13. package/src/config/cache.d.ts +1 -1
  14. package/src/config/cache.d.ts.map +1 -1
  15. package/src/config/cache.js +19 -8
  16. package/src/config/database.d.ts +1 -1
  17. package/src/config/database.d.ts.map +1 -1
  18. package/src/config/database.js +59 -43
  19. package/src/config/index.d.ts +23 -2
  20. package/src/config/index.d.ts.map +1 -1
  21. package/src/config/index.js +6 -0
  22. package/src/config/mail.d.ts +3 -3
  23. package/src/config/mail.d.ts.map +1 -1
  24. package/src/config/mail.js +24 -9
  25. package/src/config/notification.d.ts +25 -29
  26. package/src/config/notification.d.ts.map +1 -1
  27. package/src/config/notification.js +75 -20
  28. package/src/config/storage.d.ts +8 -0
  29. package/src/config/storage.d.ts.map +1 -1
  30. package/src/config/storage.js +29 -7
  31. package/src/config/type.d.ts +32 -31
  32. package/src/config/type.d.ts.map +1 -1
  33. package/src/index.d.ts +16 -3
  34. package/src/index.d.ts.map +1 -1
  35. package/src/index.js +16 -3
  36. package/src/node.d.ts +6 -4
  37. package/src/node.d.ts.map +1 -1
  38. package/src/node.js +6 -4
  39. package/src/orm/Database.d.ts.map +1 -1
  40. package/src/orm/Database.js +4 -0
  41. package/src/orm/DatabaseRuntimeRegistration.d.ts +17 -0
  42. package/src/orm/DatabaseRuntimeRegistration.d.ts.map +1 -0
  43. package/src/orm/DatabaseRuntimeRegistration.js +55 -0
  44. package/src/orm/Model.d.ts +3 -9
  45. package/src/orm/Model.d.ts.map +1 -1
  46. package/src/orm/Model.js +9 -7
  47. package/src/templates/project/basic/config/broadcast.ts.tpl +79 -11
  48. package/src/templates/project/basic/config/cache.ts.tpl +21 -9
  49. package/src/templates/project/basic/config/database.ts.tpl +67 -50
  50. package/src/templates/project/basic/config/index.ts.tpl +6 -0
  51. package/src/templates/project/basic/config/mail.ts.tpl +24 -11
  52. package/src/templates/project/basic/config/notification.ts.tpl +98 -25
  53. package/src/templates/project/basic/config/storage.ts.tpl +33 -17
  54. package/src/templates/project/basic/config/type.ts.tpl +46 -33
  55. package/src/templates/project/basic/routes/health.ts.tpl +21 -11
  56. package/src/tools/broadcast/Broadcast.d.ts +5 -3
  57. package/src/tools/broadcast/Broadcast.d.ts.map +1 -1
  58. package/src/tools/broadcast/Broadcast.js +48 -24
  59. package/src/tools/broadcast/BroadcastRegistry.d.ts +15 -0
  60. package/src/tools/broadcast/BroadcastRegistry.d.ts.map +1 -0
  61. package/src/tools/broadcast/BroadcastRegistry.js +29 -0
  62. package/src/tools/broadcast/BroadcastRuntimeRegistration.d.ts +11 -0
  63. package/src/tools/broadcast/BroadcastRuntimeRegistration.d.ts.map +1 -0
  64. package/src/tools/broadcast/BroadcastRuntimeRegistration.js +20 -0
  65. package/src/tools/broadcast/index.d.ts +2 -0
  66. package/src/tools/broadcast/index.d.ts.map +1 -1
  67. package/src/tools/broadcast/index.js +2 -0
  68. package/src/tools/mail/Mail.d.ts +8 -0
  69. package/src/tools/mail/Mail.d.ts.map +1 -1
  70. package/src/tools/mail/Mail.js +15 -2
  71. package/src/tools/mail/MailDriverRegistry.d.ts +2 -0
  72. package/src/tools/mail/MailDriverRegistry.d.ts.map +1 -1
  73. package/src/tools/mail/MailDriverRegistry.js +4 -0
  74. package/src/tools/notification/Notification.d.ts +3 -0
  75. package/src/tools/notification/Notification.d.ts.map +1 -1
  76. package/src/tools/notification/Notification.js +3 -0
  77. package/src/tools/notification/NotificationChannelRegistry.d.ts +15 -0
  78. package/src/tools/notification/NotificationChannelRegistry.d.ts.map +1 -0
  79. package/src/tools/notification/NotificationChannelRegistry.js +36 -0
  80. package/src/tools/notification/NotificationRuntimeRegistration.d.ts +13 -0
  81. package/src/tools/notification/NotificationRuntimeRegistration.d.ts.map +1 -0
  82. package/src/tools/notification/NotificationRuntimeRegistration.js +22 -0
  83. package/src/tools/notification/Registry.d.ts.map +1 -1
  84. package/src/tools/notification/Registry.js +4 -0
  85. package/src/tools/notification/Service.d.ts +1 -0
  86. package/src/tools/notification/Service.d.ts.map +1 -1
  87. package/src/tools/notification/Service.js +77 -4
  88. package/src/tools/notification/drivers/SlackNotification.d.ts +8 -0
  89. package/src/tools/notification/drivers/SlackNotification.d.ts.map +1 -0
  90. package/src/tools/notification/drivers/SlackNotification.js +13 -0
  91. package/src/tools/notification/drivers/TwilioNotification.d.ts +8 -0
  92. package/src/tools/notification/drivers/TwilioNotification.d.ts.map +1 -0
  93. package/src/tools/notification/drivers/TwilioNotification.js +13 -0
  94. package/src/tools/queue/Queue.d.ts +1 -0
  95. package/src/tools/queue/Queue.d.ts.map +1 -1
  96. package/src/tools/queue/Queue.js +3 -0
  97. package/src/tools/queue/QueueRuntimeRegistration.d.ts +11 -0
  98. package/src/tools/queue/QueueRuntimeRegistration.d.ts.map +1 -0
  99. package/src/tools/queue/QueueRuntimeRegistration.js +28 -0
  100. package/src/tools/storage/StorageDiskRegistry.d.ts +14 -0
  101. package/src/tools/storage/StorageDiskRegistry.d.ts.map +1 -0
  102. package/src/tools/storage/StorageDiskRegistry.js +36 -0
  103. package/src/tools/storage/StorageRuntimeRegistration.d.ts +10 -0
  104. package/src/tools/storage/StorageRuntimeRegistration.d.ts.map +1 -0
  105. package/src/tools/storage/StorageRuntimeRegistration.js +23 -0
  106. package/src/tools/storage/index.d.ts +1 -0
  107. package/src/tools/storage/index.d.ts.map +1 -1
  108. package/src/tools/storage/index.js +40 -6
@@ -1,16 +1,89 @@
1
+ import notificationConfig from '../../config/notification.js';
1
2
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
2
3
  import { NotificationConfig } from './config.js';
4
+ import { ConsoleDriver } from './drivers/Console.js';
5
+ import { SlackDriver } from './drivers/Slack.js';
6
+ import { TwilioDriver } from './drivers/Twilio.js';
7
+ import { NotificationChannelRegistry } from './NotificationChannelRegistry.js';
3
8
  import { NotificationRegistry } from './Registry.js';
9
+ const assertValidRecipientAndMessage = (recipient, message) => {
10
+ if (typeof recipient !== 'string' || recipient.trim() === '') {
11
+ throw ErrorFactory.createValidationError('Recipient required');
12
+ }
13
+ if (typeof message !== 'string' || message.trim() === '') {
14
+ throw ErrorFactory.createValidationError('Message required');
15
+ }
16
+ };
17
+ const resolveChannelConfig = (channelName) => {
18
+ const selected = String(channelName ?? '').trim();
19
+ const hasSelection = selected.length > 0;
20
+ return hasSelection && NotificationChannelRegistry.has(selected)
21
+ ? NotificationChannelRegistry.get(selected)
22
+ : notificationConfig.getDriverConfig(selected);
23
+ };
24
+ const sendTermii = async (cfg, recipient, message, options) => {
25
+ const apiKey = String(cfg.apiKey ?? '');
26
+ if (apiKey.trim() === '') {
27
+ throw ErrorFactory.createConfigError('TERMII_API_KEY is not configured');
28
+ }
29
+ const url = String(cfg.endpoint ?? '').trim();
30
+ if (url === '') {
31
+ throw ErrorFactory.createConfigError('TERMII_ENDPOINT is not configured');
32
+ }
33
+ const payload = {
34
+ to: recipient,
35
+ from: cfg.sender,
36
+ sms: message,
37
+ api_key: apiKey,
38
+ ...options,
39
+ };
40
+ const res = await globalThis.fetch(url, {
41
+ method: 'POST',
42
+ headers: { 'Content-Type': 'application/json' },
43
+ body: JSON.stringify(payload),
44
+ });
45
+ if (!res.ok) {
46
+ const txt = await res.text().catch(() => '');
47
+ throw ErrorFactory.createTryCatchError(`Termii request failed (${res.status})`, {
48
+ status: res.status,
49
+ body: txt,
50
+ });
51
+ }
52
+ return res.json().catch(() => ({}));
53
+ };
4
54
  export const NotificationService = Object.freeze({
5
55
  async send(recipient, message, options = {}) {
6
- if (!recipient || typeof recipient !== 'string')
7
- throw ErrorFactory.createValidationError('Recipient required');
8
- if (!message || typeof message !== 'string')
9
- throw ErrorFactory.createValidationError('Message required');
56
+ assertValidRecipientAndMessage(recipient, message);
10
57
  const driverName = NotificationConfig.getDriver();
11
58
  const driver = NotificationRegistry.get(driverName);
12
59
  return driver.send(recipient, message, options);
13
60
  },
61
+ async sendVia(channelName, recipient, message, options = {}) {
62
+ assertValidRecipientAndMessage(recipient, message);
63
+ const cfg = resolveChannelConfig(channelName);
64
+ switch (cfg.driver) {
65
+ case 'console':
66
+ return ConsoleDriver.send(recipient, message, options);
67
+ case 'slack': {
68
+ const slackCfg = cfg;
69
+ const payload = { text: message, ...options };
70
+ return SlackDriver.send({ webhookUrl: slackCfg.webhookUrl }, payload);
71
+ }
72
+ case 'twilio': {
73
+ const twilioCfg = cfg;
74
+ return TwilioDriver.send({
75
+ accountSid: twilioCfg.accountSid,
76
+ authToken: twilioCfg.authToken,
77
+ from: twilioCfg.fromNumber,
78
+ }, { to: recipient, body: message });
79
+ }
80
+ case 'termii': {
81
+ return sendTermii(cfg, recipient, message, options);
82
+ }
83
+ default:
84
+ throw ErrorFactory.createConfigError(`Notification: unsupported driver: ${String(cfg?.driver)}`);
85
+ }
86
+ },
14
87
  listDrivers() {
15
88
  return NotificationRegistry.list();
16
89
  },
@@ -0,0 +1,8 @@
1
+ export declare const SlackNotificationDriver: Readonly<{
2
+ send(_recipient: string, message: string, options?: Record<string, unknown>): Promise<{
3
+ ok: boolean;
4
+ status?: number;
5
+ }>;
6
+ }>;
7
+ export default SlackNotificationDriver;
8
+ //# sourceMappingURL=SlackNotification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackNotification.d.ts","sourceRoot":"","sources":["../../../../../src/tools/notification/drivers/SlackNotification.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,uBAAuB;qBACX,MAAM,WAAW,MAAM,YAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;EAUhF,CAAC;AAEH,eAAe,uBAAuB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import notificationConfig from '../../../config/notification.js';
2
+ import { SlackDriver } from '../drivers/Slack.js';
3
+ export const SlackNotificationDriver = Object.freeze({
4
+ async send(_recipient, message, options = {}) {
5
+ const cfg = notificationConfig.providers.slack;
6
+ const payload = {
7
+ text: message,
8
+ ...options,
9
+ };
10
+ return SlackDriver.send({ webhookUrl: cfg.webhookUrl }, payload);
11
+ },
12
+ });
13
+ export default SlackNotificationDriver;
@@ -0,0 +1,8 @@
1
+ export declare const TwilioNotificationDriver: Readonly<{
2
+ send(recipient: string, message: string): Promise<{
3
+ ok: boolean;
4
+ status?: number;
5
+ }>;
6
+ }>;
7
+ export default TwilioNotificationDriver;
8
+ //# sourceMappingURL=TwilioNotification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TwilioNotification.d.ts","sourceRoot":"","sources":["../../../../../src/tools/notification/drivers/TwilioNotification.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB;oBACb,MAAM,WAAW,MAAM;;;;EAY7C,CAAC;AAEH,eAAe,wBAAwB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import notificationConfig from '../../../config/notification.js';
2
+ import { TwilioDriver } from '../drivers/Twilio.js';
3
+ export const TwilioNotificationDriver = Object.freeze({
4
+ async send(recipient, message) {
5
+ const cfg = notificationConfig.providers.twilio;
6
+ return TwilioDriver.send({
7
+ accountSid: cfg.accountSid,
8
+ authToken: cfg.authToken,
9
+ from: cfg.fromNumber,
10
+ }, { to: recipient, body: message });
11
+ },
12
+ });
13
+ export default TwilioNotificationDriver;
@@ -12,6 +12,7 @@ interface IQueueDriver {
12
12
  }
13
13
  export declare const Queue: Readonly<{
14
14
  register(name: string, driver: IQueueDriver): void;
15
+ reset(): void;
15
16
  get(name?: string): IQueueDriver;
16
17
  enqueue<T = unknown>(queue: string, payload: T, driverName?: string): Promise<string>;
17
18
  dequeue<T = unknown>(queue: string, driverName?: string): Promise<QueueMessage<T> | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../../../../src/tools/queue/Queue.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAErF,UAAU,YAAY;IACpB,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC1E,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAID,eAAO,MAAM,KAAK;mBACD,MAAM,UAAU,YAAY;eAIhC,MAAM,GAAG,YAAY;YAUlB,CAAC,mBAAmB,MAAM,WAAW,CAAC,eAAe,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAK7E,CAAC,mBACN,MAAM,eACA,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;eAKtB,MAAM,MAAM,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;kBAKpD,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;iBAK9C,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;EAI9D,CAAC;AAEH,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../../../../src/tools/queue/Queue.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAErF,UAAU,YAAY;IACpB,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC1E,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAID,eAAO,MAAM,KAAK;mBACD,MAAM,UAAU,YAAY;aAIlC,IAAI;eAIF,MAAM,GAAG,YAAY;YAUlB,CAAC,mBAAmB,MAAM,WAAW,CAAC,eAAe,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAK7E,CAAC,mBACN,MAAM,eACA,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;eAKtB,MAAM,MAAM,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;kBAKpD,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;iBAK9C,MAAM,eAAe,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;EAI9D,CAAC;AAEH,eAAe,KAAK,CAAC"}
@@ -4,6 +4,9 @@ export const Queue = Object.freeze({
4
4
  register(name, driver) {
5
5
  drivers.set(name.toLowerCase(), driver);
6
6
  },
7
+ reset() {
8
+ drivers.clear();
9
+ },
7
10
  get(name) {
8
11
  const driverName = (name ?? process.env['QUEUE_DRIVER'] ?? 'inmemory')
9
12
  .toString()
@@ -0,0 +1,11 @@
1
+ import type { QueueConfig } from '../../config/queue';
2
+ /**
3
+ * Register queue drivers from runtime config.
4
+ *
5
+ * This follows the framework's config-driven availability pattern:
6
+ * - Built-in drivers are registered so `QUEUE_DRIVER=sync|inmemory|redis` works out of the box.
7
+ * - If the configured default is registered, it is ALSO registered as 'default'.
8
+ * - Unknown/unregistered driver names still throw when selected.
9
+ */
10
+ export declare function registerQueuesFromRuntimeConfig(config: QueueConfig): void;
11
+ //# sourceMappingURL=QueueRuntimeRegistration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueRuntimeRegistration.d.ts","sourceRoot":"","sources":["../../../../src/tools/queue/QueueRuntimeRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAMjD;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAgBzE"}
@@ -0,0 +1,28 @@
1
+ import { InMemoryQueue } from '../queue/drivers/InMemory.js';
2
+ import { RedisQueue } from '../queue/drivers/Redis.js';
3
+ import { Queue } from '../queue/Queue.js';
4
+ /**
5
+ * Register queue drivers from runtime config.
6
+ *
7
+ * This follows the framework's config-driven availability pattern:
8
+ * - Built-in drivers are registered so `QUEUE_DRIVER=sync|inmemory|redis` works out of the box.
9
+ * - If the configured default is registered, it is ALSO registered as 'default'.
10
+ * - Unknown/unregistered driver names still throw when selected.
11
+ */
12
+ export function registerQueuesFromRuntimeConfig(config) {
13
+ // Built-in drivers (core)
14
+ Queue.register('inmemory', InMemoryQueue);
15
+ // Project templates use QUEUE_DRIVER=sync; treat this as an alias of in-memory.
16
+ Queue.register('sync', InMemoryQueue);
17
+ Queue.register('redis', RedisQueue);
18
+ const defaultName = (config.default ?? '').toString().trim().toLowerCase();
19
+ if (defaultName.length === 0)
20
+ return;
21
+ try {
22
+ const drv = Queue.get(defaultName);
23
+ Queue.register('default', drv);
24
+ }
25
+ catch {
26
+ // Best-effort: external drivers may be registered by optional packages.
27
+ }
28
+ }
@@ -0,0 +1,14 @@
1
+ declare function register(name: string, config: unknown): void;
2
+ declare function has(name: string): boolean;
3
+ declare function get(name: string): unknown;
4
+ declare function list(): string[];
5
+ declare function reset(): void;
6
+ export declare const StorageDiskRegistry: Readonly<{
7
+ register: typeof register;
8
+ has: typeof has;
9
+ get: typeof get;
10
+ list: typeof list;
11
+ reset: typeof reset;
12
+ }>;
13
+ export default StorageDiskRegistry;
14
+ //# sourceMappingURL=StorageDiskRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StorageDiskRegistry.d.ts","sourceRoot":"","sources":["../../../../src/tools/storage/StorageDiskRegistry.ts"],"names":[],"mappings":"AASA,iBAAS,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAIrD;AAED,iBAAS,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElC;AAED,iBAAS,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOlC;AAED,iBAAS,IAAI,IAAI,MAAM,EAAE,CAExB;AAED,iBAAS,KAAK,IAAI,IAAI,CAErB;AAED,eAAO,MAAM,mBAAmB;;;;;;EAM9B,CAAC;AAEH,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { ErrorFactory } from '../../exceptions/ZintrustError.js';
2
+ const registry = new Map();
3
+ const normalizeKey = (name) => String(name ?? '')
4
+ .trim()
5
+ .toLowerCase();
6
+ function register(name, config) {
7
+ const key = normalizeKey(name);
8
+ if (key === '')
9
+ return;
10
+ registry.set(key, config);
11
+ }
12
+ function has(name) {
13
+ return registry.has(normalizeKey(name));
14
+ }
15
+ function get(name) {
16
+ const key = normalizeKey(name);
17
+ const cfg = registry.get(key);
18
+ if (cfg === undefined) {
19
+ throw ErrorFactory.createConfigError(`Storage disk not registered: ${name}`);
20
+ }
21
+ return cfg;
22
+ }
23
+ function list() {
24
+ return Array.from(registry.keys()).sort((a, b) => a.localeCompare(b));
25
+ }
26
+ function reset() {
27
+ registry.clear();
28
+ }
29
+ export const StorageDiskRegistry = Object.freeze({
30
+ register,
31
+ has,
32
+ get,
33
+ list,
34
+ reset,
35
+ });
36
+ export default StorageDiskRegistry;
@@ -0,0 +1,10 @@
1
+ import type { StorageConfigRuntime, StorageDriverConfig } from '../../config/type';
2
+ export type StorageRuntimeConfig = StorageConfigRuntime & {
3
+ getDriverConfig?: (name?: string) => StorageDriverConfig;
4
+ };
5
+ export declare function registerDisksFromRuntimeConfig(config: StorageRuntimeConfig): void;
6
+ export declare const StorageRuntimeRegistration: Readonly<{
7
+ registerDisksFromRuntimeConfig: typeof registerDisksFromRuntimeConfig;
8
+ }>;
9
+ export default StorageRuntimeRegistration;
10
+ //# sourceMappingURL=StorageRuntimeRegistration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StorageRuntimeRegistration.d.ts","sourceRoot":"","sources":["../../../../src/tools/storage/StorageRuntimeRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAG9E,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,GAAG;IACxD,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,mBAAmB,CAAC;CAC1D,CAAC;AAEF,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAmBjF;AAED,eAAO,MAAM,0BAA0B;;EAErC,CAAC;AAEH,eAAe,0BAA0B,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { StorageDiskRegistry } from './StorageDiskRegistry.js';
2
+ export function registerDisksFromRuntimeConfig(config) {
3
+ for (const [name, driverConfig] of Object.entries(config.drivers)) {
4
+ StorageDiskRegistry.register(name, driverConfig);
5
+ }
6
+ // Alias reserved name `default` to the configured default.
7
+ // Prefer config.getDriverConfig() so we preserve its fallback semantics.
8
+ let resolvedDefault;
9
+ if (typeof config.getDriverConfig === 'function') {
10
+ resolvedDefault = config.getDriverConfig('default');
11
+ }
12
+ else {
13
+ const values = Object.values(config.drivers);
14
+ resolvedDefault = config.drivers[config.default] ?? values[0];
15
+ }
16
+ if (resolvedDefault !== undefined) {
17
+ StorageDiskRegistry.register('default', resolvedDefault);
18
+ }
19
+ }
20
+ export const StorageRuntimeRegistration = Object.freeze({
21
+ registerDisksFromRuntimeConfig,
22
+ });
23
+ export default StorageRuntimeRegistration;
@@ -17,4 +17,5 @@ export declare const Storage: Readonly<{
17
17
  tempUrl(disk: string | undefined, path: string, options?: TempUrlOptions): Promise<string>;
18
18
  }>;
19
19
  export default Storage;
20
+ export { StorageDiskRegistry } from './StorageDiskRegistry';
20
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/storage/index.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;AAErD,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,cAAc,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAA;CAAE,CAAC;AAsCrE,eAAO,MAAM,OAAO;mBACH,MAAM,GAAG,WAAW;cAqCnB,MAAM,GAAG,SAAS,QAAQ,MAAM,YAAY,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;cAW7E,MAAM,GAAG,SAAS,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;iBAW/C,MAAM,GAAG,SAAS,QAAQ,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;iBASnD,MAAM,GAAG,SAAS,QAAQ,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;cASzD,MAAM,GAAG,SAAS,QAAQ,MAAM,GAAG,MAAM;kBAY/B,MAAM,GAAG,SAAS,QAAQ,MAAM,YAAY,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;EAqBhG,CAAC;AAEH,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/storage/index.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;AAErD,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,cAAc,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAA;CAAE,CAAC;AAsFrE,eAAO,MAAM,OAAO;mBACH,MAAM,GAAG,WAAW;cAuCnB,MAAM,GAAG,SAAS,QAAQ,MAAM,YAAY,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;cAW7E,MAAM,GAAG,SAAS,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;iBAW/C,MAAM,GAAG,SAAS,QAAQ,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;iBASnD,MAAM,GAAG,SAAS,QAAQ,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;cASzD,MAAM,GAAG,SAAS,QAAQ,MAAM,GAAG,MAAM;kBAY/B,MAAM,GAAG,SAAS,QAAQ,MAAM,YAAY,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;EAqBhG,CAAC;AAEH,eAAe,OAAO,CAAC;AAEvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { storageConfig } from '../../config/storage.js';
2
2
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
3
3
  import { LocalDriver } from './drivers/Local.js';
4
+ import { StorageDiskRegistry } from './StorageDiskRegistry.js';
4
5
  import { StorageDriverRegistry } from './StorageDriverRegistry.js';
5
6
  const normalizers = {
6
7
  local: (raw) => ({
@@ -33,14 +34,46 @@ const normalizers = {
33
34
  const normalizeDiskConfig = (driverName, raw) => {
34
35
  return normalizers[driverName]?.(raw) ?? raw;
35
36
  };
37
+ const resolveDiskConfigFromRegistry = (name) => {
38
+ const selected = String(name ?? '').trim();
39
+ const hasSelection = name !== undefined && selected.length > 0;
40
+ const registryKey = hasSelection ? selected : 'default';
41
+ if (!StorageDiskRegistry.has(registryKey))
42
+ return undefined;
43
+ return StorageDiskRegistry.get(registryKey);
44
+ };
45
+ const resolveDiskConfigFromStorageConfig = (name) => {
46
+ const maybeGetDriverConfig = storageConfig
47
+ .getDriverConfig;
48
+ if (typeof maybeGetDriverConfig !== 'function')
49
+ return undefined;
50
+ // Important: call as a method to preserve `this` binding.
51
+ return storageConfig.getDriverConfig(name);
52
+ };
53
+ const resolveDiskConfigFromLegacyConfig = (name) => {
54
+ const selected = String(name ?? '').trim();
55
+ const hasSelection = name !== undefined && selected.length > 0;
56
+ const drivers = storageConfig.drivers ?? {};
57
+ const defaultName = String(storageConfig.default ?? 'local').trim();
58
+ const requestedName = hasSelection ? selected : defaultName;
59
+ const diskName = requestedName === 'default' ? defaultName : requestedName;
60
+ if (diskName !== '' && Object.prototype.hasOwnProperty.call(drivers, diskName)) {
61
+ return drivers[diskName];
62
+ }
63
+ if (hasSelection && selected !== 'default') {
64
+ throw ErrorFactory.createConfigError(`Storage disk not configured: ${diskName}`);
65
+ }
66
+ return (drivers['local'] ??
67
+ Object.values(drivers)[0]);
68
+ };
36
69
  export const Storage = Object.freeze({
37
70
  getDisk(name) {
38
- const diskName = name ?? storageConfig.default;
39
- // disk is config object; dispatch based on requested name
40
- const drivers = storageConfig.drivers;
41
- const config = drivers[diskName];
42
- if (config === undefined)
43
- throw ErrorFactory.createValidationError('Storage: unknown disk', { disk: diskName });
71
+ const config = resolveDiskConfigFromRegistry(name) ??
72
+ resolveDiskConfigFromStorageConfig(name) ??
73
+ resolveDiskConfigFromLegacyConfig(name);
74
+ if (config === undefined) {
75
+ throw ErrorFactory.createConfigError('Storage: no disks are configured');
76
+ }
44
77
  const driverName = String(config['driver'] ?? '')
45
78
  .trim()
46
79
  .toLowerCase();
@@ -114,3 +147,4 @@ export const Storage = Object.freeze({
114
147
  },
115
148
  });
116
149
  export default Storage;
150
+ export { StorageDiskRegistry } from './StorageDiskRegistry.js';