@guren/server 1.0.0-rc.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Application-DtWDHXr1.d.ts → Application-BnsyCKXY.d.ts} +79 -8
- package/dist/AuthManager-SfhCNkAU.d.ts +79 -0
- package/dist/{BroadcastManager-AkIWUGJo.d.ts → BroadcastManager-CGWl9rUO.d.ts} +5 -0
- package/dist/{ConsoleKernel-CqCVrdZs.d.ts → ConsoleKernel-BDtBETjm.d.ts} +1 -1
- package/dist/{Gate-CNkBYf8m.d.ts → Gate-CynjZCtS.d.ts} +5 -0
- package/dist/{I18nManager-Dtgzsf5n.d.ts → I18nManager-BiSoczfV.d.ts} +6 -1
- package/dist/McpServiceProvider-JW6PDVMD.js +7 -0
- package/dist/api-token-BSSCLlFW.d.ts +541 -0
- package/dist/auth/index.d.ts +9 -327
- package/dist/auth/index.js +59 -6684
- package/dist/authorization/index.d.ts +2 -2
- package/dist/authorization/index.js +19 -604
- package/dist/broadcasting/index.d.ts +2 -2
- package/dist/broadcasting/index.js +12 -895
- package/dist/cache/index.js +8 -809
- package/dist/chunk-2T6JN4VR.js +1563 -0
- package/dist/chunk-44F7JQ7I.js +950 -0
- package/dist/chunk-74HTZG3V.js +331 -0
- package/dist/chunk-A3ISJVEV.js +598 -0
- package/dist/chunk-CSDKWLFD.js +652 -0
- package/dist/chunk-CSRQTEQA.js +839 -0
- package/dist/chunk-DAQKYKLH.js +182 -0
- package/dist/chunk-EDRGAM6G.js +647 -0
- package/dist/chunk-EGU5KB7V.js +818 -0
- package/dist/chunk-H32L2NE3.js +372 -0
- package/dist/chunk-HKQSAFSN.js +837 -0
- package/dist/chunk-IOTWFHZU.js +558 -0
- package/dist/chunk-ONSDE37A.js +125 -0
- package/dist/chunk-QQKTH5KX.js +114 -0
- package/dist/chunk-R2TCP7D7.js +409 -0
- package/dist/chunk-SIP34GBE.js +380 -0
- package/dist/chunk-THSX7OOR.js +454 -0
- package/dist/chunk-UY3AZSYL.js +14 -0
- package/dist/chunk-VT5KRDPH.js +134 -0
- package/dist/chunk-VXXZIXAP.js +255 -0
- package/dist/chunk-WJJ5CTNI.js +907 -0
- package/dist/chunk-WVY45EIW.js +359 -0
- package/dist/chunk-ZRBLZY3M.js +462 -0
- package/dist/client-CKXJLsTe.d.ts +232 -0
- package/dist/email-verification-CAeArjui.d.ts +327 -0
- package/dist/encryption/index.js +48 -556
- package/dist/errors-JOOPDDQ6.js +34 -0
- package/dist/events/index.js +14 -316
- package/dist/health/index.js +12 -367
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +14 -583
- package/dist/index.d.ts +37 -239
- package/dist/index.js +2873 -19166
- package/dist/lambda/index.d.ts +9 -7
- package/dist/lambda/index.js +4 -9
- package/dist/logging/index.js +12 -545
- package/dist/mail/index.d.ts +29 -1
- package/dist/mail/index.js +15 -684
- package/dist/mcp/index.d.ts +7 -5
- package/dist/mcp/index.js +5 -378
- package/dist/notifications/index.d.ts +8 -6
- package/dist/notifications/index.js +13 -730
- package/dist/queue/index.d.ts +37 -7
- package/dist/queue/index.js +22 -940
- package/dist/redis/index.d.ts +366 -0
- package/dist/redis/index.js +597 -0
- package/dist/runtime/index.d.ts +8 -6
- package/dist/runtime/index.js +26 -244
- package/dist/scheduling/index.js +14 -822
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +6 -824
- package/package.json +15 -7
- package/dist/api-token-JOif2CtG.d.ts +0 -1792
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// src/encryption/Hash.ts
|
|
2
|
+
import {
|
|
3
|
+
createHash,
|
|
4
|
+
createHmac,
|
|
5
|
+
randomBytes,
|
|
6
|
+
scrypt,
|
|
7
|
+
timingSafeEqual
|
|
8
|
+
} from "crypto";
|
|
9
|
+
import { promisify } from "util";
|
|
10
|
+
var scryptAsync = promisify(scrypt);
|
|
11
|
+
function hash(value, algorithm = "sha256", encoding = "hex") {
|
|
12
|
+
return createHash(algorithm).update(value).digest(encoding);
|
|
13
|
+
}
|
|
14
|
+
function hmac(value, key, options = {}) {
|
|
15
|
+
const { algorithm = "sha256", encoding = "hex" } = options;
|
|
16
|
+
return createHmac(algorithm, key).update(value).digest(encoding);
|
|
17
|
+
}
|
|
18
|
+
function verifyHmac(value, signature, key, options = {}) {
|
|
19
|
+
const expected = hmac(value, key, options);
|
|
20
|
+
return secureCompare(signature, expected);
|
|
21
|
+
}
|
|
22
|
+
function sha256(value) {
|
|
23
|
+
return hash(value, "sha256");
|
|
24
|
+
}
|
|
25
|
+
function sha512(value) {
|
|
26
|
+
return hash(value, "sha512");
|
|
27
|
+
}
|
|
28
|
+
function md5(value) {
|
|
29
|
+
return hash(value, "md5");
|
|
30
|
+
}
|
|
31
|
+
async function hashPassword(password, options = {}) {
|
|
32
|
+
const {
|
|
33
|
+
cost = 16384,
|
|
34
|
+
// N
|
|
35
|
+
memory = 8,
|
|
36
|
+
// r (block size)
|
|
37
|
+
saltLength = 16,
|
|
38
|
+
keyLength = 64
|
|
39
|
+
} = options;
|
|
40
|
+
const salt = randomBytes(saltLength);
|
|
41
|
+
const derived = await scryptAsync(password, salt, keyLength, {
|
|
42
|
+
N: cost,
|
|
43
|
+
r: memory,
|
|
44
|
+
p: 1
|
|
45
|
+
});
|
|
46
|
+
const params = `N=${cost},r=${memory},p=1`;
|
|
47
|
+
return `$scrypt$${params}$${salt.toString("base64")}$${derived.toString("base64")}`;
|
|
48
|
+
}
|
|
49
|
+
async function verifyPassword(password, hash2) {
|
|
50
|
+
if (!hash2.startsWith("$scrypt$")) {
|
|
51
|
+
throw new Error("Invalid password hash format.");
|
|
52
|
+
}
|
|
53
|
+
const parts = hash2.split("$");
|
|
54
|
+
if (parts.length !== 5) {
|
|
55
|
+
throw new Error("Invalid password hash format.");
|
|
56
|
+
}
|
|
57
|
+
const [, , paramsStr, saltB64, hashB64] = parts;
|
|
58
|
+
const params = {};
|
|
59
|
+
for (const param of paramsStr.split(",")) {
|
|
60
|
+
const [key, value] = param.split("=");
|
|
61
|
+
params[key] = parseInt(value, 10);
|
|
62
|
+
}
|
|
63
|
+
const salt = Buffer.from(saltB64, "base64");
|
|
64
|
+
const expectedHash = Buffer.from(hashB64, "base64");
|
|
65
|
+
const derived = await scryptAsync(password, salt, expectedHash.length, {
|
|
66
|
+
N: params.N,
|
|
67
|
+
r: params.r,
|
|
68
|
+
p: params.p ?? 1
|
|
69
|
+
});
|
|
70
|
+
return timingSafeEqual(derived, expectedHash);
|
|
71
|
+
}
|
|
72
|
+
function needsRehash(hash2, options = {}) {
|
|
73
|
+
const { cost = 16384, memory = 8 } = options;
|
|
74
|
+
if (!hash2.startsWith("$scrypt$")) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
const parts = hash2.split("$");
|
|
78
|
+
if (parts.length !== 5) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
const paramsStr = parts[2];
|
|
82
|
+
const params = {};
|
|
83
|
+
for (const param of paramsStr.split(",")) {
|
|
84
|
+
const [key, value] = param.split("=");
|
|
85
|
+
params[key] = parseInt(value, 10);
|
|
86
|
+
}
|
|
87
|
+
return params.N !== cost || params.r !== memory;
|
|
88
|
+
}
|
|
89
|
+
function secureCompare(a, b) {
|
|
90
|
+
if (a.length !== b.length) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const bufA = Buffer.from(a);
|
|
94
|
+
const bufB = Buffer.from(b);
|
|
95
|
+
return timingSafeEqual(bufA, bufB);
|
|
96
|
+
}
|
|
97
|
+
function check(value, hash2, algorithm = "sha256") {
|
|
98
|
+
const computed = createHash(algorithm).update(value).digest("hex");
|
|
99
|
+
return secureCompare(computed, hash2);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
hash,
|
|
104
|
+
hmac,
|
|
105
|
+
verifyHmac,
|
|
106
|
+
sha256,
|
|
107
|
+
sha512,
|
|
108
|
+
md5,
|
|
109
|
+
hashPassword,
|
|
110
|
+
verifyPassword,
|
|
111
|
+
needsRehash,
|
|
112
|
+
secureCompare,
|
|
113
|
+
check
|
|
114
|
+
};
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
// src/container/Container.ts
|
|
2
|
+
var Container = class _Container {
|
|
3
|
+
bindings = /* @__PURE__ */ new Map();
|
|
4
|
+
aliases = /* @__PURE__ */ new Map();
|
|
5
|
+
tags = /* @__PURE__ */ new Map();
|
|
6
|
+
contextualBindings = [];
|
|
7
|
+
resolvingStack = [];
|
|
8
|
+
scopedInstances = [];
|
|
9
|
+
fakes = /* @__PURE__ */ new Map();
|
|
10
|
+
/** @internal Used by ProviderManager to resolve deferred providers on demand */
|
|
11
|
+
deferredProviderLoader = null;
|
|
12
|
+
/**
|
|
13
|
+
* Bind a service to the container.
|
|
14
|
+
* Each resolution creates a new instance.
|
|
15
|
+
*/
|
|
16
|
+
bind(key, factory) {
|
|
17
|
+
this.bindings.set(key, {
|
|
18
|
+
factory,
|
|
19
|
+
singleton: false
|
|
20
|
+
});
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Bind a singleton service to the container.
|
|
25
|
+
* Only one instance is created and reused.
|
|
26
|
+
*/
|
|
27
|
+
singleton(key, factory) {
|
|
28
|
+
this.bindings.set(key, {
|
|
29
|
+
factory,
|
|
30
|
+
singleton: true
|
|
31
|
+
});
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Bind an existing instance to the container.
|
|
36
|
+
*/
|
|
37
|
+
instance(key, value) {
|
|
38
|
+
this.bindings.set(key, {
|
|
39
|
+
factory: () => value,
|
|
40
|
+
singleton: true,
|
|
41
|
+
instance: value
|
|
42
|
+
});
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
make(key) {
|
|
46
|
+
if (this.fakes.has(key)) {
|
|
47
|
+
return this.fakes.get(key);
|
|
48
|
+
}
|
|
49
|
+
const resolvedKey = this.resolveAlias(key);
|
|
50
|
+
if (resolvedKey !== key && this.fakes.has(resolvedKey)) {
|
|
51
|
+
return this.fakes.get(resolvedKey);
|
|
52
|
+
}
|
|
53
|
+
let binding = this.bindings.get(resolvedKey);
|
|
54
|
+
if (!binding && this.deferredProviderLoader) {
|
|
55
|
+
let resolved = false;
|
|
56
|
+
this.deferredProviderLoader(resolvedKey).then(() => {
|
|
57
|
+
resolved = true;
|
|
58
|
+
});
|
|
59
|
+
if (resolved) {
|
|
60
|
+
binding = this.bindings.get(resolvedKey);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!binding) {
|
|
64
|
+
throw new Error(`Service "${key}" not found in container`);
|
|
65
|
+
}
|
|
66
|
+
if (binding.singleton && binding.instance !== void 0) {
|
|
67
|
+
return binding.instance;
|
|
68
|
+
}
|
|
69
|
+
if (this.scopedInstances.length > 0) {
|
|
70
|
+
const currentScope = this.scopedInstances[this.scopedInstances.length - 1];
|
|
71
|
+
if (currentScope.has(resolvedKey)) {
|
|
72
|
+
return currentScope.get(resolvedKey);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const contextualFactory = this.findContextualBinding(resolvedKey);
|
|
76
|
+
this.resolvingStack.push(resolvedKey);
|
|
77
|
+
try {
|
|
78
|
+
const factory = contextualFactory ?? binding.factory;
|
|
79
|
+
const instance = factory(this);
|
|
80
|
+
if (binding.singleton) {
|
|
81
|
+
binding.instance = instance;
|
|
82
|
+
}
|
|
83
|
+
if (this.scopedInstances.length > 0 && !binding.singleton) {
|
|
84
|
+
const currentScope = this.scopedInstances[this.scopedInstances.length - 1];
|
|
85
|
+
currentScope.set(resolvedKey, instance);
|
|
86
|
+
}
|
|
87
|
+
return instance;
|
|
88
|
+
} finally {
|
|
89
|
+
this.resolvingStack.pop();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Resolve a service with additional parameters.
|
|
94
|
+
*/
|
|
95
|
+
makeWith(key, params) {
|
|
96
|
+
const resolvedKey = this.resolveAlias(key);
|
|
97
|
+
const binding = this.bindings.get(resolvedKey);
|
|
98
|
+
if (!binding) {
|
|
99
|
+
throw new Error(`Service "${key}" not found in container`);
|
|
100
|
+
}
|
|
101
|
+
const tempContainer = new _Container();
|
|
102
|
+
for (const [k, v] of this.bindings) {
|
|
103
|
+
tempContainer.bindings.set(k, { ...v });
|
|
104
|
+
}
|
|
105
|
+
for (const [paramKey, paramValue] of Object.entries(params)) {
|
|
106
|
+
tempContainer.instance(paramKey, paramValue);
|
|
107
|
+
}
|
|
108
|
+
return binding.factory(tempContainer);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check if a service is bound in the container.
|
|
112
|
+
*/
|
|
113
|
+
has(key) {
|
|
114
|
+
const resolvedKey = this.resolveAlias(key);
|
|
115
|
+
return this.bindings.has(resolvedKey);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Create an alias for a service.
|
|
119
|
+
*/
|
|
120
|
+
alias(alias, key) {
|
|
121
|
+
if (alias === key) {
|
|
122
|
+
throw new Error("Alias cannot be the same as the key");
|
|
123
|
+
}
|
|
124
|
+
this.aliases.set(alias, key);
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Tag multiple services with a tag name.
|
|
129
|
+
*/
|
|
130
|
+
tag(keys, tagName) {
|
|
131
|
+
let taggedKeys = this.tags.get(tagName);
|
|
132
|
+
if (!taggedKeys) {
|
|
133
|
+
taggedKeys = /* @__PURE__ */ new Set();
|
|
134
|
+
this.tags.set(tagName, taggedKeys);
|
|
135
|
+
}
|
|
136
|
+
for (const key of keys) {
|
|
137
|
+
taggedKeys.add(key);
|
|
138
|
+
}
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Resolve all services with a given tag.
|
|
143
|
+
*/
|
|
144
|
+
tagged(tagName) {
|
|
145
|
+
const taggedKeys = this.tags.get(tagName);
|
|
146
|
+
if (!taggedKeys) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
return Array.from(taggedKeys).map((key) => this.make(key));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Define a contextual binding.
|
|
153
|
+
*/
|
|
154
|
+
when(concrete) {
|
|
155
|
+
return {
|
|
156
|
+
needs: (abstract) => {
|
|
157
|
+
return {
|
|
158
|
+
give: (factoryOrValue) => {
|
|
159
|
+
const factory = typeof factoryOrValue === "function" ? factoryOrValue : () => factoryOrValue;
|
|
160
|
+
this.contextualBindings.push({
|
|
161
|
+
concrete,
|
|
162
|
+
needs: abstract,
|
|
163
|
+
factory
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Run a callback within a scoped context.
|
|
172
|
+
* Services resolved within the scope are cached and released when the scope ends.
|
|
173
|
+
*/
|
|
174
|
+
scoped(callback) {
|
|
175
|
+
this.scopedInstances.push(/* @__PURE__ */ new Map());
|
|
176
|
+
try {
|
|
177
|
+
return callback();
|
|
178
|
+
} finally {
|
|
179
|
+
this.scopedInstances.pop();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Run an async callback within a scoped context.
|
|
184
|
+
*/
|
|
185
|
+
async scopedAsync(callback) {
|
|
186
|
+
this.scopedInstances.push(/* @__PURE__ */ new Map());
|
|
187
|
+
try {
|
|
188
|
+
return await callback();
|
|
189
|
+
} finally {
|
|
190
|
+
this.scopedInstances.pop();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
fake(key, instance) {
|
|
194
|
+
this.fakes.set(key, instance);
|
|
195
|
+
return {
|
|
196
|
+
[Symbol.dispose]: () => {
|
|
197
|
+
this.fakes.delete(key);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Check if a service is currently faked.
|
|
203
|
+
*/
|
|
204
|
+
isFaked(key) {
|
|
205
|
+
return this.fakes.has(key);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Remove all fakes.
|
|
209
|
+
*/
|
|
210
|
+
clearFakes() {
|
|
211
|
+
this.fakes.clear();
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Flush all resolved singleton instances.
|
|
215
|
+
*/
|
|
216
|
+
flush() {
|
|
217
|
+
for (const binding of this.bindings.values()) {
|
|
218
|
+
binding.instance = void 0;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Remove a binding from the container.
|
|
223
|
+
*/
|
|
224
|
+
forget(key) {
|
|
225
|
+
const resolvedKey = this.resolveAlias(key);
|
|
226
|
+
this.bindings.delete(resolvedKey);
|
|
227
|
+
return this;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Get all bound service keys.
|
|
231
|
+
*/
|
|
232
|
+
getBindings() {
|
|
233
|
+
return Array.from(this.bindings.keys());
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Get all aliases.
|
|
237
|
+
*/
|
|
238
|
+
getAliases() {
|
|
239
|
+
const result = {};
|
|
240
|
+
for (const [alias, key] of this.aliases) {
|
|
241
|
+
result[alias] = key;
|
|
242
|
+
}
|
|
243
|
+
return result;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Get all tags.
|
|
247
|
+
*/
|
|
248
|
+
getTags() {
|
|
249
|
+
const result = {};
|
|
250
|
+
for (const [tag, keys] of this.tags) {
|
|
251
|
+
result[tag] = Array.from(keys);
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
resolveAlias(key) {
|
|
256
|
+
let resolved = key;
|
|
257
|
+
const seen = /* @__PURE__ */ new Set();
|
|
258
|
+
while (this.aliases.has(resolved)) {
|
|
259
|
+
if (seen.has(resolved)) {
|
|
260
|
+
throw new Error(`Circular alias detected: ${key}`);
|
|
261
|
+
}
|
|
262
|
+
seen.add(resolved);
|
|
263
|
+
resolved = this.aliases.get(resolved);
|
|
264
|
+
}
|
|
265
|
+
return resolved;
|
|
266
|
+
}
|
|
267
|
+
findContextualBinding(needs) {
|
|
268
|
+
if (this.resolvingStack.length === 0) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
const currentConcrete = this.resolvingStack[this.resolvingStack.length - 1];
|
|
272
|
+
for (const binding of this.contextualBindings) {
|
|
273
|
+
if (binding.concrete === currentConcrete && binding.needs === needs) {
|
|
274
|
+
return binding.factory;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
function createContainer() {
|
|
281
|
+
return new Container();
|
|
282
|
+
}
|
|
283
|
+
var globalContainer = null;
|
|
284
|
+
function setContainer(container) {
|
|
285
|
+
globalContainer = container;
|
|
286
|
+
}
|
|
287
|
+
function getContainer() {
|
|
288
|
+
if (!globalContainer) {
|
|
289
|
+
throw new Error("Container not initialized. Call setContainer() first.");
|
|
290
|
+
}
|
|
291
|
+
return globalContainer;
|
|
292
|
+
}
|
|
293
|
+
function resolve(key) {
|
|
294
|
+
return getContainer().make(key);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/queue/Job.ts
|
|
298
|
+
import { randomBytes } from "crypto";
|
|
299
|
+
var globalDriver = null;
|
|
300
|
+
function setQueueDriver(driver) {
|
|
301
|
+
globalDriver = driver;
|
|
302
|
+
}
|
|
303
|
+
function getQueueDriver() {
|
|
304
|
+
return globalDriver;
|
|
305
|
+
}
|
|
306
|
+
function generateJobId() {
|
|
307
|
+
return randomBytes(16).toString("hex");
|
|
308
|
+
}
|
|
309
|
+
var Job = class {
|
|
310
|
+
/**
|
|
311
|
+
* The queue this job should be dispatched to.
|
|
312
|
+
* @default 'default'
|
|
313
|
+
*/
|
|
314
|
+
static queue = "default";
|
|
315
|
+
/**
|
|
316
|
+
* Maximum number of times the job should be attempted.
|
|
317
|
+
* @default 3
|
|
318
|
+
*/
|
|
319
|
+
static maxAttempts = 3;
|
|
320
|
+
/**
|
|
321
|
+
* Backoff strategy for retries.
|
|
322
|
+
* - 'exponential': 2^attempt * 1000ms (1s, 2s, 4s, 8s, ...)
|
|
323
|
+
* - 'linear': attempt * 1000ms (1s, 2s, 3s, 4s, ...)
|
|
324
|
+
* - number: fixed delay in milliseconds
|
|
325
|
+
* @default 'exponential'
|
|
326
|
+
*/
|
|
327
|
+
static backoff = "exponential";
|
|
328
|
+
make(key) {
|
|
329
|
+
return getContainer().make(key);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Dispatch the job to the queue.
|
|
333
|
+
*
|
|
334
|
+
* @param payload - Job payload data
|
|
335
|
+
* @param options - Optional dispatch options
|
|
336
|
+
*/
|
|
337
|
+
static async dispatch(payload, options = {}) {
|
|
338
|
+
const driver = globalDriver;
|
|
339
|
+
if (!driver) {
|
|
340
|
+
throw new Error("Queue driver not configured. Call setQueueDriver() first.");
|
|
341
|
+
}
|
|
342
|
+
const jobId = generateJobId();
|
|
343
|
+
const now = /* @__PURE__ */ new Date();
|
|
344
|
+
const delay = options.delay ?? 0;
|
|
345
|
+
const job = {
|
|
346
|
+
id: jobId,
|
|
347
|
+
name: this.name,
|
|
348
|
+
payload,
|
|
349
|
+
queue: options.queue ?? this.queue,
|
|
350
|
+
attempts: 0,
|
|
351
|
+
maxAttempts: options.maxAttempts ?? this.maxAttempts,
|
|
352
|
+
availableAt: new Date(now.getTime() + delay),
|
|
353
|
+
createdAt: now,
|
|
354
|
+
reservedAt: null
|
|
355
|
+
};
|
|
356
|
+
await driver.push(job);
|
|
357
|
+
return jobId;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Dispatch the job after a delay.
|
|
361
|
+
*
|
|
362
|
+
* @param delayMs - Delay in milliseconds
|
|
363
|
+
* @param payload - Job payload data
|
|
364
|
+
* @param options - Optional dispatch options (delay is overridden)
|
|
365
|
+
*/
|
|
366
|
+
static async dispatchAfter(delayMs, payload, options = {}) {
|
|
367
|
+
return this.dispatch(payload, { ...options, delay: delayMs });
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Calculate the retry delay based on backoff strategy.
|
|
371
|
+
*/
|
|
372
|
+
static calculateRetryDelay(attempts) {
|
|
373
|
+
if (typeof this.backoff === "number") {
|
|
374
|
+
return this.backoff;
|
|
375
|
+
}
|
|
376
|
+
if (this.backoff === "linear") {
|
|
377
|
+
return attempts * 1e3;
|
|
378
|
+
}
|
|
379
|
+
return Math.pow(2, attempts) * 1e3;
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
var jobRegistry = /* @__PURE__ */ new Map();
|
|
383
|
+
function registerJob(jobClass) {
|
|
384
|
+
jobRegistry.set(jobClass.name, jobClass);
|
|
385
|
+
}
|
|
386
|
+
function getJob(name) {
|
|
387
|
+
return jobRegistry.get(name);
|
|
388
|
+
}
|
|
389
|
+
function getRegisteredJobs() {
|
|
390
|
+
return new Map(jobRegistry);
|
|
391
|
+
}
|
|
392
|
+
function clearJobRegistry() {
|
|
393
|
+
jobRegistry.clear();
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export {
|
|
397
|
+
Container,
|
|
398
|
+
createContainer,
|
|
399
|
+
setContainer,
|
|
400
|
+
getContainer,
|
|
401
|
+
resolve,
|
|
402
|
+
setQueueDriver,
|
|
403
|
+
getQueueDriver,
|
|
404
|
+
Job,
|
|
405
|
+
registerJob,
|
|
406
|
+
getJob,
|
|
407
|
+
getRegisteredJobs,
|
|
408
|
+
clearJobRegistry
|
|
409
|
+
};
|