@zintrust/core 0.1.24 → 0.1.26

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 (152) hide show
  1. package/package.json +4 -3
  2. package/src/auth/Auth.d.ts.map +1 -0
  3. package/src/boot/Application.d.ts.map +1 -1
  4. package/src/boot/Application.js +8 -0
  5. package/src/boot/bootstrap.js +34 -15
  6. package/src/cache/drivers/RedisDriver.d.ts.map +1 -1
  7. package/src/cache/drivers/RedisDriver.js +10 -5
  8. package/src/cli/CLI.d.ts.map +1 -1
  9. package/src/cli/CLI.js +6 -0
  10. package/src/cli/commands/QueueCommand.d.ts.map +1 -1
  11. package/src/cli/commands/QueueCommand.js +89 -39
  12. package/src/cli/commands/QueueLockCommand.d.ts +7 -0
  13. package/src/cli/commands/QueueLockCommand.d.ts.map +1 -0
  14. package/src/cli/commands/QueueLockCommand.js +138 -0
  15. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  16. package/src/cli/commands/StartCommand.js +15 -3
  17. package/src/cli/commands/TemplatesCommand.js +1 -1
  18. package/src/cli/commands/WorkerCommands.d.ts.map +1 -1
  19. package/src/cli/commands/WorkerCommands.js +46 -22
  20. package/src/cli/scaffolding/ProjectScaffolder.js +2 -2
  21. package/src/cli/scaffolding/RouteGenerator.d.ts.map +1 -1
  22. package/src/cli/scaffolding/RouteGenerator.js +27 -28
  23. package/src/cli/services/VersionChecker.d.ts +53 -0
  24. package/src/cli/services/VersionChecker.d.ts.map +1 -0
  25. package/src/cli/services/VersionChecker.js +180 -0
  26. package/src/cli/workers/QueueWorkRunner.d.ts.map +1 -1
  27. package/src/cli/workers/QueueWorkRunner.js +128 -7
  28. package/src/common/ExternalServiceUtils.d.ts +2 -2
  29. package/src/config/app.d.ts +4 -0
  30. package/src/config/app.d.ts.map +1 -1
  31. package/src/config/app.js +9 -0
  32. package/src/config/constants.d.ts +140 -10
  33. package/src/config/constants.d.ts.map +1 -1
  34. package/src/config/constants.js +86 -5
  35. package/src/config/index.d.ts +1 -0
  36. package/src/config/index.d.ts.map +1 -1
  37. package/src/config/middleware.d.ts +6 -6
  38. package/src/config/middleware.d.ts.map +1 -1
  39. package/src/config/middleware.js +6 -7
  40. package/src/config/queue.d.ts +4 -0
  41. package/src/config/queue.d.ts.map +1 -1
  42. package/src/config/queue.js +1 -1
  43. package/src/config/redis.d.ts +17 -0
  44. package/src/config/redis.d.ts.map +1 -0
  45. package/src/config/redis.js +54 -0
  46. package/src/config/type.d.ts +3 -0
  47. package/src/config/type.d.ts.map +1 -1
  48. package/src/http/Request.d.ts +10 -1
  49. package/src/http/Request.d.ts.map +1 -1
  50. package/src/http/Request.js +79 -7
  51. package/src/http/error-pages/ErrorPageRenderer.d.ts.map +1 -1
  52. package/src/http/error-pages/ErrorPageRenderer.js +4 -3
  53. package/src/index.d.ts +14 -11
  54. package/src/index.d.ts.map +1 -1
  55. package/src/index.js +18 -11
  56. package/src/lang/lang.d.ts +23 -0
  57. package/src/lang/lang.d.ts.map +1 -0
  58. package/src/lang/lang.js +22 -0
  59. package/src/middleware/ErrorHandlerMiddleware.d.ts.map +1 -1
  60. package/src/middleware/ErrorHandlerMiddleware.js +9 -1
  61. package/src/migrations/schema/SchemaCompiler.js +1 -1
  62. package/src/migrations/schema/types.d.ts +1 -1
  63. package/src/migrations/schema/types.d.ts.map +1 -1
  64. package/src/node.d.ts +1 -1
  65. package/src/node.d.ts.map +1 -1
  66. package/src/node.js +1 -1
  67. package/src/orm/Database.d.ts +1 -1
  68. package/src/orm/Database.d.ts.map +1 -1
  69. package/src/orm/Database.js +22 -3
  70. package/src/performance/Optimizer.js +1 -1
  71. package/src/routing/Router.d.ts +6 -2
  72. package/src/routing/Router.d.ts.map +1 -1
  73. package/src/routing/Router.js +19 -4
  74. package/src/runtime/PluginManager.js +1 -1
  75. package/src/runtime/PluginRegistry.js +2 -2
  76. package/src/start.d.ts.map +1 -1
  77. package/src/start.js +8 -7
  78. package/src/templates/TemplateRegistry.js +2 -2
  79. package/src/templates/TemplateRegistry.ts +2 -2
  80. package/src/templates/feature/Queue.ts.tpl +114 -0
  81. package/src/templates/project/basic/app/Controllers/UserController.ts.tpl +22 -0
  82. package/src/templates/project/basic/config/queue.ts.tpl +19 -0
  83. package/src/templates/project/basic/package.json.tpl +2 -1
  84. package/src/templates/project/basic/src/index.ts.tpl +0 -3
  85. package/src/tools/broadcast/drivers/Redis.d.ts.map +1 -1
  86. package/src/tools/broadcast/drivers/Redis.js +8 -56
  87. package/src/tools/mail/Mail.d.ts +1 -29
  88. package/src/tools/mail/Mail.d.ts.map +1 -1
  89. package/src/tools/mail/Mail.js +1 -111
  90. package/src/tools/mail/drivers/SendGrid.d.ts.map +1 -1
  91. package/src/tools/mail/drivers/SendGrid.js +4 -3
  92. package/src/tools/mail/drivers/Smtp.d.ts.map +1 -1
  93. package/src/tools/mail/drivers/Smtp.js +32 -10
  94. package/src/tools/mail/index.d.ts +40 -0
  95. package/src/tools/mail/index.d.ts.map +1 -0
  96. package/src/tools/mail/index.js +129 -0
  97. package/src/tools/mail/template-loader.d.ts +10 -0
  98. package/src/tools/mail/template-loader.d.ts.map +1 -0
  99. package/src/tools/mail/template-loader.js +101 -0
  100. package/src/tools/mail/template-utils.d.ts +10 -0
  101. package/src/tools/mail/template-utils.d.ts.map +1 -0
  102. package/src/tools/mail/template-utils.js +16 -0
  103. package/src/tools/mail/templates/index.d.ts +30 -0
  104. package/src/tools/mail/templates/index.d.ts.map +1 -1
  105. package/src/tools/mail/templates/index.js +69 -0
  106. package/src/tools/queue/AdvancedQueue.d.ts +19 -0
  107. package/src/tools/queue/AdvancedQueue.d.ts.map +1 -0
  108. package/src/tools/queue/AdvancedQueue.js +352 -0
  109. package/src/tools/queue/DeduplicationBuilder.d.ts +20 -0
  110. package/src/tools/queue/DeduplicationBuilder.d.ts.map +1 -0
  111. package/src/tools/queue/DeduplicationBuilder.js +77 -0
  112. package/src/tools/queue/LockProvider.d.ts +22 -0
  113. package/src/tools/queue/LockProvider.d.ts.map +1 -0
  114. package/src/tools/queue/LockProvider.js +282 -0
  115. package/src/tools/queue/Queue.d.ts.map +1 -1
  116. package/src/tools/queue/Queue.js +2 -1
  117. package/src/tools/queue/QueueExtensions.d.ts +46 -0
  118. package/src/tools/queue/QueueExtensions.d.ts.map +1 -0
  119. package/src/tools/queue/QueueExtensions.js +129 -0
  120. package/src/tools/queue/QueueRuntimeRegistration.d.ts.map +1 -1
  121. package/src/tools/queue/QueueRuntimeRegistration.js +2 -2
  122. package/src/tools/queue/drivers/Database.d.ts +23 -0
  123. package/src/tools/queue/drivers/Database.d.ts.map +1 -0
  124. package/src/tools/queue/drivers/Database.js +123 -0
  125. package/src/tools/queue/drivers/Redis.d.ts.map +1 -1
  126. package/src/tools/queue/drivers/Redis.js +11 -82
  127. package/src/tools/queue/index.d.ts +9 -0
  128. package/src/tools/queue/index.d.ts.map +1 -0
  129. package/src/tools/queue/index.js +7 -0
  130. package/src/tools/redis/RedisKeyManager.d.ts +64 -0
  131. package/src/tools/redis/RedisKeyManager.d.ts.map +1 -0
  132. package/src/tools/redis/RedisKeyManager.js +124 -0
  133. package/src/types/Queue.d.ts +62 -0
  134. package/src/types/Queue.d.ts.map +1 -0
  135. package/src/types/Queue.js +5 -0
  136. package/src/features/Auth.d.ts.map +0 -1
  137. package/src/features/Queue.d.ts +0 -21
  138. package/src/features/Queue.d.ts.map +0 -1
  139. package/src/features/Queue.js +0 -33
  140. package/src/templates/features/Queue.ts.tpl +0 -47
  141. package/src/tools/mail/templates/markdown/index.d.ts +0 -17
  142. package/src/tools/mail/templates/markdown/index.d.ts.map +0 -1
  143. package/src/tools/mail/templates/markdown/index.js +0 -49
  144. package/src/tools/mail/templates/markdown/registry.d.ts +0 -15
  145. package/src/tools/mail/templates/markdown/registry.d.ts.map +0 -1
  146. package/src/tools/mail/templates/markdown/registry.js +0 -34
  147. package/src/tools/mail/templates/markdown/validator.d.ts +0 -16
  148. package/src/tools/mail/templates/markdown/validator.d.ts.map +0 -1
  149. package/src/tools/mail/templates/markdown/validator.js +0 -24
  150. /package/src/{features → auth}/Auth.d.ts +0 -0
  151. /package/src/{features → auth}/Auth.js +0 -0
  152. /package/src/templates/{features → auth}/Auth.ts.tpl +0 -0
@@ -1,96 +1,25 @@
1
- import { generateUuid } from '../../../common/utility.js';
2
- import { Env } from '../../../config/env.js';
3
- import { ErrorFactory } from '../../../exceptions/ZintrustError.js';
4
- const getRedisUrl = () => {
5
- const anyEnv = Env;
6
- const fromEnv = typeof anyEnv.get === 'function' ? anyEnv.get('REDIS_URL', '') : '';
7
- const hasProcess = typeof process === 'object' && process !== null;
8
- const fallback = hasProcess ? (process.env?.['REDIS_URL'] ?? '') : '';
9
- const trimmed = fromEnv.trim();
10
- const url = (trimmed.length > 0 ? fromEnv : String(fallback)).trim();
11
- return url.length > 0 ? url : null;
12
- };
1
+ import { ensureDriver } from '../../../config/redis.js';
13
2
  export const RedisQueue = (() => {
14
- let client = null;
15
- let connected = false;
16
- const ensureClient = async () => {
17
- if (connected && client !== null)
18
- return client;
19
- const url = getRedisUrl();
20
- if (url === null)
21
- throw ErrorFactory.createConfigError('Redis queue driver requires REDIS_URL');
22
- // Import lazily so package is optional for environments that don't use Redis
23
- // Prefer real 'redis' package when available, otherwise allow tests to inject a fake client
24
- try {
25
- // Dynamically import the redis package if available (optional dependency)
26
- // Tests can inject a fake client on `globalThis.__fakeRedisClient` if the package is absent.
27
- // Dynamically import the redis package if available (optional dependency)
28
- const mod = (await import('redis'));
29
- const createClient = mod.createClient;
30
- client = createClient({ url });
31
- if (typeof client.connect === 'function') {
32
- try {
33
- // Await connect to ensure readiness; network errors will be surfaced
34
- await client.connect();
35
- connected = true;
36
- }
37
- catch (connectionError) {
38
- connected = false;
39
- // log non-fatally — operations will surface errors as needed
40
- // eslint-disable-next-line no-console
41
- console.warn('Redis client connect failed:', String(connectionError));
42
- }
43
- }
44
- else {
45
- connected = true;
46
- }
47
- }
48
- catch {
49
- const globalFake = globalThis
50
- .__fakeRedisClient;
51
- if (globalFake === undefined) {
52
- throw ErrorFactory.createConfigError("Redis queue driver requires the 'redis' package (run `zin add queue:redis` / `zin plugin install queue:redis`, or `npm install redis`) or a test fake client set in globalThis.__fakeRedisClient");
53
- }
54
- client = globalFake;
55
- connected = true;
56
- }
57
- if (client === null)
58
- throw ErrorFactory.createConfigError('Redis client could not be initialized');
59
- return client;
60
- };
61
3
  return {
62
4
  async enqueue(queue, payload) {
63
- const cli = await ensureClient();
64
- const id = generateUuid();
65
- const msg = JSON.stringify({ id, payload, attempts: 0 });
66
- await cli.rPush(queue, msg);
67
- return id;
5
+ const driver = await ensureDriver();
6
+ return driver.enqueue(queue, payload);
68
7
  },
69
8
  async dequeue(queue) {
70
- const cli = await ensureClient();
71
- const raw = await cli.lPop(queue);
72
- if (raw === null)
73
- return undefined;
74
- try {
75
- const parsed = JSON.parse(raw);
76
- return parsed;
77
- }
78
- catch (err) {
79
- throw ErrorFactory.createTryCatchError('Failed to parse queue message', err);
80
- }
9
+ const driver = await ensureDriver();
10
+ return driver.dequeue(queue);
81
11
  },
82
12
  async ack(_queue, _id) {
83
- // Simple list-based queue removes on dequeue, so ack is a no-op here.
84
- // For visibility timeout or retry semantics, implement BRPOPLPUSH and a processing list.
85
- return Promise.resolve(); // NOSONAR
13
+ const driver = await ensureDriver();
14
+ await driver.ack(_queue, _id);
86
15
  },
87
16
  async length(queue) {
88
- const cli = await ensureClient();
89
- return cli.lLen(queue);
17
+ const driver = await ensureDriver();
18
+ return driver.length(queue);
90
19
  },
91
20
  async drain(queue) {
92
- const cli = await ensureClient();
93
- await cli.del(queue);
21
+ const driver = await ensureDriver();
22
+ await driver.drain(queue);
94
23
  },
95
24
  };
96
25
  })();
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Queue Module Exports
3
+ * Centralized exports for advanced queue patterns
4
+ */
5
+ export { createAdvancedQueue, type AdvancedQueue } from './AdvancedQueue';
6
+ export { createDeduplicationBuilder, type DeduplicationBuilder } from './DeduplicationBuilder';
7
+ export { createLockProvider, createMemoryLockProvider, createRedisLockProvider, getLockProvider, registerLockProvider, } from './LockProvider';
8
+ export type { AdvancedJobOptions, DeduplicationOptions, JobResult, Lock, LockOptions, LockProvider, LockProviderConfig, LockStatus, QueueConfig, ReleaseCondition, } from '../../types/Queue';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/queue/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,0BAA0B,EAAE,KAAK,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACpG,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,SAAS,EACT,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,gBAAgB,GACjB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Queue Module Exports
3
+ * Centralized exports for advanced queue patterns
4
+ */
5
+ export { createAdvancedQueue } from './AdvancedQueue.js';
6
+ export { createDeduplicationBuilder } from './DeduplicationBuilder.js';
7
+ export { createLockProvider, createMemoryLockProvider, createRedisLockProvider, getLockProvider, registerLockProvider, } from './LockProvider.js';
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Creates a prefixed Redis key
3
+ * @param key - Original key name
4
+ * @returns Prefixed key in format: {prefix}-{key}
5
+ */
6
+ export declare function createRedisKey(key: string): string;
7
+ /**
8
+ * Creates a prefixed queue key
9
+ * @param queueName - Original queue name
10
+ * @returns Prefixed queue key
11
+ */
12
+ export declare function createQueueKey(queueName: string): string;
13
+ /**
14
+ * Creates a prefixed BullMQ queue key
15
+ * BullMQ uses specific patterns like 'bull:queue-name'
16
+ * @param queueName - Original queue name
17
+ * @returns Prefixed BullMQ queue key
18
+ */
19
+ export declare function createBullMQKey(queueName: string): string;
20
+ /**
21
+ * Creates a prefixed worker key
22
+ * @param workerName - Original worker name
23
+ * @returns Prefixed worker key
24
+ */
25
+ export declare function createWorkerKey(workerName: string): string;
26
+ /**
27
+ * Creates a prefixed session key
28
+ * @param sessionId - Session ID
29
+ * @returns Prefixed session key
30
+ */
31
+ export declare function createSessionKey(sessionId: string): string;
32
+ /**
33
+ * Creates a prefixed cache key
34
+ * @param cacheKey - Cache key
35
+ * @returns Prefixed cache key
36
+ */
37
+ export declare function createCacheKey(cacheKey: string): string;
38
+ /**
39
+ * Extracts original key from prefixed key
40
+ * @param prefixedKey - Full prefixed key
41
+ * @returns Original key without prefix
42
+ */
43
+ export declare function extractOriginalKey(prefixedKey: string): string;
44
+ /**
45
+ * Checks if a key belongs to this application
46
+ * @param key - Redis key to check
47
+ * @returns True if key belongs to this application
48
+ */
49
+ export declare function isAppKey(key: string): boolean;
50
+ /**
51
+ * Gets the current prefix
52
+ * @returns Current application prefix
53
+ */
54
+ export declare function getPrefix(): string;
55
+ export declare const getBullMQSafeQueueName: () => string;
56
+ export type RedisKeyType = 'queue' | 'bullmq' | 'worker' | 'session' | 'cache' | 'custom';
57
+ /**
58
+ * Creates a prefixed key based on type
59
+ * @param type - Type of key
60
+ * @param key - Original key
61
+ * @returns Prefixed key
62
+ */
63
+ export declare function createKeyByType(type: RedisKeyType, key: string): string;
64
+ //# sourceMappingURL=RedisKeyManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedisKeyManager.d.ts","sourceRoot":"","sources":["../../../../src/tools/redis/RedisKeyManager.ts"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAgBlD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAM9D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,eAAO,MAAM,sBAAsB,QAAO,MAEzC,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1F;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBvE"}
@@ -0,0 +1,124 @@
1
+ import { appConfig } from '../../config/app.js';
2
+ import { Logger } from '../../config/logger.js';
3
+ /**
4
+ * Redis Key Management Utility
5
+ *
6
+ * Centralizes Redis key prefixing using appConfigObj.prefix
7
+ * to prevent key collisions across different applications/environments
8
+ */
9
+ const PREFIX = appConfig.prefix;
10
+ /**
11
+ * Creates a prefixed Redis key
12
+ * @param key - Original key name
13
+ * @returns Prefixed key in format: {prefix}-{key}
14
+ */
15
+ export function createRedisKey(key) {
16
+ if (!key) {
17
+ Logger.warn('RedisKeyManager: Empty key provided');
18
+ return PREFIX;
19
+ }
20
+ // Remove leading/trailing colons and ensure proper format
21
+ // Using safe string operations instead of regex to prevent ReDoS
22
+ let cleanKey = key;
23
+ while (cleanKey.startsWith(':')) {
24
+ cleanKey = cleanKey.slice(1);
25
+ }
26
+ while (cleanKey.endsWith(':')) {
27
+ cleanKey = cleanKey.slice(0, -1);
28
+ }
29
+ return `${PREFIX}:${cleanKey}`;
30
+ }
31
+ /**
32
+ * Creates a prefixed queue key
33
+ * @param queueName - Original queue name
34
+ * @returns Prefixed queue key
35
+ */
36
+ export function createQueueKey(queueName) {
37
+ return createRedisKey(`queue:${queueName}`);
38
+ }
39
+ /**
40
+ * Creates a prefixed BullMQ queue key
41
+ * BullMQ uses specific patterns like 'bull:queue-name'
42
+ * @param queueName - Original queue name
43
+ * @returns Prefixed BullMQ queue key
44
+ */
45
+ export function createBullMQKey(queueName) {
46
+ return createRedisKey(`bull:${queueName}`);
47
+ }
48
+ /**
49
+ * Creates a prefixed worker key
50
+ * @param workerName - Original worker name
51
+ * @returns Prefixed worker key
52
+ */
53
+ export function createWorkerKey(workerName) {
54
+ return createRedisKey(`worker:${workerName}`);
55
+ }
56
+ /**
57
+ * Creates a prefixed session key
58
+ * @param sessionId - Session ID
59
+ * @returns Prefixed session key
60
+ */
61
+ export function createSessionKey(sessionId) {
62
+ return createRedisKey(`session:${sessionId}`);
63
+ }
64
+ /**
65
+ * Creates a prefixed cache key
66
+ * @param cacheKey - Cache key
67
+ * @returns Prefixed cache key
68
+ */
69
+ export function createCacheKey(cacheKey) {
70
+ return createRedisKey(`cache:${cacheKey}`);
71
+ }
72
+ /**
73
+ * Extracts original key from prefixed key
74
+ * @param prefixedKey - Full prefixed key
75
+ * @returns Original key without prefix
76
+ */
77
+ export function extractOriginalKey(prefixedKey) {
78
+ if (!prefixedKey.startsWith(`${PREFIX}:`)) {
79
+ return prefixedKey;
80
+ }
81
+ return prefixedKey.substring(`${PREFIX}:`.length);
82
+ }
83
+ /**
84
+ * Checks if a key belongs to this application
85
+ * @param key - Redis key to check
86
+ * @returns True if key belongs to this application
87
+ */
88
+ export function isAppKey(key) {
89
+ return key.startsWith(`${PREFIX}:`);
90
+ }
91
+ /**
92
+ * Gets the current prefix
93
+ * @returns Current application prefix
94
+ */
95
+ export function getPrefix() {
96
+ return PREFIX;
97
+ }
98
+ export const getBullMQSafeQueueName = () => {
99
+ return PREFIX;
100
+ };
101
+ /**
102
+ * Creates a prefixed key based on type
103
+ * @param type - Type of key
104
+ * @param key - Original key
105
+ * @returns Prefixed key
106
+ */
107
+ export function createKeyByType(type, key) {
108
+ switch (type) {
109
+ case 'queue':
110
+ return createQueueKey(key);
111
+ case 'bullmq':
112
+ return createBullMQKey(key);
113
+ case 'worker':
114
+ return createWorkerKey(key);
115
+ case 'session':
116
+ return createSessionKey(key);
117
+ case 'cache':
118
+ return createCacheKey(key);
119
+ case 'custom':
120
+ return createRedisKey(key);
121
+ default:
122
+ return createRedisKey(key);
123
+ }
124
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Queue Types for Advanced Queue Patterns
3
+ * Defines all interfaces and types for deduplication and lock management
4
+ */
5
+ export interface DeduplicationOptions {
6
+ id: string;
7
+ ttl?: number;
8
+ dontRelease?: boolean;
9
+ replace?: boolean;
10
+ releaseAfter?: string | number | ReleaseCondition;
11
+ }
12
+ export interface ReleaseCondition {
13
+ condition: string;
14
+ delay?: number;
15
+ }
16
+ export interface LockOptions {
17
+ ttl?: number;
18
+ autoExtend?: boolean;
19
+ retryDelay?: number;
20
+ }
21
+ export interface Lock {
22
+ key: string;
23
+ ttl: number;
24
+ acquired: boolean;
25
+ expires: Date;
26
+ }
27
+ export interface LockStatus {
28
+ exists: boolean;
29
+ ttl?: number;
30
+ expires?: Date;
31
+ }
32
+ export interface LockProviderConfig {
33
+ type: 'redis' | 'database' | 'memory';
34
+ connection?: unknown;
35
+ prefix?: string;
36
+ defaultTtl?: number;
37
+ }
38
+ export interface QueueConfig {
39
+ name: string;
40
+ connection?: unknown;
41
+ defaultDedupTtl?: number;
42
+ lockProvider?: string;
43
+ }
44
+ export interface AdvancedJobOptions {
45
+ uniqueId?: string;
46
+ uniqueVia?: string;
47
+ deduplication?: DeduplicationOptions;
48
+ }
49
+ export interface JobResult {
50
+ id: string;
51
+ deduplicated: boolean;
52
+ lockId?: string;
53
+ status: 'queued' | 'deduplicated' | 'failed';
54
+ }
55
+ export interface LockProvider {
56
+ acquire(key: string, options: LockOptions): Promise<Lock>;
57
+ release(lock: Lock): Promise<void>;
58
+ extend(lock: Lock, ttl: number): Promise<boolean>;
59
+ status(key: string): Promise<LockStatus>;
60
+ list(pattern?: string): Promise<string[]>;
61
+ }
62
+ //# sourceMappingURL=Queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../../../src/types/Queue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,gBAAgB,CAAC;CACnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,IAAI,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,QAAQ,GAAG,cAAc,GAAG,QAAQ,CAAC;CAC9C;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC3C"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Queue Types for Advanced Queue Patterns
3
+ * Defines all interfaces and types for deduplication and lock management
4
+ */
5
+ export {};
@@ -1 +0,0 @@
1
- {"version":3,"file":"Auth.d.ts","sourceRoot":"","sources":["../../../src/features/Auth.ts"],"names":[],"mappings":"AAEA,OAAY,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAIlE,eAAO,MAAM,IAAI;IACf;;OAEG;mBACkB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7C;;OAEG;sBACqB,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI/D;;OAEG;2BAEQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,UACxB,MAAM,cACH,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,GAC/C,MAAM;IAKT;;OAEG;gBACS,CAAC,SAAS,MAAM,UAAU,MAAM,GAAG,CAAC;EAGhD,CAAC"}
@@ -1,21 +0,0 @@
1
- export interface QueueJob {
2
- id: string;
3
- data: unknown;
4
- timestamp: number;
5
- }
6
- /**
7
- * Simple In-Memory Queue
8
- * For production, replace with Redis or similar.
9
- */
10
- export declare const Queue: Readonly<{
11
- jobs: QueueJob[];
12
- /**
13
- * Add a job to the queue
14
- */
15
- add<T>(data: T): string;
16
- /**
17
- * Process jobs (Placeholder)
18
- */
19
- process(handler: (job: QueueJob) => Promise<void>): Promise<void>;
20
- }>;
21
- //# sourceMappingURL=Queue.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../../../src/features/Queue.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK;UACJ,QAAQ,EAAE;IAEtB;;OAEG;QACC,CAAC,QAAQ,CAAC,GAAG,MAAM;IAcvB;;OAEG;qBACoB,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;EAMvE,CAAC"}
@@ -1,33 +0,0 @@
1
- import { generateSecureJobId } from '../common/utility.js';
2
- import { Logger } from '../config/logger.js';
3
- /**
4
- * Simple In-Memory Queue
5
- * For production, replace with Redis or similar.
6
- */
7
- export const Queue = Object.freeze({
8
- jobs: [],
9
- /**
10
- * Add a job to the queue
11
- */
12
- add(data) {
13
- const id = generateSecureJobId();
14
- const job = {
15
- id,
16
- data,
17
- timestamp: Date.now(),
18
- };
19
- // In a real implementation, this would push to Redis/SQS
20
- Queue.jobs.push(job);
21
- Logger.info(`[Queue] Job added: ${id}`);
22
- return id;
23
- },
24
- /**
25
- * Process jobs (Placeholder)
26
- */
27
- async process(handler) {
28
- Logger.info('[Queue] Processing jobs...');
29
- const jobsToProcess = [...Queue.jobs];
30
- Queue.jobs.length = 0;
31
- await Promise.all(jobsToProcess.map(async (job) => handler(job)));
32
- },
33
- });
@@ -1,47 +0,0 @@
1
- // TEMPLATE_START
2
-
3
- import { generateSecureJobId } from '@zintrust/core';
4
- import { Logger } from '@zintrust/core';
5
-
6
- export interface QueueJob {
7
- id: string;
8
- data: unknown;
9
- timestamp: number;
10
- }
11
-
12
- /**
13
- * Simple In-Memory Queue
14
- * For production, replace with Redis or similar.
15
- */
16
- export const Queue = Object.freeze({
17
- jobs: [] as QueueJob[],
18
-
19
- /**
20
- * Add a job to the queue
21
- */
22
- add<T>(data: T): string {
23
- const id = generateSecureJobId();
24
- const job: QueueJob = {
25
- id,
26
- data,
27
- timestamp: Date.now(),
28
- };
29
-
30
- // In a real implementation, this would push to Redis/SQS
31
- Queue.jobs.push(job);
32
- Logger.info(`[Queue] Job added: ${id}`);
33
- return id;
34
- },
35
-
36
- /**
37
- * Process jobs (Placeholder)
38
- */
39
- async process(handler: (job: QueueJob) => Promise<void>): Promise<void> {
40
- Logger.info('[Queue] Processing jobs...');
41
- const jobsToProcess = [...Queue.jobs];
42
- Queue.jobs.length = 0;
43
- await Promise.all(jobsToProcess.map(async (job) => handler(job)));
44
- },
45
- });
46
-
47
- // TEMPLATE_END
@@ -1,17 +0,0 @@
1
- export declare const loadTemplate: (name: string) => {
2
- subject?: string;
3
- preheader?: string;
4
- variables?: string[];
5
- content: string;
6
- };
7
- export { listTemplates, renderTemplate } from '../../templates/markdown/registry';
8
- declare const _default: {
9
- loadTemplate: (name: string) => {
10
- subject?: string;
11
- preheader?: string;
12
- variables?: string[];
13
- content: string;
14
- };
15
- };
16
- export default _default;
17
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/tools/mail/templates/markdown/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GACvB,MAAM,MAAM,KACX;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAkD/E,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;;yBArD1E,MAAM,KACX;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;;AAsDlF,wBAAgC"}
@@ -1,49 +0,0 @@
1
- import { readFileSync } from '../../../../node-singletons/fs.js';
2
- import { join } from '../../../../node-singletons/path.js';
3
- export const loadTemplate = (name) => {
4
- // name e.g. 'auth/welcome'
5
- const parts = name.split('/');
6
- // Safe parser for top comment metadata <!-- Key: Value --> lines to avoid regex backtracking
7
- const dir = join(process.cwd(), 'src', 'tools', 'mail', 'templates', 'markdown', ...parts.slice(0, -1));
8
- const leaf = parts.at(-1) ?? '';
9
- const filePath = join(dir, `${leaf}.md`);
10
- const raw = readFileSync(filePath, 'utf-8');
11
- const meta = {};
12
- const parseMetaLine = (line) => {
13
- // Must start with <!-- and end with --> exactly; trim the inner part and split at first colon
14
- if (!line.startsWith('<!--') || !line.endsWith('-->'))
15
- return null;
16
- const inner = line.slice('<!--'.length, -'-->'.length).trim();
17
- const idx = inner.indexOf(':');
18
- if (idx === -1)
19
- return null;
20
- const key = inner.slice(0, idx).trim().toLowerCase();
21
- const val = inner.slice(idx + 1).trim();
22
- if (!key)
23
- return null;
24
- return [key, val];
25
- };
26
- // Parse top comment metadata <!-- Key: Value --> lines
27
- const lines = raw.split(/\r?\n/);
28
- let i = 0;
29
- for (; i < lines.length; i++) {
30
- const kv = parseMetaLine(lines[i]);
31
- if (!kv)
32
- break;
33
- const [key, val] = kv;
34
- if (key === 'subject')
35
- meta.subject = val;
36
- if (key === 'preheader')
37
- meta.preheader = val;
38
- if (key === 'variables') {
39
- meta.variables = val
40
- .split(',')
41
- .map((s) => s.trim())
42
- .filter(Boolean);
43
- }
44
- }
45
- const content = lines.slice(i).join('\n').trim();
46
- return { content, ...meta };
47
- };
48
- export { listTemplates, renderTemplate } from '../../templates/markdown/registry.js';
49
- export default { loadTemplate };
@@ -1,15 +0,0 @@
1
- import { loadTemplate } from '../../templates/markdown';
2
- export declare const listTemplates: () => string[];
3
- export declare const renderTemplate: (name: string, vars?: Record<string, unknown>) => {
4
- html: string;
5
- meta: ReturnType<typeof loadTemplate>;
6
- };
7
- declare const _default: {
8
- listTemplates: () => string[];
9
- renderTemplate: (name: string, vars?: Record<string, unknown>) => {
10
- html: string;
11
- meta: ReturnType<typeof loadTemplate>;
12
- };
13
- };
14
- export default _default;
15
- //# sourceMappingURL=registry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../../../../src/tools/mail/templates/markdown/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AA2BxD,eAAO,MAAM,aAAa,QAAO,MAAM,EAEtC,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,OAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,KACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;CAKvD,CAAC;;yBAZ+B,MAAM,EAAE;2BAKjC,MAAM,SACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;KAAE;;AAO1D,wBAAiD"}
@@ -1,34 +0,0 @@
1
- import { loadTemplate } from '../../templates/markdown/index.js';
2
- import { validateTemplateMeta } from '../../templates/markdown/validator.js';
3
- import { readdirSync, statSync } from '../../../../node-singletons/fs.js';
4
- import { join, relative } from '../../../../node-singletons/path.js';
5
- import { MarkdownRenderer } from '../../../templates/index.js';
6
- const BASE = join(process.cwd(), 'src', 'tools', 'mail', 'templates', 'markdown');
7
- const walkDir = (dir, base = dir) => {
8
- const entries = readdirSync(dir);
9
- let files = [];
10
- for (const e of entries) {
11
- const p = join(dir, e);
12
- const s = statSync(p);
13
- if (s.isDirectory()) {
14
- files = files.concat(walkDir(p, base));
15
- continue;
16
- }
17
- if (e.endsWith('.md')) {
18
- const rel = relative(base, p).replaceAll('\\', '/');
19
- const withoutExt = rel.toLowerCase().endsWith('.md') ? rel.slice(0, -3) : rel;
20
- files.push(withoutExt);
21
- }
22
- }
23
- return files;
24
- };
25
- export const listTemplates = () => {
26
- return walkDir(BASE);
27
- };
28
- export const renderTemplate = (name, vars = {}) => {
29
- const tpl = loadTemplate(name);
30
- validateTemplateMeta(name, tpl);
31
- const html = MarkdownRenderer.render(tpl.content, vars);
32
- return { html, meta: tpl };
33
- };
34
- export default { listTemplates, renderTemplate };
@@ -1,16 +0,0 @@
1
- export declare const validateTemplateMeta: (name: string, tpl: {
2
- subject?: string;
3
- preheader?: string;
4
- variables?: string[];
5
- content: string;
6
- }) => true;
7
- declare const _default: {
8
- validateTemplateMeta: (name: string, tpl: {
9
- subject?: string;
10
- preheader?: string;
11
- variables?: string[];
12
- content: string;
13
- }) => true;
14
- };
15
- export default _default;
16
- //# sourceMappingURL=validator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../../../../src/tools/mail/templates/markdown/validator.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,EACZ,KAAK;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,KACA,IA0BF,CAAC;;iCAjCM,MAAM,OACP;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;KACjB,KACA,IAAI;;AA4BP,wBAAwC"}