better-supabase 0.4.0 → 0.5.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/README.md +2 -0
- package/dist/channel-FQW-CnGR.d.ts +70 -0
- package/dist/cli/bin.js +1 -1
- package/dist/cli/codemod-DqV7612m.js +388 -0
- package/dist/cli/{config-D9R0o1LH.js → config-CPVpXP5I.js} +78 -8
- package/dist/cli/{config-SSKSTUl2.js → config-dtoekM0v.js} +1 -1
- package/dist/cli/{read-sets-CMa29t9a.js → diff-SjkO5rNr.js} +1 -220
- package/dist/cli/{dist-CFgGknmZ.js → dist-DBPdlPYK.js} +4 -4
- package/dist/cli/{dist-B1MvLv-M.js → dist-DreZ24Sz.js} +1 -1
- package/dist/cli/{dist-Du7VnEUG.js → dist-xn4wlboc.js} +112 -1
- package/dist/cli/{doctor-BOym3mbL.js → doctor-L7Z8mYTx.js} +531 -50
- package/dist/cli/{env-BZ0uy8XK.js → env-DmKv_G4A.js} +1 -1
- package/dist/cli/gen-BJc9vdyu.js +2 -0
- package/dist/cli/{gen-Ccn_p90L.js → gen-C2osRcr5.js} +283 -87
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/cli/{init-ClnxRYBF.js → init-Saf5-R9T.js} +2 -2
- package/dist/cli/{introspect-DxqfkVIv.js → introspect--H7oGmcd.js} +2 -2
- package/dist/cli/{openapi-8WHjxiTJ.js → openapi-Cp5Fyta-.js} +1 -1
- package/dist/cli/read-sets-BfMQcKy8.js +289 -0
- package/dist/cli/{run-CP20LKk_.js → run-BKR2W_79.js} +16 -12
- package/dist/cli/{seed-5J6eu_Xg.js → seed-CUlqWh-8.js} +1 -1
- package/dist/cli/sql-DzPbfngx.js +348 -0
- package/dist/cli/{version-5mW_8sY1.js → version-BDJuO0UR.js} +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +3 -10
- package/dist/clone-BfgmLU90.js +21 -0
- package/dist/{compiler-DB3aSFOA.d.ts → compiler-BXH_aZ7N.d.ts} +2 -2
- package/dist/config/index.d.ts +4 -4
- package/dist/config/index.js +4 -4
- package/dist/{config-CbvFmGD8.js → config-DreERlKo.js} +1 -1
- package/dist/{config-C1CYcm6o.d.ts → config-T_ejwyd3.d.ts} +176 -11
- package/dist/{define-CRS2MRV3.d.ts → define-Bp_BZa5h.d.ts} +11 -7
- package/dist/{define-Bh0AqTik.js → define-cNKzqwL_.js} +202 -16
- package/dist/edge/index.d.ts +16 -5
- package/dist/edge/index.js +10 -7
- package/dist/{entitlements-Dm-FHpNH.d.ts → entitlements-DUxU4oHe.d.ts} +1 -1
- package/dist/env/index.d.ts +2 -2
- package/dist/env/index.js +34 -1
- package/dist/{errors-L0xK41y_.js → errors-DtwXa6b8.js} +1 -0
- package/dist/events/index.d.ts +3 -2
- package/dist/events/index.js +65 -12
- package/dist/events-aIO7vsIk.d.ts +230 -0
- package/dist/{result-CqEsbgYs.d.ts → executor-BunPOO-k.d.ts} +200 -1
- package/dist/{executor-CZ7ImRiD.d.ts → executor-Cghdstwu.d.ts} +1 -2
- package/dist/{executor-CVt6dD0B.js → executor-XycESQPH.js} +3 -3
- package/dist/hono/index.d.ts +17 -6
- package/dist/hono/index.js +40 -5
- package/dist/impersonation-VfaGc4Q_.js +41 -0
- package/dist/{index-BBdvo-5d.d.ts → index-BGdgBPdf.d.ts} +49 -6
- package/dist/{index-BhHEC04r.d.ts → index-C7f8cOBM.d.ts} +2 -2
- package/dist/{index-Dy6kuF0P.d.ts → index-CLg87OBW.d.ts} +6 -1
- package/dist/{index-D5IfUIDh.d.ts → index-DOESKG27.d.ts} +33 -8
- package/dist/{index-DFmOpBGC.d.ts → index-DgILJRXj.d.ts} +35 -9
- package/dist/{index-RlLXd8dL.d.ts → index-DmXSxbLi.d.ts} +4 -4
- package/dist/{index-Cf-D2jk1.d.ts → index-Dxn2a5cw.d.ts} +2 -2
- package/dist/{index-528Ugmyp.d.ts → index-SaTsEfGP.d.ts} +76 -8
- package/dist/{index-BAy4tsAP.d.ts → index-fag8VJZ2.d.ts} +3 -4
- package/dist/index.d.ts +30 -13
- package/dist/index.js +10 -9
- package/dist/jobs/index.d.ts +147 -101
- package/dist/jobs/index.js +744 -237
- package/dist/{json-schema-DP6V7cbr.js → json-schema-m1fiwKgN.js} +22 -1
- package/dist/kit-events-CTFDfSwb.js +60 -0
- package/dist/kit-transport-B82k1djG.d.ts +33 -0
- package/dist/kit-transport-DJlHQUBU.js +55 -0
- package/dist/{config-BpxDfnbg.js → kits-CGLLrNPd.js} +37 -9
- package/dist/list/index.d.ts +1 -1
- package/dist/{live-BHakSWWo.d.ts → live-D9W2M5aO.d.ts} +6 -5
- package/dist/mcp/index.d.ts +25 -8
- package/dist/mcp/index.js +23 -14
- package/dist/{mfa-C7MNQ1Ob.d.ts → mfa-CusDgPaD.d.ts} +5 -1
- package/dist/next/index.d.ts +31 -10
- package/dist/next/index.js +136 -27
- package/dist/notifications/index.d.ts +162 -0
- package/dist/notifications/index.js +264 -0
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +2 -2
- package/dist/orgs/index.d.ts +132 -0
- package/dist/orgs/index.js +245 -0
- package/dist/orpc/index.d.ts +28 -8
- package/dist/orpc/index.js +16 -3
- package/dist/otel/index.d.ts +21 -2
- package/dist/otel/index.js +50 -9
- package/dist/permdock-sql-C2Inc6Xc.d.ts +29 -0
- package/dist/permdock-sql-DgOfeixi.js +51 -0
- package/dist/plugin-DwARMuQp.js +59 -0
- package/dist/{plugin-bNhvJwRh.d.ts → plugin-o144f322.d.ts} +17 -5
- package/dist/plugins/actor/index.d.ts +5 -2
- package/dist/plugins/actor/index.js +22 -8
- package/dist/plugins/rules/index.d.ts +2 -2
- package/dist/plugins/rules/index.js +15 -10
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +14 -5
- package/dist/plugins/tenant/index.d.ts +2 -2
- package/dist/plugins/tenant/index.js +38 -20
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +4 -3
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +26 -6
- package/dist/{pool-DFwEQwmN.d.ts → pool-C9voM4Kw.d.ts} +17 -6
- package/dist/postgres/index.d.ts +5 -5
- package/dist/postgres/index.js +20 -11
- package/dist/{postgrest-Bc-0Xw62.d.ts → postgrest-CruYKAvV.d.ts} +1 -1
- package/dist/{problem-BihjPR0t.js → problem-BW1KhzSG.js} +2 -1
- package/dist/{problem-U8UEKccv.d.ts → problem-Blxe8S31.d.ts} +1 -1
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +3 -3
- package/dist/{query-BMMSWbI7.js → query-CCbo44lG.js} +2 -2
- package/dist/queue-BYUCjr59.d.ts +252 -0
- package/dist/react/index.d.ts +8 -7
- package/dist/react/index.js +4 -3
- package/dist/react/server.d.ts +14 -3
- package/dist/react/server.js +10 -2
- package/dist/react/session.d.ts +7 -1
- package/dist/react/session.js +9 -1
- package/dist/{react-CQHMaESR.js → react-C_s7kiNz.js} +103 -11
- package/dist/{read-set-FWK8qQ58.js → read-set-DQFt1N_Y.js} +22 -1
- package/dist/realtime/index.d.ts +3 -3
- package/dist/realtime/index.js +5 -4
- package/dist/{refresh-BwYkyNOQ.d.ts → refresh-BTrQ_ZTp.d.ts} +1 -1
- package/dist/{resolve-BAqQcwMW.d.ts → resolve-C15TJq77.d.ts} +11 -5
- package/dist/{resource-My_y-Syh.js → resource-CRxxwkQq.js} +22 -7
- package/dist/{resource-BJcaIfxi.d.ts → resource-D8iqWMr-.d.ts} +5 -5
- package/dist/respond-D2OQl62-.d.ts +371 -0
- package/dist/{result-Bj6yt33D.js → result-BKiliPY7.js} +1 -1
- package/dist/server/index.d.ts +14 -12
- package/dist/server/index.js +11 -17
- package/dist/{server-BA75B0mT.js → server-Csx2sRjg.js} +251 -34
- package/dist/{shared-DnoCdMDr.js → shared-D1dRUrAg.js} +16 -2
- package/dist/signers-Cc6r98SW.d.ts +162 -0
- package/dist/{simplify-Cqvfr9dj.js → simplify-_0oUKqCd.js} +4 -115
- package/dist/sql/index.d.ts +247 -10
- package/dist/sql/index.js +8590 -779
- package/dist/{sql-B34HU2DI.js → sql-Coh6n4cC.js} +9 -2
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.js +1 -2
- package/dist/{standard-BRyBGTtp.js → standard-D7r6dMUu.js} +6 -3
- package/dist/{standard-BsaCYQJc.d.ts → standard-J4YgMOLm.d.ts} +1 -1
- package/dist/{stats-C_YxA2r1.js → stats-Bqob3WqT.js} +4 -4
- package/dist/storage/index.d.ts +4 -4
- package/dist/storage/index.js +155 -26
- package/dist/support-DT-OhSxD.d.ts +88 -0
- package/dist/support-Dk6vdmEw.js +291 -0
- package/dist/support-view-Da5peKFg.d.ts +17 -0
- package/dist/support-view-g4YLBeqX.js +18 -0
- package/dist/{permdock-sql-C4KFzLc9.js → template-TxrGI5jR.js} +2 -31
- package/dist/{temporal-BwshQk0W.js → temporal-CVlIV2DZ.js} +17 -4
- package/dist/{temporal-required-CBNHT6ni.js → temporal-required-CAt4Dc9Z.js} +2 -2
- package/dist/testing/index.d.ts +100 -10
- package/dist/testing/index.js +336 -8
- package/dist/{types-DONv9SHN.d.ts → types-Dnf_wRDz.d.ts} +26 -3
- package/dist/user-change-CHFEUro1.js +49 -0
- package/dist/{webhooks-Bh_Jf_-l.js → verify-Ce49ETPz.js} +5 -5
- package/dist/{version-Bmf7_FzM.js → version-DM_Roffb.js} +1 -1
- package/dist/{view-B64o81wp.d.ts → view-BEf0diC5.d.ts} +8 -3
- package/dist/{mfa-byfjruR9.js → view-Bq64ki8-.js} +95 -38
- package/dist/webhooks/index.d.ts +135 -4
- package/dist/webhooks/index.js +588 -2
- package/dist/wire-D2dT86vi.js +35 -0
- package/package.json +16 -8
- package/schemas/config-v1.json +131 -1
- package/schemas/doctor-report-v1.json +10 -0
- package/skills/better-supabase/SKILL.md +9 -6
- package/skills/better-supabase/references/plugins.md +6 -3
- package/skills/better-supabase/references/troubleshooting.md +1 -0
- package/skills/better-supabase-api/SKILL.md +9 -2
- package/skills/better-supabase-api/references/adapters.md +11 -8
- package/skills/better-supabase-auth/SKILL.md +3 -0
- package/skills/better-supabase-auth/references/permdock.md +56 -11
- package/dist/cli/gen-D5cLCULx.js +0 -2
- package/dist/cli/sql-D4VbqmXi.js +0 -199
- package/dist/events-B21UOhvP.d.ts +0 -84
- package/dist/executor-B5IoUxLE.d.ts +0 -195
- package/dist/invalidate-CgxmRamI.js +0 -24
- package/dist/permdock-sql-DImJULY-.d.ts +0 -17
- package/dist/plugin-BqR6wKMB.js +0 -23
- package/dist/respond-DgIbdrt8.d.ts +0 -194
- package/dist/view-BrJI2LKp.js +0 -45
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as CliError } from "./errors-4v4DTtda.js";
|
|
2
|
-
import {
|
|
2
|
+
import { d as pipe, h as string, l as optional, v as url } from "./dist-xn4wlboc.js";
|
|
3
3
|
//#region ../../node_modules/.pnpm/@t3-oss+env-core@0.13.11_arktype@2.2.3_typescript@7.0.2_valibot@1.5.0_typescript@7.0.2__zod@4.6.5/node_modules/@t3-oss/env-core/dist/standard.js
|
|
4
4
|
function ensureSynchronous(value, message) {
|
|
5
5
|
if (value instanceof Promise) throw new Error(message);
|
|
@@ -2,9 +2,10 @@ import { r as defineCliCommand } from "./command-CK14fP91.js";
|
|
|
2
2
|
import { n as CliError } from "./errors-4v4DTtda.js";
|
|
3
3
|
import { n as importPath, r as writeIfChanged, t as display } from "./io-k41_z-jT.js";
|
|
4
4
|
import { r as painter } from "./style-C0NFdJRL.js";
|
|
5
|
-
import { t as VERSION } from "./version-
|
|
6
|
-
import { d as readSupabaseToml,
|
|
7
|
-
import {
|
|
5
|
+
import { t as VERSION } from "./version-BDJuO0UR.js";
|
|
6
|
+
import { d as pgFunctionHooks, f as readSupabaseToml, m as tomlGet, s as stdinDatabaseUrl, t as databaseUrl } from "./config-CPVpXP5I.js";
|
|
7
|
+
import { t as fileDiff } from "./diff-SjkO5rNr.js";
|
|
8
|
+
import { a as parseHookMarker, i as parseGrantsMarker, n as entitlementRequirements, r as entitlementsMode, s as readPermdock, t as compiledReadSets } from "./read-sets-BfMQcKy8.js";
|
|
8
9
|
import { t as byCodePoint } from "./compare-BmIWVEui.js";
|
|
9
10
|
import { n as withSpinner } from "./prompts-BNcNfAve.js";
|
|
10
11
|
import { t as connect } from "./db-DOBPt660.js";
|
|
@@ -12,7 +13,7 @@ import { basename, dirname, resolve } from "node:path";
|
|
|
12
13
|
import { existsSync } from "node:fs";
|
|
13
14
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
14
15
|
import { setTimeout } from "node:timers/promises";
|
|
15
|
-
import { kitLayout, permdockKeys, renderKit, sameKitFile } from "better-supabase/sql";
|
|
16
|
+
import { PERMDOCK_SCHEMA, kitLayout, permdockKeyStatus, permdockKeys, renderKit, sameKitFile } from "better-supabase/sql";
|
|
16
17
|
import { DEFAULT_CLAIMS, tenantClaimPaths } from "better-supabase/config";
|
|
17
18
|
import { toCamel, toSnake } from "better-supabase";
|
|
18
19
|
import { generateTypescript, pgTypeToTsType, sortGeneratorMetadata } from "@supabase/postgrest-typegen/generation";
|
|
@@ -198,7 +199,15 @@ function catalogOf(context) {
|
|
|
198
199
|
}
|
|
199
200
|
return catalog;
|
|
200
201
|
}
|
|
201
|
-
|
|
202
|
+
/** `[api] schemas` from `config.toml`, the schemas PostgREST serves, or `config.schemas` without one. */
|
|
203
|
+
function exposedSchemas(context) {
|
|
204
|
+
const listed = context.configToml ? tomlGet(context.configToml.document, ["api", "schemas"]) : void 0;
|
|
205
|
+
return Array.isArray(listed) && listed.every((entry) => typeof entry === "string") ? listed : context.config.schemas;
|
|
206
|
+
}
|
|
207
|
+
const exposed = (context) => {
|
|
208
|
+
const schemas = exposedSchemas(context);
|
|
209
|
+
return catalogOf(context).tables.filter((table) => schemas.includes(table.schema));
|
|
210
|
+
};
|
|
202
211
|
const qualified = (table) => `${table.schema}.${table.name}`;
|
|
203
212
|
const tableObject = (table) => ({
|
|
204
213
|
kind: "table",
|
|
@@ -232,7 +241,8 @@ function lineOf(text, pattern) {
|
|
|
232
241
|
/** Tables whose policies PermDock's helpers can't row-check (PermDock's PD037 scans the same ones). */
|
|
233
242
|
const HELPER_TABLES = /* @__PURE__ */ new Set(["storage.objects", "realtime.messages"]);
|
|
234
243
|
const POLICY = /create\s+policy\s+("(?:[^"]|"")+"|[\w$]+)\s+on\s+((?:"[^"]+"|\w+)\s*\.\s*(?:"[^"]+"|\w+))([\s\S]*?);/gi;
|
|
235
|
-
|
|
244
|
+
/** A helper call: optional schema, `permitted_<scope>_ids` or `permdock_has`, and the key, positional or named. */
|
|
245
|
+
const HELPER_CALL = /(?:(?:"((?:[^"]|"")+)"|([a-z_][\w$]*))\s*\.\s*)?"?(?:permitted_(\w+?)_ids|(permdock_has))"?\s*\(\s*(?:\w+\s*=>\s*)?'((?:[^']|'')*)'/gi;
|
|
236
246
|
const unquote = (name) => name.replaceAll(/^"|"$/g, "").replaceAll("\"\"", "\"");
|
|
237
247
|
/**
|
|
238
248
|
* Policies better-supabase generates (`bs_` names) on `storage.objects` and
|
|
@@ -250,99 +260,266 @@ function helperPolicies(files) {
|
|
|
250
260
|
const id = `${table}.${name}`;
|
|
251
261
|
if (seen.has(id)) continue;
|
|
252
262
|
seen.add(id);
|
|
253
|
-
const
|
|
254
|
-
|
|
263
|
+
const calls = [...match[3].matchAll(HELPER_CALL)].map((call) => {
|
|
264
|
+
const schema = call[1]?.replaceAll("\"\"", "\"") ?? call[2];
|
|
265
|
+
return {
|
|
266
|
+
key: call[5].replaceAll("''", "'"),
|
|
267
|
+
scope: call[4] ? "global" : call[3],
|
|
268
|
+
...schema ? { schema } : {}
|
|
269
|
+
};
|
|
270
|
+
});
|
|
271
|
+
if (calls.length === 0) continue;
|
|
255
272
|
found.push({
|
|
256
273
|
name,
|
|
257
274
|
table,
|
|
258
|
-
keys: [...new Set(
|
|
275
|
+
keys: [...new Set(calls.map((call) => call.key))],
|
|
276
|
+
calls,
|
|
259
277
|
file: file.path,
|
|
260
278
|
line: file.text.slice(0, match.index).split("\n").length
|
|
261
279
|
});
|
|
262
280
|
}
|
|
263
281
|
return found;
|
|
264
282
|
}
|
|
265
|
-
/** `buckets` entries with a PermDock policy,
|
|
283
|
+
/** `buckets` entries with a PermDock policy, the keys they name, their scope and helper schema. */
|
|
266
284
|
function configuredPermdockKeys(context) {
|
|
267
|
-
return Object.entries(context.config.buckets).flatMap(([bucket, config]) => config.policy !== void 0 && typeof config.policy !== "string" ? [{
|
|
285
|
+
return Object.entries(context.config.buckets).flatMap(([bucket, config]) => config.policy !== void 0 && typeof config.policy !== "string" && "permdock" in config.policy ? [{
|
|
268
286
|
bucket,
|
|
269
|
-
keys: permdockKeys(config.policy)
|
|
287
|
+
keys: permdockKeys(config.policy),
|
|
288
|
+
scope: config.policy.scope,
|
|
289
|
+
schema: config.policy.schema ?? PERMDOCK_SCHEMA
|
|
270
290
|
}] : []);
|
|
271
291
|
}
|
|
292
|
+
/** A scope name or PermDock's alias for it (`tenant` is the first scope, `team` the second), resolved against the manifest. */
|
|
293
|
+
function resolveManifestScope(manifest, name) {
|
|
294
|
+
const scopes = manifest?.rls?.scopes;
|
|
295
|
+
if (!scopes) return void 0;
|
|
296
|
+
if (scopes.some((scope) => scope.name === name)) return name;
|
|
297
|
+
if (name === "tenant") return scopes[0]?.name;
|
|
298
|
+
if (name === "team") return scopes[1]?.name;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Why a policy's helper schema or scope can't work with PermDock's
|
|
302
|
+
* manifest and catalog: a schema other than `rls.schema`, a scope the
|
|
303
|
+
* manifest doesn't declare, or a key the catalog declares at another scope.
|
|
304
|
+
*/
|
|
305
|
+
function placementProblems(project, catalog, call, where) {
|
|
306
|
+
const rls = project.manifest?.rls;
|
|
307
|
+
const problems = [];
|
|
308
|
+
if (rls && call.schema !== void 0 && call.schema !== rls.schema) problems.push(`${where} calls PermDock's helpers in schema ${call.schema}, but ${project.manifestPath} puts them in ${rls.schema}. Set schema: '${rls.schema}' on the policy.`);
|
|
309
|
+
if (call.scope === "global") return problems;
|
|
310
|
+
if (rls && !rls.scopes.some((scope) => scope.name === call.scope)) {
|
|
311
|
+
const resolved = resolveManifestScope(project.manifest, call.scope);
|
|
312
|
+
problems.push(`${where} uses scope "${call.scope}", which ${project.manifestPath} doesn't declare, so permitted_${call.scope}_ids doesn't exist. ${resolved ? `Use "${resolved}", the scope "${call.scope}" stands for.` : `Use one of ${rls.scopes.map((scope) => scope.name).join(", ") || "its scopes"}.`}`);
|
|
313
|
+
return problems;
|
|
314
|
+
}
|
|
315
|
+
const declared = catalog.permissions.find((permission) => permission.key === call.key)?.scope;
|
|
316
|
+
if (declared === void 0) return problems;
|
|
317
|
+
const resolved = resolveManifestScope(project.manifest, declared) ?? declared;
|
|
318
|
+
if (resolved !== call.scope) problems.push(`${where} checks "${call.key}" at scope "${call.scope}", but ${project.catalogPath} declares it at "${resolved}", so PermDock's helpers never grant it there. Use scope "${resolved}".`);
|
|
319
|
+
return problems;
|
|
320
|
+
}
|
|
321
|
+
const ROW_CONDITIONS_FIX = "Use the policies `permdock rls generate` writes for it, or a permission whose catalog entry has rowConditions: false.";
|
|
322
|
+
const REGENERATE_FIX = "Regenerate it with a current `permdock catalog`, which writes rowConditions for every permission.";
|
|
323
|
+
/**
|
|
324
|
+
* Why the SQL helpers can't be trusted with `key`, or `undefined` when the
|
|
325
|
+
* catalog marks it `rowConditions: false`. An entry without the flag and a
|
|
326
|
+
* key the catalog doesn't list are unknown, so they count as unsafe.
|
|
327
|
+
*/
|
|
328
|
+
function unsafeKey(catalog, key, catalogPath) {
|
|
329
|
+
const status = permdockKeyStatus(catalog, key);
|
|
330
|
+
switch (status) {
|
|
331
|
+
case "scope-only": return;
|
|
332
|
+
case "row-conditions": return {
|
|
333
|
+
reason: `has row conditions in ${catalogPath}`,
|
|
334
|
+
fix: ROW_CONDITIONS_FIX
|
|
335
|
+
};
|
|
336
|
+
case "no-flag": return {
|
|
337
|
+
reason: `has no rowConditions flag in ${catalogPath}, so whether it has row conditions is unknown`,
|
|
338
|
+
fix: REGENERATE_FIX
|
|
339
|
+
};
|
|
340
|
+
case "missing": return {
|
|
341
|
+
reason: `is not in ${catalogPath}`,
|
|
342
|
+
fix: REGENERATE_FIX
|
|
343
|
+
};
|
|
344
|
+
default: return status;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
272
347
|
/** PermDock's helpers for the `entitlements` kit module, when the manifest allows PermDock mode. */
|
|
273
348
|
function entitlementsKit(context) {
|
|
274
349
|
const mode = entitlementsMode(context.config, context.permdock);
|
|
275
350
|
return mode.kind === "permdock" ? mode.permdock : void 0;
|
|
276
351
|
}
|
|
277
|
-
const PERMDOCK_RULES = [
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const rowConditions = project.rowConditions;
|
|
293
|
-
if (!rowConditions) {
|
|
294
|
-
if (findings.length === 0 && (fromConfig.length > 0 || fromSql.length > 0)) findings.push({
|
|
295
|
-
severity: "info",
|
|
296
|
-
message: `Storage or Realtime policies call PermDock's helpers, but there is no ${project.catalogPath} to check their permissions against. Run \`permdock catalog\`, or set permdock.catalog in the config.`,
|
|
352
|
+
const PERMDOCK_RULES = [
|
|
353
|
+
{
|
|
354
|
+
code: "BS214",
|
|
355
|
+
severity: "error",
|
|
356
|
+
title: "PermDock permission with row conditions in a Storage or Realtime policy",
|
|
357
|
+
description: "PermDock's SQL helpers (`permitted_<scope>_ids`, `permdock_has`) check role and scope, not row conditions. A bucket or topic policy that names a permission whose catalog entry has `rowConditions: true` grants every object or topic in the scope. Use PermDock's generated policies for those permissions. A key whose entry has no boolean `rowConditions` (an older `permdock catalog`) or that the catalog doesn't list is unknown and reported the same way, and so are all of them when the catalog is missing or unreadable. With the manifest, a helper schema other than `rls.schema`, a scope the manifest doesn't declare and a key checked at another scope than its catalog entry's are reported too.",
|
|
358
|
+
check: (context) => {
|
|
359
|
+
const project = context.permdock;
|
|
360
|
+
if (!project) return [];
|
|
361
|
+
const fromConfig = configuredPermdockKeys(context);
|
|
362
|
+
const fromSql = helperPolicies(context.sqlFiles ?? []);
|
|
363
|
+
const uses = fromConfig.length > 0 || fromSql.length > 0;
|
|
364
|
+
const findings = project.problems.filter((problem) => problem.startsWith(project.catalogPath)).map((problem) => ({
|
|
365
|
+
...uses ? {} : { severity: "info" },
|
|
366
|
+
message: `Could not read PermDock's catalog: ${problem}`,
|
|
297
367
|
target: project.catalogPath
|
|
298
|
-
});
|
|
368
|
+
}));
|
|
369
|
+
const catalog = project.catalog;
|
|
370
|
+
if (!catalog) {
|
|
371
|
+
if (findings.length === 0 && uses) findings.push({
|
|
372
|
+
message: `Storage or Realtime policies call PermDock's helpers, but there is no ${project.catalogPath}, so whether their permissions have row conditions is unknown. Run \`permdock catalog\`, or set permdock.catalog in the config.`,
|
|
373
|
+
target: project.catalogPath
|
|
374
|
+
});
|
|
375
|
+
return findings;
|
|
376
|
+
}
|
|
377
|
+
for (const { bucket, keys, scope, schema } of fromConfig) for (const key of keys) {
|
|
378
|
+
for (const message of placementProblems(project, catalog, {
|
|
379
|
+
key,
|
|
380
|
+
scope,
|
|
381
|
+
schema
|
|
382
|
+
}, `buckets.${bucket} ("${key}")`)) findings.push({
|
|
383
|
+
message,
|
|
384
|
+
target: `buckets.${bucket}:${key}`
|
|
385
|
+
});
|
|
386
|
+
const problem = unsafeKey(catalog, key, project.catalogPath);
|
|
387
|
+
if (!problem) continue;
|
|
388
|
+
findings.push({
|
|
389
|
+
message: `buckets.${bucket} uses PermDock permission "${key}", which ${problem.reason}. The bucket policy could grant every object in the scope. ${problem.fix}`,
|
|
390
|
+
target: `buckets.${bucket}:${key}`
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
for (const policy of fromSql) {
|
|
394
|
+
const seen = /* @__PURE__ */ new Set();
|
|
395
|
+
for (const call of policy.calls) for (const message of placementProblems(project, catalog, call, `Policy "${policy.name}" on ${policy.table}`)) {
|
|
396
|
+
if (seen.has(message)) continue;
|
|
397
|
+
seen.add(message);
|
|
398
|
+
findings.push({
|
|
399
|
+
message,
|
|
400
|
+
target: `${policy.table}.${policy.name}:${call.key}`,
|
|
401
|
+
location: {
|
|
402
|
+
file: policy.file,
|
|
403
|
+
line: policy.line
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
for (const key of policy.keys) {
|
|
408
|
+
const problem = unsafeKey(catalog, key, project.catalogPath);
|
|
409
|
+
if (!problem) continue;
|
|
410
|
+
findings.push({
|
|
411
|
+
message: `Policy "${policy.name}" on ${policy.table} passes "${key}" to PermDock's helpers, but it ${problem.reason}. ${problem.fix}`,
|
|
412
|
+
target: `${policy.table}.${policy.name}:${key}`,
|
|
413
|
+
location: {
|
|
414
|
+
file: policy.file,
|
|
415
|
+
line: policy.line
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
299
420
|
return findings;
|
|
300
421
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
}, {
|
|
317
|
-
code: "BS408",
|
|
318
|
-
severity: "warning",
|
|
319
|
-
title: "PermDock helpers the entitlements module calls are missing",
|
|
320
|
-
description: "With a PermDock manifest, the `entitlements` kit module reads memberships from PermDock's `member_<scope>_ids()` (in `has_entitlement`) and `member_<scope>_ids_for(uuid)` (in `feature_claims`). Doctor warns when `entitlements.permdock.scope` is not one of the manifest's scopes, when the manifest's `rls.helpers` lacks a helper (run `permdock rls generate` with a current PermDock), or when the snapshot lacks it (apply the migration it wrote).",
|
|
321
|
-
check: (context) => {
|
|
322
|
-
if (!context.config.sql.kit.includes("entitlements")) return [];
|
|
323
|
-
const mode = entitlementsMode(context.config, context.permdock);
|
|
324
|
-
if (mode.kind === "tenant") return [];
|
|
325
|
-
const manifest = context.config.permdock.manifest;
|
|
326
|
-
if (mode.kind === "invalid") return [{
|
|
327
|
-
message: mode.problem,
|
|
328
|
-
target: "entitlements.permdock"
|
|
329
|
-
}];
|
|
330
|
-
const listed = new Set((context.permdock?.manifest?.rls?.helpers ?? []).map((helper) => `${mode.permdock.schema}.${helper.name}`));
|
|
331
|
-
const read = context.snapshot.schemas.includes(mode.permdock.schema);
|
|
332
|
-
const present = new Set(catalogOf(context).functions.map((fn) => `${fn.schema}.${fn.name}`));
|
|
333
|
-
return entitlementHelpers(mode.permdock).flatMap((helper) => {
|
|
334
|
-
if (!listed.has(helper)) return [{
|
|
335
|
-
message: `${manifest} lists no ${helper}, which the entitlements module calls. Run \`permdock rls generate\` (PermDock writes member_<scope>_ids and member_<scope>_ids_for for every scope), then \`permdock supabase inspect --out\`.`,
|
|
336
|
-
target: helper
|
|
337
|
-
}];
|
|
338
|
-
if (read && !present.has(helper)) return [{
|
|
339
|
-
message: `${helper} is in ${manifest} but not in the database. Apply the migration \`permdock rls generate\` wrote before the entitlements module.`,
|
|
340
|
-
target: helper
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
code: "BS408",
|
|
425
|
+
severity: "warning",
|
|
426
|
+
title: "PermDock helpers the entitlements module calls are missing",
|
|
427
|
+
description: "With a PermDock manifest, the `entitlements` kit module reads memberships from PermDock's `member_<scope>_ids()` (in `has_entitlement`, as `authenticated`) and `member_<scope>_ids_for(uuid)` (in `feature_claims`, which PermDock's hook calls as `supabase_auth_admin`). Doctor warns when a PermDock project has no readable manifest or no `rls` block, when the scope is not one of the manifest's scopes or can't be chosen, when the scope's id type is missing or not `uuid`, `text`, `bigint` or `integer`, when the manifest has no `claims.features` claim filled by `better_supabase.feature_claims`, when no membership source covers the scope, when the manifest's `rls.helpers` lacks one of those helpers or doesn't grant it to that role (naming the `permdock.config.ts` setting that adds it), or when the snapshot lacks it (apply the migration `permdock rls generate` wrote).",
|
|
428
|
+
check: (context) => {
|
|
429
|
+
if (!context.config.sql.kit.includes("entitlements")) return [];
|
|
430
|
+
const mode = entitlementsMode(context.config, context.permdock);
|
|
431
|
+
if (mode.kind === "tenant") return [];
|
|
432
|
+
const manifest = context.config.permdock.manifest;
|
|
433
|
+
if (mode.kind === "invalid") return [{
|
|
434
|
+
message: mode.problem,
|
|
435
|
+
target: "entitlements.permdock"
|
|
341
436
|
}];
|
|
342
|
-
|
|
343
|
-
|
|
437
|
+
const listed = new Map((context.permdock?.manifest?.rls?.helpers ?? []).map((helper) => [`${mode.permdock.schema}.${helper.name}`, helper]));
|
|
438
|
+
const read = context.snapshot.schemas.includes(mode.permdock.schema);
|
|
439
|
+
const present = new Set(catalogOf(context).functions.map((fn) => `${fn.schema}.${fn.name}`));
|
|
440
|
+
const regenerate = `then run \`permdock rls generate\`, \`permdock supabase hook generate\` and \`permdock supabase inspect --out\`.`;
|
|
441
|
+
const findings = [];
|
|
442
|
+
const project = context.permdock;
|
|
443
|
+
const features = context.config.claims.features;
|
|
444
|
+
const claims = project?.manifest?.claims ?? [];
|
|
445
|
+
const featureClaim = claims.find((claim) => claim.name === features);
|
|
446
|
+
if (featureClaim?.source !== "better_supabase.feature_claims") {
|
|
447
|
+
const registered = claims.find((claim) => claim.source === "better_supabase.feature_claims");
|
|
448
|
+
findings.push({
|
|
449
|
+
message: registered ? `${manifest} registers better_supabase.feature_claims as the "${registered.name}" claim, but claims.features is "${features}", so hasEntitlement() never finds the plan features. Set claims.features to "${registered.name}", or rename the claim in permdock.config.ts (supabase.hook.claims).` : featureClaim ? `${manifest} fills the "${features}" claim from ${featureClaim.source}, not better_supabase.feature_claims, so the claim doesn't carry the entitlements module's features. Point supabase.hook.claims.${features} in permdock.config.ts at 'better_supabase.feature_claims', ${regenerate}` : `${manifest} has no "${features}" claim, so PermDock's hook never writes the plan features hasEntitlement() reads. Add \`supabase.hook.claims: { ${features}: 'better_supabase.feature_claims' }\` to permdock.config.ts, ${regenerate}`,
|
|
450
|
+
target: `claims.${features}`
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
const scope = mode.permdock.scope;
|
|
454
|
+
if (!mode.permdock.memberships.some((source) => !("value" in source.scope) || source.scope.value === scope)) findings.push({
|
|
455
|
+
message: `No membership source in ${manifest} covers scope "${scope}", so entitlement_members() finds no users and plan changes never invalidate sessions. Add a source for "${scope}" (\`supabase.hook.memberships\` in permdock.config.ts), ${regenerate}`,
|
|
456
|
+
target: `entitlements.permdock.${scope}`
|
|
457
|
+
});
|
|
458
|
+
return findings.concat(entitlementRequirements(mode.permdock).flatMap((requirement) => {
|
|
459
|
+
const { helper, caller, role } = requirement;
|
|
460
|
+
const entry = listed.get(helper);
|
|
461
|
+
if (!entry) return [{
|
|
462
|
+
message: requirement.kind === "member" ? `${manifest} lists no ${helper}, but ${caller} calls it. Run \`permdock rls generate\` with a current PermDock, then \`permdock supabase inspect --out\`.` : `${manifest} lists no ${helper}, but ${caller} calls it. PermDock writes it only for a scope with a membership source: add one for "${mode.permdock.scope}" (\`supabase.hook.memberships\`, \`rls.membershipSources\` or a mapped \`rls.memberships\` table in permdock.config.ts), ${regenerate}`,
|
|
463
|
+
target: helper
|
|
464
|
+
}];
|
|
465
|
+
if (!entry.execute.includes(role)) {
|
|
466
|
+
const message = requirement.kind === "member" ? `${manifest} says ${role} may not execute ${helper}, but ${caller} calls it as ${role}. Run \`permdock rls generate\` with a current PermDock, then \`permdock supabase inspect --out\`.` : `${manifest} says ${role} may not execute ${helper}. feature_claims runs as its owner, so this only matters when something else calls it as ${role}; PermDock grants it when the hook has claims (\`supabase.hook.claims\` in permdock.config.ts), ${regenerate}`;
|
|
467
|
+
return [{
|
|
468
|
+
...requirement.kind === "member-for" ? { severity: "info" } : {},
|
|
469
|
+
message,
|
|
470
|
+
target: helper
|
|
471
|
+
}];
|
|
472
|
+
}
|
|
473
|
+
if (read && !present.has(helper)) return [{
|
|
474
|
+
message: `${helper} is in ${manifest} but not in the database. Apply the migration \`permdock rls generate\` wrote before the entitlements module.`,
|
|
475
|
+
target: helper
|
|
476
|
+
}];
|
|
477
|
+
return [];
|
|
478
|
+
}));
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
code: "BS409",
|
|
483
|
+
severity: "warning",
|
|
484
|
+
title: "PermDock's manifest and the better-supabase config disagree",
|
|
485
|
+
description: "PermDock's hook and helpers read the active tenant from the manifest's `rls.tenantClaim`, and its generated files start with a `-- permdock:hook v1` or `-- permdock:grants v1` marker. Doctor warns when `claims.tenant` names another claim (the tenant plugin, guards and RLS would read a claim PermDock never writes), reports an error for a marker version this release can't read, and notes when `claims.scope` resolves to another scope than the manifest's root scope.",
|
|
486
|
+
check: (context) => {
|
|
487
|
+
const project = context.permdock;
|
|
488
|
+
if (!project) return [];
|
|
489
|
+
const findings = [];
|
|
490
|
+
const manifest = project.manifest;
|
|
491
|
+
const tenantClaim = manifest?.rls?.tenantClaim ?? manifest?.tenantClaim;
|
|
492
|
+
if (tenantClaim !== void 0 && tenantClaim !== context.config.claims.tenant) findings.push({
|
|
493
|
+
message: `${project.manifestPath} says PermDock writes the active tenant to "${tenantClaim}", but claims.tenant is "${context.config.claims.tenant}". Set claims.tenant to "${tenantClaim}", or change rls.tenantClaim in permdock.config.ts.`,
|
|
494
|
+
target: "claims.tenant"
|
|
495
|
+
});
|
|
496
|
+
for (const file of context.sqlFiles ?? []) {
|
|
497
|
+
const markers = [["hook", parseHookMarker(file.text)?.version], ["grants", parseGrantsMarker(file.text)?.version]];
|
|
498
|
+
for (const [kind, version] of markers) {
|
|
499
|
+
if (version === void 0 || version === 1) continue;
|
|
500
|
+
findings.push({
|
|
501
|
+
severity: "error",
|
|
502
|
+
message: `${file.path} has a \`-- permdock:${kind} v${String(version)}\` marker, but this release reads only v1, so doctor can't trust what it says about PermDock's ${kind === "hook" ? "hook" : "grants"}. Upgrade better-supabase, or regenerate the file with the PermDock version that matches it.`,
|
|
503
|
+
target: file.path,
|
|
504
|
+
location: {
|
|
505
|
+
file: file.path,
|
|
506
|
+
line: 1
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
const root = manifest?.rls?.scopes.find((scope) => scope.within === void 0)?.name;
|
|
512
|
+
const scope = context.config.claims.scope;
|
|
513
|
+
const resolved = resolveManifestScope(manifest, scope);
|
|
514
|
+
if (root !== void 0 && resolved !== root) findings.push({
|
|
515
|
+
severity: "info",
|
|
516
|
+
message: `claims.scope is "${scope}", which ${resolved ? `stands for "${resolved}"` : "is not a scope"} in ${project.manifestPath}, whose root scope is "${root}". The tenant module's membership claims then use another scope than PermDock's. Set claims.scope to "${root}" (or "tenant").`,
|
|
517
|
+
target: "claims.scope"
|
|
518
|
+
});
|
|
519
|
+
return findings;
|
|
520
|
+
}
|
|
344
521
|
}
|
|
345
|
-
|
|
522
|
+
];
|
|
346
523
|
//#endregion
|
|
347
524
|
//#region src/cli/gen/shared.ts
|
|
348
525
|
const q = (value) => JSON.stringify(value);
|
|
@@ -792,6 +969,7 @@ function pruneTypes(metadata, schemas) {
|
|
|
792
969
|
}
|
|
793
970
|
//#endregion
|
|
794
971
|
//#region src/cli/gen/model.ts
|
|
972
|
+
const SOFT_DELETE_UDTS = /* @__PURE__ */ new Set(["timestamptz", "timestamp"]);
|
|
795
973
|
const applyCasing = (name, casing) => casing === "camel" ? toCamel(name) : name;
|
|
796
974
|
function tableKey(table, casing, schemas) {
|
|
797
975
|
const base = applyCasing(table.name, casing);
|
|
@@ -973,8 +1151,13 @@ function buildModel(snapshot, config) {
|
|
|
973
1151
|
const has = (db) => columns.find((col) => col.db === db)?.app;
|
|
974
1152
|
const flags = {};
|
|
975
1153
|
if (flagsConfig.softDelete) {
|
|
976
|
-
const
|
|
977
|
-
|
|
1154
|
+
const db = flagsConfig.softDelete.column;
|
|
1155
|
+
const column = columns.find((col) => col.db === db);
|
|
1156
|
+
if (column) {
|
|
1157
|
+
const udt = column.snapshot.udt;
|
|
1158
|
+
if (column.snapshot.isArray || !SOFT_DELETE_UDTS.has(udt)) throw new TypeError(`plugins.softDelete.column: ${table.schema}.${table.name}.${db} is ${udt}, but softDelete() writes a timestamp. Use timestamptz or timestamp.`);
|
|
1159
|
+
flags.softDelete = column.app;
|
|
1160
|
+
}
|
|
978
1161
|
}
|
|
979
1162
|
if (flagsConfig.timestamps) {
|
|
980
1163
|
const createdAt = has(flagsConfig.timestamps.createdAt);
|
|
@@ -991,9 +1174,11 @@ function buildModel(snapshot, config) {
|
|
|
991
1174
|
if (flagsConfig.actor) {
|
|
992
1175
|
const createdBy = has(flagsConfig.actor.createdBy);
|
|
993
1176
|
const updatedBy = has(flagsConfig.actor.updatedBy);
|
|
994
|
-
|
|
1177
|
+
const impersonatedBy = has(flagsConfig.actor.impersonatedBy);
|
|
1178
|
+
if (createdBy || updatedBy || impersonatedBy) flags.actor = {
|
|
995
1179
|
...createdBy ? { createdBy } : {},
|
|
996
|
-
...updatedBy ? { updatedBy } : {}
|
|
1180
|
+
...updatedBy ? { updatedBy } : {},
|
|
1181
|
+
...impersonatedBy ? { impersonatedBy } : {}
|
|
997
1182
|
};
|
|
998
1183
|
}
|
|
999
1184
|
const key = keyOf.get(id) ?? table.name;
|
|
@@ -1815,22 +2000,33 @@ async function readSetFile(config) {
|
|
|
1815
2000
|
const readSets = await compiledReadSets(config);
|
|
1816
2001
|
return renderKit(["read-sets"], kitLayout(config, config.sql.testsDir, readSets))[0];
|
|
1817
2002
|
}
|
|
1818
|
-
/**
|
|
2003
|
+
/**
|
|
2004
|
+
* `buckets` keys the catalog doesn't mark `rowConditions: false`, as error
|
|
2005
|
+
* lines. Without a readable catalog every PermDock bucket is refused, since
|
|
2006
|
+
* whether its keys have row conditions is unknown.
|
|
2007
|
+
*/
|
|
1819
2008
|
async function rowConditionedBuckets(config) {
|
|
1820
2009
|
const configured = configuredPermdockKeys({ config });
|
|
1821
2010
|
if (configured.length === 0) return [];
|
|
1822
2011
|
const project = await readPermdock(config.root, config.permdock);
|
|
1823
|
-
const
|
|
1824
|
-
if (!
|
|
1825
|
-
|
|
2012
|
+
const catalog = project?.catalog;
|
|
2013
|
+
if (!catalog) {
|
|
2014
|
+
const path = project?.catalogPath ?? config.permdock.catalog;
|
|
2015
|
+
const problem = project?.problems.find((entry) => entry.startsWith(path));
|
|
2016
|
+
return [` ${configured.map(({ bucket }) => `buckets.${bucket}`).join(", ")}: ${problem ? `could not read PermDock's catalog (${problem})` : `there is no ${path}`}, so whether the keys have row conditions is unknown. Run \`permdock catalog\`, or set permdock.catalog in the config.`];
|
|
2017
|
+
}
|
|
2018
|
+
return configured.flatMap(({ bucket, keys }) => keys.flatMap((key) => {
|
|
2019
|
+
const problem = unsafeKey(catalog, key, project.catalogPath);
|
|
2020
|
+
return problem ? [` buckets.${bucket}: "${key}" ${problem.reason}. ${problem.fix}`] : [];
|
|
2021
|
+
}));
|
|
1826
2022
|
}
|
|
1827
|
-
const UNFORMATTED = "oxfmt is not installed, so database.types.ts is not formatted like `supabase gen types` output. Install
|
|
2023
|
+
const UNFORMATTED = "oxfmt is not installed, so database.types.ts is not formatted like `supabase gen types` output. Install the version @supabase/postgrest-typegen pins: pnpm add -D oxfmt@0.66.0. To use a newer oxfmt, allow it in pnpm-workspace.yaml under peerDependencyRules.allowedVersions, keyed \"@supabase/postgrest-typegen>oxfmt\".";
|
|
1828
2024
|
async function runGen(options) {
|
|
1829
2025
|
const { config } = options;
|
|
1830
2026
|
const refused = await rowConditionedBuckets(config);
|
|
1831
2027
|
if (refused.length > 0) return {
|
|
1832
2028
|
code: 1,
|
|
1833
|
-
error: `PermDock's SQL helpers don't check row conditions, so these bucket policies
|
|
2029
|
+
error: `PermDock's SQL helpers don't check row conditions, so these bucket policies could grant every object in the scope:\n${refused.join("\n")}\nSee doctor BS214.`
|
|
1834
2030
|
};
|
|
1835
2031
|
const snapshot = options.snapshot ?? await loadSnapshot(config, options.env, options);
|
|
1836
2032
|
const files = await renderFiles(config, snapshot);
|
|
@@ -2005,4 +2201,4 @@ const genCommand = defineCliCommand({
|
|
|
2005
2201
|
}
|
|
2006
2202
|
});
|
|
2007
2203
|
//#endregion
|
|
2008
|
-
export { catalogOf as C,
|
|
2204
|
+
export { toCatalog as A, catalogOf as C, policyObject as D, lineOf as E, qualified as O, entitlementsKit as S, exposedSchemas as T, restrictSchemas as _, sourceArgs as a, emitModule as b, openSource as c, snapshotFile as d, introspect as f, buildModel as g, CACHE_DIR as h, runGen as i, tableObject as k, parseSnapshot as l, pgSource as m, genCommand as n, loadSnapshot as o, managementSource as p, renderFiles as r, managementTarget as s, SOURCE_ARGS as t, serializeSnapshot as u, serializeGenerator as v, exposed as w, PERMDOCK_RULES as x, GENERATED_HEADER as y };
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -488,6 +488,6 @@ export declare function emitModule(model: Model, options: EmitOptions): string;
|
|
|
488
488
|
export declare function loadConfig(cwd: string, explicit?: string): Promise<ResolvedConfig>;
|
|
489
489
|
//#endregion
|
|
490
490
|
//#region src/cli/version.d.ts
|
|
491
|
-
export declare const VERSION = "0.
|
|
491
|
+
export declare const VERSION = "0.5.0";
|
|
492
492
|
//#endregion
|
|
493
493
|
export type { Catalog, CatalogCheck, CatalogColumn, CatalogColumnGrant, CatalogEnum, CatalogForeignKey, CatalogFunction, CatalogFunctionArg, CatalogGrant, CatalogIndex, CatalogPolicy, CatalogTable, CatalogTrigger, CatalogUnique, CliArgs, CliCommandDef, CliContext, CliEnv, CliErrorCode, CliErrorOptions, CliIo, CliProblem, CliProblemExtensions, Command, CommandContext, CommandResult, ExitCode, ExtrasFunction, ExtrasHook, ExtrasHookFunction, ExtrasTable, ForeignKeyAction, GeneratorMetadata, IntrospectionSource, ManagementSourceOptions, ParsedArgs, Queryable, RunOptions, RunResult, Snapshot, SnapshotBucket, SnapshotExtras };
|
package/dist/cli/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { a as list, r as defineCliCommand } from "./command-CK14fP91.js";
|
|
2
2
|
import { n as CliError, t as CLI_ERRORS_URL } from "./errors-4v4DTtda.js";
|
|
3
|
-
import { i as run, n as help, r as registerCommand, t as commandNames } from "./run-
|
|
4
|
-
import { t as VERSION } from "./version-
|
|
5
|
-
import { a as loadConfig } from "./config-
|
|
6
|
-
import { b as emitModule, f as introspect, g as buildModel, i as runGen,
|
|
3
|
+
import { i as run, n as help, r as registerCommand, t as commandNames } from "./run-BKR2W_79.js";
|
|
4
|
+
import { t as VERSION } from "./version-BDJuO0UR.js";
|
|
5
|
+
import { a as loadConfig } from "./config-CPVpXP5I.js";
|
|
6
|
+
import { A as toCatalog, b as emitModule, f as introspect, g as buildModel, i as runGen, l as parseSnapshot, m as pgSource, o as loadSnapshot, p as managementSource, r as renderFiles, u as serializeSnapshot, y as GENERATED_HEADER } from "./gen-C2osRcr5.js";
|
|
7
7
|
//#region src/cli/introspect/from-catalog.ts
|
|
8
8
|
/**
|
|
9
9
|
* Builds a snapshot from catalog records: the inverse of `toCatalog`. Tests
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as list, r as defineCliCommand } from "./command-CK14fP91.js";
|
|
2
2
|
import { r as writeIfChanged, t as display } from "./io-k41_z-jT.js";
|
|
3
|
-
import { t as VERSION } from "./version-
|
|
4
|
-
import { n as findConfig } from "./config-
|
|
3
|
+
import { t as VERSION } from "./version-BDJuO0UR.js";
|
|
4
|
+
import { n as findConfig } from "./config-CPVpXP5I.js";
|
|
5
5
|
import { n as installCommand, t as detectProject } from "./project-B_GeXyHh.js";
|
|
6
6
|
import { posix, resolve } from "node:path";
|
|
7
7
|
import { existsSync } from "node:fs";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { r as defineCliCommand } from "./command-CK14fP91.js";
|
|
2
2
|
import { r as writeIfChanged, t as display } from "./io-k41_z-jT.js";
|
|
3
3
|
import { r as painter } from "./style-C0NFdJRL.js";
|
|
4
|
-
import {
|
|
5
|
-
import { _ as restrictSchemas, a as sourceArgs, o as loadSnapshot, t as SOURCE_ARGS, u as serializeSnapshot, v as serializeGenerator } from "./gen-
|
|
4
|
+
import { t as fileDiff } from "./diff-SjkO5rNr.js";
|
|
5
|
+
import { _ as restrictSchemas, a as sourceArgs, o as loadSnapshot, t as SOURCE_ARGS, u as serializeSnapshot, v as serializeGenerator } from "./gen-C2osRcr5.js";
|
|
6
6
|
import { n as withSpinner } from "./prompts-BNcNfAve.js";
|
|
7
7
|
import { resolve } from "node:path";
|
|
8
8
|
import { readFile } from "node:fs/promises";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as defineCliCommand } from "./command-CK14fP91.js";
|
|
2
2
|
import { r as writeIfChanged, t as display } from "./io-k41_z-jT.js";
|
|
3
|
-
import { r as importExport } from "./config-
|
|
3
|
+
import { r as importExport } from "./config-CPVpXP5I.js";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
6
6
|
import { readFile } from "node:fs/promises";
|