@prisma/orm-extension-supabase 8.0.0-rc.2-dev.2 → 8.0.0-rc.20
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/README.md +1 -7
- package/dist/{contract-Bg_nlDSp-BaY1Wgsj.mjs → contract-BT1LXEGv-BCF6iBts.mjs} +897 -737
- package/dist/contract-BT1LXEGv-BCF6iBts.mjs.map +1 -0
- package/dist/contract.d.mts +301 -139
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.mjs +3 -9
- package/dist/contract.mjs.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/pack.mjs.map +1 -1
- package/dist/{roles-D5vC3rNp-tYQlvifU.mjs → roles-9Ql17Kbb-p1cF6Jlt.mjs} +4 -7
- package/dist/roles-9Ql17Kbb-p1cF6Jlt.mjs.map +1 -0
- package/dist/{roles-CuXa3u9g-bhk28dKK.d.mts → roles-B4kRmZCy-CCes-zCM.d.mts} +4 -4
- package/dist/roles-B4kRmZCy-CCes-zCM.d.mts.map +1 -0
- package/dist/runtime.d.mts +3057 -4060
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +246 -172
- package/dist/runtime.mjs.map +1 -1
- package/package.json +13 -12
- package/dist/contract-Bg_nlDSp-BaY1Wgsj.mjs.map +0 -1
- package/dist/roles-CuXa3u9g-bhk28dKK.d.mts.map +0 -1
- package/dist/roles-D5vC3rNp-tYQlvifU.mjs.map +0 -1
package/dist/runtime.mjs
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { n as version, t as contract_default } from "./contract-
|
|
2
|
-
import { a as isSupabaseRole, n as SupabaseRole, t as SUPABASE_JWT_ROLE_CLAIM } from "./roles-
|
|
1
|
+
import { n as version, t as contract_default } from "./contract-BT1LXEGv-BCF6iBts.mjs";
|
|
2
|
+
import { a as isSupabaseRole, n as SupabaseRole, t as SUPABASE_JWT_ROLE_CLAIM } from "./roles-9Ql17Kbb-p1cF6Jlt.mjs";
|
|
3
3
|
import { blindCast } from "@prisma/orm-framework/utils/casts";
|
|
4
4
|
import postgresAdapter from "@prisma/orm-target-postgres/adapter/runtime";
|
|
5
|
-
import postgresDriver from "@prisma/orm-target-postgres/driver/runtime";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { createExecutionContext, createSqlExecutionStack, withTransaction } from "@prisma/orm-family-sql/runtime";
|
|
5
|
+
import postgresDriver, { suppressIdleConnectionErrors } from "@prisma/orm-target-postgres/driver/runtime";
|
|
6
|
+
import { buildPostgresStaticContext } from "@prisma/orm-postgres/internal/static-context";
|
|
7
|
+
import { buildPostgresQueryMembers } from "@prisma/orm-postgres/internal/transaction-members";
|
|
8
|
+
import { validatePostgresContract } from "@prisma/orm-postgres/internal/validate-contract";
|
|
9
|
+
import { PostgresRuntimeImpl, isPgPool } from "@prisma/orm-postgres/runtime";
|
|
10
|
+
import { checkCollectionClasses, orm, prepareQuery } from "@prisma/orm-family-sql/orm-client";
|
|
11
|
+
import { activitySource, createExecutionContext, createSqlExecutionStack, withTransaction, withTransactionMembers } from "@prisma/orm-family-sql/runtime";
|
|
12
|
+
import { createTransactionStart, preparedStatementExecute, preparedStatementQuery, transactionStart } from "@prisma/orm-family-sql/runtime/internal/prepared-query";
|
|
12
13
|
import postgresTarget, { PostgresContractSerializer } from "@prisma/orm-target-postgres/target/runtime";
|
|
13
14
|
import { ifDefined } from "@prisma/orm-framework/utils/defined";
|
|
14
15
|
import { InternalError } from "@prisma/orm-framework/utils/internal-error";
|
|
16
|
+
import { structuredError } from "@prisma/orm-framework/utils/structured-error";
|
|
15
17
|
import { createRemoteJWKSet, decodeProtectedHeader, jwtVerify } from "jose";
|
|
16
18
|
import { Pool } from "pg";
|
|
17
|
-
import { structuredError } from "@prisma/orm-framework/utils/structured-error";
|
|
18
19
|
import { AsyncIterableResult } from "@prisma/orm-framework/components/runtime";
|
|
19
|
-
import { preparedStatementExecute, preparedStatementQuery } from "@prisma/orm-family-sql/runtime/internal/prepared-query";
|
|
20
20
|
//#region ../../../3-extensions/supabase/dist/runtime.mjs
|
|
21
21
|
/**
|
|
22
22
|
* Tells the runtime that the Supabase pack's runtime component is available.
|
|
@@ -44,14 +44,22 @@ const supabaseRuntimeDescriptor = {
|
|
|
44
44
|
function supabaseError(code, message, options) {
|
|
45
45
|
return structuredError(code, message, options);
|
|
46
46
|
}
|
|
47
|
+
let buildRoleScope;
|
|
48
|
+
/**
|
|
49
|
+
* The operations under `binding` of the runtime `runtime()` returns. Each operation calls `runtime()` when it runs, so a client can build its role scope before its runtime exists; when `runtime()` throws, the operation rejects. For the facade only; the package entry does not export it.
|
|
50
|
+
*/
|
|
51
|
+
function roleScope(runtime, binding) {
|
|
52
|
+
return buildRoleScope(runtime, binding);
|
|
53
|
+
}
|
|
47
54
|
var SupabaseRuntimeImpl = class extends PostgresRuntimeImpl {
|
|
48
55
|
/**
|
|
49
|
-
* Opens a raw connection and applies role + JWT claims via session-scoped set_config.
|
|
50
|
-
* On bind failure, destroys the connection before rethrowing — no leaked connections.
|
|
51
|
-
* Not on the `SupabaseRuntime` interface; consumed by the facade, not by app code.
|
|
56
|
+
* Opens a raw connection and applies role + JWT claims via session-scoped set_config. On bind failure, destroys the connection before rethrowing — no leaked connections. Every operation of `forRole(binding)` runs on a session opened here.
|
|
52
57
|
*/
|
|
53
58
|
async openRoleSession(binding) {
|
|
54
|
-
|
|
59
|
+
return (await this.openRoleConnection(binding)).session;
|
|
60
|
+
}
|
|
61
|
+
async openRoleConnection(binding, options) {
|
|
62
|
+
const conn = await this.acquireRawConnection(options);
|
|
55
63
|
try {
|
|
56
64
|
await conn.execute({
|
|
57
65
|
sql: "SELECT set_config($1, $2, false)",
|
|
@@ -66,7 +74,9 @@ var SupabaseRuntimeImpl = class extends PostgresRuntimeImpl {
|
|
|
66
74
|
throw err;
|
|
67
75
|
}
|
|
68
76
|
const self = this;
|
|
69
|
-
|
|
77
|
+
const session = {
|
|
78
|
+
[transactionStart]: createTransactionStart(),
|
|
79
|
+
[activitySource]: self.connectionActivitySource(conn, () => session),
|
|
70
80
|
query(plan, options) {
|
|
71
81
|
return self.queryAgainstQueryable(plan, conn, {
|
|
72
82
|
...options,
|
|
@@ -80,39 +90,13 @@ var SupabaseRuntimeImpl = class extends PostgresRuntimeImpl {
|
|
|
80
90
|
});
|
|
81
91
|
},
|
|
82
92
|
[preparedStatementQuery](prepared, params, options) {
|
|
83
|
-
return self.runPreparedQueryAgainstRoleQueryable(prepared, params, conn, options
|
|
93
|
+
return self.runPreparedQueryAgainstRoleQueryable(prepared, params, conn, options);
|
|
84
94
|
},
|
|
85
95
|
[preparedStatementExecute](prepared, params, options) {
|
|
86
|
-
return self.runPreparedExecuteAgainstRoleQueryable(prepared, params, conn, options
|
|
96
|
+
return self.runPreparedExecuteAgainstRoleQueryable(prepared, params, conn, options);
|
|
87
97
|
},
|
|
88
98
|
async transaction() {
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
async commit() {
|
|
92
|
-
await tx.commit();
|
|
93
|
-
},
|
|
94
|
-
async rollback() {
|
|
95
|
-
await tx.rollback();
|
|
96
|
-
},
|
|
97
|
-
query(plan, options) {
|
|
98
|
-
return self.queryAgainstQueryable(plan, tx, {
|
|
99
|
-
...options,
|
|
100
|
-
scope: "transaction"
|
|
101
|
-
});
|
|
102
|
-
},
|
|
103
|
-
execute(plan, options) {
|
|
104
|
-
return self.executeStatisticsAgainstQueryable(plan, tx, {
|
|
105
|
-
...options,
|
|
106
|
-
scope: "transaction"
|
|
107
|
-
});
|
|
108
|
-
},
|
|
109
|
-
[preparedStatementQuery](prepared, params, options) {
|
|
110
|
-
return self.runPreparedQueryAgainstRoleQueryable(prepared, params, tx, options, "transaction");
|
|
111
|
-
},
|
|
112
|
-
[preparedStatementExecute](prepared, params, options) {
|
|
113
|
-
return self.runPreparedExecuteAgainstRoleQueryable(prepared, params, tx, options, "transaction");
|
|
114
|
-
}
|
|
115
|
-
};
|
|
99
|
+
return self.beginTransactionOn(conn, session, void 0);
|
|
116
100
|
},
|
|
117
101
|
/**
|
|
118
102
|
* Resets all session-local config then releases the connection back to the pool.
|
|
@@ -130,59 +114,100 @@ var SupabaseRuntimeImpl = class extends PostgresRuntimeImpl {
|
|
|
130
114
|
await conn.destroy(reason);
|
|
131
115
|
}
|
|
132
116
|
};
|
|
117
|
+
return {
|
|
118
|
+
conn,
|
|
119
|
+
session
|
|
120
|
+
};
|
|
133
121
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
122
|
+
forRole(binding) {
|
|
123
|
+
return buildRoleScope(() => this, binding);
|
|
124
|
+
}
|
|
125
|
+
static {
|
|
126
|
+
buildRoleScope = (runtime, binding) => {
|
|
127
|
+
const open = (options) => async () => (await runtime().openRoleConnection(binding, options)).session;
|
|
128
|
+
const scope = {
|
|
129
|
+
query(plan, options) {
|
|
130
|
+
return streamOnSession(open(options), (session) => session.query(plan, options));
|
|
131
|
+
},
|
|
132
|
+
execute(plan, options) {
|
|
133
|
+
return executeOnSession(open(options), (session) => session.execute(plan, options));
|
|
134
|
+
},
|
|
135
|
+
[preparedStatementQuery](statement, params, options) {
|
|
136
|
+
return streamOnSession(open(options), (session) => session[preparedStatementQuery](statement, params, options));
|
|
137
|
+
},
|
|
138
|
+
[preparedStatementExecute](statement, params, options) {
|
|
139
|
+
return executeOnSession(open(options), (session) => session[preparedStatementExecute](statement, params, options));
|
|
140
|
+
},
|
|
141
|
+
connection: open(void 0),
|
|
142
|
+
[activitySource]: {
|
|
143
|
+
startActivity: async (activity) => runtime().startActivityOnRoute(route, activity, void 0),
|
|
144
|
+
planContentHash: async (plan) => runtime().planContentHashFor(plan, "connection", void 0)
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const route = {
|
|
148
|
+
scope: "connection",
|
|
149
|
+
parent: () => void 0,
|
|
150
|
+
runtimeWork: true,
|
|
151
|
+
query: (plan, options) => scope.query(plan, options),
|
|
152
|
+
execute: (plan, options) => scope.execute(plan, options),
|
|
153
|
+
preparedQuery: (statement, params, options) => scope[preparedStatementQuery](statement, params, options),
|
|
154
|
+
preparedExecute: (statement, params, options) => scope[preparedStatementExecute](statement, params, options),
|
|
155
|
+
transaction: (parent) => runtime().beginRoleTransaction(binding, parent)
|
|
156
|
+
};
|
|
157
|
+
return scope;
|
|
152
158
|
};
|
|
153
|
-
return new AsyncIterableResult(generator());
|
|
154
159
|
}
|
|
155
|
-
async
|
|
156
|
-
const session = await this.
|
|
157
|
-
|
|
158
|
-
const stats = await session.execute(plan, options);
|
|
159
|
-
await session.release();
|
|
160
|
-
return stats;
|
|
161
|
-
} catch (err) {
|
|
162
|
-
await session.destroy(err).catch(() => void 0);
|
|
163
|
-
throw err;
|
|
164
|
-
}
|
|
160
|
+
async beginRoleTransaction(binding, parent) {
|
|
161
|
+
const { conn, session } = await this.openRoleConnection(binding, { activityParent: parent });
|
|
162
|
+
return this.ownTransaction(session, () => this.beginTransactionOn(conn, session, parent));
|
|
165
163
|
}
|
|
166
|
-
runPreparedExecuteAgainstRoleQueryable(prepared, params, queryable, options
|
|
164
|
+
runPreparedExecuteAgainstRoleQueryable(prepared, params, queryable, options) {
|
|
167
165
|
return this.runPreparedExecuteAgainstQueryable(blindCast(prepared), blindCast(params), queryable, {
|
|
168
166
|
...options,
|
|
169
|
-
scope
|
|
167
|
+
scope: "connection"
|
|
170
168
|
});
|
|
171
169
|
}
|
|
172
|
-
runPreparedQueryAgainstRoleQueryable(prepared, params, queryable, options
|
|
170
|
+
runPreparedQueryAgainstRoleQueryable(prepared, params, queryable, options) {
|
|
173
171
|
return this.runPreparedQueryAgainstQueryable(blindCast(prepared), blindCast(params), queryable, {
|
|
174
172
|
...options,
|
|
175
|
-
scope
|
|
173
|
+
scope: "connection"
|
|
176
174
|
});
|
|
177
175
|
}
|
|
178
176
|
};
|
|
179
|
-
function
|
|
180
|
-
|
|
177
|
+
function streamOnSession(open, rows) {
|
|
178
|
+
const generator = async function* () {
|
|
179
|
+
const session = await open();
|
|
180
|
+
let errored = false;
|
|
181
|
+
try {
|
|
182
|
+
for await (const row of rows(session)) yield row;
|
|
183
|
+
} catch (err) {
|
|
184
|
+
errored = true;
|
|
185
|
+
await session.destroy(err).catch(() => void 0);
|
|
186
|
+
throw err;
|
|
187
|
+
} finally {
|
|
188
|
+
if (!errored) await session.release();
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
return new AsyncIterableResult(generator());
|
|
192
|
+
}
|
|
193
|
+
async function executeOnSession(open, run) {
|
|
194
|
+
const session = await open();
|
|
195
|
+
try {
|
|
196
|
+
const stats = await run(session);
|
|
197
|
+
await session.release();
|
|
198
|
+
return stats;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
await session.destroy(err).catch(() => void 0);
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
181
203
|
}
|
|
182
204
|
const contractSerializer = new PostgresContractSerializer();
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
|
|
205
|
+
function closedClientError() {
|
|
206
|
+
return structuredError("DRIVER.NOT_CONNECTED", "Runtime is closed", {
|
|
207
|
+
why: "close() was called on this client.",
|
|
208
|
+
fix: "Create a new supabase(...) client.",
|
|
209
|
+
meta: { extension: "supabase" }
|
|
210
|
+
});
|
|
186
211
|
}
|
|
187
212
|
function resolveKeyMaterial(options) {
|
|
188
213
|
const jwtSecret = "jwtSecret" in options ? options.jwtSecret : void 0;
|
|
@@ -220,17 +245,25 @@ function algKeyMismatchReason(jwt, kind) {
|
|
|
220
245
|
if (kind === "secret" && asymmetric) return `token is signed with ${alg} but this client is configured with jwtSecret (HS256). Current Supabase projects sign with asymmetric keys by default — configure jwksUrl (https://<project>/auth/v1/.well-known/jwks.json) instead of jwtSecret.`;
|
|
221
246
|
if (kind === "jwks" && alg.startsWith("HS")) return `token is signed with ${alg} (a symmetric algorithm) but this client is configured with jwksUrl. A legacy HS256 Supabase project needs jwtSecret (the JWT_SECRET from \`supabase status\`) instead of jwksUrl.`;
|
|
222
247
|
}
|
|
248
|
+
function checkPgOption(pg) {
|
|
249
|
+
if (pg === void 0 || typeof pg === "object" && pg !== null && isPgPool(pg)) return;
|
|
250
|
+
throw supabaseError("SUPABASE.CONFIG_INVALID", "The pg option takes a pg.Pool", {
|
|
251
|
+
why: "Each role-bound query needs a connection of its own, which a single pg.Client cannot give.",
|
|
252
|
+
fix: "Pass a pg.Pool as pg, or pass url.",
|
|
253
|
+
meta: { reason: "pg is not a pg.Pool" }
|
|
254
|
+
});
|
|
255
|
+
}
|
|
223
256
|
function toPool(options) {
|
|
224
257
|
if (options.pg !== void 0 && isPgPool(options.pg)) return {
|
|
225
258
|
pool: options.pg,
|
|
226
259
|
owned: false
|
|
227
260
|
};
|
|
228
261
|
if (typeof options.url === "string") return {
|
|
229
|
-
pool: new Pool({
|
|
262
|
+
pool: suppressIdleConnectionErrors(new Pool({
|
|
230
263
|
connectionString: options.url,
|
|
231
264
|
connectionTimeoutMillis: options.poolOptions?.connectionTimeoutMillis ?? 2e4,
|
|
232
265
|
idleTimeoutMillis: options.poolOptions?.idleTimeoutMillis ?? 3e4
|
|
233
|
-
}),
|
|
266
|
+
})),
|
|
234
267
|
owned: true
|
|
235
268
|
};
|
|
236
269
|
}
|
|
@@ -241,16 +274,34 @@ function withSupabaseDescriptor(extensions) {
|
|
|
241
274
|
/**
|
|
242
275
|
* Deserializes the Supabase extension's own emitted contract into a runtime
|
|
243
276
|
* contract: namespaces hydrate into `PostgresSchema` instances (with
|
|
244
|
-
* `qualifyTable`), and
|
|
245
|
-
*
|
|
277
|
+
* `qualifyTable`), and each column resolves its codec through the codec
|
|
278
|
+
* registry. Exposed only via `service_role`'s `.supabase`
|
|
246
279
|
* secondary root — never merged into the app contract.
|
|
247
280
|
*/
|
|
248
281
|
function buildExtensionContract() {
|
|
249
282
|
return blindCast(contractSerializer.deserializeContract(contract_default));
|
|
250
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Creates a Supabase client whose queries run as the role a JWT names. The client infers its
|
|
286
|
+
* contract type from `contract`: a value from `contractFromJson` of `@prisma/orm-postgres/static`
|
|
287
|
+
* for an emitted contract, or a TypeScript-authored contract. A contract is validated once, however
|
|
288
|
+
* many clients are built from it. The pool is created on the first query.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* import { contractFromJson } from '@prisma/orm-postgres/static';
|
|
293
|
+
* import { supabase } from '@prisma/orm-extension-supabase/runtime';
|
|
294
|
+
* import type { Contract } from './contract.d';
|
|
295
|
+
* import contractJson from './contract.json' with { type: 'json' };
|
|
296
|
+
*
|
|
297
|
+
* export const contract = contractFromJson<Contract>(contractJson);
|
|
298
|
+
* export const db = await supabase({ contract, url, jwtSecret });
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
251
301
|
async function supabase(options) {
|
|
252
302
|
const keyMaterial = resolveKeyMaterial(options);
|
|
253
|
-
|
|
303
|
+
checkPgOption(options.pg);
|
|
304
|
+
const contract = validatePostgresContract(options.contract);
|
|
254
305
|
const stack = createSqlExecutionStack({
|
|
255
306
|
target: postgresTarget,
|
|
256
307
|
adapter: postgresAdapter,
|
|
@@ -261,25 +312,63 @@ async function supabase(options) {
|
|
|
261
312
|
contract,
|
|
262
313
|
stack
|
|
263
314
|
});
|
|
264
|
-
|
|
265
|
-
const
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (!driverDescriptor) throw new InternalError("Driver descriptor missing from execution stack");
|
|
271
|
-
const driver = driverDescriptor.create({ cursor: { disabled: true } });
|
|
272
|
-
if (poolEntry) await driver.connect({
|
|
273
|
-
kind: "pgPool",
|
|
274
|
-
pool: poolEntry.pool
|
|
275
|
-
});
|
|
276
|
-
const runtime = new SupabaseRuntimeImpl({
|
|
277
|
-
context,
|
|
278
|
-
adapter: stackInstance.adapter,
|
|
279
|
-
driver,
|
|
280
|
-
...ifDefined("verifyMarker", options.verifyMarker),
|
|
281
|
-
...ifDefined("middleware", options.middleware)
|
|
315
|
+
checkCollectionClasses(contract, options.collections);
|
|
316
|
+
const { sql: appSql, raw, toSql, enums, nativeEnums } = buildPostgresStaticContext(contract, context, stack);
|
|
317
|
+
const extContract = buildExtensionContract();
|
|
318
|
+
const extContext = createExecutionContext({
|
|
319
|
+
contract: extContract,
|
|
320
|
+
stack
|
|
282
321
|
});
|
|
322
|
+
const extStatic = buildPostgresStaticContext(extContract, extContext, stack);
|
|
323
|
+
let runtimes;
|
|
324
|
+
let connectError;
|
|
325
|
+
let closed = false;
|
|
326
|
+
function getRuntimes() {
|
|
327
|
+
if (connectError !== void 0) throw connectError.error;
|
|
328
|
+
if (runtimes !== void 0) return runtimes;
|
|
329
|
+
if (closed) throw closedClientError();
|
|
330
|
+
const driverDescriptor = stack.driver;
|
|
331
|
+
if (!driverDescriptor) throw new InternalError("Driver descriptor missing from execution stack");
|
|
332
|
+
const adapter = stack.adapter.create(stack);
|
|
333
|
+
const driver = driverDescriptor.create({ cursor: { disabled: true } });
|
|
334
|
+
const sharedOptions = {
|
|
335
|
+
adapter,
|
|
336
|
+
driver,
|
|
337
|
+
...ifDefined("middleware", options.middleware),
|
|
338
|
+
...ifDefined("log", options.log),
|
|
339
|
+
...ifDefined("mode", options.mode),
|
|
340
|
+
closeRefusal: "at-once",
|
|
341
|
+
ownsDriver: false
|
|
342
|
+
};
|
|
343
|
+
const runtime = new SupabaseRuntimeImpl({
|
|
344
|
+
context,
|
|
345
|
+
...sharedOptions,
|
|
346
|
+
...ifDefined("verifyMarker", options.verifyMarker)
|
|
347
|
+
});
|
|
348
|
+
const extRuntime = new SupabaseRuntimeImpl({
|
|
349
|
+
context: extContext,
|
|
350
|
+
...sharedOptions,
|
|
351
|
+
verifyMarker: false
|
|
352
|
+
});
|
|
353
|
+
const poolEntry = toPool(options);
|
|
354
|
+
const ownedPool = poolEntry?.owned ? poolEntry.pool : void 0;
|
|
355
|
+
if (poolEntry) driver.connect({
|
|
356
|
+
kind: "pgPool",
|
|
357
|
+
pool: poolEntry.pool
|
|
358
|
+
}).catch(async (err) => {
|
|
359
|
+
connectError = { error: err };
|
|
360
|
+
await ownedPool?.end().catch(() => void 0);
|
|
361
|
+
});
|
|
362
|
+
runtimes = {
|
|
363
|
+
runtime,
|
|
364
|
+
extRuntime,
|
|
365
|
+
driver,
|
|
366
|
+
ownedPool
|
|
367
|
+
};
|
|
368
|
+
return runtimes;
|
|
369
|
+
}
|
|
370
|
+
const runtime = () => getRuntimes().runtime;
|
|
371
|
+
const extRuntime = () => getRuntimes().extRuntime;
|
|
283
372
|
async function verifyJwt(jwt) {
|
|
284
373
|
const mismatch = algKeyMismatchReason(jwt, keyMaterial.kind);
|
|
285
374
|
if (mismatch !== void 0) throw supabaseError("SUPABASE.JWT_INVALID", `Invalid JWT: ${mismatch}`, { meta: { reason: mismatch } });
|
|
@@ -294,86 +383,71 @@ async function supabase(options) {
|
|
|
294
383
|
});
|
|
295
384
|
}
|
|
296
385
|
}
|
|
297
|
-
function
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
context: roleContext
|
|
314
|
-
}),
|
|
315
|
-
raw: rawSqlTag,
|
|
316
|
-
query(plan, execOptions) {
|
|
317
|
-
return roleRuntime.queryWithRole(plan, binding, execOptions);
|
|
318
|
-
},
|
|
319
|
-
execute(plan, execOptions) {
|
|
320
|
-
return roleRuntime.executeWithRole(plan, binding, execOptions);
|
|
386
|
+
function buildRoleBoundDb(binding) {
|
|
387
|
+
const role = roleScope(runtime, binding);
|
|
388
|
+
const roleOrm = orm({
|
|
389
|
+
runtime: role,
|
|
390
|
+
context,
|
|
391
|
+
...ifDefined("collections", options.collections)
|
|
392
|
+
});
|
|
393
|
+
const roleBound = {
|
|
394
|
+
sql: appSql,
|
|
395
|
+
orm: roleOrm,
|
|
396
|
+
raw,
|
|
397
|
+
toSql,
|
|
398
|
+
enums,
|
|
399
|
+
nativeEnums,
|
|
400
|
+
prepare(declaration, callback) {
|
|
401
|
+
return prepareQuery(runtime(), declaration, callback);
|
|
321
402
|
},
|
|
403
|
+
query: role.query,
|
|
404
|
+
execute: role.execute,
|
|
405
|
+
[preparedStatementQuery]: role[preparedStatementQuery],
|
|
406
|
+
[preparedStatementExecute]: role[preparedStatementExecute],
|
|
322
407
|
transaction(fn) {
|
|
323
|
-
return withTransaction(
|
|
408
|
+
return withTransaction(role, (txCtx) => fn(withTransactionMembers(txCtx, {
|
|
409
|
+
...buildPostgresQueryMembers({
|
|
410
|
+
context,
|
|
411
|
+
collections: options.collections,
|
|
412
|
+
sql: appSql,
|
|
413
|
+
raw,
|
|
414
|
+
toSql,
|
|
415
|
+
prepareRuntime: runtime
|
|
416
|
+
}, txCtx),
|
|
417
|
+
enums,
|
|
418
|
+
nativeEnums
|
|
419
|
+
})));
|
|
324
420
|
}
|
|
325
421
|
};
|
|
326
|
-
|
|
327
|
-
function buildRoleBoundDb(binding) {
|
|
328
|
-
return buildRoleBoundDbWithContext(binding, context, runtime);
|
|
422
|
+
return Object.assign(roleBound, { [activitySource]: role[activitySource] });
|
|
329
423
|
}
|
|
330
424
|
const serviceRoleBinding = {
|
|
331
425
|
role: SupabaseRole.members.ServiceRole,
|
|
332
426
|
claims: {}
|
|
333
427
|
};
|
|
334
|
-
const
|
|
335
|
-
const extContext = createExecutionContext({
|
|
336
|
-
contract: extContract,
|
|
337
|
-
stack
|
|
338
|
-
});
|
|
339
|
-
const extRuntime = new SupabaseRuntimeImpl({
|
|
340
|
-
context: extContext,
|
|
341
|
-
adapter: stackInstance.adapter,
|
|
342
|
-
driver,
|
|
343
|
-
verifyMarker: false,
|
|
344
|
-
...ifDefined("middleware", options.middleware)
|
|
345
|
-
});
|
|
346
|
-
const extNativeEnums = blindCast(Object.freeze(buildNamespacedNativeEnums(extContract.storage)));
|
|
428
|
+
const serviceRole = roleScope(extRuntime, serviceRoleBinding);
|
|
347
429
|
const supabaseInternal = {
|
|
348
|
-
sql: sql
|
|
349
|
-
|
|
350
|
-
rawCodecInferer
|
|
351
|
-
}),
|
|
430
|
+
sql: extStatic.sql,
|
|
431
|
+
toSql: extStatic.toSql,
|
|
352
432
|
orm: orm({
|
|
353
|
-
runtime:
|
|
354
|
-
query(plan) {
|
|
355
|
-
return extRuntime.queryWithRole(plan, serviceRoleBinding);
|
|
356
|
-
},
|
|
357
|
-
execute(plan) {
|
|
358
|
-
return extRuntime.executeWithRole(plan, serviceRoleBinding);
|
|
359
|
-
},
|
|
360
|
-
connection: () => extRuntime.openRoleSession(serviceRoleBinding)
|
|
361
|
-
},
|
|
433
|
+
runtime: serviceRole,
|
|
362
434
|
context: extContext
|
|
363
435
|
}),
|
|
364
|
-
nativeEnums:
|
|
365
|
-
query
|
|
366
|
-
|
|
367
|
-
},
|
|
368
|
-
execute(plan, execOptions) {
|
|
369
|
-
return extRuntime.executeWithRole(plan, serviceRoleBinding, execOptions);
|
|
370
|
-
}
|
|
436
|
+
nativeEnums: extStatic.nativeEnums,
|
|
437
|
+
query: serviceRole.query,
|
|
438
|
+
execute: serviceRole.execute
|
|
371
439
|
};
|
|
372
|
-
|
|
373
|
-
|
|
440
|
+
let closePromise;
|
|
441
|
+
async function closeRuntimes() {
|
|
442
|
+
if (runtimes === void 0) return;
|
|
443
|
+
const { runtime, extRuntime, driver, ownedPool } = runtimes;
|
|
444
|
+
await Promise.all([runtime.close(), extRuntime.close()]);
|
|
445
|
+
if (ownedPool !== void 0) await driver.close();
|
|
446
|
+
}
|
|
447
|
+
function closeDb() {
|
|
374
448
|
closed = true;
|
|
375
|
-
|
|
376
|
-
|
|
449
|
+
closePromise ??= closeRuntimes();
|
|
450
|
+
return closePromise;
|
|
377
451
|
}
|
|
378
452
|
return {
|
|
379
453
|
context,
|
|
@@ -395,7 +469,7 @@ async function supabase(options) {
|
|
|
395
469
|
},
|
|
396
470
|
asServiceRole() {
|
|
397
471
|
return {
|
|
398
|
-
...
|
|
472
|
+
...buildRoleBoundDb(serviceRoleBinding),
|
|
399
473
|
supabase: supabaseInternal
|
|
400
474
|
};
|
|
401
475
|
},
|