@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.
Files changed (74) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/core/cache/createCacheStore.d.ts +3 -1
  3. package/dist/core/cache/redisCacheStore.d.ts +21 -8
  4. package/dist/core/cache/repository.d.ts +3 -2
  5. package/dist/core/cache/store.d.ts +4 -1
  6. package/dist/core/cache/taggedCache.d.ts +1 -1
  7. package/dist/core/contracts/di.d.ts +4 -2
  8. package/dist/core/contracts/serviceTokens.d.ts +7 -1
  9. package/dist/core/database/baseRepository.d.ts +0 -1
  10. package/dist/core/database/index.d.ts +1 -1
  11. package/dist/core/database/model.d.ts +51 -22
  12. package/dist/core/database/repositoryQuery.d.ts +16 -1
  13. package/dist/core/database/types.d.ts +25 -2
  14. package/dist/core/database/whereBuilder.d.ts +5 -5
  15. package/dist/core/events/deferredModelEvents.d.ts +2 -1
  16. package/dist/core/http/loginThrottleMiddleware.d.ts +6 -5
  17. package/dist/core/http/memoryThrottleMiddleware.d.ts +11 -3
  18. package/dist/core/http/requestMetaContext.d.ts +2 -0
  19. package/dist/core/http/scimThrottleMiddleware.d.ts +12 -3
  20. package/dist/core/http/throttleMiddleware.d.ts +24 -6
  21. package/dist/core/lifecycle/gracefulShutdown.d.ts +33 -5
  22. package/dist/core/queue/createAppQueue.d.ts +2 -1
  23. package/dist/core/queue/failedJobService.d.ts +3 -1
  24. package/dist/core/queue/index.d.ts +17 -2
  25. package/dist/core/queue/jobRunner.d.ts +7 -1
  26. package/dist/core/queue/publicQueue.d.ts +2 -1
  27. package/dist/core/queue/queueConfig.d.ts +3 -0
  28. package/dist/core/queue/redisQueue.d.ts +6 -7
  29. package/dist/core/queue/redisQueueKeys.d.ts +8 -0
  30. package/dist/core/queue/redisStreams.d.ts +73 -0
  31. package/dist/core/queue/resilientQueue.d.ts +2 -2
  32. package/dist/core/queue/types.d.ts +1 -0
  33. package/dist/core/runtime/applicationRegistry.d.ts +2 -1
  34. package/dist/core/runtime/boundedThrottleStore.d.ts +29 -0
  35. package/dist/core/scheduler/leases.d.ts +40 -0
  36. package/dist/core/scheduler/schedule.d.ts +29 -5
  37. package/dist/core/tenant/publicTenantHost.d.ts +11 -0
  38. package/dist/core/tenant/tenantContext.d.ts +5 -4
  39. package/dist/core/tenant/tenantMiddleware.d.ts +11 -1
  40. package/dist/core/tracing/otel.d.ts +28 -26
  41. package/dist/core/tracing/tracingMiddleware.d.ts +4 -1
  42. package/dist/entries/audit/exportAuditLogs.js +14 -2
  43. package/dist/entries/auth/basicAuthGuard.js +81 -0
  44. package/dist/entries/auth/jwtGuard.js +81 -0
  45. package/dist/entries/auth/scimAuthMiddleware.js +17 -7
  46. package/dist/entries/auth/sessionGuard.js +81 -0
  47. package/dist/entries/cache/createCacheStore.js +365 -119
  48. package/dist/entries/cache/repository.js +5 -0
  49. package/dist/entries/contracts/serviceTokens.js +85 -0
  50. package/dist/entries/database/factory.js +0 -3
  51. package/dist/entries/database/model.js +1 -2486
  52. package/dist/entries/database/repositoryQuery.js +67 -9
  53. package/dist/entries/http/bodySizeLimitMiddleware.js +76 -10
  54. package/dist/entries/http/memoryThrottleMiddleware.js +276 -21
  55. package/dist/entries/http/scimThrottleMiddleware.js +576 -54
  56. package/dist/entries/http/throttleMiddleware.js +65 -16
  57. package/dist/entries/jobs/exportAuditLogsJob.js +44 -7
  58. package/dist/entries/jobs/invalidateCacheTagsJob.js +30 -5
  59. package/dist/entries/queue/createAppQueue.js +748 -72
  60. package/dist/entries/queue/failedJobRepository.js +1 -1
  61. package/dist/entries/queue/failedJobService.js +5 -1
  62. package/dist/entries/queue/jobRunner.js +67 -2
  63. package/dist/entries/queue/publicQueue.js +746 -71
  64. package/dist/entries/queue/queueMetrics.js +761 -78
  65. package/dist/entries/queue/redisQueue.js +768 -148
  66. package/dist/entries/queue.js +30 -5
  67. package/dist/entries/scheduler/schedule.js +1 -72
  68. package/dist/entries/tenant/databaseTenantContext.js +14 -2
  69. package/dist/entries/tenant/tenantDatabaseScope.js +14 -2
  70. package/dist/entries/tracing/tracingMiddleware.js +186 -454
  71. package/dist/framework/public-api.d.ts +14 -10
  72. package/dist/index.js +2444 -688
  73. package/dist/types/services.d.ts +3 -3
  74. package/package.json +17 -8
@@ -300,7 +300,88 @@ var init_dialect = __esm(() => {
300
300
  dialectContext = createAsyncContextStore("@getstrata/sqlDialect");
301
301
  });
302
302
 
303
+ // ../../src/core/contracts/container.ts
304
+ function createServiceToken(key) {
305
+ if (!key.trim())
306
+ throw new Error("Service token key must not be empty.");
307
+ return key;
308
+ }
309
+
310
+ class ServiceContainer {
311
+ services = new Map;
312
+ singletonFactories = new Map;
313
+ bindings = new Map;
314
+ set(key, value) {
315
+ this.singletonFactories.delete(key);
316
+ this.bindings.delete(key);
317
+ this.services.set(key, value);
318
+ return value;
319
+ }
320
+ singleton(key, factory) {
321
+ this.bindings.delete(key);
322
+ this.services.delete(key);
323
+ this.singletonFactories.set(key, factory);
324
+ }
325
+ bind(key, factory) {
326
+ this.singletonFactories.delete(key);
327
+ this.services.delete(key);
328
+ this.bindings.set(key, factory);
329
+ }
330
+ get(key) {
331
+ if (this.services.has(key)) {
332
+ return this.services.get(key);
333
+ }
334
+ const singletonFactory = this.singletonFactories.get(key);
335
+ if (singletonFactory) {
336
+ const value = singletonFactory(this);
337
+ this.services.set(key, value);
338
+ return value;
339
+ }
340
+ const binding = this.bindings.get(key);
341
+ if (binding) {
342
+ return binding(this);
343
+ }
344
+ throw new Error(`Service "${key}" is not registered.`);
345
+ }
346
+ resolve(key) {
347
+ return this.get(key);
348
+ }
349
+ make(key) {
350
+ return this.resolve(key);
351
+ }
352
+ instance(key, value) {
353
+ return this.set(key, value);
354
+ }
355
+ has(key) {
356
+ return this.services.has(key) || this.singletonFactories.has(key) || this.bindings.has(key);
357
+ }
358
+ }
359
+
360
+ class ConfigStore {
361
+ values = new Map;
362
+ set(key, value) {
363
+ this.values.set(key, value);
364
+ return value;
365
+ }
366
+ get(key) {
367
+ return this.values.get(key);
368
+ }
369
+ require(key) {
370
+ if (!this.values.has(key)) {
371
+ throw new Error(`Config key "${key}" is not defined.`);
372
+ }
373
+ return this.values.get(key);
374
+ }
375
+ has(key) {
376
+ return this.values.has(key);
377
+ }
378
+ }
379
+
303
380
  // ../../src/core/contracts/serviceTokens.ts
381
+ var CORE_THROTTLE_QUOTA_POLICY_TOKEN = createServiceToken("core.throttleQuotaPolicy");
382
+ var CORE_PUBLIC_TENANCY_TOKEN = createServiceToken("core.publicTenancy");
383
+ var CORE_TENANT_RESOLVER_TOKEN = createServiceToken("core.tenantResolver");
384
+ var CORE_HTTP_CLEANUP_TOKEN = createServiceToken("core.httpCleanup");
304
385
  var CORE_CONFIG_TOKEN = "core.config";
305
386
  var CORE_CACHE_TOKEN = "core.cache";
306
387
  var CORE_QUEUE_TOKEN = "core.queue";
@@ -1,5 +1,86 @@
1
1
  // @bun
2
+ // ../../src/core/contracts/container.ts
3
+ function createServiceToken(key) {
4
+ if (!key.trim())
5
+ throw new Error("Service token key must not be empty.");
6
+ return key;
7
+ }
8
+
9
+ class ServiceContainer {
10
+ services = new Map;
11
+ singletonFactories = new Map;
12
+ bindings = new Map;
13
+ set(key, value) {
14
+ this.singletonFactories.delete(key);
15
+ this.bindings.delete(key);
16
+ this.services.set(key, value);
17
+ return value;
18
+ }
19
+ singleton(key, factory) {
20
+ this.bindings.delete(key);
21
+ this.services.delete(key);
22
+ this.singletonFactories.set(key, factory);
23
+ }
24
+ bind(key, factory) {
25
+ this.singletonFactories.delete(key);
26
+ this.services.delete(key);
27
+ this.bindings.set(key, factory);
28
+ }
29
+ get(key) {
30
+ if (this.services.has(key)) {
31
+ return this.services.get(key);
32
+ }
33
+ const singletonFactory = this.singletonFactories.get(key);
34
+ if (singletonFactory) {
35
+ const value = singletonFactory(this);
36
+ this.services.set(key, value);
37
+ return value;
38
+ }
39
+ const binding = this.bindings.get(key);
40
+ if (binding) {
41
+ return binding(this);
42
+ }
43
+ throw new Error(`Service "${key}" is not registered.`);
44
+ }
45
+ resolve(key) {
46
+ return this.get(key);
47
+ }
48
+ make(key) {
49
+ return this.resolve(key);
50
+ }
51
+ instance(key, value) {
52
+ return this.set(key, value);
53
+ }
54
+ has(key) {
55
+ return this.services.has(key) || this.singletonFactories.has(key) || this.bindings.has(key);
56
+ }
57
+ }
58
+
59
+ class ConfigStore {
60
+ values = new Map;
61
+ set(key, value) {
62
+ this.values.set(key, value);
63
+ return value;
64
+ }
65
+ get(key) {
66
+ return this.values.get(key);
67
+ }
68
+ require(key) {
69
+ if (!this.values.has(key)) {
70
+ throw new Error(`Config key "${key}" is not defined.`);
71
+ }
72
+ return this.values.get(key);
73
+ }
74
+ has(key) {
75
+ return this.values.has(key);
76
+ }
77
+ }
78
+
2
79
  // ../../src/core/contracts/serviceTokens.ts
80
+ var CORE_THROTTLE_QUOTA_POLICY_TOKEN = createServiceToken("core.throttleQuotaPolicy");
81
+ var CORE_PUBLIC_TENANCY_TOKEN = createServiceToken("core.publicTenancy");
82
+ var CORE_TENANT_RESOLVER_TOKEN = createServiceToken("core.tenantResolver");
83
+ var CORE_HTTP_CLEANUP_TOKEN = createServiceToken("core.httpCleanup");
3
84
  var CORE_CONFIG_TOKEN = "core.config";
4
85
  var CORE_CACHE_TOKEN = "core.cache";
5
86
  var CORE_QUEUE_TOKEN = "core.queue";
@@ -262,9 +262,12 @@ async function runWithDeferredModelEvents(callback) {
262
262
  const existing = deferredModelEvents.getStore();
263
263
  if (existing) {
264
264
  existing.frames.push([]);
265
+ existing.rollbackFrames.push([]);
265
266
  try {
266
267
  const result = await callback();
267
268
  const nested = existing.frames.pop() ?? [];
269
+ const rollback = existing.rollbackFrames.pop() ?? [];
270
+ existing.rollbackFrames.at(-1)?.push(...rollback);
268
271
  const parent = existing.frames[existing.frames.length - 1];
269
272
  if (parent) {
270
273
  parent.push(...nested);
@@ -272,11 +275,20 @@ async function runWithDeferredModelEvents(callback) {
272
275
  return result;
273
276
  } catch (error) {
274
277
  existing.frames.pop();
278
+ for (const rollback of (existing.rollbackFrames.pop() ?? []).reverse())
279
+ rollback();
275
280
  throw error;
276
281
  }
277
282
  }
278
- const state = { frames: [[]] };
279
- const result = await deferredModelEvents.run(state, callback);
283
+ const state = { frames: [[]], rollbackFrames: [[]] };
284
+ let result;
285
+ try {
286
+ result = await deferredModelEvents.run(state, callback);
287
+ } catch (error) {
288
+ for (const rollback of (state.rollbackFrames[0] ?? []).reverse())
289
+ rollback();
290
+ throw error;
291
+ }
280
292
  await dispatchQueuedModelEvents(state.frames[0] ?? []);
281
293
  return result;
282
294
  }
@@ -849,19 +861,17 @@ async function resolveTenant(tenantId) {
849
861
  if (!isTenancyEnabled()) {
850
862
  return {
851
863
  id: tenantId,
852
- slug: "default",
853
- plan: "free",
854
- region: "eu"
864
+ slug: "default"
855
865
  };
856
866
  }
857
867
  const rows = await db`
858
- SELECT id, slug, plan, region
868
+ SELECT id, slug
859
869
  FROM tenant
860
870
  WHERE id = ${tenantId}
861
871
  LIMIT 1
862
872
  `;
863
873
  const row = rows[0];
864
- return row ? { id: row.id, slug: row.slug, plan: row.plan, region: row.region ?? "eu" } : null;
874
+ return row ? { id: row.id, slug: row.slug } : null;
865
875
  }
866
876
 
867
877
  // ../../src/core/auth/scimAuthMiddleware.ts
@@ -1,5 +1,86 @@
1
1
  // @bun
2
+ // ../../src/core/contracts/container.ts
3
+ function createServiceToken(key) {
4
+ if (!key.trim())
5
+ throw new Error("Service token key must not be empty.");
6
+ return key;
7
+ }
8
+
9
+ class ServiceContainer {
10
+ services = new Map;
11
+ singletonFactories = new Map;
12
+ bindings = new Map;
13
+ set(key, value) {
14
+ this.singletonFactories.delete(key);
15
+ this.bindings.delete(key);
16
+ this.services.set(key, value);
17
+ return value;
18
+ }
19
+ singleton(key, factory) {
20
+ this.bindings.delete(key);
21
+ this.services.delete(key);
22
+ this.singletonFactories.set(key, factory);
23
+ }
24
+ bind(key, factory) {
25
+ this.singletonFactories.delete(key);
26
+ this.services.delete(key);
27
+ this.bindings.set(key, factory);
28
+ }
29
+ get(key) {
30
+ if (this.services.has(key)) {
31
+ return this.services.get(key);
32
+ }
33
+ const singletonFactory = this.singletonFactories.get(key);
34
+ if (singletonFactory) {
35
+ const value = singletonFactory(this);
36
+ this.services.set(key, value);
37
+ return value;
38
+ }
39
+ const binding = this.bindings.get(key);
40
+ if (binding) {
41
+ return binding(this);
42
+ }
43
+ throw new Error(`Service "${key}" is not registered.`);
44
+ }
45
+ resolve(key) {
46
+ return this.get(key);
47
+ }
48
+ make(key) {
49
+ return this.resolve(key);
50
+ }
51
+ instance(key, value) {
52
+ return this.set(key, value);
53
+ }
54
+ has(key) {
55
+ return this.services.has(key) || this.singletonFactories.has(key) || this.bindings.has(key);
56
+ }
57
+ }
58
+
59
+ class ConfigStore {
60
+ values = new Map;
61
+ set(key, value) {
62
+ this.values.set(key, value);
63
+ return value;
64
+ }
65
+ get(key) {
66
+ return this.values.get(key);
67
+ }
68
+ require(key) {
69
+ if (!this.values.has(key)) {
70
+ throw new Error(`Config key "${key}" is not defined.`);
71
+ }
72
+ return this.values.get(key);
73
+ }
74
+ has(key) {
75
+ return this.values.has(key);
76
+ }
77
+ }
78
+
2
79
  // ../../src/core/contracts/serviceTokens.ts
80
+ var CORE_THROTTLE_QUOTA_POLICY_TOKEN = createServiceToken("core.throttleQuotaPolicy");
81
+ var CORE_PUBLIC_TENANCY_TOKEN = createServiceToken("core.publicTenancy");
82
+ var CORE_TENANT_RESOLVER_TOKEN = createServiceToken("core.tenantResolver");
83
+ var CORE_HTTP_CLEANUP_TOKEN = createServiceToken("core.httpCleanup");
3
84
  var CORE_CONFIG_TOKEN = "core.config";
4
85
  var CORE_CACHE_TOKEN = "core.cache";
5
86
  var CORE_QUEUE_TOKEN = "core.queue";