@getstrata/core 1.1.7 → 1.1.9
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 +12 -0
- package/dist/core/events/deferredModelEvents.d.ts +3 -0
- package/dist/core/events/index.d.ts +1 -0
- package/dist/entries/audit/exportAuditLogs.js +247 -53
- package/dist/entries/auth/accessControl.js +16 -2
- package/dist/entries/auth/basicAuthGuard.js +47 -26
- 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 +47 -26
- package/dist/entries/auth/oneTimeToken.js +18 -2
- package/dist/entries/auth/passwordLogin.js +29 -13
- package/dist/entries/auth/policy.js +16 -2
- package/dist/entries/auth/saml/samlServiceProvider.js +47 -26
- package/dist/entries/auth/scimAuthMiddleware.js +217 -63
- package/dist/entries/database/migrations.js +20 -4
- 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/jobs/exportAuditLogsJob.js +247 -53
- package/dist/entries/runtime/asyncContextStore.js +16 -0
- package/dist/entries/tenant/databaseTenantContext.js +203 -9
- package/dist/entries/tenant/tenancyConfig.js +19 -1
- package/dist/entries/tenant/tenantDatabaseScope.js +173 -17
- package/dist/entries/tracing/tracingMiddleware.js +28 -14
- package/dist/framework/public-api.d.ts +1 -1
- package/dist/index.js +406 -210
- package/package.json +1 -1
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
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
|
+
};
|
|
4
13
|
|
|
5
14
|
// ../../src/core/runtime/asyncContextStore.ts
|
|
6
15
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -15,6 +24,13 @@ function createAsyncContextStore(key) {
|
|
|
15
24
|
globalRecord[symbol] = store;
|
|
16
25
|
return store;
|
|
17
26
|
}
|
|
27
|
+
var init_asyncContextStore = () => {};
|
|
28
|
+
|
|
29
|
+
// ../../src/core/auth/oneTimeToken.ts
|
|
30
|
+
import { randomBytes } from "crypto";
|
|
31
|
+
|
|
32
|
+
// ../../src/core/database/dialect.ts
|
|
33
|
+
init_asyncContextStore();
|
|
18
34
|
|
|
19
35
|
// ../../src/core/database/schema/driver.ts
|
|
20
36
|
function normalizeConnectionName(connection) {
|
|
@@ -1,4 +1,31 @@
|
|
|
1
1
|
// @bun
|
|
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
|
+
};
|
|
13
|
+
|
|
14
|
+
// ../../src/core/runtime/asyncContextStore.ts
|
|
15
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
16
|
+
function createAsyncContextStore(key) {
|
|
17
|
+
const symbol = Symbol.for(key);
|
|
18
|
+
const globalRecord = globalThis;
|
|
19
|
+
const existing = globalRecord[symbol];
|
|
20
|
+
if (existing) {
|
|
21
|
+
return existing;
|
|
22
|
+
}
|
|
23
|
+
const store = new AsyncLocalStorage;
|
|
24
|
+
globalRecord[symbol] = store;
|
|
25
|
+
return store;
|
|
26
|
+
}
|
|
27
|
+
var init_asyncContextStore = () => {};
|
|
28
|
+
|
|
2
29
|
// ../../src/core/runtime/appEnv.ts
|
|
3
30
|
var NON_PRODUCTION_APP_ENVS = new Set(["local", "development", "dev", "test", "testing", "ci"]);
|
|
4
31
|
function normalizeEnvValue(value) {
|
|
@@ -126,19 +153,8 @@ function revealMfaSecret(stored) {
|
|
|
126
153
|
return decryptField(stored, key);
|
|
127
154
|
}
|
|
128
155
|
|
|
129
|
-
// ../../src/core/
|
|
130
|
-
|
|
131
|
-
function createAsyncContextStore(key) {
|
|
132
|
-
const symbol = Symbol.for(key);
|
|
133
|
-
const globalRecord = globalThis;
|
|
134
|
-
const existing = globalRecord[symbol];
|
|
135
|
-
if (existing) {
|
|
136
|
-
return existing;
|
|
137
|
-
}
|
|
138
|
-
const store = new AsyncLocalStorage;
|
|
139
|
-
globalRecord[symbol] = store;
|
|
140
|
-
return store;
|
|
141
|
-
}
|
|
156
|
+
// ../../src/core/database/dialect.ts
|
|
157
|
+
init_asyncContextStore();
|
|
142
158
|
|
|
143
159
|
// ../../src/core/database/schema/driver.ts
|
|
144
160
|
function normalizeConnectionName(connection) {
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
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
|
+
};
|
|
4
13
|
|
|
5
14
|
// ../../src/core/runtime/asyncContextStore.ts
|
|
6
15
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -15,8 +24,13 @@ function createAsyncContextStore(key) {
|
|
|
15
24
|
globalRecord[symbol] = store;
|
|
16
25
|
return store;
|
|
17
26
|
}
|
|
27
|
+
var init_asyncContextStore = () => {};
|
|
28
|
+
|
|
29
|
+
// ../../src/core/auth/policy.ts
|
|
30
|
+
import { ForbiddenError } from "@getstrata/core/errors/http";
|
|
18
31
|
|
|
19
32
|
// ../../src/core/auth/authContext.ts
|
|
33
|
+
init_asyncContextStore();
|
|
20
34
|
var authContext = createAsyncContextStore("@getstrata/authContext");
|
|
21
35
|
var credentialSourceContext = createAsyncContextStore("@getstrata/credentialSource");
|
|
22
36
|
function currentAuthUser() {
|
|
@@ -1,4 +1,47 @@
|
|
|
1
1
|
// @bun
|
|
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
|
+
};
|
|
13
|
+
|
|
14
|
+
// ../../src/core/runtime/asyncContextStore.ts
|
|
15
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
16
|
+
function createAsyncContextStore(key) {
|
|
17
|
+
const symbol = Symbol.for(key);
|
|
18
|
+
const globalRecord = globalThis;
|
|
19
|
+
const existing = globalRecord[symbol];
|
|
20
|
+
if (existing) {
|
|
21
|
+
return existing;
|
|
22
|
+
}
|
|
23
|
+
const store = new AsyncLocalStorage;
|
|
24
|
+
globalRecord[symbol] = store;
|
|
25
|
+
return store;
|
|
26
|
+
}
|
|
27
|
+
var init_asyncContextStore = () => {};
|
|
28
|
+
|
|
29
|
+
// ../../src/core/database/connectionContext.ts
|
|
30
|
+
function runWithDatabaseConnection(connection, callback) {
|
|
31
|
+
return activeConnection.run(connection, callback);
|
|
32
|
+
}
|
|
33
|
+
function getActiveDatabaseConnection(fallback) {
|
|
34
|
+
return activeConnection.getStore() ?? fallback;
|
|
35
|
+
}
|
|
36
|
+
function hasActiveDatabaseConnection() {
|
|
37
|
+
return activeConnection.getStore() !== undefined;
|
|
38
|
+
}
|
|
39
|
+
var activeConnection;
|
|
40
|
+
var init_connectionContext = __esm(() => {
|
|
41
|
+
init_asyncContextStore();
|
|
42
|
+
activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
|
|
43
|
+
});
|
|
44
|
+
|
|
2
45
|
// ../../src/core/runtime/optionalPeer.ts
|
|
3
46
|
function missingOptionalPeer(packageName, reason, error) {
|
|
4
47
|
return new Error(`Install ${packageName} ${reason} (\`bun add ${packageName}\`).`, {
|
|
@@ -33,33 +76,8 @@ function getBoundDatabaseConnection() {
|
|
|
33
76
|
return boundConnectionState().connection;
|
|
34
77
|
}
|
|
35
78
|
|
|
36
|
-
// ../../src/core/runtime/asyncContextStore.ts
|
|
37
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
38
|
-
function createAsyncContextStore(key) {
|
|
39
|
-
const symbol = Symbol.for(key);
|
|
40
|
-
const globalRecord = globalThis;
|
|
41
|
-
const existing = globalRecord[symbol];
|
|
42
|
-
if (existing) {
|
|
43
|
-
return existing;
|
|
44
|
-
}
|
|
45
|
-
const store = new AsyncLocalStorage;
|
|
46
|
-
globalRecord[symbol] = store;
|
|
47
|
-
return store;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ../../src/core/database/connectionContext.ts
|
|
51
|
-
var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
|
|
52
|
-
function runWithDatabaseConnection(connection, callback) {
|
|
53
|
-
return activeConnection.run(connection, callback);
|
|
54
|
-
}
|
|
55
|
-
function getActiveDatabaseConnection(fallback) {
|
|
56
|
-
return activeConnection.getStore() ?? fallback;
|
|
57
|
-
}
|
|
58
|
-
function hasActiveDatabaseConnection() {
|
|
59
|
-
return activeConnection.getStore() !== undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
79
|
// ../../src/core/database/queryProxy.ts
|
|
80
|
+
init_connectionContext();
|
|
63
81
|
var POOL_CONNECTION_METHODS = new Set(["begin", "close", "connect"]);
|
|
64
82
|
|
|
65
83
|
// ../../src/core/database/defaultConnection.ts
|
|
@@ -82,6 +100,9 @@ function getDefaultDatabasePool() {
|
|
|
82
100
|
return pool;
|
|
83
101
|
}
|
|
84
102
|
|
|
103
|
+
// ../../src/core/database/dialect.ts
|
|
104
|
+
init_asyncContextStore();
|
|
105
|
+
|
|
85
106
|
// ../../src/core/database/schema/driver.ts
|
|
86
107
|
function normalizeConnectionName(connection) {
|
|
87
108
|
const normalized = connection.trim().toLowerCase();
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
+
};
|
|
6
13
|
|
|
7
14
|
// ../../src/core/runtime/asyncContextStore.ts
|
|
8
15
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -17,9 +24,9 @@ function createAsyncContextStore(key) {
|
|
|
17
24
|
globalRecord[symbol] = store;
|
|
18
25
|
return store;
|
|
19
26
|
}
|
|
27
|
+
var init_asyncContextStore = () => {};
|
|
20
28
|
|
|
21
29
|
// ../../src/core/database/connectionContext.ts
|
|
22
|
-
var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
|
|
23
30
|
function runWithDatabaseConnection(connection, callback) {
|
|
24
31
|
return activeConnection.run(connection, callback);
|
|
25
32
|
}
|
|
@@ -29,6 +36,209 @@ function getActiveDatabaseConnection(fallback) {
|
|
|
29
36
|
function hasActiveDatabaseConnection() {
|
|
30
37
|
return activeConnection.getStore() !== undefined;
|
|
31
38
|
}
|
|
39
|
+
var activeConnection;
|
|
40
|
+
var init_connectionContext = __esm(() => {
|
|
41
|
+
init_asyncContextStore();
|
|
42
|
+
activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// ../../src/core/tenant/tenancyConfig.ts
|
|
46
|
+
function readTenancyDriver(env = process.env) {
|
|
47
|
+
const raw = env.TENANCY_DRIVER?.trim();
|
|
48
|
+
if (raw === undefined || raw === "") {
|
|
49
|
+
return "rls";
|
|
50
|
+
}
|
|
51
|
+
if (TENANCY_DRIVERS.includes(raw)) {
|
|
52
|
+
return raw;
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`TENANCY_DRIVER must be one of ${TENANCY_DRIVERS.join(", ")}; received "${raw}".`);
|
|
55
|
+
}
|
|
56
|
+
function isTenancyEnabled(env = process.env) {
|
|
57
|
+
return readTenancyDriver(env) !== "none";
|
|
58
|
+
}
|
|
59
|
+
function isRlsTenancy(env = process.env) {
|
|
60
|
+
return readTenancyDriver(env) === "rls";
|
|
61
|
+
}
|
|
62
|
+
var TENANCY_DRIVERS;
|
|
63
|
+
var init_tenancyConfig = __esm(() => {
|
|
64
|
+
TENANCY_DRIVERS = ["rls", "column", "none"];
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// ../../src/core/tenant/tenantContext.ts
|
|
68
|
+
function runWithTenant(tenant, callback) {
|
|
69
|
+
return tenantContext.run(tenant, callback);
|
|
70
|
+
}
|
|
71
|
+
function currentTenant() {
|
|
72
|
+
return tenantContext.getStore() ?? null;
|
|
73
|
+
}
|
|
74
|
+
var tenantContext;
|
|
75
|
+
var init_tenantContext = __esm(() => {
|
|
76
|
+
init_asyncContextStore();
|
|
77
|
+
tenantContext = createAsyncContextStore("@getstrata/tenantContext");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// ../../src/core/events/eventBus.ts
|
|
81
|
+
class EventBus {
|
|
82
|
+
constructor() {}
|
|
83
|
+
listeners = new Map;
|
|
84
|
+
on(event, listener) {
|
|
85
|
+
return this.listen(event, listener);
|
|
86
|
+
}
|
|
87
|
+
listen(event, listener) {
|
|
88
|
+
const handlers = this.listeners.get(event) ?? new Set;
|
|
89
|
+
handlers.add(listener);
|
|
90
|
+
this.listeners.set(event, handlers);
|
|
91
|
+
return () => {
|
|
92
|
+
handlers.delete(listener);
|
|
93
|
+
if (handlers.size === 0) {
|
|
94
|
+
this.listeners.delete(event);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async emit(event, payload) {
|
|
99
|
+
await this.dispatch(event, payload);
|
|
100
|
+
}
|
|
101
|
+
async dispatch(event, payload) {
|
|
102
|
+
const handlers = this.listeners.get(event);
|
|
103
|
+
if (!handlers || handlers.size === 0) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
for (const handler of handlers) {
|
|
107
|
+
await handler(payload);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function readSharedEventBus() {
|
|
112
|
+
const globalBus = globalThis[EVENT_BUS_KEY];
|
|
113
|
+
if (globalBus) {
|
|
114
|
+
return globalBus;
|
|
115
|
+
}
|
|
116
|
+
const bus = new EventBus;
|
|
117
|
+
globalThis[EVENT_BUS_KEY] = bus;
|
|
118
|
+
return bus;
|
|
119
|
+
}
|
|
120
|
+
var EVENT_BUS_KEY, eventBus;
|
|
121
|
+
var init_eventBus = __esm(() => {
|
|
122
|
+
EVENT_BUS_KEY = Symbol.for("@getstrata/eventBus");
|
|
123
|
+
eventBus = readSharedEventBus();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// ../../src/core/events/deferredModelEvents.ts
|
|
127
|
+
function sameTenant(left, right) {
|
|
128
|
+
if (left === null && right === null) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
if (left === null || right === null) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
return left.id === right.id;
|
|
135
|
+
}
|
|
136
|
+
function groupQueuedModelEvents(queued) {
|
|
137
|
+
const groups = [];
|
|
138
|
+
for (const item of queued) {
|
|
139
|
+
const lastGroup = groups[groups.length - 1];
|
|
140
|
+
const last = lastGroup?.[lastGroup.length - 1];
|
|
141
|
+
if (!lastGroup || !last || !sameTenant(last.tenant, item.tenant)) {
|
|
142
|
+
groups.push([item]);
|
|
143
|
+
} else {
|
|
144
|
+
lastGroup.push(item);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return groups;
|
|
148
|
+
}
|
|
149
|
+
async function dispatchEventBatch(batch) {
|
|
150
|
+
for (const item of batch) {
|
|
151
|
+
await eventBus.dispatch(item.event, item.payload);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function dispatchQueuedModelEvents(queued) {
|
|
155
|
+
if (queued.length === 0) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
await Promise.resolve().then(() => init_tenantDatabaseScope());
|
|
159
|
+
for (const batch of groupQueuedModelEvents(queued)) {
|
|
160
|
+
const tenant = batch[0]?.tenant ?? null;
|
|
161
|
+
if (tenant) {
|
|
162
|
+
await runWithTenantDatabase(tenant, () => dispatchEventBatch(batch));
|
|
163
|
+
} else {
|
|
164
|
+
await dispatchEventBatch(batch);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async function runWithDeferredModelEvents(callback) {
|
|
169
|
+
const existing = deferredModelEvents.getStore();
|
|
170
|
+
if (existing) {
|
|
171
|
+
existing.frames.push([]);
|
|
172
|
+
try {
|
|
173
|
+
const result = await callback();
|
|
174
|
+
const nested = existing.frames.pop() ?? [];
|
|
175
|
+
const parent = existing.frames[existing.frames.length - 1];
|
|
176
|
+
if (parent) {
|
|
177
|
+
parent.push(...nested);
|
|
178
|
+
}
|
|
179
|
+
return result;
|
|
180
|
+
} catch (error) {
|
|
181
|
+
existing.frames.pop();
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const state = { frames: [[]] };
|
|
186
|
+
const result = await deferredModelEvents.run(state, callback);
|
|
187
|
+
await dispatchQueuedModelEvents(state.frames[0] ?? []);
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
var deferredModelEvents;
|
|
191
|
+
var init_deferredModelEvents = __esm(() => {
|
|
192
|
+
init_asyncContextStore();
|
|
193
|
+
init_tenantContext();
|
|
194
|
+
init_eventBus();
|
|
195
|
+
deferredModelEvents = createAsyncContextStore("@getstrata/deferredModelEvents");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// ../../src/core/tenant/tenantDatabaseScope.ts
|
|
199
|
+
import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
|
|
200
|
+
async function applyTenantContextToTransaction(transaction, tenantId) {
|
|
201
|
+
await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
|
|
202
|
+
await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
|
|
203
|
+
}
|
|
204
|
+
async function runWithTenantDatabase(tenant, callback) {
|
|
205
|
+
if (!isTenancyEnabled() || !isRlsTenancy()) {
|
|
206
|
+
return await runWithTenant(tenant, callback);
|
|
207
|
+
}
|
|
208
|
+
if (hasActiveDatabaseConnection()) {
|
|
209
|
+
const activeConnection = getActiveDatabaseConnection(getDefaultDatabasePool());
|
|
210
|
+
await applyTenantContextToTransaction(activeConnection, tenant.id);
|
|
211
|
+
return await runWithTenant(tenant, callback);
|
|
212
|
+
}
|
|
213
|
+
const pool = getDefaultDatabasePool();
|
|
214
|
+
const begin = pool.begin;
|
|
215
|
+
if (typeof begin !== "function") {
|
|
216
|
+
throw new Error("RLS tenant scope requires a pool that supports begin(). Session-scoped set_config is not used on pooled connections.");
|
|
217
|
+
}
|
|
218
|
+
return await runWithDeferredModelEvents(async () => {
|
|
219
|
+
return await begin(async (transaction) => {
|
|
220
|
+
await applyTenantContextToTransaction(transaction, tenant.id);
|
|
221
|
+
return await runWithDatabaseConnection(transaction, async () => {
|
|
222
|
+
return await runWithTenant(tenant, callback);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
|
|
228
|
+
return hasActiveDatabaseConnection() && currentTenant()?.id === tenantId;
|
|
229
|
+
}
|
|
230
|
+
var init_tenantDatabaseScope = __esm(() => {
|
|
231
|
+
init_connectionContext();
|
|
232
|
+
init_deferredModelEvents();
|
|
233
|
+
init_tenancyConfig();
|
|
234
|
+
init_tenantContext();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// ../../src/core/auth/scimAuthMiddleware.ts
|
|
238
|
+
init_connectionContext();
|
|
239
|
+
import { bindDatabaseConnection } from "@getstrata/core/database/bindConnection";
|
|
240
|
+
import { resetBoundDatabaseConnection } from "@getstrata/core/database/boundConnection";
|
|
241
|
+
import { getDefaultDatabasePool as getDefaultDatabasePool2 } from "@getstrata/core/database/defaultConnection";
|
|
32
242
|
|
|
33
243
|
// ../../src/core/security/timingSafeCompare.ts
|
|
34
244
|
import { timingSafeEqual } from "crypto";
|
|
@@ -82,28 +292,8 @@ function resolveScimTenantFromToken(token) {
|
|
|
82
292
|
}
|
|
83
293
|
|
|
84
294
|
// ../../src/core/tenant/resolveTenant.ts
|
|
295
|
+
init_tenancyConfig();
|
|
85
296
|
import { repositoryConnection as db } from "@getstrata/core/database/repositoryConnection";
|
|
86
|
-
|
|
87
|
-
// ../../src/core/tenant/tenancyConfig.ts
|
|
88
|
-
var TENANCY_DRIVERS = ["rls", "column", "none"];
|
|
89
|
-
function readTenancyDriver(env = process.env) {
|
|
90
|
-
const raw = env.TENANCY_DRIVER?.trim();
|
|
91
|
-
if (raw === undefined || raw === "") {
|
|
92
|
-
return "rls";
|
|
93
|
-
}
|
|
94
|
-
if (TENANCY_DRIVERS.includes(raw)) {
|
|
95
|
-
return raw;
|
|
96
|
-
}
|
|
97
|
-
throw new Error(`TENANCY_DRIVER must be one of ${TENANCY_DRIVERS.join(", ")}; received "${raw}".`);
|
|
98
|
-
}
|
|
99
|
-
function isTenancyEnabled(env = process.env) {
|
|
100
|
-
return readTenancyDriver(env) !== "none";
|
|
101
|
-
}
|
|
102
|
-
function isRlsTenancy(env = process.env) {
|
|
103
|
-
return readTenancyDriver(env) === "rls";
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ../../src/core/tenant/resolveTenant.ts
|
|
107
297
|
async function resolveTenant(tenantId) {
|
|
108
298
|
if (!isTenancyEnabled()) {
|
|
109
299
|
return {
|
|
@@ -123,44 +313,8 @@ async function resolveTenant(tenantId) {
|
|
|
123
313
|
return row ? { id: row.id, slug: row.slug, plan: row.plan, region: row.region ?? "eu" } : null;
|
|
124
314
|
}
|
|
125
315
|
|
|
126
|
-
// ../../src/core/tenant/tenantDatabaseScope.ts
|
|
127
|
-
import { getDefaultDatabasePool } from "@getstrata/core/database/defaultConnection";
|
|
128
|
-
|
|
129
|
-
// ../../src/core/tenant/tenantContext.ts
|
|
130
|
-
var tenantContext = createAsyncContextStore("@getstrata/tenantContext");
|
|
131
|
-
function runWithTenant(tenant, callback) {
|
|
132
|
-
return tenantContext.run(tenant, callback);
|
|
133
|
-
}
|
|
134
|
-
function currentTenant() {
|
|
135
|
-
return tenantContext.getStore() ?? null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// ../../src/core/tenant/tenantDatabaseScope.ts
|
|
139
|
-
async function applyTenantContextToTransaction(transaction, tenantId) {
|
|
140
|
-
await transaction.unsafe(`SELECT set_config('app.tenant_id', $1, true)`, [String(tenantId)]);
|
|
141
|
-
await transaction.unsafe(`SELECT set_config('app.bypass_rls', $1, true)`, ["false"]);
|
|
142
|
-
}
|
|
143
|
-
async function runWithTenantDatabase(tenant, callback) {
|
|
144
|
-
if (!isTenancyEnabled() || !isRlsTenancy()) {
|
|
145
|
-
return await runWithTenant(tenant, callback);
|
|
146
|
-
}
|
|
147
|
-
if (hasActiveDatabaseConnection()) {
|
|
148
|
-
const activeConnection = getActiveDatabaseConnection(getDefaultDatabasePool());
|
|
149
|
-
await applyTenantContextToTransaction(activeConnection, tenant.id);
|
|
150
|
-
return await runWithTenant(tenant, callback);
|
|
151
|
-
}
|
|
152
|
-
return await getDefaultDatabasePool().begin(async (transaction) => {
|
|
153
|
-
await applyTenantContextToTransaction(transaction, tenant.id);
|
|
154
|
-
return await runWithDatabaseConnection(transaction, async () => {
|
|
155
|
-
return await runWithTenant(tenant, callback);
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
function isInsideTenantDatabaseScope(tenantId = currentTenant()?.id) {
|
|
160
|
-
return hasActiveDatabaseConnection() && currentTenant()?.id === tenantId;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
316
|
// ../../src/core/auth/scimAuthMiddleware.ts
|
|
317
|
+
init_tenantDatabaseScope();
|
|
164
318
|
function createScimAuthMiddleware() {
|
|
165
319
|
return async (request, next) => {
|
|
166
320
|
const authorization = request.headers.get("authorization");
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
+
};
|
|
6
13
|
|
|
7
14
|
// ../../src/core/runtime/asyncContextStore.ts
|
|
8
15
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -17,6 +24,15 @@ function createAsyncContextStore(key) {
|
|
|
17
24
|
globalRecord[symbol] = store;
|
|
18
25
|
return store;
|
|
19
26
|
}
|
|
27
|
+
var init_asyncContextStore = () => {};
|
|
28
|
+
|
|
29
|
+
// ../../src/core/database/migrations/runner.ts
|
|
30
|
+
import { readdir } from "fs/promises";
|
|
31
|
+
import { join } from "path";
|
|
32
|
+
import { pathToFileURL } from "url";
|
|
33
|
+
|
|
34
|
+
// ../../src/core/database/dialect.ts
|
|
35
|
+
init_asyncContextStore();
|
|
20
36
|
|
|
21
37
|
// ../../src/core/database/schema/driver.ts
|
|
22
38
|
function normalizeConnectionName(connection) {
|
|
@@ -1,4 +1,31 @@
|
|
|
1
1
|
// @bun
|
|
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
|
+
};
|
|
13
|
+
|
|
14
|
+
// ../../src/core/runtime/asyncContextStore.ts
|
|
15
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
16
|
+
function createAsyncContextStore(key) {
|
|
17
|
+
const symbol = Symbol.for(key);
|
|
18
|
+
const globalRecord = globalThis;
|
|
19
|
+
const existing = globalRecord[symbol];
|
|
20
|
+
if (existing) {
|
|
21
|
+
return existing;
|
|
22
|
+
}
|
|
23
|
+
const store = new AsyncLocalStorage;
|
|
24
|
+
globalRecord[symbol] = store;
|
|
25
|
+
return store;
|
|
26
|
+
}
|
|
27
|
+
var init_asyncContextStore = () => {};
|
|
28
|
+
|
|
2
29
|
// ../../src/core/http/csrfMiddleware.ts
|
|
3
30
|
import { currentCredentialSource } from "@getstrata/core/auth/authContext";
|
|
4
31
|
import { ForbiddenError } from "@getstrata/core/errors/http";
|
|
@@ -120,21 +147,8 @@ function readBunRequestCookie(request, name) {
|
|
|
120
147
|
return request.cookies.get(name) ?? readRequestCookie(request, name);
|
|
121
148
|
}
|
|
122
149
|
|
|
123
|
-
// ../../src/core/runtime/asyncContextStore.ts
|
|
124
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
125
|
-
function createAsyncContextStore(key) {
|
|
126
|
-
const symbol = Symbol.for(key);
|
|
127
|
-
const globalRecord = globalThis;
|
|
128
|
-
const existing = globalRecord[symbol];
|
|
129
|
-
if (existing) {
|
|
130
|
-
return existing;
|
|
131
|
-
}
|
|
132
|
-
const store = new AsyncLocalStorage;
|
|
133
|
-
globalRecord[symbol] = store;
|
|
134
|
-
return store;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
150
|
// ../../src/core/http/requestMetaContext.ts
|
|
151
|
+
init_asyncContextStore();
|
|
138
152
|
var requestMetaContext = createAsyncContextStore("@getstrata/requestMetaContext");
|
|
139
153
|
function runWithRequestMeta(meta, callback) {
|
|
140
154
|
return requestMetaContext.run(meta, callback);
|
|
@@ -1,4 +1,31 @@
|
|
|
1
1
|
// @bun
|
|
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
|
+
};
|
|
13
|
+
|
|
14
|
+
// ../../src/core/runtime/asyncContextStore.ts
|
|
15
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
16
|
+
function createAsyncContextStore(key) {
|
|
17
|
+
const symbol = Symbol.for(key);
|
|
18
|
+
const globalRecord = globalThis;
|
|
19
|
+
const existing = globalRecord[symbol];
|
|
20
|
+
if (existing) {
|
|
21
|
+
return existing;
|
|
22
|
+
}
|
|
23
|
+
const store = new AsyncLocalStorage;
|
|
24
|
+
globalRecord[symbol] = store;
|
|
25
|
+
return store;
|
|
26
|
+
}
|
|
27
|
+
var init_asyncContextStore = () => {};
|
|
28
|
+
|
|
2
29
|
// ../../src/core/http/csrfToken.ts
|
|
3
30
|
import { timingSafeEqual } from "crypto";
|
|
4
31
|
|
|
@@ -116,21 +143,8 @@ function readBunRequestCookie(request, name) {
|
|
|
116
143
|
return request.cookies.get(name) ?? readRequestCookie(request, name);
|
|
117
144
|
}
|
|
118
145
|
|
|
119
|
-
// ../../src/core/runtime/asyncContextStore.ts
|
|
120
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
121
|
-
function createAsyncContextStore(key) {
|
|
122
|
-
const symbol = Symbol.for(key);
|
|
123
|
-
const globalRecord = globalThis;
|
|
124
|
-
const existing = globalRecord[symbol];
|
|
125
|
-
if (existing) {
|
|
126
|
-
return existing;
|
|
127
|
-
}
|
|
128
|
-
const store = new AsyncLocalStorage;
|
|
129
|
-
globalRecord[symbol] = store;
|
|
130
|
-
return store;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
146
|
// ../../src/core/http/requestMetaContext.ts
|
|
147
|
+
init_asyncContextStore();
|
|
134
148
|
var requestMetaContext = createAsyncContextStore("@getstrata/requestMetaContext");
|
|
135
149
|
function runWithRequestMeta(meta, callback) {
|
|
136
150
|
return requestMetaContext.run(meta, callback);
|