@getstrata/core 2.1.0 → 2.2.1
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/CHANGELOG.md +40 -0
- package/dist/core/cache/createCacheStore.d.ts +3 -1
- package/dist/core/cache/redisCacheStore.d.ts +21 -8
- package/dist/core/cache/repository.d.ts +3 -2
- package/dist/core/cache/store.d.ts +4 -1
- package/dist/core/cache/taggedCache.d.ts +1 -1
- package/dist/core/contracts/di.d.ts +4 -2
- package/dist/core/contracts/serviceTokens.d.ts +7 -1
- package/dist/core/database/baseRepository.d.ts +0 -1
- package/dist/core/database/index.d.ts +1 -1
- package/dist/core/database/model.d.ts +51 -22
- package/dist/core/database/repositoryQuery.d.ts +16 -1
- package/dist/core/database/types.d.ts +25 -2
- package/dist/core/database/whereBuilder.d.ts +5 -5
- package/dist/core/events/deferredModelEvents.d.ts +2 -1
- package/dist/core/http/loginThrottleMiddleware.d.ts +6 -5
- package/dist/core/http/memoryThrottleMiddleware.d.ts +11 -3
- package/dist/core/http/requestMetaContext.d.ts +2 -0
- package/dist/core/http/scimThrottleMiddleware.d.ts +12 -3
- package/dist/core/http/throttleMiddleware.d.ts +24 -6
- package/dist/core/lifecycle/gracefulShutdown.d.ts +33 -5
- package/dist/core/queue/createAppQueue.d.ts +2 -1
- package/dist/core/queue/failedJobService.d.ts +3 -1
- package/dist/core/queue/index.d.ts +17 -2
- package/dist/core/queue/jobRunner.d.ts +7 -1
- package/dist/core/queue/publicQueue.d.ts +2 -1
- package/dist/core/queue/queueConfig.d.ts +3 -0
- package/dist/core/queue/redisQueue.d.ts +6 -7
- package/dist/core/queue/redisQueueKeys.d.ts +8 -0
- package/dist/core/queue/redisStreams.d.ts +73 -0
- package/dist/core/queue/resilientQueue.d.ts +2 -2
- package/dist/core/queue/types.d.ts +1 -0
- package/dist/core/runtime/applicationRegistry.d.ts +2 -1
- package/dist/core/runtime/boundedThrottleStore.d.ts +29 -0
- package/dist/core/scheduler/leases.d.ts +40 -0
- package/dist/core/scheduler/schedule.d.ts +29 -5
- package/dist/core/tenant/publicTenantHost.d.ts +11 -0
- package/dist/core/tenant/tenantContext.d.ts +5 -4
- package/dist/core/tenant/tenantMiddleware.d.ts +11 -1
- package/dist/core/tracing/otel.d.ts +28 -26
- package/dist/core/tracing/tracingMiddleware.d.ts +4 -1
- package/dist/entries/audit/exportAuditLogs.js +14 -2
- package/dist/entries/auth/basicAuthGuard.js +81 -0
- package/dist/entries/auth/jwtGuard.js +81 -0
- package/dist/entries/auth/scimAuthMiddleware.js +17 -7
- package/dist/entries/auth/sessionGuard.js +81 -0
- package/dist/entries/cache/createCacheStore.js +365 -119
- package/dist/entries/cache/repository.js +5 -0
- package/dist/entries/contracts/serviceTokens.js +85 -0
- package/dist/entries/database/factory.js +0 -3
- package/dist/entries/database/model.js +1 -2486
- package/dist/entries/database/repositoryQuery.js +67 -9
- package/dist/entries/http/bodySizeLimitMiddleware.js +76 -10
- package/dist/entries/http/memoryThrottleMiddleware.js +276 -21
- package/dist/entries/http/scimThrottleMiddleware.js +576 -54
- package/dist/entries/http/throttleMiddleware.js +65 -16
- package/dist/entries/jobs/exportAuditLogsJob.js +44 -7
- package/dist/entries/jobs/invalidateCacheTagsJob.js +30 -5
- package/dist/entries/queue/createAppQueue.js +748 -72
- package/dist/entries/queue/failedJobRepository.js +1 -1
- package/dist/entries/queue/failedJobService.js +5 -1
- package/dist/entries/queue/jobRunner.js +67 -2
- package/dist/entries/queue/publicQueue.js +746 -71
- package/dist/entries/queue/queueMetrics.js +761 -78
- package/dist/entries/queue/redisQueue.js +768 -148
- package/dist/entries/queue.js +30 -5
- package/dist/entries/scheduler/schedule.js +1 -72
- package/dist/entries/tenant/databaseTenantContext.js +14 -2
- package/dist/entries/tenant/tenantDatabaseScope.js +14 -2
- package/dist/entries/tracing/tracingMiddleware.js +186 -454
- package/dist/framework/public-api.d.ts +14 -10
- package/dist/index.js +2444 -688
- package/dist/types/services.d.ts +3 -3
- package/package.json +17 -8
package/dist/entries/queue.js
CHANGED
|
@@ -57,12 +57,37 @@ class SyncQueue {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
class AsyncQueue {
|
|
60
|
+
active = new Set;
|
|
61
|
+
closing;
|
|
62
|
+
closed = false;
|
|
63
|
+
assertOpen() {
|
|
64
|
+
if (this.closed)
|
|
65
|
+
throw new Error("Async queue is closed.");
|
|
66
|
+
}
|
|
67
|
+
enqueue(task, onError) {
|
|
68
|
+
this.assertOpen();
|
|
69
|
+
const running = new Promise((resolve) => {
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
Promise.resolve().then(task).catch(onError).finally(resolve);
|
|
72
|
+
}, 0);
|
|
73
|
+
});
|
|
74
|
+
this.active.add(running);
|
|
75
|
+
running.then(() => {
|
|
76
|
+
this.active.delete(running);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
60
79
|
async dispatch(job, payload) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
80
|
+
this.enqueue(() => job.handle(payload), (error) => {
|
|
81
|
+
console.error("[AsyncQueue] Job failed:", error);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
close() {
|
|
85
|
+
this.closing ??= (async () => {
|
|
86
|
+
while (this.active.size)
|
|
87
|
+
await Promise.all([...this.active]);
|
|
88
|
+
this.closed = true;
|
|
89
|
+
})();
|
|
90
|
+
return this.closing;
|
|
66
91
|
}
|
|
67
92
|
}
|
|
68
93
|
function createQueue(driver) {
|
|
@@ -1,72 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// ../../src/core/scheduler/osCron.ts
|
|
3
|
-
var DEFAULT_SCHEDULE_RUN_EXPRESSION = "* * * * *";
|
|
4
|
-
var OS_CRON_JOB_TITLE = "getstrata-schedule-run";
|
|
5
|
-
function parseScheduleExpression(expression, from = new Date) {
|
|
6
|
-
return Bun.cron.parse(expression, from);
|
|
7
|
-
}
|
|
8
|
-
function minuteWindow(now) {
|
|
9
|
-
const start = new Date(now);
|
|
10
|
-
start.setSeconds(0, 0);
|
|
11
|
-
return { start, end: new Date(start.getTime() + 60000) };
|
|
12
|
-
}
|
|
13
|
-
function isScheduleExpressionDue(expression, now = new Date) {
|
|
14
|
-
const { start, end } = minuteWindow(now);
|
|
15
|
-
const next = parseScheduleExpression(expression, new Date(start.getTime() - 1));
|
|
16
|
-
if (!next) {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
const timestamp = next.getTime();
|
|
20
|
-
return timestamp >= start.getTime() && timestamp < end.getTime();
|
|
21
|
-
}
|
|
22
|
-
function assertScheduleExpression(expression) {
|
|
23
|
-
try {
|
|
24
|
-
const next = parseScheduleExpression(expression);
|
|
25
|
-
if (!(next instanceof Date) || Number.isNaN(next.getTime())) {
|
|
26
|
-
throw new Error("unparsable");
|
|
27
|
-
}
|
|
28
|
-
} catch {
|
|
29
|
-
throw new Error(`Unsupported schedule expression "${expression}".`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function registerInProcessScheduleRunner(run, expression = DEFAULT_SCHEDULE_RUN_EXPRESSION) {
|
|
33
|
-
const register = Bun.cron;
|
|
34
|
-
return register(expression, async () => {
|
|
35
|
-
await run();
|
|
36
|
-
}).unref();
|
|
37
|
-
}
|
|
38
|
-
async function installOsScheduleRunner(workerScriptPath, expression = DEFAULT_SCHEDULE_RUN_EXPRESSION, title = OS_CRON_JOB_TITLE) {
|
|
39
|
-
await Bun.cron(workerScriptPath, expression, title);
|
|
40
|
-
}
|
|
41
|
-
async function uninstallOsScheduleRunner(title = OS_CRON_JOB_TITLE) {
|
|
42
|
-
await Bun.cron.remove(title);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// ../../src/core/scheduler/schedule.ts
|
|
46
|
-
class Schedule {
|
|
47
|
-
tasks = [];
|
|
48
|
-
command(expression, name, run) {
|
|
49
|
-
assertScheduleExpression(expression);
|
|
50
|
-
this.tasks.push({ expression, name, run });
|
|
51
|
-
return this;
|
|
52
|
-
}
|
|
53
|
-
dueTasks(now = new Date) {
|
|
54
|
-
return this.tasks.filter((task) => isScheduleExpressionDue(task.expression, now));
|
|
55
|
-
}
|
|
56
|
-
tasksList() {
|
|
57
|
-
return [...this.tasks];
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
var appSchedule = new Schedule;
|
|
61
|
-
async function runDueScheduledTasks(schedule = appSchedule, now = new Date) {
|
|
62
|
-
const due = schedule.dueTasks(now);
|
|
63
|
-
for (const task of due) {
|
|
64
|
-
await task.run();
|
|
65
|
-
}
|
|
66
|
-
return due.length;
|
|
67
|
-
}
|
|
68
|
-
export {
|
|
69
|
-
Schedule,
|
|
70
|
-
appSchedule,
|
|
71
|
-
runDueScheduledTasks
|
|
72
|
-
};
|
|
1
|
+
export * from "../../index.js";
|
|
@@ -306,9 +306,12 @@ async function runWithDeferredModelEvents(callback) {
|
|
|
306
306
|
const existing = deferredModelEvents.getStore();
|
|
307
307
|
if (existing) {
|
|
308
308
|
existing.frames.push([]);
|
|
309
|
+
existing.rollbackFrames.push([]);
|
|
309
310
|
try {
|
|
310
311
|
const result = await callback();
|
|
311
312
|
const nested = existing.frames.pop() ?? [];
|
|
313
|
+
const rollback = existing.rollbackFrames.pop() ?? [];
|
|
314
|
+
existing.rollbackFrames.at(-1)?.push(...rollback);
|
|
312
315
|
const parent = existing.frames[existing.frames.length - 1];
|
|
313
316
|
if (parent) {
|
|
314
317
|
parent.push(...nested);
|
|
@@ -316,11 +319,20 @@ async function runWithDeferredModelEvents(callback) {
|
|
|
316
319
|
return result;
|
|
317
320
|
} catch (error) {
|
|
318
321
|
existing.frames.pop();
|
|
322
|
+
for (const rollback of (existing.rollbackFrames.pop() ?? []).reverse())
|
|
323
|
+
rollback();
|
|
319
324
|
throw error;
|
|
320
325
|
}
|
|
321
326
|
}
|
|
322
|
-
const state = { frames: [[]] };
|
|
323
|
-
|
|
327
|
+
const state = { frames: [[]], rollbackFrames: [[]] };
|
|
328
|
+
let result;
|
|
329
|
+
try {
|
|
330
|
+
result = await deferredModelEvents.run(state, callback);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
for (const rollback of (state.rollbackFrames[0] ?? []).reverse())
|
|
333
|
+
rollback();
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
324
336
|
await dispatchQueuedModelEvents(state.frames[0] ?? []);
|
|
325
337
|
return result;
|
|
326
338
|
}
|
|
@@ -240,9 +240,12 @@ async function runWithDeferredModelEvents(callback) {
|
|
|
240
240
|
const existing = deferredModelEvents.getStore();
|
|
241
241
|
if (existing) {
|
|
242
242
|
existing.frames.push([]);
|
|
243
|
+
existing.rollbackFrames.push([]);
|
|
243
244
|
try {
|
|
244
245
|
const result = await callback();
|
|
245
246
|
const nested = existing.frames.pop() ?? [];
|
|
247
|
+
const rollback = existing.rollbackFrames.pop() ?? [];
|
|
248
|
+
existing.rollbackFrames.at(-1)?.push(...rollback);
|
|
246
249
|
const parent = existing.frames[existing.frames.length - 1];
|
|
247
250
|
if (parent) {
|
|
248
251
|
parent.push(...nested);
|
|
@@ -250,11 +253,20 @@ async function runWithDeferredModelEvents(callback) {
|
|
|
250
253
|
return result;
|
|
251
254
|
} catch (error) {
|
|
252
255
|
existing.frames.pop();
|
|
256
|
+
for (const rollback of (existing.rollbackFrames.pop() ?? []).reverse())
|
|
257
|
+
rollback();
|
|
253
258
|
throw error;
|
|
254
259
|
}
|
|
255
260
|
}
|
|
256
|
-
const state = { frames: [[]] };
|
|
257
|
-
|
|
261
|
+
const state = { frames: [[]], rollbackFrames: [[]] };
|
|
262
|
+
let result;
|
|
263
|
+
try {
|
|
264
|
+
result = await deferredModelEvents.run(state, callback);
|
|
265
|
+
} catch (error) {
|
|
266
|
+
for (const rollback of (state.rollbackFrames[0] ?? []).reverse())
|
|
267
|
+
rollback();
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
258
270
|
await dispatchQueuedModelEvents(state.frames[0] ?? []);
|
|
259
271
|
return result;
|
|
260
272
|
}
|