@supabase/postgrest-typegen 0.0.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/LICENSE +21 -0
- package/README.md +133 -0
- package/dist/generation/constants.d.ts +9 -0
- package/dist/generation/constants.js +10 -0
- package/dist/generation/go.d.ts +6 -0
- package/dist/generation/go.js +233 -0
- package/dist/generation/index.d.ts +5 -0
- package/dist/generation/index.js +5 -0
- package/dist/generation/python.d.ts +6 -0
- package/dist/generation/python.js +339 -0
- package/dist/generation/swift.d.ts +11 -0
- package/dist/generation/swift.js +309 -0
- package/dist/generation/typescript.d.ts +32 -0
- package/dist/generation/typescript.js +796 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/introspection/index.d.ts +27 -0
- package/dist/introspection/index.js +70 -0
- package/dist/introspection/normalize.d.ts +31 -0
- package/dist/introspection/normalize.js +65 -0
- package/dist/introspection/relationships.d.ts +47 -0
- package/dist/introspection/relationships.js +85 -0
- package/dist/introspection/sql/columns.sql.d.ts +7 -0
- package/dist/introspection/sql/columns.sql.js +122 -0
- package/dist/introspection/sql/common.d.ts +16 -0
- package/dist/introspection/sql/common.js +1 -0
- package/dist/introspection/sql/foreign_tables.sql.d.ts +6 -0
- package/dist/introspection/sql/foreign_tables.sql.js +18 -0
- package/dist/introspection/sql/functions.sql.d.ts +5 -0
- package/dist/introspection/sql/functions.sql.js +148 -0
- package/dist/introspection/sql/helpers.d.ts +12 -0
- package/dist/introspection/sql/helpers.js +28 -0
- package/dist/introspection/sql/materialized_views.sql.d.ts +4 -0
- package/dist/introspection/sql/materialized_views.sql.js +19 -0
- package/dist/introspection/sql/primary_keys.sql.d.ts +4 -0
- package/dist/introspection/sql/primary_keys.sql.js +32 -0
- package/dist/introspection/sql/schemas.sql.d.ts +6 -0
- package/dist/introspection/sql/schemas.sql.js +24 -0
- package/dist/introspection/sql/table.sql.d.ts +4 -0
- package/dist/introspection/sql/table.sql.js +41 -0
- package/dist/introspection/sql/table_relationships.sql.d.ts +2 -0
- package/dist/introspection/sql/table_relationships.sql.js +49 -0
- package/dist/introspection/sql/types.sql.d.ts +5 -0
- package/dist/introspection/sql/types.sql.js +65 -0
- package/dist/introspection/sql/views.sql.d.ts +4 -0
- package/dist/introspection/sql/views.sql.js +20 -0
- package/dist/introspection/sql/views_key_dependencies.sql.d.ts +2 -0
- package/dist/introspection/sql/views_key_dependencies.sql.js +195 -0
- package/dist/sort.d.ts +35 -0
- package/dist/sort.js +48 -0
- package/dist/types.d.ts +372 -0
- package/dist/types.js +207 -0
- package/package.json +87 -0
- package/src/generation/constants.ts +11 -0
- package/src/generation/go.ts +356 -0
- package/src/generation/index.ts +13 -0
- package/src/generation/python.ts +461 -0
- package/src/generation/swift.ts +481 -0
- package/src/generation/typescript.ts +1144 -0
- package/src/index.ts +4 -0
- package/src/introspection/index.ts +124 -0
- package/src/introspection/normalize.ts +71 -0
- package/src/introspection/relationships.ts +173 -0
- package/src/introspection/sql/columns.sql.ts +131 -0
- package/src/introspection/sql/common.ts +18 -0
- package/src/introspection/sql/foreign_tables.sql.ts +26 -0
- package/src/introspection/sql/functions.sql.ts +159 -0
- package/src/introspection/sql/helpers.ts +33 -0
- package/src/introspection/sql/materialized_views.sql.ts +25 -0
- package/src/introspection/sql/primary_keys.sql.ts +38 -0
- package/src/introspection/sql/schemas.sql.ts +32 -0
- package/src/introspection/sql/table.sql.ts +47 -0
- package/src/introspection/sql/table_relationships.sql.ts +53 -0
- package/src/introspection/sql/types.sql.ts +74 -0
- package/src/introspection/sql/views.sql.ts +26 -0
- package/src/introspection/sql/views_key_dependencies.sql.ts +199 -0
- package/src/sort.ts +102 -0
- package/src/types.ts +237 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
GeneratorMetadata,
|
|
3
|
+
PostgresColumn,
|
|
4
|
+
PostgresMaterializedView,
|
|
5
|
+
PostgresSchema,
|
|
6
|
+
PostgresTable,
|
|
7
|
+
PostgresType,
|
|
8
|
+
PostgresView,
|
|
9
|
+
} from "../types.ts";
|
|
10
|
+
|
|
11
|
+
type Operation = "Select" | "Insert" | "Update";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Emits tables/views/materialized views in `GeneratorMetadata` order. Pass
|
|
15
|
+
* input pre-sorted with `sortGeneratorMetadata` for deterministic output.
|
|
16
|
+
*/
|
|
17
|
+
export const generateGo = ({
|
|
18
|
+
schemas,
|
|
19
|
+
tables,
|
|
20
|
+
views,
|
|
21
|
+
materializedViews,
|
|
22
|
+
columns,
|
|
23
|
+
types,
|
|
24
|
+
}: GeneratorMetadata): string => {
|
|
25
|
+
const columnsByTableId = columns.reduce(
|
|
26
|
+
(acc, curr) => {
|
|
27
|
+
acc[curr.table_id] ??= [];
|
|
28
|
+
acc[curr.table_id].push(curr);
|
|
29
|
+
return acc;
|
|
30
|
+
},
|
|
31
|
+
{} as Record<string, PostgresColumn[]>,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const compositeTypes = types.filter((type) => type.attributes.length > 0);
|
|
35
|
+
|
|
36
|
+
let output = `
|
|
37
|
+
package database
|
|
38
|
+
|
|
39
|
+
${tables
|
|
40
|
+
.filter((table) => schemas.some((schema) => schema.name === table.schema))
|
|
41
|
+
.flatMap((table) =>
|
|
42
|
+
generateTableStructsForOperations(
|
|
43
|
+
schemas.find((schema) => schema.name === table.schema)!,
|
|
44
|
+
table,
|
|
45
|
+
columnsByTableId[table.id],
|
|
46
|
+
types,
|
|
47
|
+
["Select", "Insert", "Update"],
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
.join("\n\n")}
|
|
51
|
+
|
|
52
|
+
${views
|
|
53
|
+
.filter((view) => schemas.some((schema) => schema.name === view.schema))
|
|
54
|
+
.flatMap((view) =>
|
|
55
|
+
generateTableStructsForOperations(
|
|
56
|
+
schemas.find((schema) => schema.name === view.schema)!,
|
|
57
|
+
view,
|
|
58
|
+
columnsByTableId[view.id],
|
|
59
|
+
types,
|
|
60
|
+
["Select"],
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
.join("\n\n")}
|
|
64
|
+
|
|
65
|
+
${materializedViews
|
|
66
|
+
.filter((materializedView) =>
|
|
67
|
+
schemas.some((schema) => schema.name === materializedView.schema),
|
|
68
|
+
)
|
|
69
|
+
.flatMap((materializedView) =>
|
|
70
|
+
generateTableStructsForOperations(
|
|
71
|
+
schemas.find((schema) => schema.name === materializedView.schema)!,
|
|
72
|
+
materializedView,
|
|
73
|
+
columnsByTableId[materializedView.id],
|
|
74
|
+
types,
|
|
75
|
+
["Select"],
|
|
76
|
+
),
|
|
77
|
+
)
|
|
78
|
+
.join("\n\n")}
|
|
79
|
+
|
|
80
|
+
${compositeTypes
|
|
81
|
+
.filter((compositeType) =>
|
|
82
|
+
schemas.some((schema) => schema.name === compositeType.schema),
|
|
83
|
+
)
|
|
84
|
+
.map((compositeType) =>
|
|
85
|
+
generateCompositeTypeStruct(
|
|
86
|
+
schemas.find((schema) => schema.name === compositeType.schema)!,
|
|
87
|
+
compositeType,
|
|
88
|
+
types,
|
|
89
|
+
),
|
|
90
|
+
)
|
|
91
|
+
.join("\n\n")}
|
|
92
|
+
`.trim();
|
|
93
|
+
|
|
94
|
+
return output;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Converts a Postgres name to PascalCase.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* formatForGoTypeName('pokedex') // Pokedex
|
|
103
|
+
* formatForGoTypeName('pokemon_center') // PokemonCenter
|
|
104
|
+
* formatForGoTypeName('victory-road') // VictoryRoad
|
|
105
|
+
* formatForGoTypeName('pokemon league') // PokemonLeague
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
function formatForGoTypeName(name: string): string {
|
|
109
|
+
return name
|
|
110
|
+
.split(/[^a-zA-Z0-9]/)
|
|
111
|
+
.map((word) => {
|
|
112
|
+
if (word) {
|
|
113
|
+
return `${word[0].toUpperCase()}${word.slice(1)}`;
|
|
114
|
+
} else {
|
|
115
|
+
return "";
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
.join("");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function generateTableStruct(
|
|
122
|
+
schema: PostgresSchema,
|
|
123
|
+
table: PostgresTable | PostgresView | PostgresMaterializedView,
|
|
124
|
+
columns: PostgresColumn[] | undefined,
|
|
125
|
+
types: PostgresType[],
|
|
126
|
+
operation: Operation,
|
|
127
|
+
): string {
|
|
128
|
+
// Storing columns as a tuple of [formattedName, type, name] rather than creating the string
|
|
129
|
+
// representation of the line allows us to pre-format the entries. Go formats
|
|
130
|
+
// struct fields to be aligned, e.g.:
|
|
131
|
+
// ```go
|
|
132
|
+
// type Pokemon struct {
|
|
133
|
+
// id int `json:"id"`
|
|
134
|
+
// name string `json:"name"`
|
|
135
|
+
// }
|
|
136
|
+
const columnEntries: [string, string, string][] =
|
|
137
|
+
columns?.map((column) => {
|
|
138
|
+
let nullable: boolean;
|
|
139
|
+
if (operation === "Insert") {
|
|
140
|
+
nullable =
|
|
141
|
+
column.is_nullable ||
|
|
142
|
+
column.is_identity ||
|
|
143
|
+
column.is_generated ||
|
|
144
|
+
!!column.default_value;
|
|
145
|
+
} else if (operation === "Update") {
|
|
146
|
+
nullable = true;
|
|
147
|
+
} else {
|
|
148
|
+
nullable = column.is_nullable;
|
|
149
|
+
}
|
|
150
|
+
return [
|
|
151
|
+
formatForGoTypeName(column.name),
|
|
152
|
+
pgTypeToGoType(column.format, nullable, types),
|
|
153
|
+
column.name,
|
|
154
|
+
];
|
|
155
|
+
}) ?? [];
|
|
156
|
+
|
|
157
|
+
const [maxFormattedNameLength, maxTypeLength] = columnEntries.reduce(
|
|
158
|
+
([maxFormattedName, maxType], [formattedName, type]) => {
|
|
159
|
+
return [
|
|
160
|
+
Math.max(maxFormattedName, formattedName.length),
|
|
161
|
+
Math.max(maxType, type.length),
|
|
162
|
+
];
|
|
163
|
+
},
|
|
164
|
+
[0, 0],
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
// Pad the formatted name and type to align the struct fields, then join
|
|
168
|
+
// create the final string representation of the struct fields.
|
|
169
|
+
const formattedColumnEntries = columnEntries.map(
|
|
170
|
+
([formattedName, type, name]) => {
|
|
171
|
+
return ` ${formattedName.padEnd(maxFormattedNameLength)} ${type.padEnd(
|
|
172
|
+
maxTypeLength,
|
|
173
|
+
)} \`json:"${name}"\``;
|
|
174
|
+
},
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
return `
|
|
178
|
+
type ${formatForGoTypeName(schema.name)}${formatForGoTypeName(table.name)}${operation} struct {
|
|
179
|
+
${formattedColumnEntries.join("\n")}
|
|
180
|
+
}
|
|
181
|
+
`.trim();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function generateTableStructsForOperations(
|
|
185
|
+
schema: PostgresSchema,
|
|
186
|
+
table: PostgresTable | PostgresView | PostgresMaterializedView,
|
|
187
|
+
columns: PostgresColumn[] | undefined,
|
|
188
|
+
types: PostgresType[],
|
|
189
|
+
operations: Operation[],
|
|
190
|
+
): string[] {
|
|
191
|
+
return operations.map((operation) =>
|
|
192
|
+
generateTableStruct(schema, table, columns, types, operation),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function generateCompositeTypeStruct(
|
|
197
|
+
schema: PostgresSchema,
|
|
198
|
+
type: PostgresType,
|
|
199
|
+
types: PostgresType[],
|
|
200
|
+
): string {
|
|
201
|
+
// Use the type_id of the attributes to find the types of the attributes
|
|
202
|
+
const typeWithRetrievedAttributes = {
|
|
203
|
+
...type,
|
|
204
|
+
attributes: type.attributes.map((attribute) => {
|
|
205
|
+
const type = types.find((type) => type.id === attribute.type_id);
|
|
206
|
+
return {
|
|
207
|
+
...attribute,
|
|
208
|
+
type,
|
|
209
|
+
};
|
|
210
|
+
}),
|
|
211
|
+
};
|
|
212
|
+
const attributeEntries: [string, string, string][] =
|
|
213
|
+
typeWithRetrievedAttributes.attributes.map((attribute) => [
|
|
214
|
+
formatForGoTypeName(attribute.name),
|
|
215
|
+
pgTypeToGoType(attribute.type!.format, false),
|
|
216
|
+
attribute.name,
|
|
217
|
+
]);
|
|
218
|
+
|
|
219
|
+
const [maxFormattedNameLength, maxTypeLength] = attributeEntries.reduce(
|
|
220
|
+
([maxFormattedName, maxType], [formattedName, type]) => {
|
|
221
|
+
return [
|
|
222
|
+
Math.max(maxFormattedName, formattedName.length),
|
|
223
|
+
Math.max(maxType, type.length),
|
|
224
|
+
];
|
|
225
|
+
},
|
|
226
|
+
[0, 0],
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
// Pad the formatted name and type to align the struct fields, then join
|
|
230
|
+
// create the final string representation of the struct fields.
|
|
231
|
+
const formattedAttributeEntries = attributeEntries.map(
|
|
232
|
+
([formattedName, type, name]) => {
|
|
233
|
+
return ` ${formattedName.padEnd(maxFormattedNameLength)} ${type.padEnd(
|
|
234
|
+
maxTypeLength,
|
|
235
|
+
)} \`json:"${name}"\``;
|
|
236
|
+
},
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
return `
|
|
240
|
+
type ${formatForGoTypeName(schema.name)}${formatForGoTypeName(type.name)} struct {
|
|
241
|
+
${formattedAttributeEntries.join("\n")}
|
|
242
|
+
}
|
|
243
|
+
`.trim();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Note: the type map uses `interface{ } `, not `any`, to remain compatible with
|
|
247
|
+
// older versions of Go.
|
|
248
|
+
const GO_TYPE_MAP = {
|
|
249
|
+
// Bool
|
|
250
|
+
bool: "bool",
|
|
251
|
+
|
|
252
|
+
// Numbers
|
|
253
|
+
int2: "int16",
|
|
254
|
+
int4: "int32",
|
|
255
|
+
int8: "int64",
|
|
256
|
+
float4: "float32",
|
|
257
|
+
float8: "float64",
|
|
258
|
+
numeric: "float64",
|
|
259
|
+
|
|
260
|
+
// Strings
|
|
261
|
+
bytea: "[]byte",
|
|
262
|
+
bpchar: "string",
|
|
263
|
+
varchar: "string",
|
|
264
|
+
date: "string",
|
|
265
|
+
text: "string",
|
|
266
|
+
citext: "string",
|
|
267
|
+
time: "string",
|
|
268
|
+
timetz: "string",
|
|
269
|
+
timestamp: "string",
|
|
270
|
+
timestamptz: "string",
|
|
271
|
+
interval: "string",
|
|
272
|
+
uuid: "string",
|
|
273
|
+
vector: "string",
|
|
274
|
+
|
|
275
|
+
// JSON
|
|
276
|
+
json: "interface{}",
|
|
277
|
+
jsonb: "interface{}",
|
|
278
|
+
|
|
279
|
+
// Range
|
|
280
|
+
int4range: "string",
|
|
281
|
+
int4multirange: "string",
|
|
282
|
+
int8range: "string",
|
|
283
|
+
int8multirange: "string",
|
|
284
|
+
numrange: "string",
|
|
285
|
+
nummultirange: "string",
|
|
286
|
+
tsrange: "string",
|
|
287
|
+
tsmultirange: "string",
|
|
288
|
+
tstzrange: "string",
|
|
289
|
+
tstzmultirange: "string",
|
|
290
|
+
daterange: "string",
|
|
291
|
+
datemultirange: "string",
|
|
292
|
+
|
|
293
|
+
// Misc
|
|
294
|
+
void: "interface{}",
|
|
295
|
+
record: "map[string]interface{}",
|
|
296
|
+
} as const;
|
|
297
|
+
|
|
298
|
+
type GoType = (typeof GO_TYPE_MAP)[keyof typeof GO_TYPE_MAP];
|
|
299
|
+
|
|
300
|
+
const GO_NULLABLE_TYPE_MAP: Record<GoType, string> = {
|
|
301
|
+
string: "*string",
|
|
302
|
+
bool: "*bool",
|
|
303
|
+
int16: "*int16",
|
|
304
|
+
int32: "*int32",
|
|
305
|
+
int64: "*int64",
|
|
306
|
+
float32: "*float32",
|
|
307
|
+
float64: "*float64",
|
|
308
|
+
"[]byte": "[]byte",
|
|
309
|
+
"interface{}": "interface{}",
|
|
310
|
+
"map[string]interface{}": "map[string]interface{}",
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
function pgTypeToGoType(
|
|
314
|
+
pgType: string,
|
|
315
|
+
nullable: boolean,
|
|
316
|
+
types: PostgresType[] = [],
|
|
317
|
+
): string {
|
|
318
|
+
let goType: GoType | undefined = undefined;
|
|
319
|
+
if (pgType in GO_TYPE_MAP) {
|
|
320
|
+
goType = GO_TYPE_MAP[pgType as keyof typeof GO_TYPE_MAP];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Enums
|
|
324
|
+
const enumType = types.find(
|
|
325
|
+
(type) => type.name === pgType && type.enums.length > 0,
|
|
326
|
+
);
|
|
327
|
+
if (enumType) {
|
|
328
|
+
goType = "string";
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (goType) {
|
|
332
|
+
if (nullable) {
|
|
333
|
+
return GO_NULLABLE_TYPE_MAP[goType];
|
|
334
|
+
}
|
|
335
|
+
return goType;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Composite types
|
|
339
|
+
const compositeType = types.find(
|
|
340
|
+
(type) => type.name === pgType && type.attributes.length > 0,
|
|
341
|
+
);
|
|
342
|
+
if (compositeType) {
|
|
343
|
+
// TODO: generate composite types
|
|
344
|
+
// return formatForGoTypeName(pgType)
|
|
345
|
+
return "map[string]interface{}";
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Arrays
|
|
349
|
+
if (pgType.startsWith("_")) {
|
|
350
|
+
const innerType = pgTypeToGoType(pgType.slice(1), nullable, types);
|
|
351
|
+
return `[]${innerType} `;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Fallback
|
|
355
|
+
return "interface{}";
|
|
356
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { sortGeneratorMetadata } from "../sort.ts";
|
|
2
|
+
export { generateGo } from "./go.ts";
|
|
3
|
+
export { generatePython } from "./python.ts";
|
|
4
|
+
export {
|
|
5
|
+
generateTypescript,
|
|
6
|
+
type GenerateTypescriptOptions,
|
|
7
|
+
pgTypeToTsType,
|
|
8
|
+
} from "./typescript.ts";
|
|
9
|
+
export {
|
|
10
|
+
type AccessControl,
|
|
11
|
+
generateSwift,
|
|
12
|
+
type GenerateSwiftOptions,
|
|
13
|
+
} from "./swift.ts";
|