@polardbx/pxbaas 0.0.0-stage → 0.1.0-beta.2
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 +107 -2
- package/bin/pxbaas.js +13 -0
- package/dist/app/preflight.d.ts +38 -0
- package/dist/app/preflight.d.ts.map +1 -0
- package/dist/app/preflight.js +79 -0
- package/dist/app/preflight.js.map +1 -0
- package/dist/app/spec-lint.d.ts +45 -0
- package/dist/app/spec-lint.d.ts.map +1 -0
- package/dist/app/spec-lint.js +407 -0
- package/dist/app/spec-lint.js.map +1 -0
- package/dist/app/templates.d.ts +143 -0
- package/dist/app/templates.d.ts.map +1 -0
- package/dist/app/templates.js +151 -0
- package/dist/app/templates.js.map +1 -0
- package/dist/cli/root.d.ts +3 -0
- package/dist/cli/root.d.ts.map +1 -0
- package/dist/cli/root.js +69 -0
- package/dist/cli/root.js.map +1 -0
- package/dist/commands/app/index.d.ts +8 -0
- package/dist/commands/app/index.d.ts.map +1 -0
- package/dist/commands/app/index.js +1476 -0
- package/dist/commands/app/index.js.map +1 -0
- package/dist/commands/auth/index.d.ts +3 -0
- package/dist/commands/auth/index.d.ts.map +1 -0
- package/dist/commands/auth/index.js +198 -0
- package/dist/commands/auth/index.js.map +1 -0
- package/dist/commands/completion/index.d.ts +3 -0
- package/dist/commands/completion/index.d.ts.map +1 -0
- package/dist/commands/completion/index.js +10 -0
- package/dist/commands/completion/index.js.map +1 -0
- package/dist/commands/data/index.d.ts +3 -0
- package/dist/commands/data/index.d.ts.map +1 -0
- package/dist/commands/data/index.js +245 -0
- package/dist/commands/data/index.js.map +1 -0
- package/dist/commands/db/index.d.ts +15 -0
- package/dist/commands/db/index.d.ts.map +1 -0
- package/dist/commands/db/index.js +389 -0
- package/dist/commands/db/index.js.map +1 -0
- package/dist/commands/doctor/index.d.ts +3 -0
- package/dist/commands/doctor/index.d.ts.map +1 -0
- package/dist/commands/doctor/index.js +305 -0
- package/dist/commands/doctor/index.js.map +1 -0
- package/dist/commands/functions/delete.d.ts +3 -0
- package/dist/commands/functions/delete.d.ts.map +1 -0
- package/dist/commands/functions/delete.js +55 -0
- package/dist/commands/functions/delete.js.map +1 -0
- package/dist/commands/functions/deploy.d.ts +3 -0
- package/dist/commands/functions/deploy.d.ts.map +1 -0
- package/dist/commands/functions/deploy.js +118 -0
- package/dist/commands/functions/deploy.js.map +1 -0
- package/dist/commands/functions/index.d.ts +3 -0
- package/dist/commands/functions/index.d.ts.map +1 -0
- package/dist/commands/functions/index.js +15 -0
- package/dist/commands/functions/index.js.map +1 -0
- package/dist/commands/functions/list.d.ts +6 -0
- package/dist/commands/functions/list.d.ts.map +1 -0
- package/dist/commands/functions/list.js +63 -0
- package/dist/commands/functions/list.js.map +1 -0
- package/dist/commands/functions/new.d.ts +3 -0
- package/dist/commands/functions/new.d.ts.map +1 -0
- package/dist/commands/functions/new.js +57 -0
- package/dist/commands/functions/new.js.map +1 -0
- package/dist/commands/gen/index.d.ts +3 -0
- package/dist/commands/gen/index.d.ts.map +1 -0
- package/dist/commands/gen/index.js +320 -0
- package/dist/commands/gen/index.js.map +1 -0
- package/dist/commands/instance/index.d.ts +8 -0
- package/dist/commands/instance/index.d.ts.map +1 -0
- package/dist/commands/instance/index.js +361 -0
- package/dist/commands/instance/index.js.map +1 -0
- package/dist/commands/login/index.d.ts +3 -0
- package/dist/commands/login/index.d.ts.map +1 -0
- package/dist/commands/login/index.js +160 -0
- package/dist/commands/login/index.js.map +1 -0
- package/dist/commands/login/login.d.ts +3 -0
- package/dist/commands/login/login.d.ts.map +1 -0
- package/dist/commands/login/login.js +185 -0
- package/dist/commands/login/login.js.map +1 -0
- package/dist/commands/logout/index.d.ts +3 -0
- package/dist/commands/logout/index.d.ts.map +1 -0
- package/dist/commands/logout/index.js +41 -0
- package/dist/commands/logout/index.js.map +1 -0
- package/dist/commands/profile/import-env.d.ts +13 -0
- package/dist/commands/profile/import-env.d.ts.map +1 -0
- package/dist/commands/profile/import-env.js +81 -0
- package/dist/commands/profile/import-env.js.map +1 -0
- package/dist/commands/profile/index.d.ts +3 -0
- package/dist/commands/profile/index.d.ts.map +1 -0
- package/dist/commands/profile/index.js +112 -0
- package/dist/commands/profile/index.js.map +1 -0
- package/dist/commands/rest/index.d.ts +3 -0
- package/dist/commands/rest/index.d.ts.map +1 -0
- package/dist/commands/rest/index.js +102 -0
- package/dist/commands/rest/index.js.map +1 -0
- package/dist/commands/skill/index.d.ts +11 -0
- package/dist/commands/skill/index.d.ts.map +1 -0
- package/dist/commands/skill/index.js +153 -0
- package/dist/commands/skill/index.js.map +1 -0
- package/dist/commands/status/index.d.ts +3 -0
- package/dist/commands/status/index.d.ts.map +1 -0
- package/dist/commands/status/index.js +59 -0
- package/dist/commands/status/index.js.map +1 -0
- package/dist/commands/storage/index.d.ts +3 -0
- package/dist/commands/storage/index.d.ts.map +1 -0
- package/dist/commands/storage/index.js +198 -0
- package/dist/commands/storage/index.js.map +1 -0
- package/dist/commands/whoami/index.d.ts +3 -0
- package/dist/commands/whoami/index.d.ts.map +1 -0
- package/dist/commands/whoami/index.js +82 -0
- package/dist/commands/whoami/index.js.map +1 -0
- package/dist/credentials/commit.d.ts +38 -0
- package/dist/credentials/commit.d.ts.map +1 -0
- package/dist/credentials/commit.js +57 -0
- package/dist/credentials/commit.js.map +1 -0
- package/dist/credentials/credential-store.d.ts +57 -0
- package/dist/credentials/credential-store.d.ts.map +1 -0
- package/dist/credentials/credential-store.js +180 -0
- package/dist/credentials/credential-store.js.map +1 -0
- package/dist/credentials/env-file.d.ts +44 -0
- package/dist/credentials/env-file.d.ts.map +1 -0
- package/dist/credentials/env-file.js +118 -0
- package/dist/credentials/env-file.js.map +1 -0
- package/dist/credentials/formatter.d.ts +39 -0
- package/dist/credentials/formatter.d.ts.map +1 -0
- package/dist/credentials/formatter.js +79 -0
- package/dist/credentials/formatter.js.map +1 -0
- package/dist/credentials/index.d.ts +13 -0
- package/dist/credentials/index.d.ts.map +1 -0
- package/dist/credentials/index.js +13 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/credentials/jwt-introspect.d.ts +32 -0
- package/dist/credentials/jwt-introspect.d.ts.map +1 -0
- package/dist/credentials/jwt-introspect.js +64 -0
- package/dist/credentials/jwt-introspect.js.map +1 -0
- package/dist/credentials/masker.d.ts +20 -0
- package/dist/credentials/masker.d.ts.map +1 -0
- package/dist/credentials/masker.js +37 -0
- package/dist/credentials/masker.js.map +1 -0
- package/dist/credentials/profile.d.ts +83 -0
- package/dist/credentials/profile.d.ts.map +1 -0
- package/dist/credentials/profile.js +184 -0
- package/dist/credentials/profile.js.map +1 -0
- package/dist/credentials/tenant-guard.d.ts +16 -0
- package/dist/credentials/tenant-guard.d.ts.map +1 -0
- package/dist/credentials/tenant-guard.js +53 -0
- package/dist/credentials/tenant-guard.js.map +1 -0
- package/dist/credentials/tty-guard.d.ts +19 -0
- package/dist/credentials/tty-guard.d.ts.map +1 -0
- package/dist/credentials/tty-guard.js +47 -0
- package/dist/credentials/tty-guard.js.map +1 -0
- package/dist/db/apply-schema.d.ts +144 -0
- package/dist/db/apply-schema.d.ts.map +1 -0
- package/dist/db/apply-schema.js +359 -0
- package/dist/db/apply-schema.js.map +1 -0
- package/dist/db/sql-file.d.ts +104 -0
- package/dist/db/sql-file.d.ts.map +1 -0
- package/dist/db/sql-file.js +584 -0
- package/dist/db/sql-file.js.map +1 -0
- package/dist/instance/provision.d.ts +89 -0
- package/dist/instance/provision.d.ts.map +1 -0
- package/dist/instance/provision.js +139 -0
- package/dist/instance/provision.js.map +1 -0
- package/dist/instance/zero-store.d.ts +47 -0
- package/dist/instance/zero-store.d.ts.map +1 -0
- package/dist/instance/zero-store.js +91 -0
- package/dist/instance/zero-store.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +46 -0
- package/dist/main.js.map +1 -0
- package/dist/skill/assets.d.ts +38 -0
- package/dist/skill/assets.d.ts.map +1 -0
- package/dist/skill/assets.js +111 -0
- package/dist/skill/assets.js.map +1 -0
- package/dist/skill/hint.d.ts +39 -0
- package/dist/skill/hint.d.ts.map +1 -0
- package/dist/skill/hint.js +109 -0
- package/dist/skill/hint.js.map +1 -0
- package/dist/skill/hosts.d.ts +21 -0
- package/dist/skill/hosts.d.ts.map +1 -0
- package/dist/skill/hosts.js +38 -0
- package/dist/skill/hosts.js.map +1 -0
- package/dist/skill/installer.d.ts +88 -0
- package/dist/skill/installer.d.ts.map +1 -0
- package/dist/skill/installer.js +203 -0
- package/dist/skill/installer.js.map +1 -0
- package/dist/skill/ownership.d.ts +35 -0
- package/dist/skill/ownership.d.ts.map +1 -0
- package/dist/skill/ownership.js +52 -0
- package/dist/skill/ownership.js.map +1 -0
- package/package.json +63 -3
- package/skills/pxbaas-app-spec/SKILL.md +163 -0
- package/skills/pxbaas-app-spec/references/deploy-options.md +157 -0
- package/skills/pxbaas-app-spec/references/guardrails-pitfalls.md +89 -0
- package/skills/pxbaas-app-spec/references/runtime-contract.md +151 -0
- package/skills/pxbaas-app-spec/references/ssr-session.md +121 -0
- package/skills/pxbaas-app-spec/references/templates-examples.md +311 -0
- package/skills/pxbaas-cli/SKILL.md +171 -0
- package/skills/pxbaas-cli/references/api-reference.md +68 -0
- package/skills/pxbaas-cli/references/app-deploy.md +170 -0
- package/skills/pxbaas-cli/references/auth-and-credentials.md +100 -0
- package/skills/pxbaas-cli/references/data-postgrest.md +85 -0
- package/skills/pxbaas-cli/references/db-and-meta.md +97 -0
- package/skills/pxbaas-cli/references/edge-functions.md +71 -0
- package/skills/pxbaas-cli/references/multi-tenant-apps.md +138 -0
- package/skills/pxbaas-cli/references/provision.md +86 -0
- package/skills/pxbaas-cli/references/safety-and-two-phase.md +49 -0
- package/skills/pxbaas-cli/references/storage.md +61 -0
- package/skills/pxbaas-cli/references/troubleshooting.md +73 -0
- package/templates/webapp/api/index.ts +55 -0
- package/templates/webapp/csr-bff/README.md +81 -0
- package/templates/webapp/csr-bff/backend/index.ts +168 -0
- package/templates/webapp/csr-bff/db/rls.json +13 -0
- package/templates/webapp/csr-bff/db/schema.sql +49 -0
- package/templates/webapp/csr-bff/frontend/dist/admin.html +101 -0
- package/templates/webapp/csr-bff/frontend/dist/article.html +44 -0
- package/templates/webapp/csr-bff/frontend/dist/blog.js +206 -0
- package/templates/webapp/csr-bff/frontend/dist/blogger.html +53 -0
- package/templates/webapp/csr-bff/frontend/dist/index.html +70 -0
- package/templates/webapp/csr-bff/frontend/dist/login.html +56 -0
- package/templates/webapp/csr-bff/frontend/dist/profile.html +59 -0
- package/templates/webapp/csr-bff/frontend/dist/signup.html +78 -0
- package/templates/webapp/csr-bff/frontend/dist/style.css +27 -0
- package/templates/webapp/manifest.json +299 -0
- package/templates/webapp/mpa/about.html +29 -0
- package/templates/webapp/mpa/app.js +42 -0
- package/templates/webapp/mpa/index.html +42 -0
- package/templates/webapp/mpa/index.ts +60 -0
- package/templates/webapp/mpa/style.css +42 -0
- package/templates/webapp/react-vite/frontend/index.html +12 -0
- package/templates/webapp/react-vite/frontend/package-lock.json +1826 -0
- package/templates/webapp/react-vite/frontend/package.json +23 -0
- package/templates/webapp/react-vite/frontend/src/App.tsx +34 -0
- package/templates/webapp/react-vite/frontend/src/main.tsx +13 -0
- package/templates/webapp/react-vite/frontend/src/style.css +46 -0
- package/templates/webapp/react-vite/frontend/tsconfig.json +20 -0
- package/templates/webapp/react-vite/frontend/vite.config.ts +10 -0
- package/templates/webapp/react-vite-hono/backend/index.ts +21 -0
- package/templates/webapp/react-vite-hono/frontend/index.html +12 -0
- package/templates/webapp/react-vite-hono/frontend/package-lock.json +1826 -0
- package/templates/webapp/react-vite-hono/frontend/package.json +23 -0
- package/templates/webapp/react-vite-hono/frontend/src/App.tsx +47 -0
- package/templates/webapp/react-vite-hono/frontend/src/main.tsx +13 -0
- package/templates/webapp/react-vite-hono/frontend/src/style.css +66 -0
- package/templates/webapp/react-vite-hono/frontend/tsconfig.json +20 -0
- package/templates/webapp/react-vite-hono/frontend/vite.config.ts +10 -0
- package/templates/webapp/spa/index.ts +119 -0
- package/templates/webapp/ssr-auth/backend/index.ts +133 -0
- package/templates/webapp/ssr-auth/frontend/dist/index.html +15 -0
- package/templates/webapp/ssr-blog/README.md +111 -0
- package/templates/webapp/ssr-blog/backend/index.ts +764 -0
- package/templates/webapp/ssr-blog/db/rls.json +13 -0
- package/templates/webapp/ssr-blog/db/schema.sql +51 -0
- package/templates/webapp/ssr-blog/frontend/dist/index.html +39 -0
- package/templates/webapp/ssr-frameworks/README.md +64 -0
- package/templates/webapp/ssr-frameworks/backend/index.ts +241 -0
- package/templates/webapp/ssr-frameworks/frontend/dist/index.html +31 -0
- package/templates/webapp/ssr-hono/backend/index.ts +92 -0
- package/templates/webapp/ssr-hono/frontend/dist/index.html +12 -0
- package/templates/webapp/ssr-shop/README.md +80 -0
- package/templates/webapp/ssr-shop/backend/index.ts +491 -0
- package/templates/webapp/ssr-shop/db/rls.json +16 -0
- package/templates/webapp/ssr-shop/db/schema.sql +90 -0
- package/templates/webapp/ssr-shop/frontend/dist/index.html +12 -0
- package/templates/webapp/vanilla-static/frontend/app.js +6 -0
- package/templates/webapp/vanilla-static/frontend/index.html +19 -0
- package/templates/webapp/vanilla-static/frontend/style.css +43 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema apply engine shared by `pxbaas db push <file>` and `pxbaas app db-init <name>`.
|
|
3
|
+
*
|
|
4
|
+
* Two execution identities (chosen by profile.mode via {@link getSchemaSink}):
|
|
5
|
+
* - single-tenant → MetaDriver `/pg/query` with the global service_role key
|
|
6
|
+
* (that key IS the platform admin, so it can also write the central RLS
|
|
7
|
+
* registry `supabase._mysqlrest_rls_*` directly).
|
|
8
|
+
* - multi-tenant → TenantDdlDriver `/api/tenant-ddl/*` with the per-tenant
|
|
9
|
+
* service_role key. DDL/DML runs on the tenant's OWN database; RLS goes
|
|
10
|
+
* through the structured endpoints (the tenant account has NO grant on the
|
|
11
|
+
* shared `supabase` database, so a raw central INSERT would be denied).
|
|
12
|
+
*
|
|
13
|
+
* Safety contract (agreed design, unchanged):
|
|
14
|
+
* - The plan (every step) is shown BEFORE anything runs.
|
|
15
|
+
* - Execution requires explicit authorization: an interactive confirm, or
|
|
16
|
+
* `--yes` for non-interactive use. `--dry-run` only previews.
|
|
17
|
+
* - Steps run sequentially and STOP ON THE FIRST ERROR.
|
|
18
|
+
* - No automatic rollback — already-applied steps stay applied.
|
|
19
|
+
*
|
|
20
|
+
* RLS source (see plan §5, decision R-C "hybrid"):
|
|
21
|
+
* - a declarative `db/rls.json` is preferred when present;
|
|
22
|
+
* - otherwise the `INSERT ... supabase._mysqlrest_rls_*` statements embedded in
|
|
23
|
+
* schema.sql are parsed (multi-tenant) or run verbatim (single-tenant).
|
|
24
|
+
*/
|
|
25
|
+
import { MetaDriver, type RlsTableInput, type RlsPolicyInput } from "@polardbx/pxbaas-client";
|
|
26
|
+
import type { ProfileMode } from "../credentials/profile.js";
|
|
27
|
+
import { type RlsJson } from "./sql-file.js";
|
|
28
|
+
export type { RlsJson };
|
|
29
|
+
export interface ApplyOptions {
|
|
30
|
+
/** Target schema the `__SCHEMA__` placeholder resolves to (single-tenant: public). */
|
|
31
|
+
schema: string;
|
|
32
|
+
/** Preview only; never execute. */
|
|
33
|
+
dryRun: boolean;
|
|
34
|
+
/** Non-interactive authorization; skips the confirm prompt. */
|
|
35
|
+
assumeYes: boolean;
|
|
36
|
+
/** Emit a structured result instead of human text (caller prints JSON). */
|
|
37
|
+
json: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type StepKind = "sql" | "rls-table" | "rls-policy";
|
|
40
|
+
export interface StatementResult {
|
|
41
|
+
index: number;
|
|
42
|
+
/** For sql steps this is the SQL; for RLS steps a human-readable description. */
|
|
43
|
+
sql: string;
|
|
44
|
+
kind?: StepKind;
|
|
45
|
+
status: "pending" | "ok" | "failed" | "skipped";
|
|
46
|
+
error?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface ApplyResult {
|
|
49
|
+
source: string;
|
|
50
|
+
schema: string;
|
|
51
|
+
total: number;
|
|
52
|
+
executed: number;
|
|
53
|
+
failed: number;
|
|
54
|
+
dryRun: boolean;
|
|
55
|
+
authorized: boolean;
|
|
56
|
+
statements: StatementResult[];
|
|
57
|
+
/** Present when produced by {@link applySchema}. */
|
|
58
|
+
mode?: ProfileMode;
|
|
59
|
+
rls?: {
|
|
60
|
+
tables: number;
|
|
61
|
+
policies: number;
|
|
62
|
+
source: "rls.json" | "schema.sql" | "none";
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** A minimal SQL executor so this module stays unit-testable without MetaDriver. */
|
|
66
|
+
export type SqlExecutor = (sql: string) => Promise<unknown>;
|
|
67
|
+
/** Per-call context the sink needs to render/apply structured RLS. */
|
|
68
|
+
export interface RlsApplyContext {
|
|
69
|
+
/** Single-tenant target schema; ignored by the multi-tenant sink (server-bound). */
|
|
70
|
+
schema: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Execution strategy for a resolved profile. Encapsulates the single- vs
|
|
74
|
+
* multi-tenant channel difference so {@link applySchema} stays mode-agnostic.
|
|
75
|
+
*/
|
|
76
|
+
export interface SchemaSink {
|
|
77
|
+
mode: ProfileMode;
|
|
78
|
+
profileName: string;
|
|
79
|
+
/** Run one DDL/DML statement on the appropriate channel. */
|
|
80
|
+
runStatement(sql: string): Promise<unknown>;
|
|
81
|
+
/** Apply one RLS table toggle. */
|
|
82
|
+
applyRlsTable(input: RlsTableInput, ctx: RlsApplyContext): Promise<unknown>;
|
|
83
|
+
/** Apply one RLS policy. */
|
|
84
|
+
applyRlsPolicy(input: RlsPolicyInput, ctx: RlsApplyContext): Promise<unknown>;
|
|
85
|
+
/** Human-readable label for the plan preview. */
|
|
86
|
+
renderRlsTable(input: RlsTableInput, ctx: RlsApplyContext): string;
|
|
87
|
+
renderRlsPolicy(input: RlsPolicyInput, ctx: RlsApplyContext): string;
|
|
88
|
+
/** Drop one of the app's tables (used by `app destroy --purge-db`). */
|
|
89
|
+
dropTable(table: string, ctx: RlsApplyContext): Promise<unknown>;
|
|
90
|
+
/**
|
|
91
|
+
* Remove the RLS registry rows for one table. `toggleRemoved` reports whether
|
|
92
|
+
* the central `_mysqlrest_rls_tables` enable/force row was deleted. In
|
|
93
|
+
* multi-tenant this uses `DELETE /api/tenant-ddl/rls/tables`; on instances that
|
|
94
|
+
* predate that endpoint the call fails and we degrade gracefully (the benign
|
|
95
|
+
* toggle row is left and self-heals on the next db-init upsert).
|
|
96
|
+
*/
|
|
97
|
+
purgeRlsForTable(table: string, ctx: RlsApplyContext): Promise<{
|
|
98
|
+
policiesDeleted: number;
|
|
99
|
+
toggleRemoved: boolean;
|
|
100
|
+
}>;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Resolve the active profile into a single-tenant MetaDriver.
|
|
104
|
+
* @throws when there is no profile, no credentials, or the profile is multi-tenant.
|
|
105
|
+
* @deprecated prefer {@link getSchemaSink}, which supports both modes. Kept for
|
|
106
|
+
* single-tenant callers and existing tests.
|
|
107
|
+
*/
|
|
108
|
+
export declare function getSingleTenantMetaDriver(role?: "anon" | "service_role"): Promise<{
|
|
109
|
+
driver: MetaDriver;
|
|
110
|
+
useServiceRole: boolean;
|
|
111
|
+
profileName: string;
|
|
112
|
+
}>;
|
|
113
|
+
/**
|
|
114
|
+
* Resolve the active profile into a mode-appropriate {@link SchemaSink}.
|
|
115
|
+
* Unlike {@link getSingleTenantMetaDriver}, a multi-tenant profile is fully
|
|
116
|
+
* supported: DDL/RLS route through the tenant self-service endpoints using the
|
|
117
|
+
* per-tenant service_role key (Kong injects the trusted X-Tenant-Id).
|
|
118
|
+
*/
|
|
119
|
+
export declare function getSchemaSink(role?: "anon" | "service_role"): Promise<SchemaSink>;
|
|
120
|
+
/**
|
|
121
|
+
* Apply a raw SQL script through an injected executor (single-tenant legacy
|
|
122
|
+
* path). Schema substitution uses the single-tenant rule; RLS statements are
|
|
123
|
+
* NOT diverted (they run verbatim through the executor). For mode-aware apply
|
|
124
|
+
* with RLS diversion use {@link applySchema}.
|
|
125
|
+
*/
|
|
126
|
+
export declare function applySqlStatements(rawSql: string, source: string, opts: ApplyOptions, executor: SqlExecutor): Promise<ApplyResult>;
|
|
127
|
+
export interface ApplySchemaParams extends ApplyOptions {
|
|
128
|
+
rawSql: string;
|
|
129
|
+
source: string;
|
|
130
|
+
/** Parsed `db/rls.json` (preferred RLS source); null/absent → fall back to schema.sql. */
|
|
131
|
+
rls?: RlsJson | null;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Mode-aware apply used by `db push` and `app db-init`.
|
|
135
|
+
*
|
|
136
|
+
* - Splits the script, then (multi-tenant OR when rls.json is present) diverts
|
|
137
|
+
* the embedded central-registry RLS INSERTs out of the raw-SQL stream.
|
|
138
|
+
* - RLS source: `db/rls.json` when present; else parsed from schema.sql
|
|
139
|
+
* (multi-tenant) or left embedded (single-tenant legacy).
|
|
140
|
+
* - `__SCHEMA__`: single-tenant → --schema; multi-tenant → de-qualified.
|
|
141
|
+
* - Order: DDL/seed first (tables must exist), then RLS tables, then policies.
|
|
142
|
+
*/
|
|
143
|
+
export declare function applySchema(params: ApplySchemaParams, sink: SchemaSink): Promise<ApplyResult>;
|
|
144
|
+
//# sourceMappingURL=apply-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-schema.d.ts","sourceRoot":"","sources":["../../src/db/apply-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema apply engine shared by `pxbaas db push <file>` and `pxbaas app db-init <name>`.
|
|
3
|
+
*
|
|
4
|
+
* Two execution identities (chosen by profile.mode via {@link getSchemaSink}):
|
|
5
|
+
* - single-tenant → MetaDriver `/pg/query` with the global service_role key
|
|
6
|
+
* (that key IS the platform admin, so it can also write the central RLS
|
|
7
|
+
* registry `supabase._mysqlrest_rls_*` directly).
|
|
8
|
+
* - multi-tenant → TenantDdlDriver `/api/tenant-ddl/*` with the per-tenant
|
|
9
|
+
* service_role key. DDL/DML runs on the tenant's OWN database; RLS goes
|
|
10
|
+
* through the structured endpoints (the tenant account has NO grant on the
|
|
11
|
+
* shared `supabase` database, so a raw central INSERT would be denied).
|
|
12
|
+
*
|
|
13
|
+
* Safety contract (agreed design, unchanged):
|
|
14
|
+
* - The plan (every step) is shown BEFORE anything runs.
|
|
15
|
+
* - Execution requires explicit authorization: an interactive confirm, or
|
|
16
|
+
* `--yes` for non-interactive use. `--dry-run` only previews.
|
|
17
|
+
* - Steps run sequentially and STOP ON THE FIRST ERROR.
|
|
18
|
+
* - No automatic rollback — already-applied steps stay applied.
|
|
19
|
+
*
|
|
20
|
+
* RLS source (see plan §5, decision R-C "hybrid"):
|
|
21
|
+
* - a declarative `db/rls.json` is preferred when present;
|
|
22
|
+
* - otherwise the `INSERT ... supabase._mysqlrest_rls_*` statements embedded in
|
|
23
|
+
* schema.sql are parsed (multi-tenant) or run verbatim (single-tenant).
|
|
24
|
+
*/
|
|
25
|
+
import inquirer from "inquirer";
|
|
26
|
+
import { MetaDriver, TenantDdlDriver, } from "@polardbx/pxbaas-client";
|
|
27
|
+
import { CredentialStore, ProfileManager, formatError, formatSuccess, formatWarning, } from "../credentials/index.js";
|
|
28
|
+
import { buildStatementPlan, partitionStatements, parseRlsPolicyInsert, parseRlsTableInsert, renderRlsPolicyInsert, renderRlsTableInsert, splitSqlStatements, substituteSchema, substituteSchemaForTenant, SCHEMA_PLACEHOLDER, } from "./sql-file.js";
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the active profile into a single-tenant MetaDriver.
|
|
31
|
+
* @throws when there is no profile, no credentials, or the profile is multi-tenant.
|
|
32
|
+
* @deprecated prefer {@link getSchemaSink}, which supports both modes. Kept for
|
|
33
|
+
* single-tenant callers and existing tests.
|
|
34
|
+
*/
|
|
35
|
+
export async function getSingleTenantMetaDriver(role = "service_role") {
|
|
36
|
+
const profileManager = new ProfileManager();
|
|
37
|
+
const profile = await profileManager.getCurrentProfile();
|
|
38
|
+
if (!profile) {
|
|
39
|
+
throw new Error('No active profile. Use "pxbaas login" to authenticate first.');
|
|
40
|
+
}
|
|
41
|
+
if (profile.mode === "multi-tenant") {
|
|
42
|
+
throw new Error("Multi-tenant DDL is not supported by this command. In multi-tenant mode run DDL " +
|
|
43
|
+
"via POST {endpoint}/pg/query using the GLOBAL service_role key with fully-qualified " +
|
|
44
|
+
"tenant_<id>.<table> names (per-tenant keys are rejected 401 on /pg/query).");
|
|
45
|
+
}
|
|
46
|
+
const credentials = await new CredentialStore().getCredentials(profile.name);
|
|
47
|
+
if (!credentials) {
|
|
48
|
+
throw new Error(`No credentials found for profile: ${profile.name}. Use "pxbaas login" to authenticate.`);
|
|
49
|
+
}
|
|
50
|
+
const driver = new MetaDriver({
|
|
51
|
+
endpoint: profile.endpoint,
|
|
52
|
+
anonKey: credentials.anonKey,
|
|
53
|
+
serviceRoleKey: credentials.serviceRoleKey,
|
|
54
|
+
tenantId: profile.tenantId,
|
|
55
|
+
});
|
|
56
|
+
return { driver, useServiceRole: role === "service_role", profileName: profile.name };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve the active profile into a mode-appropriate {@link SchemaSink}.
|
|
60
|
+
* Unlike {@link getSingleTenantMetaDriver}, a multi-tenant profile is fully
|
|
61
|
+
* supported: DDL/RLS route through the tenant self-service endpoints using the
|
|
62
|
+
* per-tenant service_role key (Kong injects the trusted X-Tenant-Id).
|
|
63
|
+
*/
|
|
64
|
+
export async function getSchemaSink(role = "service_role") {
|
|
65
|
+
const profileManager = new ProfileManager();
|
|
66
|
+
const profile = await profileManager.getCurrentProfile();
|
|
67
|
+
if (!profile) {
|
|
68
|
+
throw new Error('No active profile. Use "pxbaas login" to authenticate first.');
|
|
69
|
+
}
|
|
70
|
+
const credentials = await new CredentialStore().getCredentials(profile.name);
|
|
71
|
+
if (!credentials) {
|
|
72
|
+
throw new Error(`No credentials found for profile: ${profile.name}. Use "pxbaas login" to authenticate.`);
|
|
73
|
+
}
|
|
74
|
+
if (profile.mode === "multi-tenant") {
|
|
75
|
+
if (!profile.tenantId) {
|
|
76
|
+
throw new Error('Multi-tenant profile is missing tenantId; re-run "pxbaas login --tenant-id <id>" ' +
|
|
77
|
+
"with this tenant's per-tenant anon/service keys.");
|
|
78
|
+
}
|
|
79
|
+
// Only the per-tenant service_role key is accepted by /api/tenant-ddl (the
|
|
80
|
+
// resolver role-gates on service_role). Kong injects X-Tenant-Id from the JWT.
|
|
81
|
+
const driver = new TenantDdlDriver({
|
|
82
|
+
endpoint: profile.endpoint,
|
|
83
|
+
serviceRoleKey: credentials.serviceRoleKey,
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
mode: "multi-tenant",
|
|
87
|
+
profileName: profile.name,
|
|
88
|
+
runStatement: (sql) => driver.query(sql),
|
|
89
|
+
applyRlsTable: (input) => driver.upsertRlsTable(input),
|
|
90
|
+
applyRlsPolicy: (input) => driver.upsertRlsPolicy(input),
|
|
91
|
+
renderRlsTable: (input) => `RLS ${input.rls_forced ? "FORCE" : "ENABLE"} ${input.table_name}`,
|
|
92
|
+
renderRlsPolicy: (input) => `RLS POLICY ${input.policy_name} ON ${input.table_name} ` +
|
|
93
|
+
`[${(input.command ?? "ALL").toString().toUpperCase()} / ${input.role_name ?? "*"}]`,
|
|
94
|
+
dropTable: (table) => driver.query(`DROP TABLE IF EXISTS ${quoteIdent(table)}`),
|
|
95
|
+
purgeRlsForTable: async (table) => {
|
|
96
|
+
assertSafeIdent(table);
|
|
97
|
+
const policies = await driver.listRlsPolicies(table);
|
|
98
|
+
for (const p of policies)
|
|
99
|
+
await driver.deleteRlsPolicy(table, p.policy_name);
|
|
100
|
+
// Remove the central toggle row via DELETE /rls/tables. Tolerate instances
|
|
101
|
+
// that predate the endpoint (it 404/405s): degrade to leaving the benign
|
|
102
|
+
// row rather than failing the whole purge.
|
|
103
|
+
let toggleRemoved = false;
|
|
104
|
+
try {
|
|
105
|
+
await driver.deleteRlsTable(table);
|
|
106
|
+
toggleRemoved = true;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
toggleRemoved = false;
|
|
110
|
+
}
|
|
111
|
+
return { policiesDeleted: policies.length, toggleRemoved };
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const driver = new MetaDriver({
|
|
116
|
+
endpoint: profile.endpoint,
|
|
117
|
+
anonKey: credentials.anonKey,
|
|
118
|
+
serviceRoleKey: credentials.serviceRoleKey,
|
|
119
|
+
tenantId: profile.tenantId,
|
|
120
|
+
});
|
|
121
|
+
const useServiceRole = role === "service_role";
|
|
122
|
+
return {
|
|
123
|
+
mode: "single-tenant",
|
|
124
|
+
profileName: profile.name,
|
|
125
|
+
runStatement: (sql) => driver.query(sql, useServiceRole),
|
|
126
|
+
// Single-tenant: the service_role key is the platform admin, so RLS is
|
|
127
|
+
// written straight into the central registry via /pg/query.
|
|
128
|
+
applyRlsTable: (input, ctx) => driver.query(renderRlsTableInsert(ctx.schema, input), useServiceRole),
|
|
129
|
+
applyRlsPolicy: (input, ctx) => driver.query(renderRlsPolicyInsert(ctx.schema, input), useServiceRole),
|
|
130
|
+
renderRlsTable: (input, ctx) => renderRlsTableInsert(ctx.schema, input),
|
|
131
|
+
renderRlsPolicy: (input, ctx) => renderRlsPolicyInsert(ctx.schema, input),
|
|
132
|
+
dropTable: (table, ctx) => driver.query(`DROP TABLE IF EXISTS ${quoteIdent(ctx.schema)}.${quoteIdent(table)}`, useServiceRole),
|
|
133
|
+
purgeRlsForTable: async (table, ctx) => {
|
|
134
|
+
assertSafeIdent(table);
|
|
135
|
+
const schemaLit = sqlQuote(ctx.schema);
|
|
136
|
+
const tableLit = sqlQuote(table);
|
|
137
|
+
const found = await driver.query(`SELECT policy_name FROM supabase._mysqlrest_rls_policies ` +
|
|
138
|
+
`WHERE table_schema = '${schemaLit}' AND table_name = '${tableLit}'`, useServiceRole);
|
|
139
|
+
const names = found.rows.map((r) => String(r.policy_name));
|
|
140
|
+
for (const pn of names) {
|
|
141
|
+
await driver.query(`DELETE FROM supabase._mysqlrest_rls_policies WHERE table_schema = '${schemaLit}' ` +
|
|
142
|
+
`AND table_name = '${tableLit}' AND policy_name = '${sqlQuote(pn)}'`, useServiceRole);
|
|
143
|
+
}
|
|
144
|
+
await driver.query(`DELETE FROM supabase._mysqlrest_rls_tables WHERE table_schema = '${schemaLit}' AND table_name = '${tableLit}'`, useServiceRole);
|
|
145
|
+
return { policiesDeleted: names.length, toggleRemoved: true };
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const SAFE_IDENT_RE = /^[A-Za-z0-9_]+$/;
|
|
150
|
+
/** Reject anything but a bare identifier before interpolating into DDL. */
|
|
151
|
+
function assertSafeIdent(name) {
|
|
152
|
+
if (!SAFE_IDENT_RE.test(name) || name.length > 64) {
|
|
153
|
+
throw new Error(`Unsafe table identifier refused: '${name}'`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** Backtick-quote a validated identifier. */
|
|
157
|
+
function quoteIdent(name) {
|
|
158
|
+
assertSafeIdent(name);
|
|
159
|
+
return `\`${name}\``;
|
|
160
|
+
}
|
|
161
|
+
/** Escape a single-quoted SQL string literal. */
|
|
162
|
+
function sqlQuote(value) {
|
|
163
|
+
return String(value).replace(/'/g, "''");
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Shared show-plan → authorize → execute-sequentially (stop on first error) core.
|
|
167
|
+
* Used by both {@link applySqlStatements} and {@link applySchema} so the safety
|
|
168
|
+
* contract lives in exactly one place.
|
|
169
|
+
*/
|
|
170
|
+
async function executePlan(params) {
|
|
171
|
+
const { items, opts, source } = params;
|
|
172
|
+
const skippedAll = () => items.map((it, i) => ({ index: i + 1, sql: it.label, kind: it.kind, status: "skipped" }));
|
|
173
|
+
const envelope = (partial, statements) => ({
|
|
174
|
+
source,
|
|
175
|
+
schema: opts.schema,
|
|
176
|
+
total: partial.total,
|
|
177
|
+
executed: partial.executed,
|
|
178
|
+
failed: partial.failed,
|
|
179
|
+
dryRun: partial.dryRun,
|
|
180
|
+
authorized: partial.authorized,
|
|
181
|
+
statements,
|
|
182
|
+
...(params.mode ? { mode: params.mode } : {}),
|
|
183
|
+
...(params.rls ? { rls: params.rls } : {}),
|
|
184
|
+
});
|
|
185
|
+
if (items.length === 0) {
|
|
186
|
+
if (!opts.json) {
|
|
187
|
+
console.log(formatWarning(`No executable statements found in ${source}.`));
|
|
188
|
+
}
|
|
189
|
+
return envelope({ total: 0, executed: 0, failed: 0, dryRun: opts.dryRun, authorized: false }, []);
|
|
190
|
+
}
|
|
191
|
+
// 1) Show the plan (text mode). JSON callers receive the structured result.
|
|
192
|
+
if (!opts.json) {
|
|
193
|
+
console.log(formatSuccess(`Plan for ${source} (schema: ${opts.schema})`));
|
|
194
|
+
for (const w of params.preWarnings ?? [])
|
|
195
|
+
console.log(formatWarning(w));
|
|
196
|
+
items.forEach((it, i) => {
|
|
197
|
+
console.log(`\n[${i + 1}/${items.length}] ${it.label}`);
|
|
198
|
+
});
|
|
199
|
+
console.log("");
|
|
200
|
+
}
|
|
201
|
+
// 2) Dry run: preview only.
|
|
202
|
+
if (opts.dryRun) {
|
|
203
|
+
if (!opts.json) {
|
|
204
|
+
console.log(formatWarning(`Dry run: 0 of ${items.length} statement(s) executed.`));
|
|
205
|
+
}
|
|
206
|
+
return envelope({ total: items.length, executed: 0, failed: 0, dryRun: true, authorized: false }, skippedAll());
|
|
207
|
+
}
|
|
208
|
+
// 3) Authorization gate.
|
|
209
|
+
const authorized = await authorize(items.length, opts);
|
|
210
|
+
if (!authorized) {
|
|
211
|
+
if (!opts.json) {
|
|
212
|
+
console.log(formatWarning("Aborted by operator; nothing was executed."));
|
|
213
|
+
}
|
|
214
|
+
return envelope({ total: items.length, executed: 0, failed: 0, dryRun: false, authorized: false }, skippedAll());
|
|
215
|
+
}
|
|
216
|
+
// 4) Execute sequentially; stop on the first error; no rollback.
|
|
217
|
+
const results = [];
|
|
218
|
+
let executed = 0;
|
|
219
|
+
let failed = 0;
|
|
220
|
+
for (let i = 0; i < items.length; i++) {
|
|
221
|
+
const item = items[i];
|
|
222
|
+
const r = { index: i + 1, sql: item.label, kind: item.kind, status: "pending" };
|
|
223
|
+
results.push(r);
|
|
224
|
+
try {
|
|
225
|
+
await item.exec();
|
|
226
|
+
r.status = "ok";
|
|
227
|
+
executed++;
|
|
228
|
+
if (!opts.json)
|
|
229
|
+
console.log(formatSuccess(`[${i + 1}/${items.length}] ok`));
|
|
230
|
+
}
|
|
231
|
+
catch (e) {
|
|
232
|
+
r.status = "failed";
|
|
233
|
+
r.error = e instanceof Error ? e.message : String(e);
|
|
234
|
+
failed++;
|
|
235
|
+
if (!opts.json) {
|
|
236
|
+
console.error(formatError(`[${i + 1}/${items.length}] failed: ${r.error}`));
|
|
237
|
+
}
|
|
238
|
+
for (let j = i + 1; j < items.length; j++) {
|
|
239
|
+
results.push({ index: j + 1, sql: items[j].label, kind: items[j].kind, status: "skipped" });
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (!opts.json) {
|
|
245
|
+
console.log("");
|
|
246
|
+
if (failed === 0) {
|
|
247
|
+
console.log(formatSuccess(`Applied ${executed}/${items.length} statement(s) to schema '${opts.schema}'.`));
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
console.log(formatError(`Stopped after failure: ${executed} ok, ${failed} failed, ` +
|
|
251
|
+
`${items.length - executed - failed} skipped. No rollback performed.`));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return envelope({ total: items.length, executed, failed, dryRun: false, authorized: true }, results);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Apply a raw SQL script through an injected executor (single-tenant legacy
|
|
258
|
+
* path). Schema substitution uses the single-tenant rule; RLS statements are
|
|
259
|
+
* NOT diverted (they run verbatim through the executor). For mode-aware apply
|
|
260
|
+
* with RLS diversion use {@link applySchema}.
|
|
261
|
+
*/
|
|
262
|
+
export async function applySqlStatements(rawSql, source, opts, executor) {
|
|
263
|
+
const { statements, substituted } = buildStatementPlan(rawSql, opts.schema);
|
|
264
|
+
const items = statements.map((sql) => ({
|
|
265
|
+
label: sql,
|
|
266
|
+
kind: "sql",
|
|
267
|
+
exec: () => executor(sql),
|
|
268
|
+
}));
|
|
269
|
+
const preWarnings = substituted
|
|
270
|
+
? []
|
|
271
|
+
: [`Script contains no ${SCHEMA_PLACEHOLDER} placeholder; --schema has no effect.`];
|
|
272
|
+
return executePlan({ items, opts, source, preWarnings });
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Mode-aware apply used by `db push` and `app db-init`.
|
|
276
|
+
*
|
|
277
|
+
* - Splits the script, then (multi-tenant OR when rls.json is present) diverts
|
|
278
|
+
* the embedded central-registry RLS INSERTs out of the raw-SQL stream.
|
|
279
|
+
* - RLS source: `db/rls.json` when present; else parsed from schema.sql
|
|
280
|
+
* (multi-tenant) or left embedded (single-tenant legacy).
|
|
281
|
+
* - `__SCHEMA__`: single-tenant → --schema; multi-tenant → de-qualified.
|
|
282
|
+
* - Order: DDL/seed first (tables must exist), then RLS tables, then policies.
|
|
283
|
+
*/
|
|
284
|
+
export async function applySchema(params, sink) {
|
|
285
|
+
const statements = splitSqlStatements(params.rawSql);
|
|
286
|
+
const { rlsTableInserts, rlsPolicyInserts, plain } = partitionStatements(statements);
|
|
287
|
+
const embeddedRlsCount = rlsTableInserts.length + rlsPolicyInserts.length;
|
|
288
|
+
const rls = params.rls;
|
|
289
|
+
const hasRlsJson = Boolean(rls && (rls.tables.length > 0 || rls.policies.length > 0));
|
|
290
|
+
// Single-tenant without rls.json keeps the legacy behavior: run schema.sql
|
|
291
|
+
// verbatim (embedded RLS INSERTs work through the admin /pg/query channel).
|
|
292
|
+
const divertEmbedded = sink.mode === "multi-tenant" || hasRlsJson;
|
|
293
|
+
const rawRun = divertEmbedded ? plain : statements;
|
|
294
|
+
const preWarnings = [];
|
|
295
|
+
let tables = [];
|
|
296
|
+
let policies = [];
|
|
297
|
+
let rlsSource = "none";
|
|
298
|
+
if (hasRlsJson) {
|
|
299
|
+
tables = rls.tables;
|
|
300
|
+
policies = rls.policies;
|
|
301
|
+
rlsSource = "rls.json";
|
|
302
|
+
if (embeddedRlsCount > 0) {
|
|
303
|
+
preWarnings.push(`db/rls.json is present — ignoring ${embeddedRlsCount} RLS INSERT statement(s) embedded ` +
|
|
304
|
+
`in ${params.source} to keep a single source of truth.`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
else if (sink.mode === "multi-tenant") {
|
|
308
|
+
tables = rlsTableInserts.flatMap(parseRlsTableInsert);
|
|
309
|
+
policies = rlsPolicyInserts.flatMap(parseRlsPolicyInsert);
|
|
310
|
+
rlsSource = tables.length || policies.length ? "schema.sql" : "none";
|
|
311
|
+
}
|
|
312
|
+
const substitute = (sql) => sink.mode === "multi-tenant" ? substituteSchemaForTenant(sql) : substituteSchema(sql, params.schema);
|
|
313
|
+
const ctx = { schema: params.schema };
|
|
314
|
+
const items = [];
|
|
315
|
+
for (const sql of rawRun) {
|
|
316
|
+
const rendered = substitute(sql);
|
|
317
|
+
items.push({ label: rendered, kind: "sql", exec: () => sink.runStatement(rendered) });
|
|
318
|
+
}
|
|
319
|
+
for (const t of tables) {
|
|
320
|
+
items.push({ label: sink.renderRlsTable(t, ctx), kind: "rls-table", exec: () => sink.applyRlsTable(t, ctx) });
|
|
321
|
+
}
|
|
322
|
+
for (const p of policies) {
|
|
323
|
+
items.push({ label: sink.renderRlsPolicy(p, ctx), kind: "rls-policy", exec: () => sink.applyRlsPolicy(p, ctx) });
|
|
324
|
+
}
|
|
325
|
+
return executePlan({
|
|
326
|
+
items,
|
|
327
|
+
opts: params,
|
|
328
|
+
source: params.source,
|
|
329
|
+
preWarnings,
|
|
330
|
+
mode: sink.mode,
|
|
331
|
+
rls: { tables: tables.length, policies: policies.length, source: rlsSource },
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Decide whether execution is authorized. `--yes` authorizes outright; JSON mode
|
|
336
|
+
* and non-TTY sessions cannot prompt, so they require `--yes` explicitly.
|
|
337
|
+
*/
|
|
338
|
+
async function authorize(count, opts) {
|
|
339
|
+
if (opts.assumeYes)
|
|
340
|
+
return true;
|
|
341
|
+
if (opts.json) {
|
|
342
|
+
throw new Error("Refusing to run DDL in --json mode without explicit authorization. " +
|
|
343
|
+
"Re-run with --yes to apply, or --dry-run to preview only.");
|
|
344
|
+
}
|
|
345
|
+
if (!process.stdin.isTTY) {
|
|
346
|
+
throw new Error("Refusing to run DDL without explicit authorization: pass --yes for " +
|
|
347
|
+
"non-interactive use, or run in a TTY to confirm.");
|
|
348
|
+
}
|
|
349
|
+
const { ok } = await inquirer.prompt([
|
|
350
|
+
{
|
|
351
|
+
type: "confirm",
|
|
352
|
+
name: "ok",
|
|
353
|
+
message: `Execute ${count} statement(s) against schema '${opts.schema}'? (no automatic rollback)`,
|
|
354
|
+
default: false,
|
|
355
|
+
},
|
|
356
|
+
]);
|
|
357
|
+
return ok;
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=apply-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-schema.js","sourceRoot":"","sources":["../../src/db/apply-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure SQL-file helpers for single-tenant DDL apply (`pxbaas db push` and
|
|
3
|
+
* `pxbaas app db-init`).
|
|
4
|
+
*
|
|
5
|
+
* These functions do NO I/O and NO network — they only transform the text of a
|
|
6
|
+
* schema.sql script so they can be unit-tested in isolation:
|
|
7
|
+
* - substituteSchema: fill the `__SCHEMA__` placeholder templates ship with.
|
|
8
|
+
* - splitSqlStatements: cut a script into individual statements on top-level
|
|
9
|
+
* `;`, correctly ignoring separators that appear inside strings, quoted
|
|
10
|
+
* identifiers, or comments.
|
|
11
|
+
*/
|
|
12
|
+
import type { RlsTableInput, RlsPolicyInput } from "@polardbx/pxbaas-client";
|
|
13
|
+
/** Placeholder that every webapp template's db/schema.sql uses for the target schema. */
|
|
14
|
+
export declare const SCHEMA_PLACEHOLDER = "__SCHEMA__";
|
|
15
|
+
/** True when the script still contains the `__SCHEMA__` placeholder. */
|
|
16
|
+
export declare function hasSchemaPlaceholder(sql: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Replace every `__SCHEMA__` occurrence with the target schema name.
|
|
19
|
+
* Single-tenant instances use `public`; the value is inserted verbatim because
|
|
20
|
+
* it is a database identifier the operator chose (not user free-text).
|
|
21
|
+
*/
|
|
22
|
+
export declare function substituteSchema(sql: string, schema: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Split a SQL script into individual statements on top-level `;`.
|
|
25
|
+
*
|
|
26
|
+
* Semicolons are ignored when they appear inside:
|
|
27
|
+
* - single-quoted strings (`''` is an escaped literal quote)
|
|
28
|
+
* - double-quoted strings (`""` is an escaped literal quote)
|
|
29
|
+
* - backtick-quoted identifiers
|
|
30
|
+
* - `--` / `#` line comments
|
|
31
|
+
* - `/* *\/` block comments
|
|
32
|
+
*
|
|
33
|
+
* Comments are stripped from the returned statements (replaced by a single
|
|
34
|
+
* space) so the plan we show the operator is clean and each element is exactly
|
|
35
|
+
* one executable statement. Empty / comment-only fragments are dropped.
|
|
36
|
+
*
|
|
37
|
+
* This is intentionally a scanner, not a SQL parser: it only needs to find
|
|
38
|
+
* statement boundaries safely for the idempotent scripts our templates ship.
|
|
39
|
+
*/
|
|
40
|
+
export declare function splitSqlStatements(sql: string): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Convenience: substitute the schema placeholder then split into statements.
|
|
43
|
+
* Returns the statements plus whether any placeholder was actually present
|
|
44
|
+
* (so callers can warn when a schema was supplied but the script ignores it).
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildStatementPlan(rawSql: string, schema: string): {
|
|
47
|
+
statements: string[];
|
|
48
|
+
substituted: boolean;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Multi-tenant variant of {@link substituteSchema}: DROP the `__SCHEMA__`.
|
|
52
|
+
* qualifier entirely instead of filling it in. The tenant-ddl connection is
|
|
53
|
+
* already bound to the tenant's own database, and cross-schema fully-qualified
|
|
54
|
+
* names are denied by GRANT / the server pre-check — so `__SCHEMA__`.`t` must
|
|
55
|
+
* become just `t`. The CLI never knows the tenant's real db_name (the resolver
|
|
56
|
+
* does not expose it), so de-qualifying is the only safe substitution.
|
|
57
|
+
*/
|
|
58
|
+
export declare function substituteSchemaForTenant(sql: string): string;
|
|
59
|
+
export interface StatementPartition {
|
|
60
|
+
/** `INSERT ... supabase._mysqlrest_rls_tables` statements. */
|
|
61
|
+
rlsTableInserts: string[];
|
|
62
|
+
/** `INSERT ... supabase._mysqlrest_rls_policies` statements. */
|
|
63
|
+
rlsPolicyInserts: string[];
|
|
64
|
+
/** Everything else (DDL, seed DML) — runs verbatim through the query channel. */
|
|
65
|
+
plain: string[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Split statements into central-registry RLS INSERTs vs. plain DDL/DML. In
|
|
69
|
+
* multi-tenant mode the RLS INSERTs MUST be diverted to the structured
|
|
70
|
+
* `/api/tenant-ddl/rls/*` endpoints (the tenant account has no GRANT on the
|
|
71
|
+
* shared `supabase` database, so a raw INSERT would be denied).
|
|
72
|
+
*/
|
|
73
|
+
export declare function partitionStatements(statements: string[]): StatementPartition;
|
|
74
|
+
/** Thrown when an RLS INSERT does not match the constrained shape we can parse. */
|
|
75
|
+
export declare class SqlParseError extends Error {
|
|
76
|
+
constructor(message: string);
|
|
77
|
+
}
|
|
78
|
+
/** Parse one `_mysqlrest_rls_tables` INSERT into structured inputs (schema dropped). */
|
|
79
|
+
export declare function parseRlsTableInsert(stmt: string): RlsTableInput[];
|
|
80
|
+
/** Parse one `_mysqlrest_rls_policies` INSERT into structured inputs (schema dropped). */
|
|
81
|
+
export declare function parseRlsPolicyInsert(stmt: string): RlsPolicyInput[];
|
|
82
|
+
/** Render an idempotent central-registry INSERT for one RLS table toggle. */
|
|
83
|
+
export declare function renderRlsTableInsert(schema: string, input: RlsTableInput): string;
|
|
84
|
+
/** Render an idempotent central-registry INSERT for one RLS policy. */
|
|
85
|
+
export declare function renderRlsPolicyInsert(schema: string, input: RlsPolicyInput): string;
|
|
86
|
+
/**
|
|
87
|
+
* Extract the table names created by a schema.sql script (for `--purge-db`).
|
|
88
|
+
* Handles `CREATE TABLE [IF NOT EXISTS] [`__SCHEMA__`.]<name>` with optional
|
|
89
|
+
* backticks. Names are returned de-qualified and de-duplicated, in first-seen order.
|
|
90
|
+
*/
|
|
91
|
+
export declare function extractCreateTableNames(sql: string): string[];
|
|
92
|
+
export interface RlsJson {
|
|
93
|
+
tables: RlsTableInput[];
|
|
94
|
+
policies: RlsPolicyInput[];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Parse + validate a declarative `db/rls.json`. Accepts the documented friendly
|
|
98
|
+
* keys (table/name/role/using/check/rlsEnabled/...) and their snake_case aliases,
|
|
99
|
+
* mapping them onto the driver's structured inputs. `table_schema` is NEVER read
|
|
100
|
+
* here — the execution layer decides it (single-tenant = --schema; multi-tenant =
|
|
101
|
+
* server-bound).
|
|
102
|
+
*/
|
|
103
|
+
export declare function parseRlsJson(text: string): RlsJson;
|
|
104
|
+
//# sourceMappingURL=sql-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-file.d.ts","sourceRoot":"","sources":["../../src/db/sql-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE7E,yFAAyF;AACzF,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C,wEAAwE;AACxE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAmHxD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAIhD;AAMD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7D;AAQD,MAAM,WAAW,kBAAkB;IACjC,8DAA8D;IAC9D,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gEAAgE;IAChE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iFAAiF;IACjF,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAU5E;AAED,mFAAmF;AACnF,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AA2ID,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAiBjE;AAED,0FAA0F;AAC1F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CA2BnE;AAaD,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAOjF;AAED,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAYnF;AAGD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAU7D;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAgBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAoDlD"}
|