supaschema 0.1.0-rc.1
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/.agents/skills/supaschema/SKILL.md +61 -0
- package/.claude/hooks/block-generated-migration-edits.mjs +32 -0
- package/.claude/rules/supaschema.md +22 -0
- package/.claude/settings.json +16 -0
- package/.claude/skills/supaschema/SKILL.md +61 -0
- package/.codex/hooks/supaschema-tool-gate.mjs +73 -0
- package/.codex/hooks.json +16 -0
- package/.codex/rules/supaschema.rules +22 -0
- package/AGENTS.md +40 -0
- package/LICENSE +661 -0
- package/LICENSE-COMMERCIAL.md +35 -0
- package/README.md +249 -0
- package/benchmarks/README.md +104 -0
- package/benchmarks/compare.js +489 -0
- package/benchmarks/fixtures/additive/from.sql +8 -0
- package/benchmarks/fixtures/additive/manifest.json +1 -0
- package/benchmarks/fixtures/additive/to.sql +9 -0
- package/benchmarks/fixtures/functions-policies/from.sql +24 -0
- package/benchmarks/fixtures/functions-policies/manifest.json +5 -0
- package/benchmarks/fixtures/functions-policies/to.sql +24 -0
- package/benchmarks/plot-lib.js +234 -0
- package/benchmarks/plot-svg.js +339 -0
- package/benchmarks/plot.js +154 -0
- package/benchmarks/tools/bench-all.sh +49 -0
- package/benchmarks/tools/build-project-fixture.mjs +245 -0
- package/benchmarks/tools/compare-db.mjs +101 -0
- package/benchmarks/tools/compare-fixtures.mjs +84 -0
- package/benchmarks/tools/compare-report.mjs +90 -0
- package/benchmarks/tools/compare-supabase.mjs +67 -0
- package/benchmarks/tools/registry.js +266 -0
- package/benchmarks/tools/run-workflow.mjs +77 -0
- package/bin/postinstall.mjs +26 -0
- package/bin/supaschema +2 -0
- package/config-schema.json +208 -0
- package/corpus/supabase-style/corpus.json +6 -0
- package/corpus/supabase-style/migrations/20260101000000_init.sql +28 -0
- package/corpus/supabase-style/migrations/20260102000000_noise.sql +13 -0
- package/corpus/supabase-style/migrations/20260103000000_churn.sql +4 -0
- package/corpus/supabase-style/migrations/20260104000000_triggers.sql +17 -0
- package/corpus/supabase-style/roles.sql +13 -0
- package/corpus/supabase-style/tree/functions.sql +26 -0
- package/corpus/supabase-style/tree/policies.sql +4 -0
- package/corpus/supabase-style/tree/schema.sql +4 -0
- package/corpus/supabase-style/tree/tables.sql +20 -0
- package/corpus/supabase-style/tree/triggers.sql +3 -0
- package/corpus/supabase-style/tree/types.sql +2 -0
- package/corpus/supabase-style/tree/views.sql +6 -0
- package/dist/audit.d.ts +20 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +68 -0
- package/dist/benchmark-db.d.ts +5 -0
- package/dist/benchmark-db.d.ts.map +1 -0
- package/dist/benchmark-db.js +71 -0
- package/dist/benchmark-fixtures.d.ts +10 -0
- package/dist/benchmark-fixtures.d.ts.map +1 -0
- package/dist/benchmark-fixtures.js +201 -0
- package/dist/benchmark.d.ts +2 -0
- package/dist/benchmark.d.ts.map +1 -0
- package/dist/benchmark.js +308 -0
- package/dist/catalog-comments.d.ts +9 -0
- package/dist/catalog-comments.d.ts.map +1 -0
- package/dist/catalog-comments.js +194 -0
- package/dist/catalog-extras.d.ts +12 -0
- package/dist/catalog-extras.d.ts.map +1 -0
- package/dist/catalog-extras.js +408 -0
- package/dist/catalog-foreign.d.ts +15 -0
- package/dist/catalog-foreign.d.ts.map +1 -0
- package/dist/catalog-foreign.js +114 -0
- package/dist/catalog-tables.d.ts +9 -0
- package/dist/catalog-tables.d.ts.map +1 -0
- package/dist/catalog-tables.js +114 -0
- package/dist/catalog.d.ts +8 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +351 -0
- package/dist/check-hazards.d.ts +7 -0
- package/dist/check-hazards.d.ts.map +1 -0
- package/dist/check-hazards.js +83 -0
- package/dist/check-reporters.d.ts +8 -0
- package/dist/check-reporters.d.ts.map +1 -0
- package/dist/check-reporters.js +76 -0
- package/dist/check.d.ts +3 -0
- package/dist/check.d.ts.map +1 -0
- package/dist/check.js +229 -0
- package/dist/cli-defaults.d.ts +24 -0
- package/dist/cli-defaults.d.ts.map +1 -0
- package/dist/cli-defaults.js +65 -0
- package/dist/cli-diff.d.ts +13 -0
- package/dist/cli-diff.d.ts.map +1 -0
- package/dist/cli-diff.js +348 -0
- package/dist/cli-reports.d.ts +9 -0
- package/dist/cli-reports.d.ts.map +1 -0
- package/dist/cli-reports.js +90 -0
- package/dist/cli-tools.d.ts +17 -0
- package/dist/cli-tools.d.ts.map +1 -0
- package/dist/cli-tools.js +136 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +239 -0
- package/dist/config-schema-gen.d.ts +2 -0
- package/dist/config-schema-gen.d.ts.map +1 -0
- package/dist/config-schema-gen.js +11 -0
- package/dist/config.d.ts +58 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +132 -0
- package/dist/core.d.ts +115 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +1 -0
- package/dist/corpus.d.ts +26 -0
- package/dist/corpus.d.ts.map +1 -0
- package/dist/corpus.js +112 -0
- package/dist/database-url.d.ts +8 -0
- package/dist/database-url.d.ts.map +1 -0
- package/dist/database-url.js +74 -0
- package/dist/db-admin.d.ts +23 -0
- package/dist/db-admin.d.ts.map +1 -0
- package/dist/db-admin.js +147 -0
- package/dist/diagnostics.d.ts +16 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +155 -0
- package/dist/diff-score.d.ts +12 -0
- package/dist/diff-score.d.ts.map +1 -0
- package/dist/diff-score.js +339 -0
- package/dist/doctor.d.ts +17 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +110 -0
- package/dist/hash.d.ts +7 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +34 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/lineage.d.ts +23 -0
- package/dist/lineage.d.ts.map +1 -0
- package/dist/lineage.js +61 -0
- package/dist/migrations-status.d.ts +35 -0
- package/dist/migrations-status.d.ts.map +1 -0
- package/dist/migrations-status.js +131 -0
- package/dist/plan-order.d.ts +4 -0
- package/dist/plan-order.d.ts.map +1 -0
- package/dist/plan-order.js +178 -0
- package/dist/planner-replace.d.ts +4 -0
- package/dist/planner-replace.d.ts.map +1 -0
- package/dist/planner-replace.js +76 -0
- package/dist/planner-table.d.ts +3 -0
- package/dist/planner-table.d.ts.map +1 -0
- package/dist/planner-table.js +165 -0
- package/dist/planner.d.ts +5 -0
- package/dist/planner.d.ts.map +1 -0
- package/dist/planner.js +385 -0
- package/dist/render-guards.d.ts +12 -0
- package/dist/render-guards.d.ts.map +1 -0
- package/dist/render-guards.js +159 -0
- package/dist/render.d.ts +7 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +325 -0
- package/dist/selfcheck.d.ts +11 -0
- package/dist/selfcheck.d.ts.map +1 -0
- package/dist/selfcheck.js +43 -0
- package/dist/source-normalize.d.ts +14 -0
- package/dist/source-normalize.d.ts.map +1 -0
- package/dist/source-normalize.js +420 -0
- package/dist/source.d.ts +4 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +233 -0
- package/dist/sql/ast.d.ts +42 -0
- package/dist/sql/ast.d.ts.map +1 -0
- package/dist/sql/ast.js +241 -0
- package/dist/sql/canonical-nodes.d.ts +5 -0
- package/dist/sql/canonical-nodes.d.ts.map +1 -0
- package/dist/sql/canonical-nodes.js +101 -0
- package/dist/sql/extract-helpers.d.ts +18 -0
- package/dist/sql/extract-helpers.d.ts.map +1 -0
- package/dist/sql/extract-helpers.js +127 -0
- package/dist/sql/extract.d.ts +13 -0
- package/dist/sql/extract.d.ts.map +1 -0
- package/dist/sql/extract.js +323 -0
- package/dist/sql/facts.d.ts +34 -0
- package/dist/sql/facts.d.ts.map +1 -0
- package/dist/sql/facts.js +392 -0
- package/dist/sql/identifiers.d.ts +13 -0
- package/dist/sql/identifiers.d.ts.map +1 -0
- package/dist/sql/identifiers.js +83 -0
- package/dist/sql/normalize-deparse.d.ts +25 -0
- package/dist/sql/normalize-deparse.d.ts.map +1 -0
- package/dist/sql/normalize-deparse.js +96 -0
- package/dist/sql/object-hash.d.ts +5 -0
- package/dist/sql/object-hash.d.ts.map +1 -0
- package/dist/sql/object-hash.js +24 -0
- package/dist/sql/parser.d.ts +8 -0
- package/dist/sql/parser.d.ts.map +1 -0
- package/dist/sql/parser.js +89 -0
- package/dist/sql/privileges.d.ts +33 -0
- package/dist/sql/privileges.d.ts.map +1 -0
- package/dist/sql/privileges.js +379 -0
- package/dist/sql/split.d.ts +3 -0
- package/dist/sql/split.d.ts.map +1 -0
- package/dist/sql/split.js +182 -0
- package/dist/sql/statements.d.ts +17 -0
- package/dist/sql/statements.d.ts.map +1 -0
- package/dist/sql/statements.js +284 -0
- package/dist/sql/table-constraints.d.ts +15 -0
- package/dist/sql/table-constraints.d.ts.map +1 -0
- package/dist/sql/table-constraints.js +304 -0
- package/dist/sql/table-shape.d.ts +38 -0
- package/dist/sql/table-shape.d.ts.map +1 -0
- package/dist/sql/table-shape.js +287 -0
- package/dist/sync.d.ts +27 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +86 -0
- package/dist/typegen-model.d.ts +78 -0
- package/dist/typegen-model.d.ts.map +1 -0
- package/dist/typegen-model.js +338 -0
- package/dist/typegen-views.d.ts +7 -0
- package/dist/typegen-views.d.ts.map +1 -0
- package/dist/typegen-views.js +92 -0
- package/dist/typegen-zod.d.ts +3 -0
- package/dist/typegen-zod.d.ts.map +1 -0
- package/dist/typegen-zod.js +149 -0
- package/dist/typegen.d.ts +4 -0
- package/dist/typegen.d.ts.map +1 -0
- package/dist/typegen.js +184 -0
- package/dist/validators.d.ts +3 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +104 -0
- package/dist/verify-environment.d.ts +5 -0
- package/dist/verify-environment.d.ts.map +1 -0
- package/dist/verify-environment.js +92 -0
- package/dist/verify.d.ts +3 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +261 -0
- package/docs/benchmarks/additive-correctness.svg +86 -0
- package/docs/benchmarks/additive-latency.svg +60 -0
- package/docs/benchmarks/functions-policies-correctness.svg +86 -0
- package/docs/benchmarks/functions-policies-latency.svg +60 -0
- package/docs/benchmarks/realistic-correctness.svg +86 -0
- package/docs/benchmarks/realistic-latency.svg +60 -0
- package/docs/benchmarks/scaling-latency.svg +106 -0
- package/docs/benchmarks/workflow-latency.svg +98 -0
- package/docs/benchmarks/xl-correctness.svg +86 -0
- package/docs/benchmarks/xl-latency.svg +60 -0
- package/docs/benchmarks/xxl-correctness.svg +86 -0
- package/docs/benchmarks/xxl-latency.svg +66 -0
- package/docs/case-study-anilize.md +51 -0
- package/docs/ci-gate.md +44 -0
- package/docs/ci.md +68 -0
- package/docs/commands.md +35 -0
- package/docs/config.md +72 -0
- package/docs/corpus.md +33 -0
- package/docs/diagnostics.md +77 -0
- package/docs/hints.md +92 -0
- package/docs/release.md +19 -0
- package/docs/support-matrix.md +57 -0
- package/examples/postgres/schemas/001_app.sql +17 -0
- package/examples/supabase/schemas/001_app.sql +13 -0
- package/examples/supabase/schemas-next/001_app.sql +21 -0
- package/examples/supabase/supaschema.config.json +15 -0
- package/package.json +99 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { quoteKey } from "./typegen.js";
|
|
2
|
+
import { collectSchemaShapes, resolveColumnType } from "./typegen-model.js";
|
|
3
|
+
export async function generateZodSchemas(model) {
|
|
4
|
+
const shapes = await collectSchemaShapes(model);
|
|
5
|
+
const sortedSchemas = [...shapes.schemas.entries()].sort(([left], [right]) => left.localeCompare(right));
|
|
6
|
+
const enumIdents = buildEnumIdentifiers(sortedSchemas);
|
|
7
|
+
const lines = [
|
|
8
|
+
'import { z } from "zod";',
|
|
9
|
+
"",
|
|
10
|
+
"export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[];",
|
|
11
|
+
"",
|
|
12
|
+
"export const jsonSchema: z.ZodType<Json> = z.lazy(() =>",
|
|
13
|
+
" z.union([",
|
|
14
|
+
" z.string(),",
|
|
15
|
+
" z.number(),",
|
|
16
|
+
" z.boolean(),",
|
|
17
|
+
" z.null(),",
|
|
18
|
+
" z.record(z.string(), z.union([jsonSchema, z.undefined()])),",
|
|
19
|
+
" z.array(jsonSchema),",
|
|
20
|
+
" ]),",
|
|
21
|
+
");",
|
|
22
|
+
"",
|
|
23
|
+
];
|
|
24
|
+
for (const [schemaName, entry] of sortedSchemas) {
|
|
25
|
+
for (const item of [...entry.enums].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
26
|
+
const ident = enumIdents.get(`${schemaName}.${item.name}`);
|
|
27
|
+
if (ident && item.values.length > 0) {
|
|
28
|
+
lines.push(`const ${ident} = z.enum([${item.values.map((value) => JSON.stringify(value)).join(", ")}]);`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
lines.push("");
|
|
33
|
+
lines.push("export const schemas = {");
|
|
34
|
+
for (const [schemaName, entry] of sortedSchemas) {
|
|
35
|
+
const zodFor = (sqlType) => zodExpr(shapes, schemaName, enumIdents, sqlType);
|
|
36
|
+
lines.push(` ${quoteKey(schemaName)}: {`);
|
|
37
|
+
lines.push(" Enums: {");
|
|
38
|
+
for (const item of [...entry.enums].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
39
|
+
const ident = enumIdents.get(`${schemaName}.${item.name}`);
|
|
40
|
+
if (ident && item.values.length > 0) {
|
|
41
|
+
lines.push(` ${quoteKey(item.name)}: ${ident},`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
lines.push(" },");
|
|
45
|
+
lines.push(" Tables: {");
|
|
46
|
+
for (const table of [...entry.tables].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
47
|
+
lines.push(` ${quoteKey(table.name)}: {`);
|
|
48
|
+
lines.push(" Row: z.object({");
|
|
49
|
+
for (const column of table.columns) {
|
|
50
|
+
const base = zodFor(column.type);
|
|
51
|
+
lines.push(` ${quoteKey(column.name)}: ${column.notNull ? base : `${base}.nullable()`},`);
|
|
52
|
+
}
|
|
53
|
+
lines.push(" }),");
|
|
54
|
+
lines.push(" Insert: z.object({");
|
|
55
|
+
for (const column of table.columns) {
|
|
56
|
+
const field = zodInsertField(column, zodFor);
|
|
57
|
+
if (field) {
|
|
58
|
+
lines.push(` ${field}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
lines.push(" }),");
|
|
62
|
+
lines.push(" Update: z.object({");
|
|
63
|
+
for (const column of table.columns) {
|
|
64
|
+
if (column.generated !== undefined || column.identity === "a") {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const base = zodFor(column.type);
|
|
68
|
+
const value = column.notNull ? base : `${base}.nullable()`;
|
|
69
|
+
lines.push(` ${quoteKey(column.name)}: ${value}.optional(),`);
|
|
70
|
+
}
|
|
71
|
+
lines.push(" }),");
|
|
72
|
+
lines.push(" },");
|
|
73
|
+
}
|
|
74
|
+
lines.push(" },");
|
|
75
|
+
lines.push(" Views: {");
|
|
76
|
+
for (const view of [...entry.views].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
77
|
+
lines.push(` ${quoteKey(view.name)}: {`);
|
|
78
|
+
lines.push(" Row: z.object({");
|
|
79
|
+
for (const column of view.columns) {
|
|
80
|
+
lines.push(` ${quoteKey(column.name)}: ${zodFor(column.type)}.nullable(),`);
|
|
81
|
+
}
|
|
82
|
+
lines.push(" }),");
|
|
83
|
+
lines.push(" },");
|
|
84
|
+
}
|
|
85
|
+
lines.push(" },");
|
|
86
|
+
lines.push(" },");
|
|
87
|
+
}
|
|
88
|
+
lines.push("} as const;");
|
|
89
|
+
return `${lines.join("\n")}\n`;
|
|
90
|
+
}
|
|
91
|
+
function buildEnumIdentifiers(schemas) {
|
|
92
|
+
const idents = new Map();
|
|
93
|
+
const used = new Set();
|
|
94
|
+
for (const [schemaName, entry] of schemas) {
|
|
95
|
+
for (const item of entry.enums) {
|
|
96
|
+
let ident = `${sanitizeIdent(schemaName)}_${sanitizeIdent(item.name)}`;
|
|
97
|
+
let suffix = 1;
|
|
98
|
+
while (used.has(ident)) {
|
|
99
|
+
suffix += 1;
|
|
100
|
+
ident = `${sanitizeIdent(schemaName)}_${sanitizeIdent(item.name)}_${suffix}`;
|
|
101
|
+
}
|
|
102
|
+
used.add(ident);
|
|
103
|
+
idents.set(`${schemaName}.${item.name}`, ident);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return idents;
|
|
107
|
+
}
|
|
108
|
+
function sanitizeIdent(value) {
|
|
109
|
+
let result = "";
|
|
110
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
111
|
+
const char = value[index] ?? "";
|
|
112
|
+
const isWord = (char >= "a" && char <= "z") ||
|
|
113
|
+
(char >= "A" && char <= "Z") ||
|
|
114
|
+
(char >= "0" && char <= "9") ||
|
|
115
|
+
char === "_";
|
|
116
|
+
result += isWord ? char : "_";
|
|
117
|
+
}
|
|
118
|
+
const first = result[0] ?? "";
|
|
119
|
+
return first >= "0" && first <= "9" ? `_${result}` : result;
|
|
120
|
+
}
|
|
121
|
+
function zodExpr(shapes, schemaName, enumIdents, sqlType) {
|
|
122
|
+
const resolved = resolveColumnType(shapes, schemaName, sqlType);
|
|
123
|
+
let mapped;
|
|
124
|
+
if (resolved.kind === "enum" && resolved.enumRef) {
|
|
125
|
+
mapped = enumIdents.get(`${resolved.enumRef.schema}.${resolved.enumRef.name}`) ?? "z.unknown()";
|
|
126
|
+
}
|
|
127
|
+
else if (resolved.kind === "json") {
|
|
128
|
+
mapped = "jsonSchema";
|
|
129
|
+
}
|
|
130
|
+
else if (resolved.kind === "unknown") {
|
|
131
|
+
mapped = "z.unknown()";
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
mapped = `z.${resolved.kind}()`;
|
|
135
|
+
}
|
|
136
|
+
for (let depth = 0; depth < resolved.arrayDepth; depth += 1) {
|
|
137
|
+
mapped = `z.array(${mapped})`;
|
|
138
|
+
}
|
|
139
|
+
return mapped;
|
|
140
|
+
}
|
|
141
|
+
function zodInsertField(column, zodFor) {
|
|
142
|
+
if (column.generated !== undefined || column.identity === "a") {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
const base = zodFor(column.type);
|
|
146
|
+
const value = column.notNull ? base : `${base}.nullable()`;
|
|
147
|
+
const optional = !column.notNull || column.default !== undefined || column.identity !== undefined;
|
|
148
|
+
return `${quoteKey(column.name)}: ${optional ? `${value}.optional()` : value},`;
|
|
149
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typegen.d.ts","sourceRoot":"","sources":["../src/typegen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAS7C,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAyE/E;AA0FD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAe7C"}
|
package/dist/typegen.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { collectSchemaShapes, resolveColumnType } from "./typegen-model.js";
|
|
2
|
+
export async function generateDatabaseTypes(model) {
|
|
3
|
+
const shapes = await collectSchemaShapes(model);
|
|
4
|
+
const lines = [
|
|
5
|
+
"export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[];",
|
|
6
|
+
"",
|
|
7
|
+
"export type Database = {",
|
|
8
|
+
];
|
|
9
|
+
const sortedSchemas = [...shapes.schemas.entries()].sort(([left], [right]) => left.localeCompare(right));
|
|
10
|
+
for (const [schemaName, entry] of sortedSchemas) {
|
|
11
|
+
const typeOf = (sqlType) => tsType(shapes, schemaName, sqlType);
|
|
12
|
+
lines.push(` ${quoteKey(schemaName)}: {`);
|
|
13
|
+
lines.push(" Tables: {");
|
|
14
|
+
for (const table of [...entry.tables].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
15
|
+
lines.push(` ${quoteKey(table.name)}: {`);
|
|
16
|
+
lines.push(" Row: {");
|
|
17
|
+
for (const column of table.columns) {
|
|
18
|
+
const base = typeOf(column.type);
|
|
19
|
+
lines.push(` ${quoteKey(column.name)}: ${column.notNull ? base : `${base} | null`};`);
|
|
20
|
+
}
|
|
21
|
+
lines.push(" };");
|
|
22
|
+
lines.push(" Insert: {");
|
|
23
|
+
for (const column of table.columns) {
|
|
24
|
+
lines.push(` ${insertField(column, typeOf)}`);
|
|
25
|
+
}
|
|
26
|
+
lines.push(" };");
|
|
27
|
+
lines.push(" Update: {");
|
|
28
|
+
for (const column of table.columns) {
|
|
29
|
+
lines.push(` ${updateField(column, typeOf)}`);
|
|
30
|
+
}
|
|
31
|
+
lines.push(" };");
|
|
32
|
+
lines.push(` Relationships: ${renderRelationships(table.relationships)};`);
|
|
33
|
+
lines.push(" };");
|
|
34
|
+
}
|
|
35
|
+
lines.push(" };");
|
|
36
|
+
lines.push(" Views: {");
|
|
37
|
+
for (const view of [...entry.views].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
38
|
+
lines.push(` ${quoteKey(view.name)}: {`);
|
|
39
|
+
lines.push(" Row: {");
|
|
40
|
+
for (const column of view.columns) {
|
|
41
|
+
lines.push(` ${quoteKey(column.name)}: ${typeOf(column.type)} | null;`);
|
|
42
|
+
}
|
|
43
|
+
lines.push(" };");
|
|
44
|
+
lines.push(" };");
|
|
45
|
+
}
|
|
46
|
+
lines.push(" };");
|
|
47
|
+
lines.push(" Enums: {");
|
|
48
|
+
for (const item of [...entry.enums].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
49
|
+
const union = item.values.map((value) => JSON.stringify(value)).join(" | ");
|
|
50
|
+
lines.push(` ${quoteKey(item.name)}: ${union.length > 0 ? union : "never"};`);
|
|
51
|
+
}
|
|
52
|
+
lines.push(" };");
|
|
53
|
+
lines.push(" CompositeTypes: {");
|
|
54
|
+
for (const composite of [...entry.composites].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
55
|
+
lines.push(` ${quoteKey(composite.name)}: {`);
|
|
56
|
+
for (const column of composite.columns) {
|
|
57
|
+
lines.push(` ${quoteKey(column.name)}: ${typeOf(column.type)} | null;`);
|
|
58
|
+
}
|
|
59
|
+
lines.push(" };");
|
|
60
|
+
}
|
|
61
|
+
lines.push(" };");
|
|
62
|
+
lines.push(...functionsBlock(entry.functions, typeOf));
|
|
63
|
+
lines.push(" };");
|
|
64
|
+
}
|
|
65
|
+
lines.push("};");
|
|
66
|
+
lines.push("");
|
|
67
|
+
lines.push(...helperBlock());
|
|
68
|
+
lines.push("");
|
|
69
|
+
lines.push(...constantsBlock(sortedSchemas));
|
|
70
|
+
return `${lines.join("\n")}\n`;
|
|
71
|
+
}
|
|
72
|
+
function tsType(shapes, schemaName, sqlType) {
|
|
73
|
+
const resolved = resolveColumnType(shapes, schemaName, sqlType);
|
|
74
|
+
let mapped;
|
|
75
|
+
if (resolved.kind === "enum" && resolved.enumRef) {
|
|
76
|
+
mapped = `Database["${resolved.enumRef.schema}"]["Enums"]["${resolved.enumRef.name}"]`;
|
|
77
|
+
}
|
|
78
|
+
else if (resolved.kind === "json") {
|
|
79
|
+
mapped = "Json";
|
|
80
|
+
}
|
|
81
|
+
else if (resolved.kind === "unknown") {
|
|
82
|
+
mapped = "unknown";
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
mapped = resolved.kind;
|
|
86
|
+
}
|
|
87
|
+
return mapped + "[]".repeat(resolved.arrayDepth);
|
|
88
|
+
}
|
|
89
|
+
function insertField(column, typeOf) {
|
|
90
|
+
if (column.generated !== undefined || column.identity === "a") {
|
|
91
|
+
return `${quoteKey(column.name)}?: never;`;
|
|
92
|
+
}
|
|
93
|
+
const base = typeOf(column.type);
|
|
94
|
+
const type = column.notNull ? base : `${base} | null`;
|
|
95
|
+
const optional = !column.notNull || column.default !== undefined || column.identity !== undefined;
|
|
96
|
+
return `${quoteKey(column.name)}${optional ? "?" : ""}: ${type};`;
|
|
97
|
+
}
|
|
98
|
+
function updateField(column, typeOf) {
|
|
99
|
+
if (column.generated !== undefined || column.identity === "a") {
|
|
100
|
+
return `${quoteKey(column.name)}?: never;`;
|
|
101
|
+
}
|
|
102
|
+
const base = typeOf(column.type);
|
|
103
|
+
return `${quoteKey(column.name)}?: ${column.notNull ? base : `${base} | null`};`;
|
|
104
|
+
}
|
|
105
|
+
function functionsBlock(functions, typeOf) {
|
|
106
|
+
const grouped = new Map();
|
|
107
|
+
for (const fn of functions) {
|
|
108
|
+
const overloads = grouped.get(fn.name) ?? [];
|
|
109
|
+
overloads.push(fn);
|
|
110
|
+
grouped.set(fn.name, overloads);
|
|
111
|
+
}
|
|
112
|
+
if (grouped.size === 0) {
|
|
113
|
+
return [" Functions: { [_ in never]: never };"];
|
|
114
|
+
}
|
|
115
|
+
const lines = [" Functions: {"];
|
|
116
|
+
for (const [name, overloads] of [...grouped.entries()].sort(([left], [right]) => left.localeCompare(right))) {
|
|
117
|
+
const argVariants = sortedUnique(overloads.map((fn) => renderFunctionArgs(fn, typeOf)));
|
|
118
|
+
const returnVariants = sortedUnique(overloads.map((fn) => renderFunctionReturns(fn, typeOf)));
|
|
119
|
+
lines.push(` ${quoteKey(name)}: { Args: ${argVariants.join(" | ")}; Returns: ${returnVariants.join(" | ")} };`);
|
|
120
|
+
}
|
|
121
|
+
lines.push(" };");
|
|
122
|
+
return lines;
|
|
123
|
+
}
|
|
124
|
+
function renderFunctionArgs(fn, typeOf) {
|
|
125
|
+
const args = fn.args
|
|
126
|
+
.map((arg) => `${quoteKey(arg.name)}${arg.optional ? "?" : ""}: ${typeOf(arg.type)}`)
|
|
127
|
+
.join("; ");
|
|
128
|
+
return args.length > 0 ? `{ ${args} }` : "Record<PropertyKey, never>";
|
|
129
|
+
}
|
|
130
|
+
function renderFunctionReturns(fn, typeOf) {
|
|
131
|
+
const base = fn.returns ? typeOf(fn.returns.type) : "unknown";
|
|
132
|
+
return fn.returns?.setof ? `${base}[]` : base;
|
|
133
|
+
}
|
|
134
|
+
function sortedUnique(values) {
|
|
135
|
+
return [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
136
|
+
}
|
|
137
|
+
function renderRelationships(relationships) {
|
|
138
|
+
if (relationships.length === 0) {
|
|
139
|
+
return "[]";
|
|
140
|
+
}
|
|
141
|
+
const items = relationships.map((item) => `{ foreignKeyName: ${JSON.stringify(item.foreignKeyName)}; columns: ${tupleType(item.columns)}; isOneToOne: ${item.isOneToOne}; referencedRelation: ${JSON.stringify(item.referencedRelation)}; referencedColumns: ${tupleType(item.referencedColumns)} }`);
|
|
142
|
+
return `[${items.join(", ")}]`;
|
|
143
|
+
}
|
|
144
|
+
function tupleType(values) {
|
|
145
|
+
return `[${values.map((value) => JSON.stringify(value)).join(", ")}]`;
|
|
146
|
+
}
|
|
147
|
+
export function quoteKey(name) {
|
|
148
|
+
let simple = name.length > 0;
|
|
149
|
+
for (let index = 0; index < name.length; index += 1) {
|
|
150
|
+
const char = name[index] ?? "";
|
|
151
|
+
const isWord = (char >= "a" && char <= "z") ||
|
|
152
|
+
(char >= "A" && char <= "Z") ||
|
|
153
|
+
char === "_" ||
|
|
154
|
+
(index > 0 && char >= "0" && char <= "9");
|
|
155
|
+
if (!isWord) {
|
|
156
|
+
simple = false;
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return simple ? name : JSON.stringify(name);
|
|
161
|
+
}
|
|
162
|
+
function helperBlock() {
|
|
163
|
+
return [
|
|
164
|
+
'export type Tables<S extends keyof Database, T extends keyof Database[S]["Tables"]> = Database[S]["Tables"][T] extends { Row: infer R } ? R : never;',
|
|
165
|
+
'export type TablesInsert<S extends keyof Database, T extends keyof Database[S]["Tables"]> = Database[S]["Tables"][T] extends { Insert: infer I } ? I : never;',
|
|
166
|
+
'export type TablesUpdate<S extends keyof Database, T extends keyof Database[S]["Tables"]> = Database[S]["Tables"][T] extends { Update: infer U } ? U : never;',
|
|
167
|
+
'export type Views<S extends keyof Database, V extends keyof Database[S]["Views"]> = Database[S]["Views"][V] extends { Row: infer R } ? R : never;',
|
|
168
|
+
'export type Enums<S extends keyof Database, E extends keyof Database[S]["Enums"]> = Database[S]["Enums"][E];',
|
|
169
|
+
];
|
|
170
|
+
}
|
|
171
|
+
function constantsBlock(schemas) {
|
|
172
|
+
const lines = ["export const Constants = {"];
|
|
173
|
+
for (const [schemaName, entry] of schemas) {
|
|
174
|
+
lines.push(` ${quoteKey(schemaName)}: {`);
|
|
175
|
+
lines.push(" Enums: {");
|
|
176
|
+
for (const item of [...entry.enums].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
177
|
+
lines.push(` ${quoteKey(item.name)}: [${item.values.map((value) => JSON.stringify(value)).join(", ")}],`);
|
|
178
|
+
}
|
|
179
|
+
lines.push(" },");
|
|
180
|
+
lines.push(" },");
|
|
181
|
+
}
|
|
182
|
+
lines.push("} as const;");
|
|
183
|
+
return lines;
|
|
184
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAgB1D,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,UAAU,EAAE,CAAC,CA6BvB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { resolveConfig } from "./config.js";
|
|
7
|
+
import { diagnostic } from "./diagnostics.js";
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
export async function runConfiguredValidators(sql, options = {}) {
|
|
10
|
+
const config = resolveConfig(options.config);
|
|
11
|
+
const externalValidators = config.validators.filter((validator) => validator !== "internal-parser");
|
|
12
|
+
if (externalValidators.length === 0) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
const diagnostics = [];
|
|
16
|
+
const tempRoot = await mkdtemp(join(tmpdir(), "supaschema-"));
|
|
17
|
+
const tempFile = join(tempRoot, "migration.sql");
|
|
18
|
+
try {
|
|
19
|
+
await writeFile(tempFile, sql);
|
|
20
|
+
for (const validator of externalValidators) {
|
|
21
|
+
const spec = validatorSpec(validator);
|
|
22
|
+
if (!spec) {
|
|
23
|
+
diagnostics.push(diagnostic("SUPA_VALIDATOR_UNKNOWN", "error", `unknown validator "${validator}"`, {
|
|
24
|
+
hint: "Supported validators: internal-parser, squawk, squawk-cli, pgls, postgres-language-server, sqlfluff, pg-formatter.",
|
|
25
|
+
}));
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
diagnostics.push(...(await runValidator(validator, spec, tempFile, options.cwd)));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
await rm(tempRoot, { force: true, recursive: true }).catch(() => undefined);
|
|
33
|
+
}
|
|
34
|
+
return diagnostics;
|
|
35
|
+
}
|
|
36
|
+
function validatorSpec(name) {
|
|
37
|
+
switch (name) {
|
|
38
|
+
case "squawk":
|
|
39
|
+
case "squawk-cli":
|
|
40
|
+
return { args: [], command: "squawk" };
|
|
41
|
+
case "pgls":
|
|
42
|
+
case "@postgres-language-server/cli":
|
|
43
|
+
case "postgres-language-server":
|
|
44
|
+
return {
|
|
45
|
+
args: [
|
|
46
|
+
"check",
|
|
47
|
+
"--disable-db",
|
|
48
|
+
"--reporter=summary",
|
|
49
|
+
"--max-diagnostics=none",
|
|
50
|
+
"--no-errors-on-unmatched",
|
|
51
|
+
],
|
|
52
|
+
command: "postgres-language-server",
|
|
53
|
+
};
|
|
54
|
+
case "sqlfluff":
|
|
55
|
+
return { args: ["lint", "--dialect", "postgres"], command: "sqlfluff" };
|
|
56
|
+
case "pg-formatter":
|
|
57
|
+
case "pgformatter":
|
|
58
|
+
return { args: ["--check"], command: "pg-formatter" };
|
|
59
|
+
default:
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function runValidator(name, spec, path, cwd = process.cwd()) {
|
|
64
|
+
try {
|
|
65
|
+
await execFileAsync(spec.command, [...spec.args, path], {
|
|
66
|
+
cwd,
|
|
67
|
+
maxBuffer: 1024 * 1024 * 10,
|
|
68
|
+
timeout: 30_000,
|
|
69
|
+
});
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (isMissingExecutable(error)) {
|
|
74
|
+
return [
|
|
75
|
+
diagnostic("SUPA_VALIDATOR_UNAVAILABLE", "error", `validator "${name}" is not available`, {
|
|
76
|
+
hint: `Install the validator or remove "${name}" from validators.`,
|
|
77
|
+
}),
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
return [
|
|
81
|
+
diagnostic("SUPA_VALIDATOR_FAILED", "error", `validator "${name}" reported diagnostics`, {
|
|
82
|
+
hint: commandOutput(error),
|
|
83
|
+
}),
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function isMissingExecutable(error) {
|
|
88
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
89
|
+
}
|
|
90
|
+
function commandOutput(error) {
|
|
91
|
+
if (!error || typeof error !== "object") {
|
|
92
|
+
return String(error);
|
|
93
|
+
}
|
|
94
|
+
const output = [readStringProperty(error, "stdout"), readStringProperty(error, "stderr")]
|
|
95
|
+
.filter((value) => value.length > 0)
|
|
96
|
+
.join("\n")
|
|
97
|
+
.trim();
|
|
98
|
+
return output.length > 0 ? output.slice(0, 2000) : String(error);
|
|
99
|
+
}
|
|
100
|
+
function readStringProperty(value, property) {
|
|
101
|
+
const record = value;
|
|
102
|
+
const output = record[property];
|
|
103
|
+
return typeof output === "string" ? output : "";
|
|
104
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Client } from "pg";
|
|
2
|
+
import type { Diagnostic } from "./core.js";
|
|
3
|
+
export declare function preflightCapability(admin: Client): Promise<Diagnostic | undefined>;
|
|
4
|
+
export declare const supabaseEnvironmentStubSql = "\nCREATE SCHEMA IF NOT EXISTS auth;\nCREATE TABLE IF NOT EXISTS auth.users (\n instance_id uuid,\n id uuid PRIMARY KEY,\n aud varchar(255),\n role varchar(255),\n email varchar(255),\n encrypted_password varchar(255),\n email_confirmed_at timestamptz,\n invited_at timestamptz,\n confirmation_token varchar(255),\n confirmation_sent_at timestamptz,\n recovery_token varchar(255),\n recovery_sent_at timestamptz,\n email_change_token_new varchar(255),\n email_change varchar(255),\n email_change_sent_at timestamptz,\n last_sign_in_at timestamptz,\n raw_app_meta_data jsonb,\n raw_user_meta_data jsonb,\n is_super_admin boolean,\n created_at timestamptz DEFAULT now(),\n updated_at timestamptz,\n phone text,\n phone_confirmed_at timestamptz,\n phone_change text,\n phone_change_token varchar(255),\n phone_change_sent_at timestamptz,\n confirmed_at timestamptz,\n email_change_token_current varchar(255),\n email_change_confirm_status smallint,\n banned_until timestamptz,\n reauthentication_token varchar(255),\n reauthentication_sent_at timestamptz,\n is_sso_user boolean DEFAULT false,\n deleted_at timestamptz,\n is_anonymous boolean DEFAULT false\n);\nCREATE OR REPLACE FUNCTION auth.uid() RETURNS uuid LANGUAGE sql STABLE AS $$\n SELECT nullif(current_setting('request.jwt.claim.sub', true), '')::uuid\n$$;\nCREATE OR REPLACE FUNCTION auth.role() RETURNS text LANGUAGE sql STABLE AS $$\n SELECT coalesce(nullif(current_setting('request.jwt.claim.role', true), ''), 'anon')\n$$;\nCREATE OR REPLACE FUNCTION auth.jwt() RETURNS jsonb LANGUAGE sql STABLE AS $$\n SELECT coalesce(nullif(current_setting('request.jwt.claims', true), ''), '{}')::jsonb\n$$;\nCREATE OR REPLACE FUNCTION auth.email() RETURNS text LANGUAGE sql STABLE AS $$\n SELECT nullif(current_setting('request.jwt.claim.email', true), '')\n$$;\nCREATE SCHEMA IF NOT EXISTS cron;\nCREATE TABLE IF NOT EXISTS cron.job (\n jobid bigint PRIMARY KEY,\n schedule text,\n command text,\n nodename text,\n nodeport integer,\n database text,\n username text,\n active boolean DEFAULT true,\n jobname text\n);\nCREATE TABLE IF NOT EXISTS cron.job_run_details (\n jobid bigint,\n runid bigint PRIMARY KEY,\n job_pid integer,\n database text,\n username text,\n command text,\n status text,\n return_message text,\n start_time timestamptz,\n end_time timestamptz\n);\n";
|
|
5
|
+
//# sourceMappingURL=verify-environment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-environment.d.ts","sourceRoot":"","sources":["../src/verify-environment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAexF;AAQD,eAAO,MAAM,0BAA0B,k1EA2EtC,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { diagnostic } from "./diagnostics.js";
|
|
2
|
+
export async function preflightCapability(admin) {
|
|
3
|
+
const result = await admin.query("SELECT (rolcreatedb OR rolsuper) AS can_create FROM pg_catalog.pg_roles WHERE rolname = current_user");
|
|
4
|
+
if (result.rows[0]?.can_create === true) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
return diagnostic("SUPA_VERIFY_ROLE_CAPABILITY", "error", "the verification role cannot CREATE DATABASE", {
|
|
8
|
+
hint: "Use a role with CREATEDB. On a local Supabase stack, `postgres` lacks superuser for many extensions too — prefer `supabase_admin` (postgresql://supabase_admin:postgres@127.0.0.1:<db.port>/postgres).",
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
// The stub mirrors the stable GoTrue auth.users column set so that RLS
|
|
12
|
+
// policies, foreign keys, and views referencing auth.users columns
|
|
13
|
+
// (role, email, phone, raw_app_meta_data, ...) resolve during verify
|
|
14
|
+
// instead of failing with a false-negative undefined-column error. auth
|
|
15
|
+
// is a managed schema, so user trees only reference it; a wider stub is
|
|
16
|
+
// pure reference-resolution benefit and is subtracted from reconvergence.
|
|
17
|
+
export const supabaseEnvironmentStubSql = `
|
|
18
|
+
CREATE SCHEMA IF NOT EXISTS auth;
|
|
19
|
+
CREATE TABLE IF NOT EXISTS auth.users (
|
|
20
|
+
instance_id uuid,
|
|
21
|
+
id uuid PRIMARY KEY,
|
|
22
|
+
aud varchar(255),
|
|
23
|
+
role varchar(255),
|
|
24
|
+
email varchar(255),
|
|
25
|
+
encrypted_password varchar(255),
|
|
26
|
+
email_confirmed_at timestamptz,
|
|
27
|
+
invited_at timestamptz,
|
|
28
|
+
confirmation_token varchar(255),
|
|
29
|
+
confirmation_sent_at timestamptz,
|
|
30
|
+
recovery_token varchar(255),
|
|
31
|
+
recovery_sent_at timestamptz,
|
|
32
|
+
email_change_token_new varchar(255),
|
|
33
|
+
email_change varchar(255),
|
|
34
|
+
email_change_sent_at timestamptz,
|
|
35
|
+
last_sign_in_at timestamptz,
|
|
36
|
+
raw_app_meta_data jsonb,
|
|
37
|
+
raw_user_meta_data jsonb,
|
|
38
|
+
is_super_admin boolean,
|
|
39
|
+
created_at timestamptz DEFAULT now(),
|
|
40
|
+
updated_at timestamptz,
|
|
41
|
+
phone text,
|
|
42
|
+
phone_confirmed_at timestamptz,
|
|
43
|
+
phone_change text,
|
|
44
|
+
phone_change_token varchar(255),
|
|
45
|
+
phone_change_sent_at timestamptz,
|
|
46
|
+
confirmed_at timestamptz,
|
|
47
|
+
email_change_token_current varchar(255),
|
|
48
|
+
email_change_confirm_status smallint,
|
|
49
|
+
banned_until timestamptz,
|
|
50
|
+
reauthentication_token varchar(255),
|
|
51
|
+
reauthentication_sent_at timestamptz,
|
|
52
|
+
is_sso_user boolean DEFAULT false,
|
|
53
|
+
deleted_at timestamptz,
|
|
54
|
+
is_anonymous boolean DEFAULT false
|
|
55
|
+
);
|
|
56
|
+
CREATE OR REPLACE FUNCTION auth.uid() RETURNS uuid LANGUAGE sql STABLE AS $$
|
|
57
|
+
SELECT nullif(current_setting('request.jwt.claim.sub', true), '')::uuid
|
|
58
|
+
$$;
|
|
59
|
+
CREATE OR REPLACE FUNCTION auth.role() RETURNS text LANGUAGE sql STABLE AS $$
|
|
60
|
+
SELECT coalesce(nullif(current_setting('request.jwt.claim.role', true), ''), 'anon')
|
|
61
|
+
$$;
|
|
62
|
+
CREATE OR REPLACE FUNCTION auth.jwt() RETURNS jsonb LANGUAGE sql STABLE AS $$
|
|
63
|
+
SELECT coalesce(nullif(current_setting('request.jwt.claims', true), ''), '{}')::jsonb
|
|
64
|
+
$$;
|
|
65
|
+
CREATE OR REPLACE FUNCTION auth.email() RETURNS text LANGUAGE sql STABLE AS $$
|
|
66
|
+
SELECT nullif(current_setting('request.jwt.claim.email', true), '')
|
|
67
|
+
$$;
|
|
68
|
+
CREATE SCHEMA IF NOT EXISTS cron;
|
|
69
|
+
CREATE TABLE IF NOT EXISTS cron.job (
|
|
70
|
+
jobid bigint PRIMARY KEY,
|
|
71
|
+
schedule text,
|
|
72
|
+
command text,
|
|
73
|
+
nodename text,
|
|
74
|
+
nodeport integer,
|
|
75
|
+
database text,
|
|
76
|
+
username text,
|
|
77
|
+
active boolean DEFAULT true,
|
|
78
|
+
jobname text
|
|
79
|
+
);
|
|
80
|
+
CREATE TABLE IF NOT EXISTS cron.job_run_details (
|
|
81
|
+
jobid bigint,
|
|
82
|
+
runid bigint PRIMARY KEY,
|
|
83
|
+
job_pid integer,
|
|
84
|
+
database text,
|
|
85
|
+
username text,
|
|
86
|
+
command text,
|
|
87
|
+
status text,
|
|
88
|
+
return_message text,
|
|
89
|
+
start_time timestamptz,
|
|
90
|
+
end_time timestamptz
|
|
91
|
+
);
|
|
92
|
+
`;
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAA+B,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAkBjG,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA8K5F"}
|