@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.
- package/CHANGELOG.md +23 -0
- package/dist/core/database/transaction.d.ts +2 -1
- package/dist/core/database/transactionControl.d.ts +5 -0
- package/dist/core/events/deferredModelEvents.d.ts +3 -0
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/http/loginThrottleMiddleware.d.ts +3 -0
- package/dist/core/http/metricsMiddleware.d.ts +1 -2
- package/dist/core/http/requestMetaContext.d.ts +2 -0
- package/dist/core/http/throttleMiddleware.d.ts +11 -2
- package/dist/core/metrics/prometheus.d.ts +11 -1
- package/dist/core/queue/jobRunner.d.ts +3 -1
- package/dist/core/queue/redisQueue.d.ts +20 -3
- package/dist/core/tenant/databaseTenantContext.d.ts +5 -1
- package/dist/entries/audit/exportAuditLogs.js +751 -97
- package/dist/entries/auth/accessControl.js +16 -2
- package/dist/entries/auth/basicAuthGuard.js +271 -224
- package/dist/entries/auth/membershipMiddleware.js +17 -0
- package/dist/entries/auth/membershipScope.js +21 -6
- package/dist/entries/auth/membershipService.js +20 -5
- package/dist/entries/auth/oauth/samlProvider.js +187 -142
- package/dist/entries/auth/oneTimeToken.js +142 -123
- package/dist/entries/auth/passwordLogin.js +212 -191
- package/dist/entries/auth/policy.js +16 -2
- package/dist/entries/auth/saml/samlServiceProvider.js +187 -142
- package/dist/entries/auth/scimAuthMiddleware.js +732 -64
- package/dist/entries/database/migrations.js +144 -125
- package/dist/entries/database/schema.js +58 -39
- package/dist/entries/http/csrfMiddleware.js +28 -14
- package/dist/entries/http/csrfToken.js +28 -14
- package/dist/entries/http/flashMiddleware.js +28 -14
- package/dist/entries/http/metricsMiddleware.js +124 -27
- package/dist/entries/http/response.js +107 -0
- package/dist/entries/http/routeMiddleware.js +40 -0
- package/dist/entries/http/throttleMiddleware.js +124 -11
- package/dist/entries/jobs/exportAuditLogsJob.js +751 -97
- package/dist/entries/metrics/prometheus.js +71 -11
- package/dist/entries/queue/createAppQueue.js +215 -21
- package/dist/entries/queue/jobRunner.js +3 -2
- package/dist/entries/queue/publicQueue.js +215 -21
- package/dist/entries/queue/queueMetrics.js +215 -21
- package/dist/entries/queue/redisQueue.js +223 -22
- package/dist/entries/runtime/asyncContextStore.js +16 -0
- package/dist/entries/tenant/databaseTenantContext.js +666 -11
- package/dist/entries/tenant/tenancyConfig.js +19 -1
- package/dist/entries/tenant/tenantDatabaseScope.js +688 -18
- package/dist/entries/tracing/tracingMiddleware.js +28 -14
- package/dist/framework/public-api.d.ts +3 -3
- package/dist/index.js +1344 -651
- package/package.json +1 -1
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
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 {
|