@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Supabase
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# @supabase/postgrest-typegen
|
|
2
|
+
|
|
3
|
+
Type generation for [PostgREST](https://postgrest.org) from a PostgreSQL
|
|
4
|
+
schema. This is the type-generation engine behind `supabase gen types`,
|
|
5
|
+
extracted from [postgres-meta](https://github.com/supabase/postgres-meta) into a
|
|
6
|
+
small, driver-agnostic library.
|
|
7
|
+
|
|
8
|
+
> **Status:** alpha. The public API is settling as generators and introspection
|
|
9
|
+
> are ported.
|
|
10
|
+
|
|
11
|
+
## Scope: introspection is permanent, four generators are transitional
|
|
12
|
+
|
|
13
|
+
This package's permanent job is introspection and the `GeneratorMetadata`
|
|
14
|
+
contract (see "Out-of-process generators" below): any *new* language's
|
|
15
|
+
generator lives in that language's own SDK repo, consuming this package's
|
|
16
|
+
JSON output, not inside `postgrest-typegen`.
|
|
17
|
+
|
|
18
|
+
The TypeScript, Go, Python, and Swift generators bundled here are a
|
|
19
|
+
**deliberate transition**, not the target architecture for new languages.
|
|
20
|
+
They were ported byte-parity from postgres-meta's own templates so
|
|
21
|
+
`supabase gen types` keeps working unchanged while postgres-meta's copies get
|
|
22
|
+
deprecated in favor of this package. It's decided that all four eventually
|
|
23
|
+
move out to their own SDK repos too (tracked in SDK-1641), not yet scheduled
|
|
24
|
+
— sequenced after postgres-meta's cutover to this package settles.
|
|
25
|
+
|
|
26
|
+
## Design
|
|
27
|
+
|
|
28
|
+
There is a hard split between **introspection** (database → metadata) and
|
|
29
|
+
**generation** (metadata → string):
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { introspect } from "@supabase/postgrest-typegen/introspection";
|
|
33
|
+
import {
|
|
34
|
+
generateTypescript,
|
|
35
|
+
sortGeneratorMetadata,
|
|
36
|
+
} from "@supabase/postgrest-typegen/generation";
|
|
37
|
+
|
|
38
|
+
// Any `pg.Pool` / `pg.Client` (or compatible driver) works here.
|
|
39
|
+
const metadata = await introspect(pool, { includedSchemas: ["public"] });
|
|
40
|
+
// Canonically sort before generating (see "Stable ordering" below).
|
|
41
|
+
const types = await generateTypescript(sortGeneratorMetadata(metadata), {
|
|
42
|
+
postgrestVersion: "12",
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`GeneratorMetadata` is the pluggable contract: the SQL introspector is the
|
|
47
|
+
default producer, but any source that can produce that shape can feed the
|
|
48
|
+
generators.
|
|
49
|
+
|
|
50
|
+
### Stable ordering (`sortGeneratorMetadata`)
|
|
51
|
+
|
|
52
|
+
The Go/Python/Swift generators emit tables, views, and materialized views in
|
|
53
|
+
`GeneratorMetadata` order, so their output depends on how the producer ordered
|
|
54
|
+
its collections (a SQL introspector returns rows in environment-dependent heap
|
|
55
|
+
order). `sortGeneratorMetadata` is a pure pass that canonically sorts every
|
|
56
|
+
collection; **apply it after introspection and before any `generate*` call** so
|
|
57
|
+
output is deterministic regardless of the producer. Generators expect
|
|
58
|
+
pre-sorted input and do not re-sort it themselves.
|
|
59
|
+
|
|
60
|
+
### Runtime validation (opt-in)
|
|
61
|
+
|
|
62
|
+
`GeneratorMetadata` is backed by an [ArkType](https://arktype.io) schema, so a
|
|
63
|
+
result coming from a custom/injected producer can be validated at runtime
|
|
64
|
+
rather than blindly cast. `introspect()` does **not** validate — wrap its
|
|
65
|
+
result yourself when you want the guarantee:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { parseGeneratorMetadata, generatorMetadataSchema } from "@supabase/postgrest-typegen";
|
|
69
|
+
|
|
70
|
+
// Throws a TypeError with a readable summary if the shape is wrong.
|
|
71
|
+
const metadata = parseGeneratorMetadata(await someCustomIntrospector(db));
|
|
72
|
+
|
|
73
|
+
// Or use the raw schema directly for custom flows.
|
|
74
|
+
const out = generatorMetadataSchema(unknownInput);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Out-of-process generators (JSON Schema + serialization)
|
|
78
|
+
|
|
79
|
+
Generators that live outside this package's process, in another language's
|
|
80
|
+
own SDK repo, receive `GeneratorMetadata` as JSON rather than a live object.
|
|
81
|
+
This package owns that boundary, so no consumer serializes the contract a
|
|
82
|
+
different way:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import {
|
|
86
|
+
serializeGeneratorMetadata,
|
|
87
|
+
generatorMetadataJsonSchema,
|
|
88
|
+
} from "@supabase/postgrest-typegen";
|
|
89
|
+
|
|
90
|
+
// The exact JSON document an out-of-process generator (e.g. `dart run
|
|
91
|
+
// supabase_typegen`) receives over stdin/stdout.
|
|
92
|
+
const json = serializeGeneratorMetadata(sortGeneratorMetadata(metadata));
|
|
93
|
+
|
|
94
|
+
// The JSON Schema for that document, for consumers that want to validate or
|
|
95
|
+
// codegen against the contract without depending on ArkType or TypeScript.
|
|
96
|
+
generatorMetadataJsonSchema;
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`GeneratorMetadata.version` is bumped whenever the shape changes in a way a
|
|
100
|
+
consumer should branch on, since an out-of-process consumer only sees the
|
|
101
|
+
serialized document and can't otherwise detect a shape change until something
|
|
102
|
+
breaks at read time.
|
|
103
|
+
|
|
104
|
+
### Generators
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import {
|
|
108
|
+
generateTypescript, // async (uses prettier)
|
|
109
|
+
generateGo,
|
|
110
|
+
generatePython,
|
|
111
|
+
generateSwift,
|
|
112
|
+
} from "@supabase/postgrest-typegen/generation";
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
| Function | Options |
|
|
116
|
+
| -------------------- | ----------------------------------------------------------------------- |
|
|
117
|
+
| `generateTypescript` | `{ detectOneToOneRelationships?, postgrestVersion?, defaultSchema? }` |
|
|
118
|
+
| `generateGo` | — |
|
|
119
|
+
| `generatePython` | — |
|
|
120
|
+
| `generateSwift` | `{ accessControl?: 'internal' \| 'public' \| 'private' \| 'package' }` |
|
|
121
|
+
|
|
122
|
+
## Installation
|
|
123
|
+
|
|
124
|
+
Not yet published; consumed in-repo for now (`packages/postgrest-typegen`).
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# pg is a peer of your application, not bundled here
|
|
128
|
+
npm install pg
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-generation constants ported verbatim from
|
|
3
|
+
* `postgres-meta/src/server/constants.ts`. Only the typegen-relevant values
|
|
4
|
+
* live here; server/runtime constants stay in postgres-meta.
|
|
5
|
+
*
|
|
6
|
+
* Consumed by the TypeScript generator's function-argument handling.
|
|
7
|
+
*/
|
|
8
|
+
export declare const VALID_UNNAMED_FUNCTION_ARG_TYPES: Set<number>;
|
|
9
|
+
export declare const VALID_FUNCTION_ARGS_MODE: Set<string>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-generation constants ported verbatim from
|
|
3
|
+
* `postgres-meta/src/server/constants.ts`. Only the typegen-relevant values
|
|
4
|
+
* live here; server/runtime constants stay in postgres-meta.
|
|
5
|
+
*
|
|
6
|
+
* Consumed by the TypeScript generator's function-argument handling.
|
|
7
|
+
*/
|
|
8
|
+
// json/jsonb/text types
|
|
9
|
+
export const VALID_UNNAMED_FUNCTION_ARG_TYPES = new Set([114, 3802, 25]);
|
|
10
|
+
export const VALID_FUNCTION_ARGS_MODE = new Set(["in", "inout", "variadic"]);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { GeneratorMetadata } from "../types.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Emits tables/views/materialized views in `GeneratorMetadata` order. Pass
|
|
4
|
+
* input pre-sorted with `sortGeneratorMetadata` for deterministic output.
|
|
5
|
+
*/
|
|
6
|
+
export declare const generateGo: ({ schemas, tables, views, materializedViews, columns, types, }: GeneratorMetadata) => string;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emits tables/views/materialized views in `GeneratorMetadata` order. Pass
|
|
3
|
+
* input pre-sorted with `sortGeneratorMetadata` for deterministic output.
|
|
4
|
+
*/
|
|
5
|
+
export const generateGo = ({ schemas, tables, views, materializedViews, columns, types, }) => {
|
|
6
|
+
const columnsByTableId = columns.reduce((acc, curr) => {
|
|
7
|
+
acc[curr.table_id] ??= [];
|
|
8
|
+
acc[curr.table_id].push(curr);
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
const compositeTypes = types.filter((type) => type.attributes.length > 0);
|
|
12
|
+
let output = `
|
|
13
|
+
package database
|
|
14
|
+
|
|
15
|
+
${tables
|
|
16
|
+
.filter((table) => schemas.some((schema) => schema.name === table.schema))
|
|
17
|
+
.flatMap((table) => generateTableStructsForOperations(schemas.find((schema) => schema.name === table.schema), table, columnsByTableId[table.id], types, ["Select", "Insert", "Update"]))
|
|
18
|
+
.join("\n\n")}
|
|
19
|
+
|
|
20
|
+
${views
|
|
21
|
+
.filter((view) => schemas.some((schema) => schema.name === view.schema))
|
|
22
|
+
.flatMap((view) => generateTableStructsForOperations(schemas.find((schema) => schema.name === view.schema), view, columnsByTableId[view.id], types, ["Select"]))
|
|
23
|
+
.join("\n\n")}
|
|
24
|
+
|
|
25
|
+
${materializedViews
|
|
26
|
+
.filter((materializedView) => schemas.some((schema) => schema.name === materializedView.schema))
|
|
27
|
+
.flatMap((materializedView) => generateTableStructsForOperations(schemas.find((schema) => schema.name === materializedView.schema), materializedView, columnsByTableId[materializedView.id], types, ["Select"]))
|
|
28
|
+
.join("\n\n")}
|
|
29
|
+
|
|
30
|
+
${compositeTypes
|
|
31
|
+
.filter((compositeType) => schemas.some((schema) => schema.name === compositeType.schema))
|
|
32
|
+
.map((compositeType) => generateCompositeTypeStruct(schemas.find((schema) => schema.name === compositeType.schema), compositeType, types))
|
|
33
|
+
.join("\n\n")}
|
|
34
|
+
`.trim();
|
|
35
|
+
return output;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Converts a Postgres name to PascalCase.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* formatForGoTypeName('pokedex') // Pokedex
|
|
43
|
+
* formatForGoTypeName('pokemon_center') // PokemonCenter
|
|
44
|
+
* formatForGoTypeName('victory-road') // VictoryRoad
|
|
45
|
+
* formatForGoTypeName('pokemon league') // PokemonLeague
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
function formatForGoTypeName(name) {
|
|
49
|
+
return name
|
|
50
|
+
.split(/[^a-zA-Z0-9]/)
|
|
51
|
+
.map((word) => {
|
|
52
|
+
if (word) {
|
|
53
|
+
return `${word[0].toUpperCase()}${word.slice(1)}`;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
.join("");
|
|
60
|
+
}
|
|
61
|
+
function generateTableStruct(schema, table, columns, types, operation) {
|
|
62
|
+
// Storing columns as a tuple of [formattedName, type, name] rather than creating the string
|
|
63
|
+
// representation of the line allows us to pre-format the entries. Go formats
|
|
64
|
+
// struct fields to be aligned, e.g.:
|
|
65
|
+
// ```go
|
|
66
|
+
// type Pokemon struct {
|
|
67
|
+
// id int `json:"id"`
|
|
68
|
+
// name string `json:"name"`
|
|
69
|
+
// }
|
|
70
|
+
const columnEntries = columns?.map((column) => {
|
|
71
|
+
let nullable;
|
|
72
|
+
if (operation === "Insert") {
|
|
73
|
+
nullable =
|
|
74
|
+
column.is_nullable ||
|
|
75
|
+
column.is_identity ||
|
|
76
|
+
column.is_generated ||
|
|
77
|
+
!!column.default_value;
|
|
78
|
+
}
|
|
79
|
+
else if (operation === "Update") {
|
|
80
|
+
nullable = true;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
nullable = column.is_nullable;
|
|
84
|
+
}
|
|
85
|
+
return [
|
|
86
|
+
formatForGoTypeName(column.name),
|
|
87
|
+
pgTypeToGoType(column.format, nullable, types),
|
|
88
|
+
column.name,
|
|
89
|
+
];
|
|
90
|
+
}) ?? [];
|
|
91
|
+
const [maxFormattedNameLength, maxTypeLength] = columnEntries.reduce(([maxFormattedName, maxType], [formattedName, type]) => {
|
|
92
|
+
return [
|
|
93
|
+
Math.max(maxFormattedName, formattedName.length),
|
|
94
|
+
Math.max(maxType, type.length),
|
|
95
|
+
];
|
|
96
|
+
}, [0, 0]);
|
|
97
|
+
// Pad the formatted name and type to align the struct fields, then join
|
|
98
|
+
// create the final string representation of the struct fields.
|
|
99
|
+
const formattedColumnEntries = columnEntries.map(([formattedName, type, name]) => {
|
|
100
|
+
return ` ${formattedName.padEnd(maxFormattedNameLength)} ${type.padEnd(maxTypeLength)} \`json:"${name}"\``;
|
|
101
|
+
});
|
|
102
|
+
return `
|
|
103
|
+
type ${formatForGoTypeName(schema.name)}${formatForGoTypeName(table.name)}${operation} struct {
|
|
104
|
+
${formattedColumnEntries.join("\n")}
|
|
105
|
+
}
|
|
106
|
+
`.trim();
|
|
107
|
+
}
|
|
108
|
+
function generateTableStructsForOperations(schema, table, columns, types, operations) {
|
|
109
|
+
return operations.map((operation) => generateTableStruct(schema, table, columns, types, operation));
|
|
110
|
+
}
|
|
111
|
+
function generateCompositeTypeStruct(schema, type, types) {
|
|
112
|
+
// Use the type_id of the attributes to find the types of the attributes
|
|
113
|
+
const typeWithRetrievedAttributes = {
|
|
114
|
+
...type,
|
|
115
|
+
attributes: type.attributes.map((attribute) => {
|
|
116
|
+
const type = types.find((type) => type.id === attribute.type_id);
|
|
117
|
+
return {
|
|
118
|
+
...attribute,
|
|
119
|
+
type,
|
|
120
|
+
};
|
|
121
|
+
}),
|
|
122
|
+
};
|
|
123
|
+
const attributeEntries = typeWithRetrievedAttributes.attributes.map((attribute) => [
|
|
124
|
+
formatForGoTypeName(attribute.name),
|
|
125
|
+
pgTypeToGoType(attribute.type.format, false),
|
|
126
|
+
attribute.name,
|
|
127
|
+
]);
|
|
128
|
+
const [maxFormattedNameLength, maxTypeLength] = attributeEntries.reduce(([maxFormattedName, maxType], [formattedName, type]) => {
|
|
129
|
+
return [
|
|
130
|
+
Math.max(maxFormattedName, formattedName.length),
|
|
131
|
+
Math.max(maxType, type.length),
|
|
132
|
+
];
|
|
133
|
+
}, [0, 0]);
|
|
134
|
+
// Pad the formatted name and type to align the struct fields, then join
|
|
135
|
+
// create the final string representation of the struct fields.
|
|
136
|
+
const formattedAttributeEntries = attributeEntries.map(([formattedName, type, name]) => {
|
|
137
|
+
return ` ${formattedName.padEnd(maxFormattedNameLength)} ${type.padEnd(maxTypeLength)} \`json:"${name}"\``;
|
|
138
|
+
});
|
|
139
|
+
return `
|
|
140
|
+
type ${formatForGoTypeName(schema.name)}${formatForGoTypeName(type.name)} struct {
|
|
141
|
+
${formattedAttributeEntries.join("\n")}
|
|
142
|
+
}
|
|
143
|
+
`.trim();
|
|
144
|
+
}
|
|
145
|
+
// Note: the type map uses `interface{ } `, not `any`, to remain compatible with
|
|
146
|
+
// older versions of Go.
|
|
147
|
+
const GO_TYPE_MAP = {
|
|
148
|
+
// Bool
|
|
149
|
+
bool: "bool",
|
|
150
|
+
// Numbers
|
|
151
|
+
int2: "int16",
|
|
152
|
+
int4: "int32",
|
|
153
|
+
int8: "int64",
|
|
154
|
+
float4: "float32",
|
|
155
|
+
float8: "float64",
|
|
156
|
+
numeric: "float64",
|
|
157
|
+
// Strings
|
|
158
|
+
bytea: "[]byte",
|
|
159
|
+
bpchar: "string",
|
|
160
|
+
varchar: "string",
|
|
161
|
+
date: "string",
|
|
162
|
+
text: "string",
|
|
163
|
+
citext: "string",
|
|
164
|
+
time: "string",
|
|
165
|
+
timetz: "string",
|
|
166
|
+
timestamp: "string",
|
|
167
|
+
timestamptz: "string",
|
|
168
|
+
interval: "string",
|
|
169
|
+
uuid: "string",
|
|
170
|
+
vector: "string",
|
|
171
|
+
// JSON
|
|
172
|
+
json: "interface{}",
|
|
173
|
+
jsonb: "interface{}",
|
|
174
|
+
// Range
|
|
175
|
+
int4range: "string",
|
|
176
|
+
int4multirange: "string",
|
|
177
|
+
int8range: "string",
|
|
178
|
+
int8multirange: "string",
|
|
179
|
+
numrange: "string",
|
|
180
|
+
nummultirange: "string",
|
|
181
|
+
tsrange: "string",
|
|
182
|
+
tsmultirange: "string",
|
|
183
|
+
tstzrange: "string",
|
|
184
|
+
tstzmultirange: "string",
|
|
185
|
+
daterange: "string",
|
|
186
|
+
datemultirange: "string",
|
|
187
|
+
// Misc
|
|
188
|
+
void: "interface{}",
|
|
189
|
+
record: "map[string]interface{}",
|
|
190
|
+
};
|
|
191
|
+
const GO_NULLABLE_TYPE_MAP = {
|
|
192
|
+
string: "*string",
|
|
193
|
+
bool: "*bool",
|
|
194
|
+
int16: "*int16",
|
|
195
|
+
int32: "*int32",
|
|
196
|
+
int64: "*int64",
|
|
197
|
+
float32: "*float32",
|
|
198
|
+
float64: "*float64",
|
|
199
|
+
"[]byte": "[]byte",
|
|
200
|
+
"interface{}": "interface{}",
|
|
201
|
+
"map[string]interface{}": "map[string]interface{}",
|
|
202
|
+
};
|
|
203
|
+
function pgTypeToGoType(pgType, nullable, types = []) {
|
|
204
|
+
let goType = undefined;
|
|
205
|
+
if (pgType in GO_TYPE_MAP) {
|
|
206
|
+
goType = GO_TYPE_MAP[pgType];
|
|
207
|
+
}
|
|
208
|
+
// Enums
|
|
209
|
+
const enumType = types.find((type) => type.name === pgType && type.enums.length > 0);
|
|
210
|
+
if (enumType) {
|
|
211
|
+
goType = "string";
|
|
212
|
+
}
|
|
213
|
+
if (goType) {
|
|
214
|
+
if (nullable) {
|
|
215
|
+
return GO_NULLABLE_TYPE_MAP[goType];
|
|
216
|
+
}
|
|
217
|
+
return goType;
|
|
218
|
+
}
|
|
219
|
+
// Composite types
|
|
220
|
+
const compositeType = types.find((type) => type.name === pgType && type.attributes.length > 0);
|
|
221
|
+
if (compositeType) {
|
|
222
|
+
// TODO: generate composite types
|
|
223
|
+
// return formatForGoTypeName(pgType)
|
|
224
|
+
return "map[string]interface{}";
|
|
225
|
+
}
|
|
226
|
+
// Arrays
|
|
227
|
+
if (pgType.startsWith("_")) {
|
|
228
|
+
const innerType = pgTypeToGoType(pgType.slice(1), nullable, types);
|
|
229
|
+
return `[]${innerType} `;
|
|
230
|
+
}
|
|
231
|
+
// Fallback
|
|
232
|
+
return "interface{}";
|
|
233
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { sortGeneratorMetadata } from "../sort.ts";
|
|
2
|
+
export { generateGo } from "./go.ts";
|
|
3
|
+
export { generatePython } from "./python.ts";
|
|
4
|
+
export { generateTypescript, type GenerateTypescriptOptions, pgTypeToTsType, } from "./typescript.ts";
|
|
5
|
+
export { type AccessControl, generateSwift, type GenerateSwiftOptions, } from "./swift.ts";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { GeneratorMetadata } from "../types.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Emits tables/views/materialized views in `GeneratorMetadata` order. Pass
|
|
4
|
+
* input pre-sorted with `sortGeneratorMetadata` for deterministic output.
|
|
5
|
+
*/
|
|
6
|
+
export declare const generatePython: ({ schemas, tables, views, materializedViews, columns, types, }: GeneratorMetadata) => string;
|