@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
@@ -4,61 +4,77 @@
4
4
  * Sealed namespace for immutability
5
5
  */
6
6
  import { Env } from './env.js';
7
- const isDatabaseConnectionName = (value) => {
8
- return value === 'sqlite' || value === 'postgresql' || value === 'mysql';
7
+ import { ErrorFactory } from '../exceptions/ZintrustError.js';
8
+ const hasOwn = (obj, key) => {
9
+ return Object.prototype.hasOwnProperty.call(obj, key);
9
10
  };
10
- const getDefaultConnection = () => {
11
- const value = Env.DB_CONNECTION;
12
- return isDatabaseConnectionName(value) ? value : 'sqlite';
11
+ const getDefaultConnection = (connections) => {
12
+ const value = String(Env.DB_CONNECTION || '').trim();
13
+ if (value.length > 0 && hasOwn(connections, value)) {
14
+ return value;
15
+ }
16
+ // Backwards-compatible default.
17
+ return hasOwn(connections, 'sqlite') ? 'sqlite' : (Object.keys(connections)[0] ?? 'sqlite');
13
18
  };
14
19
  const getDatabaseConnection = (config) => {
15
20
  const connName = config.default;
16
- return config.connections[connName];
21
+ const resolved = config.connections[connName];
22
+ if (resolved !== undefined)
23
+ return resolved;
24
+ // Backwards-compatible fallback.
25
+ const sqliteFallback = config.connections['sqlite'];
26
+ if (sqliteFallback !== undefined)
27
+ return sqliteFallback;
28
+ const first = Object.values(config.connections)[0];
29
+ if (first !== undefined)
30
+ return first;
31
+ throw ErrorFactory.createConfigError(`No database connections are configured (default='${connName}').`);
32
+ };
33
+ const connections = {
34
+ sqlite: {
35
+ driver: 'sqlite',
36
+ database: Env.DB_DATABASE,
37
+ migrations: 'database/migrations',
38
+ },
39
+ postgresql: {
40
+ driver: 'postgresql',
41
+ host: Env.DB_HOST,
42
+ port: Env.DB_PORT,
43
+ database: Env.DB_DATABASE,
44
+ username: Env.DB_USERNAME,
45
+ password: Env.DB_PASSWORD,
46
+ ssl: Env.getBool('DB_SSL', false),
47
+ pooling: {
48
+ enabled: Env.getBool('DB_POOLING', true),
49
+ min: Env.getInt('DB_POOL_MIN', 5),
50
+ max: Env.getInt('DB_POOL_MAX', 20),
51
+ idleTimeout: Env.getInt('DB_IDLE_TIMEOUT', 30000),
52
+ connectionTimeout: Env.getInt('DB_CONNECTION_TIMEOUT', 10000),
53
+ },
54
+ },
55
+ mysql: {
56
+ driver: 'mysql',
57
+ host: Env.DB_HOST,
58
+ port: Env.DB_PORT,
59
+ database: Env.DB_DATABASE,
60
+ username: Env.DB_USERNAME,
61
+ password: Env.DB_PASSWORD,
62
+ pooling: {
63
+ enabled: Env.getBool('DB_POOLING', true),
64
+ min: Env.getInt('DB_POOL_MIN', 5),
65
+ max: Env.getInt('DB_POOL_MAX', 20),
66
+ },
67
+ },
17
68
  };
18
69
  const databaseConfigObj = {
19
70
  /**
20
71
  * Default database connection
21
72
  */
22
- default: getDefaultConnection(),
73
+ default: getDefaultConnection(connections),
23
74
  /**
24
75
  * Database connections
25
76
  */
26
- connections: {
27
- sqlite: {
28
- driver: 'sqlite',
29
- database: Env.DB_DATABASE,
30
- migrations: 'database/migrations',
31
- },
32
- postgresql: {
33
- driver: 'postgresql',
34
- host: Env.DB_HOST,
35
- port: Env.DB_PORT,
36
- database: Env.DB_DATABASE,
37
- username: Env.DB_USERNAME,
38
- password: Env.DB_PASSWORD,
39
- ssl: Env.getBool('DB_SSL', false),
40
- pooling: {
41
- enabled: Env.getBool('DB_POOLING', true),
42
- min: Env.getInt('DB_POOL_MIN', 5),
43
- max: Env.getInt('DB_POOL_MAX', 20),
44
- idleTimeout: Env.getInt('DB_IDLE_TIMEOUT', 30000),
45
- connectionTimeout: Env.getInt('DB_CONNECTION_TIMEOUT', 10000),
46
- },
47
- },
48
- mysql: {
49
- driver: 'mysql',
50
- host: Env.DB_HOST,
51
- port: Env.DB_PORT,
52
- database: Env.DB_DATABASE,
53
- username: Env.DB_USERNAME,
54
- password: Env.DB_PASSWORD,
55
- pooling: {
56
- enabled: Env.getBool('DB_POOLING', true),
57
- min: Env.getInt('DB_POOL_MIN', 5),
58
- max: Env.getInt('DB_POOL_MAX', 20),
59
- },
60
- },
61
- },
77
+ connections,
62
78
  /**
63
79
  * Get current connection config
64
80
  */
@@ -3,10 +3,12 @@
3
3
  * Central export point for all configuration
4
4
  */
5
5
  export { appConfig, type AppConfig } from './app';
6
+ export { default as broadcastConfig } from './broadcast';
6
7
  export { cacheConfig, type CacheConfig } from './cache';
7
8
  export { databaseConfig, type DatabaseConfig } from './database';
8
9
  export { microservicesConfig, type MicroservicesConfig } from './microservices';
9
10
  export { middlewareConfig } from './middleware';
11
+ export { notificationConfig, type NotificationConfig } from './notification';
10
12
  export { queueConfig, type QueueConfig } from './queue';
11
13
  export { securityConfig } from './security';
12
14
  export { storageConfig, type StorageConfig } from './storage';
@@ -29,8 +31,19 @@ export declare const config: Readonly<{
29
31
  readonly maxBodySize: string;
30
32
  readonly getSafeEnv: () => NodeJS.ProcessEnv;
31
33
  }>;
34
+ readonly broadcast: Readonly<{
35
+ readonly default: string;
36
+ readonly drivers: {
37
+ readonly inmemory: import("./type").InMemoryBroadcastDriverConfig;
38
+ readonly pusher: import("./type").PusherBroadcastDriverConfig;
39
+ readonly redis: import("./type").RedisBroadcastDriverConfig;
40
+ readonly redishttps: import("./type").RedisHttpsBroadcastDriverConfig;
41
+ };
42
+ readonly getDriverName: () => string;
43
+ readonly getDriverConfig: (name?: string) => import("./type").KnownBroadcastDriverConfig;
44
+ }>;
32
45
  readonly database: Readonly<{
33
- default: keyof import("./type").DatabaseConnections;
46
+ default: string;
34
47
  connections: {
35
48
  sqlite: {
36
49
  driver: "sqlite";
@@ -84,6 +97,7 @@ export declare const config: Readonly<{
84
97
  readonly default: string;
85
98
  readonly drivers: import("./type").StorageDrivers;
86
99
  getDriver(this: import("./type").StorageConfigRuntime): import("./type").StorageDriverConfig;
100
+ getDriverConfig(this: import("./type").StorageConfigRuntime, name?: string): import("./type").StorageDriverConfig;
87
101
  readonly temp: {
88
102
  path: string;
89
103
  maxAge: number;
@@ -98,6 +112,13 @@ export declare const config: Readonly<{
98
112
  driver: string;
99
113
  };
100
114
  }>;
115
+ readonly notification: Readonly<{
116
+ readonly default: string;
117
+ readonly drivers: import("./type").NotificationDrivers;
118
+ readonly providers: import("./type").NotificationProviders;
119
+ readonly getDriverName: () => string;
120
+ readonly getDriverConfig: (name?: string) => import("./type").KnownNotificationDriverConfig;
121
+ }>;
101
122
  readonly security: Readonly<{
102
123
  readonly jwt: {
103
124
  readonly enabled: boolean;
@@ -250,7 +271,7 @@ export declare const config: Readonly<{
250
271
  ttl: number;
251
272
  };
252
273
  };
253
- getDriver(): import("./type").CacheDriverConfig;
274
+ getDriver(name?: string): import("./type").CacheDriverConfig;
254
275
  keyPrefix: string;
255
276
  ttl: number;
256
277
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASR,CAAC;AAEZ,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWR,CAAC;AAEZ,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC"}
@@ -3,18 +3,22 @@
3
3
  * Central export point for all configuration
4
4
  */
5
5
  import { appConfig } from './app.js';
6
+ import broadcastConfig from './broadcast.js';
6
7
  import { cacheConfig } from './cache.js';
7
8
  import { databaseConfig } from './database.js';
8
9
  import { microservicesConfig } from './microservices.js';
9
10
  import { middlewareConfig } from './middleware.js';
11
+ import notificationConfig from './notification.js';
10
12
  import { queueConfig } from './queue.js';
11
13
  import { securityConfig } from './security.js';
12
14
  import { storageConfig } from './storage.js';
13
15
  export { appConfig } from './app.js';
16
+ export { default as broadcastConfig } from './broadcast.js';
14
17
  export { cacheConfig } from './cache.js';
15
18
  export { databaseConfig } from './database.js';
16
19
  export { microservicesConfig } from './microservices.js';
17
20
  export { middlewareConfig } from './middleware.js';
21
+ export { notificationConfig } from './notification.js';
18
22
  export { queueConfig } from './queue.js';
19
23
  export { securityConfig } from './security.js';
20
24
  export { storageConfig } from './storage.js';
@@ -24,8 +28,10 @@ export { storageConfig } from './storage.js';
24
28
  */
25
29
  export const config = Object.freeze({
26
30
  app: appConfig,
31
+ broadcast: broadcastConfig,
27
32
  database: databaseConfig,
28
33
  storage: storageConfig,
34
+ notification: notificationConfig,
29
35
  security: securityConfig,
30
36
  middleware: middlewareConfig,
31
37
  microservices: microservicesConfig,
@@ -3,12 +3,12 @@
3
3
  * Runtime mail drivers and settings
4
4
  * Sealed namespace for immutability
5
5
  */
6
- import type { MailDriverConfig, MailDriverName } from './type';
6
+ import type { MailDriverConfig } from './type';
7
7
  export declare const mailConfig: Readonly<{
8
8
  /**
9
9
  * Default mail driver
10
10
  */
11
- readonly default: MailDriverName;
11
+ readonly default: string;
12
12
  /**
13
13
  * Default "From" identity
14
14
  */
@@ -57,7 +57,7 @@ export declare const mailConfig: Readonly<{
57
57
  /**
58
58
  * Get selected driver config
59
59
  */
60
- readonly getDriver: () => MailDriverConfig;
60
+ readonly getDriver: (name?: string) => MailDriverConfig;
61
61
  }>;
62
62
  export type MailConfig = typeof mailConfig;
63
63
  //# sourceMappingURL=mail.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mail.d.ts","sourceRoot":"","sources":["../../../src/config/mail.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAmB,gBAAgB,EAAE,cAAc,EAAe,MAAM,cAAc,CAAC;AA2FnG,eAAO,MAAM,UAAU;IA7ErB;;OAEG;;IAGH;;OAEG;;;;;IAMH;;OAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsDH;;OAEG;8BACU,gBAAgB;EAKuB,CAAC;AACvD,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"mail.d.ts","sourceRoot":"","sources":["../../../src/config/mail.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAmB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAwGtE,eAAO,MAAM,UAAU;IA7ErB;;OAEG;;IAGH;;OAEG;;;;;IAMH;;OAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsDH;;OAEG;gCACc,MAAM,KAAG,gBAAgB;EAKU,CAAC;AACvD,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC"}
@@ -4,19 +4,34 @@
4
4
  * Sealed namespace for immutability
5
5
  */
6
6
  import { Env } from './env.js';
7
- const getMailDriver = (config) => {
8
- const defaultDriver = config.default;
9
- if (Object.hasOwn(config.drivers, defaultDriver)) {
10
- const driverName = defaultDriver;
11
- return config.drivers[driverName];
7
+ import { ErrorFactory } from '../exceptions/ZintrustError.js';
8
+ const getMailDriver = (config, name) => {
9
+ const selected = (name ?? config.default).toString().trim();
10
+ if (selected.length === 0) {
11
+ const disabled = config.drivers['disabled'];
12
+ if (disabled !== undefined)
13
+ return disabled;
14
+ throw ErrorFactory.createConfigError('Mail driver not configured: disabled');
12
15
  }
13
- return config.drivers.disabled;
16
+ if (Object.hasOwn(config.drivers, selected)) {
17
+ const resolved = config.drivers[selected];
18
+ if (resolved !== undefined)
19
+ return resolved;
20
+ }
21
+ // Backward-compatible fallback: if the default is misconfigured, treat mail as disabled.
22
+ if (name === undefined) {
23
+ const disabled = config.drivers['disabled'];
24
+ if (disabled !== undefined)
25
+ return disabled;
26
+ throw ErrorFactory.createConfigError('Mail driver not configured: disabled');
27
+ }
28
+ throw ErrorFactory.createConfigError(`Mail driver not configured: ${selected}`);
14
29
  };
15
30
  const mailConfigObj = {
16
31
  /**
17
32
  * Default mail driver
18
33
  */
19
- default: Env.get('MAIL_DRIVER', 'disabled') ?? 'disabled',
34
+ default: Env.get('MAIL_DRIVER', 'disabled').trim().toLowerCase() || 'disabled',
20
35
  /**
21
36
  * Default "From" identity
22
37
  */
@@ -83,8 +98,8 @@ const mailConfigObj = {
83
98
  /**
84
99
  * Get selected driver config
85
100
  */
86
- getDriver() {
87
- return getMailDriver(this);
101
+ getDriver(name) {
102
+ return getMailDriver(this, name);
88
103
  },
89
104
  };
90
105
  export const mailConfig = Object.freeze(mailConfigObj);
@@ -1,41 +1,37 @@
1
1
  /**
2
2
  * Notification Configuration
3
3
  *
4
- * Config-first mapping of notification providers.
5
- * Keeps runtime driver selection in one place and uses Env for safe access.
4
+ * Config-first mapping of notification providers/channels.
5
+ * Driver selection must be dynamic (tests may mutate process.env).
6
6
  */
7
- declare const _default: Readonly<{
7
+ import type { KnownNotificationDriverConfig, NotificationDrivers, NotificationProviders } from './type';
8
+ export declare const notificationConfig: Readonly<{
8
9
  /**
9
- * Normalized notification driver name.
10
+ * Default notification channel name (normalized).
11
+ */
12
+ readonly default: string;
13
+ /**
14
+ * Notification channels.
10
15
  *
11
- * NOTE: This intentionally supports custom driver names (e.g. project-specific drivers),
12
- * so it returns a string rather than a strict union.
16
+ * You may add custom named channels (e.g. `opsSlack`, `smsMarketing`) that
17
+ * point to any known driver config.
18
+ */
19
+ readonly drivers: NotificationDrivers;
20
+ /**
21
+ * Legacy provider configs (kept for backwards compatibility with wrappers).
22
+ */
23
+ readonly providers: NotificationProviders;
24
+ /**
25
+ * Normalized notification channel name.
13
26
  */
14
27
  readonly getDriverName: () => string;
15
28
  /**
16
- * Provider configs.
29
+ * Resolve a channel config.
30
+ * - Unknown names throw when explicitly selected.
31
+ * - `default` is a reserved alias of the configured default.
17
32
  */
18
- readonly providers: {
19
- console: {
20
- driver: "console";
21
- };
22
- termii: {
23
- driver: "termii";
24
- apiKey: string;
25
- sender: string;
26
- endpoint: string;
27
- };
28
- twilio: {
29
- driver: "twilio";
30
- accountSid: string;
31
- authToken: string;
32
- fromNumber: string;
33
- };
34
- slack: {
35
- driver: "slack";
36
- webhookUrl: string;
37
- };
38
- };
33
+ readonly getDriverConfig: (name?: string) => KnownNotificationDriverConfig;
39
34
  }>;
40
- export default _default;
35
+ export type NotificationConfig = typeof notificationConfig;
36
+ export default notificationConfig;
41
37
  //# sourceMappingURL=notification.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../../src/config/notification.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;IAMD;;;;;OAKG;kCACc,MAAM;IAIvB;;OAEG;;;;;;;;;;;;;;;;;;;;;;;AA2BL,wBAAoD"}
1
+ {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../../src/config/notification.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,6BAA6B,EAE7B,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,cAAc,CAAC;AA2GtB,eAAO,MAAM,kBAAkB;IA1C7B;;OAEG;sBACY,MAAM;IAIrB;;;;;OAKG;sBACY,mBAAmB;IAKlC;;OAEG;wBACc,qBAAqB;IAItC;;OAEG;kCACc,MAAM;IAIvB;;;;OAIG;sCACoB,MAAM,KAAG,6BAA6B;EAKO,CAAC;AACvE,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC;AAE3D,eAAe,kBAAkB,CAAC"}
@@ -1,27 +1,43 @@
1
1
  /**
2
2
  * Notification Configuration
3
3
  *
4
- * Config-first mapping of notification providers.
5
- * Keeps runtime driver selection in one place and uses Env for safe access.
4
+ * Config-first mapping of notification providers/channels.
5
+ * Driver selection must be dynamic (tests may mutate process.env).
6
6
  */
7
7
  import { Env } from './env.js';
8
- const notificationConfigObj = {
9
- /**
10
- * Normalized notification driver name.
11
- *
12
- * NOTE: This intentionally supports custom driver names (e.g. project-specific drivers),
13
- * so it returns a string rather than a strict union.
14
- */
15
- getDriverName() {
16
- return Env.get('NOTIFICATION_DRIVER', 'console').trim().toLowerCase();
17
- },
18
- /**
19
- * Provider configs.
20
- */
21
- providers: {
22
- console: {
23
- driver: 'console',
24
- },
8
+ import { ErrorFactory } from '../exceptions/ZintrustError.js';
9
+ const normalizeName = (value) => value.trim().toLowerCase();
10
+ const hasOwn = (obj, key) => {
11
+ return Object.prototype.hasOwnProperty.call(obj, key);
12
+ };
13
+ const getDefaultChannel = (drivers) => {
14
+ const value = normalizeName(Env.get('NOTIFICATION_DRIVER', 'console'));
15
+ if (value.length > 0 && hasOwn(drivers, value))
16
+ return value;
17
+ return hasOwn(drivers, 'console') ? 'console' : (Object.keys(drivers)[0] ?? 'console');
18
+ };
19
+ const getNotificationDriver = (config, name) => {
20
+ const selected = normalizeName(String(name ?? config.default));
21
+ const channelName = selected === 'default' ? normalizeName(config.default) : selected;
22
+ const isExplicitSelection = name !== undefined &&
23
+ String(name).trim().length > 0 &&
24
+ normalizeName(String(name)) !== 'default';
25
+ if (channelName.length > 0 && hasOwn(config.drivers, channelName)) {
26
+ const resolved = config.drivers[channelName];
27
+ if (resolved !== undefined)
28
+ return resolved;
29
+ }
30
+ if (isExplicitSelection) {
31
+ throw ErrorFactory.createConfigError(`Notification channel not configured: ${channelName}`);
32
+ }
33
+ const fallback = config.drivers['console'] ?? Object.values(config.drivers)[0];
34
+ if (fallback !== undefined)
35
+ return fallback;
36
+ throw ErrorFactory.createConfigError('No notification channels are configured');
37
+ };
38
+ const getBaseProviders = () => {
39
+ return {
40
+ console: { driver: 'console' },
25
41
  termii: {
26
42
  driver: 'termii',
27
43
  apiKey: Env.get('TERMII_API_KEY', ''),
@@ -38,6 +54,45 @@ const notificationConfigObj = {
38
54
  driver: 'slack',
39
55
  webhookUrl: Env.get('SLACK_WEBHOOK_URL', ''),
40
56
  },
57
+ };
58
+ };
59
+ const notificationConfigObj = {
60
+ /**
61
+ * Default notification channel name (normalized).
62
+ */
63
+ get default() {
64
+ return getDefaultChannel(this.drivers);
65
+ },
66
+ /**
67
+ * Notification channels.
68
+ *
69
+ * You may add custom named channels (e.g. `opsSlack`, `smsMarketing`) that
70
+ * point to any known driver config.
71
+ */
72
+ get drivers() {
73
+ // Return a record of channels; can be extended by app-level config.
74
+ return getBaseProviders();
75
+ },
76
+ /**
77
+ * Legacy provider configs (kept for backwards compatibility with wrappers).
78
+ */
79
+ get providers() {
80
+ return getBaseProviders();
81
+ },
82
+ /**
83
+ * Normalized notification channel name.
84
+ */
85
+ getDriverName() {
86
+ return normalizeName(this.default);
87
+ },
88
+ /**
89
+ * Resolve a channel config.
90
+ * - Unknown names throw when explicitly selected.
91
+ * - `default` is a reserved alias of the configured default.
92
+ */
93
+ getDriverConfig(name) {
94
+ return getNotificationDriver(this, name);
41
95
  },
42
96
  };
43
- export default Object.freeze(notificationConfigObj);
97
+ export const notificationConfig = Object.freeze(notificationConfigObj);
98
+ export default notificationConfig;
@@ -17,6 +17,14 @@ export declare const storageConfig: Readonly<{
17
17
  * Get storage driver config
18
18
  */
19
19
  getDriver(this: StorageConfigRuntime): StorageDriverConfig;
20
+ /**
21
+ * Get a storage disk configuration by name.
22
+ *
23
+ * - When `name` is provided and not configured, this throws.
24
+ * - When `name` is omitted, it resolves the configured default with a backwards-compatible fallback.
25
+ * - Reserved name `default` aliases the configured default.
26
+ */
27
+ getDriverConfig(this: StorageConfigRuntime, name?: string): StorageDriverConfig;
20
28
  /**
21
29
  * Temporary file settings
22
30
  */
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/config/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EAEnB,cAAc,EACf,MAAM,cAAc,CAAC;AA4GtB,eAAO,MAAM,aAAa;IArDxB;;OAEG;sBACY,MAAM;IAIrB;;OAEG;sBACY,cAAc;IAI7B;;OAEG;oBACa,oBAAoB,GAAG,mBAAmB;IAI1D;;OAEG;mBACS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAO5C;;OAEG;sBACY;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAQtE;;OAEG;sBACY;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;EAQW,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/config/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAiI9F,eAAO,MAAM,aAAa;IAhExB;;OAEG;sBACY,MAAM;IAIrB;;OAEG;sBACY,cAAc;IAI7B;;OAEG;oBACa,oBAAoB,GAAG,mBAAmB;IAI1D;;;;;;OAMG;0BACmB,oBAAoB,SAAS,MAAM,GAAG,mBAAmB;IAI/E;;OAEG;mBACS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAO5C;;OAEG;sBACY;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAQtE;;OAEG;sBACY;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;EAQW,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC"}
@@ -4,15 +4,27 @@
4
4
  * Sealed namespace for immutability
5
5
  */
6
6
  import { Env } from './env.js';
7
- const isStorageDriverName = (value, drivers) => {
8
- return value in drivers;
7
+ import { ErrorFactory } from '../exceptions/ZintrustError.js';
8
+ const hasOwn = (obj, key) => {
9
+ return Object.prototype.hasOwnProperty.call(obj, key);
9
10
  };
10
- const getStorageDriver = (config) => {
11
- const driverName = config.default;
12
- if (isStorageDriverName(driverName, config.drivers)) {
13
- return config.drivers[driverName];
11
+ const getStorageDriver = (config, name) => {
12
+ const selected = String(name ?? config.default).trim();
13
+ const diskName = selected === 'default' ? String(config.default).trim() : selected;
14
+ const isExplicitSelection = name !== undefined && String(name).trim().length > 0 && String(name).trim() !== 'default';
15
+ if (diskName !== '' && hasOwn(config.drivers, diskName)) {
16
+ const resolved = config.drivers[diskName];
17
+ if (resolved !== undefined)
18
+ return resolved;
14
19
  }
15
- return config.drivers.local;
20
+ if (isExplicitSelection) {
21
+ throw ErrorFactory.createConfigError(`Storage disk not configured: ${diskName}`);
22
+ }
23
+ // Backwards-compatible fallback.
24
+ const fallback = config.drivers['local'] ?? Object.values(config.drivers)[0];
25
+ if (fallback !== undefined)
26
+ return fallback;
27
+ throw ErrorFactory.createConfigError('No storage disks are configured');
16
28
  };
17
29
  const getDrivers = () => ({
18
30
  local: {
@@ -67,6 +79,16 @@ const storageConfigObj = {
67
79
  getDriver() {
68
80
  return getStorageDriver(this);
69
81
  },
82
+ /**
83
+ * Get a storage disk configuration by name.
84
+ *
85
+ * - When `name` is provided and not configured, this throws.
86
+ * - When `name` is omitted, it resolves the configured default with a backwards-compatible fallback.
87
+ * - Reserved name `default` aliases the configured default.
88
+ */
89
+ getDriverConfig(name) {
90
+ return getStorageDriver(this, name);
91
+ },
70
92
  /**
71
93
  * Temporary file settings
72
94
  */