@supabase/postgrest-typegen 0.0.1 → 0.2.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.
|
@@ -16,6 +16,13 @@ export interface GenerateTypescriptOptions {
|
|
|
16
16
|
* env read. Default `'public'`.
|
|
17
17
|
*/
|
|
18
18
|
defaultSchema?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Formatter used on the generated output. Defaults to `oxfmt`, called
|
|
21
|
+
* inline. Callers on a latency-sensitive request path (e.g. postgres-meta's
|
|
22
|
+
* hosted `/generators/typescript` route) can substitute a worker-pool-backed
|
|
23
|
+
* formatter here instead of blocking the event loop on every call.
|
|
24
|
+
*/
|
|
25
|
+
format?: (code: string) => Promise<string>;
|
|
19
26
|
}
|
|
20
27
|
/**
|
|
21
28
|
* Does not re-sort collections; pass input pre-sorted with
|
|
@@ -3,8 +3,20 @@
|
|
|
3
3
|
// literals (relying on Array#toString) to build the output. Preserving that is required for
|
|
4
4
|
// byte-parity, and the offending expressions sit inside template literals where a targeted
|
|
5
5
|
// disable comment would corrupt the emitted string.
|
|
6
|
-
import
|
|
6
|
+
import { format as oxfmtFormat } from "oxfmt";
|
|
7
7
|
import { VALID_FUNCTION_ARGS_MODE, VALID_UNNAMED_FUNCTION_ARG_TYPES, } from "./constants.js";
|
|
8
|
+
const defaultFormat = async (code) => {
|
|
9
|
+
const { code: formatted, errors } = await oxfmtFormat("output.ts", code, {
|
|
10
|
+
semi: false,
|
|
11
|
+
printWidth: 80,
|
|
12
|
+
});
|
|
13
|
+
if (errors.length > 0) {
|
|
14
|
+
throw new Error(`oxfmt failed to format generated TypeScript output: ${errors
|
|
15
|
+
.map((error) => error.message)
|
|
16
|
+
.join("; ")}`);
|
|
17
|
+
}
|
|
18
|
+
return formatted;
|
|
19
|
+
};
|
|
8
20
|
/**
|
|
9
21
|
* Does not re-sort collections; pass input pre-sorted with
|
|
10
22
|
* `sortGeneratorMetadata` first. Still merge-sorts tables+foreign tables and
|
|
@@ -13,7 +25,7 @@ import { VALID_FUNCTION_ARGS_MODE, VALID_UNNAMED_FUNCTION_ARG_TYPES, } from "./c
|
|
|
13
25
|
*/
|
|
14
26
|
export const generateTypescript = async (metadata, opts = {}) => {
|
|
15
27
|
const { schemas, tables, foreignTables, views, materializedViews, columns, relationships, functions, types, } = metadata;
|
|
16
|
-
const { detectOneToOneRelationships = false, postgrestVersion, defaultSchema = "public", } = opts;
|
|
28
|
+
const { detectOneToOneRelationships = false, postgrestVersion, defaultSchema = "public", format = defaultFormat, } = opts;
|
|
17
29
|
// Ordering of all collections (incl. relationships, columns, args below) is
|
|
18
30
|
// provided by `sortGeneratorMetadata`; this generator no longer re-sorts.
|
|
19
31
|
const introspectionBySchema = Object.fromEntries(schemas.map((s) => [
|
|
@@ -705,10 +717,7 @@ export const Constants = {
|
|
|
705
717
|
})}
|
|
706
718
|
} as const
|
|
707
719
|
`;
|
|
708
|
-
output = await
|
|
709
|
-
parser: "typescript",
|
|
710
|
-
semi: false,
|
|
711
|
-
});
|
|
720
|
+
output = await format(output);
|
|
712
721
|
return output;
|
|
713
722
|
};
|
|
714
723
|
// TODO: Make this more robust. Currently doesn't handle range types - returns them as unknown.
|
|
@@ -32,27 +32,33 @@ export async function introspect(db, opts = {}) {
|
|
|
32
32
|
const systemExcludingFilter = filterByList(included, excluded, DEFAULT_SYSTEM_SCHEMAS);
|
|
33
33
|
const plainFilter = filterByList(included, excluded);
|
|
34
34
|
const queryRows = async (sql) => normalizeRows((await db.query(sql)).rows);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const tables = await
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
35
|
+
// Issued concurrently, matching postgres-meta's CLI path which ran its nine
|
|
36
|
+
// introspection queries under Promise.all. A pooled Queryable runs them in
|
|
37
|
+
// parallel; a single-connection one pipelines them, which is no worse than
|
|
38
|
+
// awaiting each in turn.
|
|
39
|
+
const [schemas, tables, foreignTables, views, materializedViews, columns, primaryKeys, relationships, functions, types,] = await Promise.all([
|
|
40
|
+
queryRows(SCHEMAS_SQL({
|
|
41
|
+
includeSystemSchemas: false,
|
|
42
|
+
nameFilter: systemExcludingFilter,
|
|
43
|
+
})),
|
|
44
|
+
queryRows(TABLES_SQL({ schemaFilter: systemExcludingFilter })),
|
|
45
|
+
queryRows(FOREIGN_TABLES_SQL({ schemaFilter: plainFilter })),
|
|
46
|
+
queryRows(VIEWS_SQL({ schemaFilter: systemExcludingFilter })),
|
|
47
|
+
queryRows(MATERIALIZED_VIEWS_SQL({ schemaFilter: plainFilter })),
|
|
48
|
+
queryRows(COLUMNS_SQL({ schemaFilter: systemExcludingFilter })),
|
|
49
|
+
queryRows(PRIMARY_KEYS_SQL({ schemaFilter: systemExcludingFilter })),
|
|
50
|
+
listRelationships(db, {
|
|
51
|
+
includedSchemas: included,
|
|
52
|
+
excludedSchemas: excluded,
|
|
53
|
+
}),
|
|
54
|
+
queryRows(FUNCTIONS_SQL({ schemaFilter: systemExcludingFilter })),
|
|
55
|
+
// types: includeSystemSchemas true (no schema filter), table + array types included.
|
|
56
|
+
queryRows(TYPES_SQL({
|
|
57
|
+
schemaFilter: "",
|
|
58
|
+
includeTableTypes: true,
|
|
59
|
+
includeArrayTypes: true,
|
|
60
|
+
})),
|
|
61
|
+
]);
|
|
56
62
|
return {
|
|
57
63
|
version: GENERATOR_METADATA_VERSION,
|
|
58
64
|
schemas: schemas.filter(({ name }) => !excludedSchemas.includes(name) &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supabase/postgrest-typegen",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Type generation for PostgREST from PostgreSQL schemas",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codegen",
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"arktype": "2.2.3",
|
|
65
|
-
"
|
|
66
|
-
"
|
|
65
|
+
"oxfmt": "0.65.0",
|
|
66
|
+
"pg-format": "1.0.4"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@testcontainers/postgresql": "^12.1.0",
|
|
@@ -74,7 +74,6 @@
|
|
|
74
74
|
"@types/pg": "^8.23.1",
|
|
75
75
|
"@types/pg-format": "^1.0.5",
|
|
76
76
|
"knip": "^6.32.3",
|
|
77
|
-
"oxfmt": "0.65.0",
|
|
78
77
|
"oxlint": "1.80.0",
|
|
79
78
|
"oxlint-tsgolint": "7.0.2001",
|
|
80
79
|
"pg": "^8.23.0",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// literals (relying on Array#toString) to build the output. Preserving that is required for
|
|
4
4
|
// byte-parity, and the offending expressions sit inside template literals where a targeted
|
|
5
5
|
// disable comment would corrupt the emitted string.
|
|
6
|
-
import
|
|
6
|
+
import { format as oxfmtFormat } from "oxfmt";
|
|
7
7
|
import type {
|
|
8
8
|
GeneratorMetadata,
|
|
9
9
|
PostgresColumn,
|
|
@@ -35,8 +35,30 @@ export interface GenerateTypescriptOptions {
|
|
|
35
35
|
* env read. Default `'public'`.
|
|
36
36
|
*/
|
|
37
37
|
defaultSchema?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Formatter used on the generated output. Defaults to `oxfmt`, called
|
|
40
|
+
* inline. Callers on a latency-sensitive request path (e.g. postgres-meta's
|
|
41
|
+
* hosted `/generators/typescript` route) can substitute a worker-pool-backed
|
|
42
|
+
* formatter here instead of blocking the event loop on every call.
|
|
43
|
+
*/
|
|
44
|
+
format?: (code: string) => Promise<string>;
|
|
38
45
|
}
|
|
39
46
|
|
|
47
|
+
const defaultFormat = async (code: string): Promise<string> => {
|
|
48
|
+
const { code: formatted, errors } = await oxfmtFormat("output.ts", code, {
|
|
49
|
+
semi: false,
|
|
50
|
+
printWidth: 80,
|
|
51
|
+
});
|
|
52
|
+
if (errors.length > 0) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`oxfmt failed to format generated TypeScript output: ${errors
|
|
55
|
+
.map((error) => error.message)
|
|
56
|
+
.join("; ")}`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return formatted;
|
|
60
|
+
};
|
|
61
|
+
|
|
40
62
|
type TsRelationship = Pick<
|
|
41
63
|
GeneratorMetadata["relationships"][number],
|
|
42
64
|
| "foreign_key_name"
|
|
@@ -71,6 +93,7 @@ export const generateTypescript = async (
|
|
|
71
93
|
detectOneToOneRelationships = false,
|
|
72
94
|
postgrestVersion,
|
|
73
95
|
defaultSchema = "public",
|
|
96
|
+
format = defaultFormat,
|
|
74
97
|
} = opts;
|
|
75
98
|
// Ordering of all collections (incl. relationships, columns, args below) is
|
|
76
99
|
// provided by `sortGeneratorMetadata`; this generator no longer re-sorts.
|
|
@@ -1016,10 +1039,7 @@ export const Constants = {
|
|
|
1016
1039
|
} as const
|
|
1017
1040
|
`;
|
|
1018
1041
|
|
|
1019
|
-
output = await
|
|
1020
|
-
parser: "typescript",
|
|
1021
|
-
semi: false,
|
|
1022
|
-
});
|
|
1042
|
+
output = await format(output);
|
|
1023
1043
|
return output;
|
|
1024
1044
|
};
|
|
1025
1045
|
|
|
@@ -62,45 +62,48 @@ export async function introspect(
|
|
|
62
62
|
const queryRows = async (sql: string) =>
|
|
63
63
|
normalizeRows((await db.query(sql)).rows);
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// types: includeSystemSchemas true (no schema filter), table + array types included.
|
|
97
|
-
const types = await queryRows(
|
|
98
|
-
TYPES_SQL({
|
|
99
|
-
schemaFilter: "",
|
|
100
|
-
includeTableTypes: true,
|
|
101
|
-
includeArrayTypes: true,
|
|
65
|
+
// Issued concurrently, matching postgres-meta's CLI path which ran its nine
|
|
66
|
+
// introspection queries under Promise.all. A pooled Queryable runs them in
|
|
67
|
+
// parallel; a single-connection one pipelines them, which is no worse than
|
|
68
|
+
// awaiting each in turn.
|
|
69
|
+
const [
|
|
70
|
+
schemas,
|
|
71
|
+
tables,
|
|
72
|
+
foreignTables,
|
|
73
|
+
views,
|
|
74
|
+
materializedViews,
|
|
75
|
+
columns,
|
|
76
|
+
primaryKeys,
|
|
77
|
+
relationships,
|
|
78
|
+
functions,
|
|
79
|
+
types,
|
|
80
|
+
] = await Promise.all([
|
|
81
|
+
queryRows(
|
|
82
|
+
SCHEMAS_SQL({
|
|
83
|
+
includeSystemSchemas: false,
|
|
84
|
+
nameFilter: systemExcludingFilter,
|
|
85
|
+
}),
|
|
86
|
+
),
|
|
87
|
+
queryRows(TABLES_SQL({ schemaFilter: systemExcludingFilter })),
|
|
88
|
+
queryRows(FOREIGN_TABLES_SQL({ schemaFilter: plainFilter })),
|
|
89
|
+
queryRows(VIEWS_SQL({ schemaFilter: systemExcludingFilter })),
|
|
90
|
+
queryRows(MATERIALIZED_VIEWS_SQL({ schemaFilter: plainFilter })),
|
|
91
|
+
queryRows(COLUMNS_SQL({ schemaFilter: systemExcludingFilter })),
|
|
92
|
+
queryRows(PRIMARY_KEYS_SQL({ schemaFilter: systemExcludingFilter })),
|
|
93
|
+
listRelationships(db, {
|
|
94
|
+
includedSchemas: included,
|
|
95
|
+
excludedSchemas: excluded,
|
|
102
96
|
}),
|
|
103
|
-
|
|
97
|
+
queryRows(FUNCTIONS_SQL({ schemaFilter: systemExcludingFilter })),
|
|
98
|
+
// types: includeSystemSchemas true (no schema filter), table + array types included.
|
|
99
|
+
queryRows(
|
|
100
|
+
TYPES_SQL({
|
|
101
|
+
schemaFilter: "",
|
|
102
|
+
includeTableTypes: true,
|
|
103
|
+
includeArrayTypes: true,
|
|
104
|
+
}),
|
|
105
|
+
),
|
|
106
|
+
]);
|
|
104
107
|
|
|
105
108
|
return {
|
|
106
109
|
version: GENERATOR_METADATA_VERSION,
|