@supawatch/target-supabase-types 0.7.1 → 0.9.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/dist/index.js +41 -29
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -20,6 +20,8 @@ function tsType(runtime, jsonRef) {
|
|
|
20
20
|
return el.includes("|") ? `(${el})[]` : `${el}[]`;
|
|
21
21
|
}
|
|
22
22
|
case "enum":
|
|
23
|
+
if (runtime.labels.length === 0)
|
|
24
|
+
return "never";
|
|
23
25
|
return runtime.labels.map((l) => JSON.stringify(l)).join(" | ");
|
|
24
26
|
}
|
|
25
27
|
}
|
|
@@ -30,14 +32,6 @@ function bridgeRuntime(col, snapshot) {
|
|
|
30
32
|
if (col.runtime.kind === "array") {
|
|
31
33
|
return arrayRuntimeFor(runtimeFromName(col.runtime.element, snapshot), 1, "supabase-js");
|
|
32
34
|
}
|
|
33
|
-
if (col.runtime.kind === "string" && col.runtime.format === "array-literal") {
|
|
34
|
-
// postgres-js collapses enum arrays to a raw literal; PostgREST
|
|
35
|
-
// parses them. Recover the element labels via the enum reference.
|
|
36
|
-
const e = snapshot.enums.find((x) => x.name === col.enumRef);
|
|
37
|
-
if (e) {
|
|
38
|
-
return { kind: "array", element: { kind: "enum", labels: e.labels } };
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
35
|
return runtimeFor(col.pgTypeName, kindOf(col, snapshot), { enums: snapshot.enums }, "supabase-js");
|
|
42
36
|
}
|
|
43
37
|
function kindOf(col, snapshot) {
|
|
@@ -50,6 +44,11 @@ function kindOf(col, snapshot) {
|
|
|
50
44
|
function runtimeFromName(element, _snapshot) {
|
|
51
45
|
return element;
|
|
52
46
|
}
|
|
47
|
+
// Database identifiers are free-form ("Order Log", "café", "select");
|
|
48
|
+
// quote any key that is not a plain TS identifier.
|
|
49
|
+
function tsKey(name) {
|
|
50
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
51
|
+
}
|
|
53
52
|
function writableColumns(table) {
|
|
54
53
|
return table.columns.filter((c) => !c.generated && c.identity !== "always");
|
|
55
54
|
}
|
|
@@ -61,7 +60,7 @@ function fieldLine(col, snapshot, optional, indent) {
|
|
|
61
60
|
let t = tsType(runtime, "Json");
|
|
62
61
|
if (col.nullable && t !== "unknown")
|
|
63
62
|
t = `${t} | null`;
|
|
64
|
-
return `${indent}${col.name}${optional ? "?" : ""}: ${t}`;
|
|
63
|
+
return `${indent}${tsKey(col.name)}${optional ? "?" : ""}: ${t}`;
|
|
65
64
|
}
|
|
66
65
|
export class SupabaseTypesTarget {
|
|
67
66
|
name = "supabase-types";
|
|
@@ -89,14 +88,15 @@ export class SupabaseTypesTarget {
|
|
|
89
88
|
"export interface Database {",
|
|
90
89
|
];
|
|
91
90
|
for (const schema of schemas) {
|
|
92
|
-
|
|
91
|
+
// PostgREST exposes foreign tables beside plain ones.
|
|
92
|
+
const tables = snapshot.tables.filter((t) => t.schema === schema && t.kind !== "view");
|
|
93
93
|
const views = snapshot.tables.filter((t) => t.schema === schema && t.kind === "view");
|
|
94
94
|
const enums = snapshot.enums.filter((e) => e.schema === schema);
|
|
95
95
|
const composites = snapshot.composites.filter((c) => c.schema === schema);
|
|
96
|
-
lines.push(` ${schema}: {`);
|
|
96
|
+
lines.push(` ${tsKey(schema)}: {`);
|
|
97
97
|
lines.push(" Tables: {");
|
|
98
98
|
for (const table of tables) {
|
|
99
|
-
lines.push(` ${table.name}: {`);
|
|
99
|
+
lines.push(` ${tsKey(table.name)}: {`);
|
|
100
100
|
lines.push(" Row: {");
|
|
101
101
|
for (const col of table.columns) {
|
|
102
102
|
lines.push(fieldLine(col, snapshot, false, " ") + ";");
|
|
@@ -128,7 +128,7 @@ export class SupabaseTypesTarget {
|
|
|
128
128
|
lines.push(" };");
|
|
129
129
|
lines.push(" Views: {");
|
|
130
130
|
for (const view of views) {
|
|
131
|
-
lines.push(` ${view.name}: {`);
|
|
131
|
+
lines.push(` ${tsKey(view.name)}: {`);
|
|
132
132
|
lines.push(" Row: {");
|
|
133
133
|
for (const col of view.columns) {
|
|
134
134
|
lines.push(fieldLine(col, snapshot, false, " ") + ";");
|
|
@@ -143,36 +143,48 @@ export class SupabaseTypesTarget {
|
|
|
143
143
|
}
|
|
144
144
|
else {
|
|
145
145
|
lines.push(" Functions: {");
|
|
146
|
+
// Overloaded names share one key: Args and Returns become unions
|
|
147
|
+
// of the signatures, never duplicate keys (invalid TS).
|
|
148
|
+
const byName = new Map();
|
|
146
149
|
for (const fn of fns) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
const group = byName.get(fn.name) ?? [];
|
|
151
|
+
group.push(fn);
|
|
152
|
+
byName.set(fn.name, group);
|
|
153
|
+
}
|
|
154
|
+
for (const [name, group] of byName) {
|
|
155
|
+
const argShapes = group.map((fn) => {
|
|
156
|
+
if (fn.args.length === 0)
|
|
157
|
+
return "Record<string, never>";
|
|
158
|
+
const fields = fn.args.map((arg) => {
|
|
154
159
|
const t = tsType(runtimeFor(arg.pgTypeName, "b", { enums: snapshot.enums }, "supabase-js"), "Json");
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
const
|
|
160
|
-
|
|
160
|
+
return `${tsKey(arg.name)}${arg.hasDefault ? "?" : ""}: ${t}`;
|
|
161
|
+
});
|
|
162
|
+
return `{ ${fields.join("; ")} }`;
|
|
163
|
+
});
|
|
164
|
+
const returnShapes = [
|
|
165
|
+
...new Set(group.map((fn) => {
|
|
166
|
+
const ret = tsType(runtimeFor(fn.returns.pgTypeName, "b", { enums: snapshot.enums }, "supabase-js"), "Json");
|
|
167
|
+
return fn.returns.isSet ? `(${ret})[]` : ret;
|
|
168
|
+
})),
|
|
169
|
+
];
|
|
170
|
+
lines.push(` ${tsKey(name)}: {`);
|
|
171
|
+
lines.push(` Args: ${[...new Set(argShapes)].join(" | ")};`);
|
|
172
|
+
lines.push(` Returns: ${returnShapes.join(" | ")};`);
|
|
161
173
|
lines.push(" };");
|
|
162
174
|
}
|
|
163
175
|
lines.push(" };");
|
|
164
176
|
}
|
|
165
177
|
lines.push(" Enums: {");
|
|
166
178
|
for (const e of enums) {
|
|
167
|
-
lines.push(` ${e.name}: ${e.labels.map((l) => JSON.stringify(l)).join(" | ")};`);
|
|
179
|
+
lines.push(` ${tsKey(e.name)}: ${e.labels.length === 0 ? "never" : e.labels.map((l) => JSON.stringify(l)).join(" | ")};`);
|
|
168
180
|
}
|
|
169
181
|
lines.push(" };");
|
|
170
182
|
lines.push(" CompositeTypes: {");
|
|
171
183
|
for (const c of composites) {
|
|
172
|
-
lines.push(` ${c.name}: {`);
|
|
184
|
+
lines.push(` ${tsKey(c.name)}: {`);
|
|
173
185
|
for (const f of c.fields) {
|
|
174
186
|
const t = tsType(f.runtime, "Json");
|
|
175
|
-
lines.push(` ${f.name}: ${t} | null;`);
|
|
187
|
+
lines.push(` ${tsKey(f.name)}: ${t} | null;`);
|
|
176
188
|
}
|
|
177
189
|
lines.push(" };");
|
|
178
190
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supawatch/target-supabase-types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "A supabase-js compatible Database interface generated from live Postgres by supawatch, foreign-key relationships included.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"supabase",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dist"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@supawatch/core": "0.
|
|
36
|
+
"@supawatch/core": "0.9.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^22.20.1",
|