@getstrata/core 1.1.8 → 2.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/core/database/transaction.d.ts +2 -1
  3. package/dist/core/database/transactionControl.d.ts +5 -0
  4. package/dist/core/events/deferredModelEvents.d.ts +3 -0
  5. package/dist/core/events/index.d.ts +1 -0
  6. package/dist/core/http/loginThrottleMiddleware.d.ts +3 -0
  7. package/dist/core/http/metricsMiddleware.d.ts +1 -2
  8. package/dist/core/http/requestMetaContext.d.ts +2 -0
  9. package/dist/core/http/throttleMiddleware.d.ts +11 -2
  10. package/dist/core/metrics/prometheus.d.ts +11 -1
  11. package/dist/core/queue/jobRunner.d.ts +3 -1
  12. package/dist/core/queue/redisQueue.d.ts +20 -3
  13. package/dist/core/tenant/databaseTenantContext.d.ts +5 -1
  14. package/dist/entries/audit/exportAuditLogs.js +751 -97
  15. package/dist/entries/auth/accessControl.js +16 -2
  16. package/dist/entries/auth/basicAuthGuard.js +271 -224
  17. package/dist/entries/auth/membershipMiddleware.js +17 -0
  18. package/dist/entries/auth/membershipScope.js +21 -6
  19. package/dist/entries/auth/membershipService.js +20 -5
  20. package/dist/entries/auth/oauth/samlProvider.js +187 -142
  21. package/dist/entries/auth/oneTimeToken.js +142 -123
  22. package/dist/entries/auth/passwordLogin.js +212 -191
  23. package/dist/entries/auth/policy.js +16 -2
  24. package/dist/entries/auth/saml/samlServiceProvider.js +187 -142
  25. package/dist/entries/auth/scimAuthMiddleware.js +732 -64
  26. package/dist/entries/database/migrations.js +144 -125
  27. package/dist/entries/database/schema.js +58 -39
  28. package/dist/entries/http/csrfMiddleware.js +28 -14
  29. package/dist/entries/http/csrfToken.js +28 -14
  30. package/dist/entries/http/flashMiddleware.js +28 -14
  31. package/dist/entries/http/metricsMiddleware.js +124 -27
  32. package/dist/entries/http/response.js +107 -0
  33. package/dist/entries/http/routeMiddleware.js +40 -0
  34. package/dist/entries/http/throttleMiddleware.js +124 -11
  35. package/dist/entries/jobs/exportAuditLogsJob.js +751 -97
  36. package/dist/entries/metrics/prometheus.js +71 -11
  37. package/dist/entries/queue/createAppQueue.js +215 -21
  38. package/dist/entries/queue/jobRunner.js +3 -2
  39. package/dist/entries/queue/publicQueue.js +215 -21
  40. package/dist/entries/queue/queueMetrics.js +215 -21
  41. package/dist/entries/queue/redisQueue.js +223 -22
  42. package/dist/entries/runtime/asyncContextStore.js +16 -0
  43. package/dist/entries/tenant/databaseTenantContext.js +666 -11
  44. package/dist/entries/tenant/tenancyConfig.js +19 -1
  45. package/dist/entries/tenant/tenantDatabaseScope.js +688 -18
  46. package/dist/entries/tracing/tracingMiddleware.js +28 -14
  47. package/dist/framework/public-api.d.ts +3 -3
  48. package/dist/index.js +1344 -651
  49. package/package.json +1 -1
@@ -1,24 +1,17 @@
1
1
  // @bun
2
- // ../../src/core/runtime/optionalPeer.ts
3
- function missingOptionalPeer(packageName, reason, error) {
4
- return new Error(`Install ${packageName} ${reason} (\`bun add ${packageName}\`).`, {
5
- cause: error
6
- });
7
- }
8
-
9
- // ../../src/core/security/timingSafeCompare.ts
10
- import { timingSafeEqual } from "crypto";
11
- function timingSafeCompareString(left, right) {
12
- const leftBuffer = Buffer.from(left);
13
- const rightBuffer = Buffer.from(right);
14
- if (leftBuffer.length !== rightBuffer.length) {
15
- return false;
16
- }
17
- return timingSafeEqual(leftBuffer, rightBuffer);
18
- }
2
+ var __esm = (fn, res, err) => () => {
3
+ if (fn)
4
+ try {
5
+ res = fn(fn = 0);
6
+ } catch (e) {
7
+ err = [e];
8
+ }
9
+ if (err)
10
+ throw err[0];
11
+ return res;
12
+ };
19
13
 
20
14
  // ../../src/core/database/boundConnection.ts
21
- var BOUND_CONNECTION_KEY = Symbol.for("@getstrata/boundDatabaseConnection");
22
15
  function boundConnectionState() {
23
16
  const globalRecord = globalThis;
24
17
  const existing = globalRecord[BOUND_CONNECTION_KEY];
@@ -32,6 +25,10 @@ function boundConnectionState() {
32
25
  function getBoundDatabaseConnection() {
33
26
  return boundConnectionState().connection;
34
27
  }
28
+ var BOUND_CONNECTION_KEY;
29
+ var init_boundConnection = __esm(() => {
30
+ BOUND_CONNECTION_KEY = Symbol.for("@getstrata/boundDatabaseConnection");
31
+ });
35
32
 
36
33
  // ../../src/core/runtime/asyncContextStore.ts
37
34
  import { AsyncLocalStorage } from "async_hooks";
@@ -46,9 +43,9 @@ function createAsyncContextStore(key) {
46
43
  globalRecord[symbol] = store;
47
44
  return store;
48
45
  }
46
+ var init_asyncContextStore = () => {};
49
47
 
50
48
  // ../../src/core/database/connectionContext.ts
51
- var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
52
49
  function runWithDatabaseConnection(connection, callback) {
53
50
  return activeConnection.run(connection, callback);
54
51
  }
@@ -58,12 +55,20 @@ function getActiveDatabaseConnection(fallback) {
58
55
  function hasActiveDatabaseConnection() {
59
56
  return activeConnection.getStore() !== undefined;
60
57
  }
58
+ var activeConnection;
59
+ var init_connectionContext = __esm(() => {
60
+ init_asyncContextStore();
61
+ activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
62
+ });
61
63
 
62
64
  // ../../src/core/database/queryProxy.ts
63
- var POOL_CONNECTION_METHODS = new Set(["begin", "close", "connect"]);
65
+ var POOL_CONNECTION_METHODS;
66
+ var init_queryProxy = __esm(() => {
67
+ init_connectionContext();
68
+ POOL_CONNECTION_METHODS = new Set(["begin", "close", "connect"]);
69
+ });
64
70
 
65
71
  // ../../src/core/database/defaultConnection.ts
66
- var DEFAULT_CONNECTION_KEY = Symbol.for("@getstrata/defaultDatabaseConnection");
67
72
  function defaultConnectionState() {
68
73
  const globalRecord = globalThis;
69
74
  const existing = globalRecord[DEFAULT_CONNECTION_KEY];
@@ -81,6 +86,18 @@ function getDefaultDatabasePool() {
81
86
  }
82
87
  return pool;
83
88
  }
89
+ function getDefaultDatabaseQuery() {
90
+ const query = defaultConnectionState().query;
91
+ if (!query) {
92
+ throw new Error("Default database query handle is not registered. Call registerDefaultDatabasePool() during app bootstrap.");
93
+ }
94
+ return query;
95
+ }
96
+ var DEFAULT_CONNECTION_KEY;
97
+ var init_defaultConnection = __esm(() => {
98
+ init_queryProxy();
99
+ DEFAULT_CONNECTION_KEY = Symbol.for("@getstrata/defaultDatabaseConnection");
100
+ });
84
101
 
85
102
  // ../../src/core/database/schema/driver.ts
86
103
  function normalizeConnectionName(connection) {
@@ -121,6 +138,7 @@ function resolveDatabaseDriver(options = {}) {
121
138
  }
122
139
  return "pgsql";
123
140
  }
141
+ var init_driver = () => {};
124
142
 
125
143
  // ../../src/core/database/dialect.ts
126
144
  function assertSafeIdentifier(identifier) {
@@ -132,133 +150,160 @@ function assertSafeIdentifier(identifier) {
132
150
  function quoteIdentifierFor(dialect, column) {
133
151
  return dialect.quoteIdentifier(column);
134
152
  }
135
- var postgresDialect = {
136
- driver: "pgsql",
137
- placeholder(index) {
138
- return `$${index}`;
139
- },
140
- quoteIdentifier(identifier) {
141
- return `"${assertSafeIdentifier(identifier)}"`;
142
- },
143
- nowExpression() {
144
- return "NOW()";
145
- },
146
- timestampValue(value) {
147
- return value.toISOString();
148
- },
149
- returningClause(columns) {
150
- return ` RETURNING ${columns}`;
151
- },
152
- ilikeOperator() {
153
- return "ILIKE";
154
- },
155
- nullsLastSuffix() {
156
- return " NULLS LAST";
157
- },
158
- castToText(expression) {
159
- return `${expression}::text`;
160
- },
161
- upsertSuffix(conflictColumns, updateColumns) {
162
- const target = conflictColumns.map((column) => quoteIdentifierFor(this, column)).join(", ");
163
- if (updateColumns.length === 0) {
164
- return ` ON CONFLICT (${target}) DO NOTHING`;
165
- }
166
- const assignments = updateColumns.map((column) => {
167
- const quoted = quoteIdentifierFor(this, column);
168
- return `${quoted} = excluded.${quoted}`;
169
- }).join(", ");
170
- return ` ON CONFLICT (${target}) DO UPDATE SET ${assignments}`;
171
- }
172
- };
173
- var mysqlDialect = {
174
- driver: "mysql",
175
- placeholder() {
176
- return "?";
177
- },
178
- quoteIdentifier(identifier) {
179
- return `\`${assertSafeIdentifier(identifier)}\``;
180
- },
181
- nowExpression() {
182
- return "CURRENT_TIMESTAMP";
183
- },
184
- timestampValue(value) {
185
- return value.toISOString().slice(0, 19).replace("T", " ");
186
- },
187
- returningClause() {
188
- return "";
189
- },
190
- ilikeOperator() {
191
- return "LIKE";
192
- },
193
- nullsLastSuffix() {
194
- return "";
195
- },
196
- castToText(expression) {
197
- return `CAST(${expression} AS CHAR)`;
198
- },
199
- upsertSuffix(conflictColumns, updateColumns) {
200
- if (updateColumns.length === 0) {
201
- const anchor = quoteIdentifierFor(this, conflictColumns[0] ?? "");
202
- return ` ON DUPLICATE KEY UPDATE ${anchor} = ${anchor}`;
203
- }
204
- const assignments = updateColumns.map((column) => {
205
- const quoted = quoteIdentifierFor(this, column);
206
- return `${quoted} = VALUES(${quoted})`;
207
- }).join(", ");
208
- return ` ON DUPLICATE KEY UPDATE ${assignments}`;
209
- }
210
- };
211
- var sqliteDialect = {
212
- driver: "sqlite",
213
- placeholder() {
214
- return "?";
215
- },
216
- quoteIdentifier(identifier) {
217
- return `"${assertSafeIdentifier(identifier)}"`;
218
- },
219
- nowExpression() {
220
- return "strftime('%Y-%m-%dT%H:%M:%fZ', 'now')";
221
- },
222
- timestampValue(value) {
223
- return value.toISOString();
224
- },
225
- returningClause(columns) {
226
- return ` RETURNING ${columns}`;
227
- },
228
- ilikeOperator() {
229
- return "LIKE";
230
- },
231
- nullsLastSuffix() {
232
- return "";
233
- },
234
- castToText(expression) {
235
- return `CAST(${expression} AS TEXT)`;
236
- },
237
- upsertSuffix(conflictColumns, updateColumns) {
238
- const target = conflictColumns.map((column) => quoteIdentifierFor(this, column)).join(", ");
239
- if (updateColumns.length === 0) {
240
- return ` ON CONFLICT (${target}) DO NOTHING`;
241
- }
242
- const assignments = updateColumns.map((column) => {
243
- const quoted = quoteIdentifierFor(this, column);
244
- return `${quoted} = excluded.${quoted}`;
245
- }).join(", ");
246
- return ` ON CONFLICT (${target}) DO UPDATE SET ${assignments}`;
247
- }
248
- };
249
- var dialects = {
250
- pgsql: postgresDialect,
251
- mysql: mysqlDialect,
252
- sqlite: sqliteDialect
253
- };
254
- var dialectContext = createAsyncContextStore("@getstrata/sqlDialect");
255
- var dialectOverride = null;
256
153
  function dialectFor(driver) {
257
154
  return dialects[driver];
258
155
  }
259
156
  function currentSqlDialect() {
260
157
  return dialectContext.getStore() ?? dialectOverride ?? dialectFor(resolveDatabaseDriver());
261
158
  }
159
+ var postgresDialect, mysqlDialect, sqliteDialect, dialects, dialectContext, dialectOverride = null;
160
+ var init_dialect = __esm(() => {
161
+ init_asyncContextStore();
162
+ init_driver();
163
+ postgresDialect = {
164
+ driver: "pgsql",
165
+ placeholder(index) {
166
+ return `$${index}`;
167
+ },
168
+ quoteIdentifier(identifier) {
169
+ return `"${assertSafeIdentifier(identifier)}"`;
170
+ },
171
+ nowExpression() {
172
+ return "NOW()";
173
+ },
174
+ timestampValue(value) {
175
+ return value.toISOString();
176
+ },
177
+ returningClause(columns) {
178
+ return ` RETURNING ${columns}`;
179
+ },
180
+ ilikeOperator() {
181
+ return "ILIKE";
182
+ },
183
+ nullsLastSuffix() {
184
+ return " NULLS LAST";
185
+ },
186
+ castToText(expression) {
187
+ return `${expression}::text`;
188
+ },
189
+ upsertSuffix(conflictColumns, updateColumns) {
190
+ const target = conflictColumns.map((column) => quoteIdentifierFor(this, column)).join(", ");
191
+ if (updateColumns.length === 0) {
192
+ return ` ON CONFLICT (${target}) DO NOTHING`;
193
+ }
194
+ const assignments = updateColumns.map((column) => {
195
+ const quoted = quoteIdentifierFor(this, column);
196
+ return `${quoted} = excluded.${quoted}`;
197
+ }).join(", ");
198
+ return ` ON CONFLICT (${target}) DO UPDATE SET ${assignments}`;
199
+ }
200
+ };
201
+ mysqlDialect = {
202
+ driver: "mysql",
203
+ placeholder() {
204
+ return "?";
205
+ },
206
+ quoteIdentifier(identifier) {
207
+ return `\`${assertSafeIdentifier(identifier)}\``;
208
+ },
209
+ nowExpression() {
210
+ return "CURRENT_TIMESTAMP";
211
+ },
212
+ timestampValue(value) {
213
+ return value.toISOString().slice(0, 19).replace("T", " ");
214
+ },
215
+ returningClause() {
216
+ return "";
217
+ },
218
+ ilikeOperator() {
219
+ return "LIKE";
220
+ },
221
+ nullsLastSuffix() {
222
+ return "";
223
+ },
224
+ castToText(expression) {
225
+ return `CAST(${expression} AS CHAR)`;
226
+ },
227
+ upsertSuffix(conflictColumns, updateColumns) {
228
+ if (updateColumns.length === 0) {
229
+ const anchor = quoteIdentifierFor(this, conflictColumns[0] ?? "");
230
+ return ` ON DUPLICATE KEY UPDATE ${anchor} = ${anchor}`;
231
+ }
232
+ const assignments = updateColumns.map((column) => {
233
+ const quoted = quoteIdentifierFor(this, column);
234
+ return `${quoted} = VALUES(${quoted})`;
235
+ }).join(", ");
236
+ return ` ON DUPLICATE KEY UPDATE ${assignments}`;
237
+ }
238
+ };
239
+ sqliteDialect = {
240
+ driver: "sqlite",
241
+ placeholder() {
242
+ return "?";
243
+ },
244
+ quoteIdentifier(identifier) {
245
+ return `"${assertSafeIdentifier(identifier)}"`;
246
+ },
247
+ nowExpression() {
248
+ return "strftime('%Y-%m-%dT%H:%M:%fZ', 'now')";
249
+ },
250
+ timestampValue(value) {
251
+ return value.toISOString();
252
+ },
253
+ returningClause(columns) {
254
+ return ` RETURNING ${columns}`;
255
+ },
256
+ ilikeOperator() {
257
+ return "LIKE";
258
+ },
259
+ nullsLastSuffix() {
260
+ return "";
261
+ },
262
+ castToText(expression) {
263
+ return `CAST(${expression} AS TEXT)`;
264
+ },
265
+ upsertSuffix(conflictColumns, updateColumns) {
266
+ const target = conflictColumns.map((column) => quoteIdentifierFor(this, column)).join(", ");
267
+ if (updateColumns.length === 0) {
268
+ return ` ON CONFLICT (${target}) DO NOTHING`;
269
+ }
270
+ const assignments = updateColumns.map((column) => {
271
+ const quoted = quoteIdentifierFor(this, column);
272
+ return `${quoted} = excluded.${quoted}`;
273
+ }).join(", ");
274
+ return ` ON CONFLICT (${target}) DO UPDATE SET ${assignments}`;
275
+ }
276
+ };
277
+ dialects = {
278
+ pgsql: postgresDialect,
279
+ mysql: mysqlDialect,
280
+ sqlite: sqliteDialect
281
+ };
282
+ dialectContext = createAsyncContextStore("@getstrata/sqlDialect");
283
+ });
284
+
285
+ // ../../src/core/runtime/optionalPeer.ts
286
+ function missingOptionalPeer(packageName, reason, error) {
287
+ return new Error(`Install ${packageName} ${reason} (\`bun add ${packageName}\`).`, {
288
+ cause: error
289
+ });
290
+ }
291
+
292
+ // ../../src/core/security/timingSafeCompare.ts
293
+ import { timingSafeEqual } from "crypto";
294
+ function timingSafeCompareString(left, right) {
295
+ const leftBuffer = Buffer.from(left);
296
+ const rightBuffer = Buffer.from(right);
297
+ if (leftBuffer.length !== rightBuffer.length) {
298
+ return false;
299
+ }
300
+ return timingSafeEqual(leftBuffer, rightBuffer);
301
+ }
302
+
303
+ // ../../src/core/auth/saml/samlAssertionReplay.ts
304
+ init_boundConnection();
305
+ init_defaultConnection();
306
+ init_dialect();
262
307
 
263
308
  // ../../src/core/database/errors.ts
264
309
  import {