true-pg 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/.github/workflows/releases.yml +29 -0
- package/README.md +133 -0
- package/package.json +26 -0
- package/src/bin.ts +81 -0
- package/src/consumer.ts +38 -0
- package/src/index.ts +185 -0
- package/src/kysely/builtins.ts +38 -0
- package/src/kysely/index.ts +315 -0
- package/src/types.ts +297 -0
- package/src/util.ts +1 -0
- package/src/zod/builtins.ts +38 -0
- package/src/zod/index.ts +301 -0
- package/tsconfig.json +28 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
name: Release
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- v*
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
release:
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
|
12
|
+
permissions:
|
13
|
+
contents: read
|
14
|
+
id-token: write
|
15
|
+
|
16
|
+
steps:
|
17
|
+
- uses: actions/checkout@v4
|
18
|
+
- uses: oven-sh/setup-bun@v2
|
19
|
+
- run : bun install
|
20
|
+
- run : bun run prepare
|
21
|
+
- name: Publish to npm
|
22
|
+
run : |
|
23
|
+
bun run version.ts
|
24
|
+
bun publish --ignore-scripts --access=public
|
25
|
+
env :
|
26
|
+
NPM_CONFIG_TOKEN: ${{ secrets.NPM_CONFIG_TOKEN }}
|
27
|
+
NPM_CONFIG_PROVENANCE: true
|
28
|
+
- name: Publish to JSR
|
29
|
+
run: bunx jsr publish --allow-dirty
|
package/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# true-pg
|
2
|
+
|
3
|
+
A truthful and complete<sup>†</sup> TypeScript code generator for PostgreSQL database schemas.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
npm install true-pg
|
9
|
+
# or
|
10
|
+
yarn add true-pg
|
11
|
+
# or
|
12
|
+
bun add true-pg
|
13
|
+
```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
### Command Line Interface
|
18
|
+
|
19
|
+
```bash
|
20
|
+
true-pg [options]
|
21
|
+
```
|
22
|
+
|
23
|
+
Options:
|
24
|
+
|
25
|
+
- `-h, --help` - Show help information
|
26
|
+
- `-c, --config [path]` - Path to config file (JSON)
|
27
|
+
- `-u, --uri [uri]` - Database URI (Postgres only!)
|
28
|
+
- `-o, --out [path]` - Path to output directory (defaults to "models")
|
29
|
+
- `-a, --adapter [adapter]` - Adapter to use (e.g. `kysely`, `zod`). Can be specified multiple times.
|
30
|
+
- `-A, --all-adapters` - Enable all built-in adapters
|
31
|
+
|
32
|
+
You can configure true-pg either through command-line arguments or a config file.
|
33
|
+
|
34
|
+
### Configuration file
|
35
|
+
|
36
|
+
The tool looks for configuration in the following locations (in order):
|
37
|
+
|
38
|
+
1. `.truepgrc.json`
|
39
|
+
2. `.config/.truepgrc.json`
|
40
|
+
|
41
|
+
Example config file:
|
42
|
+
|
43
|
+
```json
|
44
|
+
{
|
45
|
+
"uri": "postgres://user:password@localhost:5432/database",
|
46
|
+
"out": "src/models",
|
47
|
+
"adapters": ["kysely", "zod"],
|
48
|
+
"defaultSchema": "public"
|
49
|
+
}
|
50
|
+
```
|
51
|
+
|
52
|
+
## Configuration Options
|
53
|
+
|
54
|
+
| Option | Description | Default |
|
55
|
+
| --------------- | -------------------------------------------------------- | ---------- |
|
56
|
+
| `uri` | PostgreSQL connection URI | Required |
|
57
|
+
| `out` | Output directory for generated files | `"models"` |
|
58
|
+
| `adapters` | Adapters to use (e.g. `kysely`, `zod`) | `"kysely"` |
|
59
|
+
| `defaultSchema` | Default schema to use (Kysely schema will be unprefixed) | `"public"` |
|
60
|
+
|
61
|
+
## Customising Code Generation
|
62
|
+
|
63
|
+
> 🔔 HERE BE DRAGONS!
|
64
|
+
>
|
65
|
+
> Keep in mind that programmatic usage of `true-pg` is not yet stable. Functions and methods may change until we're comfortable with the API.
|
66
|
+
>
|
67
|
+
> However, if you're interested, we welcome your feedback and contributions!
|
68
|
+
|
69
|
+
You can create a custom generator to control how code is generated:
|
70
|
+
|
71
|
+
```typescript
|
72
|
+
import { createGenerator, generate } from "true-pg";
|
73
|
+
|
74
|
+
const generator = createGenerator(opts => ({
|
75
|
+
formatSchema: name => `${name}Schema`,
|
76
|
+
formatSchemaType: type => `${type}Type`,
|
77
|
+
formatType: type => `${type}Interface`,
|
78
|
+
table: (imports, table) => {
|
79
|
+
// Custom table type generation
|
80
|
+
},
|
81
|
+
enum: (imports, en) => {
|
82
|
+
// Custom enum type generation
|
83
|
+
},
|
84
|
+
composite: (imports, composite) => {
|
85
|
+
// Custom composite type generation
|
86
|
+
},
|
87
|
+
function: (imports, func) => {
|
88
|
+
// Custom function type generation
|
89
|
+
},
|
90
|
+
schemaKindIndex: (schema, kind) => {
|
91
|
+
// Custom schema kind index generation
|
92
|
+
},
|
93
|
+
schemaIndex: schema => {
|
94
|
+
// Custom schema index generation
|
95
|
+
},
|
96
|
+
fullIndex: schemas => {
|
97
|
+
// Custom full index generation
|
98
|
+
},
|
99
|
+
}));
|
100
|
+
|
101
|
+
await generate(
|
102
|
+
{
|
103
|
+
uri: "postgres://user:password@localhost:5432/database",
|
104
|
+
out: "src/models",
|
105
|
+
},
|
106
|
+
[generator],
|
107
|
+
);
|
108
|
+
```
|
109
|
+
|
110
|
+
Filenames will be created using the `format*` methods of the FIRST generator passed to `generate` or via the `--adapter` CLI option.
|
111
|
+
|
112
|
+
## Schema Generator Interface
|
113
|
+
|
114
|
+
The `SchemaGenerator` interface provides methods to customize code generation:
|
115
|
+
|
116
|
+
| Method | Description |
|
117
|
+
| ------------------------------- | ----------------------------------------------------------------- |
|
118
|
+
| `formatSchema(name)` | Formats schema names (public -> PublicSchema) |
|
119
|
+
| `formatSchemaType(type)` | Formats schema type names (user_sessions -> UserSessions) |
|
120
|
+
| `formatType(type)` | Formats type names (pg_catalog.int4 -> number) |
|
121
|
+
| `table(types, table)` | Generates code for tables |
|
122
|
+
| `enum(types, en)` | Generates code for enums |
|
123
|
+
| `composite(types, composite)` | Generates code for composite types |
|
124
|
+
| `function(types, func)` | Generates code for functions |
|
125
|
+
| `schemaKindIndex(schema, kind)` | Generates index for a schema kind (models/public/tables/index.ts) |
|
126
|
+
| `schemaIndex(schema)` | Generates index for a schema (models/public/index.ts) |
|
127
|
+
| `fullIndex(schemas)` | Generates full index (models/index.ts) |
|
128
|
+
|
129
|
+
## License
|
130
|
+
|
131
|
+
[MIT](LICENSE)
|
132
|
+
|
133
|
+
<sup>†</sup> We only support tables, enums, composite types, and functions at the moment, but we're working on adding support for views, materialised views, domains, and more.
|
package/package.json
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"name": "true-pg",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"module": "src/index.ts",
|
5
|
+
"type": "module",
|
6
|
+
"main": "src/index.ts",
|
7
|
+
"bin": {
|
8
|
+
"true-pg": "src/bin.ts"
|
9
|
+
},
|
10
|
+
"scripts": {
|
11
|
+
"check": "tsc --noEmit",
|
12
|
+
"build": "tsc"
|
13
|
+
},
|
14
|
+
"devDependencies": {
|
15
|
+
"@types/bun": "latest"
|
16
|
+
},
|
17
|
+
"peerDependencies": {
|
18
|
+
"kysely": "^0.27",
|
19
|
+
"typescript": "^5",
|
20
|
+
"zod": "^3"
|
21
|
+
},
|
22
|
+
"dependencies": {
|
23
|
+
"mri": "^1.2.0",
|
24
|
+
"pg-extract": "^0.0.3"
|
25
|
+
}
|
26
|
+
}
|
package/src/bin.ts
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
import mri from "mri";
|
2
|
+
import { existsSync } from "fs";
|
3
|
+
import { generate, adapters } from "./index.ts";
|
4
|
+
|
5
|
+
const args = process.argv.slice(2);
|
6
|
+
const opts = mri<{
|
7
|
+
"help"?: boolean;
|
8
|
+
"config"?: string;
|
9
|
+
"uri"?: string;
|
10
|
+
"out"?: string;
|
11
|
+
"adapter"?: string | string[];
|
12
|
+
"all-adapters"?: boolean;
|
13
|
+
}>(args, {
|
14
|
+
boolean: ["help", "all-adapters"],
|
15
|
+
string: ["config", "uri", "out", "adapter"],
|
16
|
+
alias: {
|
17
|
+
h: "help",
|
18
|
+
c: "config",
|
19
|
+
u: "uri",
|
20
|
+
o: "out",
|
21
|
+
a: "adapter",
|
22
|
+
A: "all-adapters",
|
23
|
+
},
|
24
|
+
});
|
25
|
+
|
26
|
+
const help = opts.help || (!opts.config && !opts.uri);
|
27
|
+
|
28
|
+
if (help) {
|
29
|
+
// if help is triggered unintentionally, it's a user error
|
30
|
+
const type = opts.help ? "log" : "error";
|
31
|
+
const log = console[type];
|
32
|
+
|
33
|
+
log();
|
34
|
+
log("Usage: true-pg [options]");
|
35
|
+
log();
|
36
|
+
log("Options:");
|
37
|
+
log(" -h, --help Show help");
|
38
|
+
log(" -u, --uri [uri] Database URI (Postgres only!)");
|
39
|
+
log(" -o, --out [path] Path to output directory");
|
40
|
+
log(" -a, --adapter [adapter] Output adapter to use (default: 'kysely')");
|
41
|
+
log(" -A, --all-adapters Output all adapters");
|
42
|
+
log(" -c, --config [path] Path to config file (JSON)");
|
43
|
+
log(" Defaults to '.truepgrc.json' or '.config/.truepgrc.json'");
|
44
|
+
log("Example:");
|
45
|
+
log(" true-pg -u postgres://user:pass@localhost:5432/my-database -o models -a kysely -a zod");
|
46
|
+
log();
|
47
|
+
if (opts.help) process.exit(0);
|
48
|
+
else process.exit(1);
|
49
|
+
}
|
50
|
+
|
51
|
+
let configfile = opts.config;
|
52
|
+
if (!configfile) {
|
53
|
+
const candidates = [".truepgrc.json", ".config/.truepgrc.json"];
|
54
|
+
for (const candidate of candidates) {
|
55
|
+
if (await existsSync(candidate)) {
|
56
|
+
configfile = candidate;
|
57
|
+
break;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
const config = configfile ? await Bun.file(configfile).json() : {};
|
63
|
+
|
64
|
+
if (opts["all-adapters"]) {
|
65
|
+
opts.adapter = Object.keys(adapters);
|
66
|
+
console.log("Enabling all built-in adapters:", opts.adapter);
|
67
|
+
}
|
68
|
+
|
69
|
+
if (!(opts.adapter || config.adapters)) console.warn('No adapters specified, using default: ["kysely"]');
|
70
|
+
|
71
|
+
opts.out ??= "models";
|
72
|
+
// allow single adapter or comma-separated list of adapters
|
73
|
+
if (typeof opts.adapter === "string") opts.adapter = opts.adapter.split(",");
|
74
|
+
opts.adapter ??= ["kysely"];
|
75
|
+
|
76
|
+
// CLI args take precedence over config file
|
77
|
+
config.uri = opts.uri ?? config.uri;
|
78
|
+
config.out = opts.out ?? config.out;
|
79
|
+
config.adapters = opts.adapter ?? config.adapters;
|
80
|
+
|
81
|
+
await generate(config);
|
package/src/consumer.ts
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
export declare namespace True {
|
2
|
+
export type Column<Selectable, Insertable = Selectable, Updateable = Selectable> = {
|
3
|
+
"@true-pg/insert": Insertable;
|
4
|
+
"@true-pg/update": Updateable;
|
5
|
+
"@true-pg/select": Selectable;
|
6
|
+
};
|
7
|
+
|
8
|
+
export type Generated<T> = Column<T, T | undefined, T | undefined>;
|
9
|
+
export type HasDefault<T> = Column<T, T | undefined, T | undefined>;
|
10
|
+
export type AlwaysGenerated<T> = Column<T, never, never>;
|
11
|
+
|
12
|
+
type DrainOuterGeneric<T> = [T] extends [unknown] ? T : never;
|
13
|
+
type Simplify<T> = DrainOuterGeneric<{ [K in keyof T]: T[K] } & {}>;
|
14
|
+
|
15
|
+
export type Selectable<T extends Record<string, any>> = Simplify<{
|
16
|
+
[K in keyof T]: T[K] extends Record<string, any>
|
17
|
+
? Selectable<T[K]>
|
18
|
+
: T[K] extends Column<infer S, infer I, infer U>
|
19
|
+
? S
|
20
|
+
: T[K];
|
21
|
+
}>;
|
22
|
+
|
23
|
+
export type Insertable<T extends Record<string, any>> = Simplify<{
|
24
|
+
[K in keyof T]: T[K] extends Record<string, any>
|
25
|
+
? Insertable<T[K]>
|
26
|
+
: T[K] extends Column<infer S, infer I, infer U>
|
27
|
+
? I
|
28
|
+
: T[K];
|
29
|
+
}>;
|
30
|
+
|
31
|
+
export type Updateable<T extends Record<string, any>> = Simplify<{
|
32
|
+
[K in keyof T]?: T[K] extends Record<string, any>
|
33
|
+
? Updateable<T[K]>
|
34
|
+
: T[K] extends Column<infer S, infer I, infer U>
|
35
|
+
? U
|
36
|
+
: T[K];
|
37
|
+
}>;
|
38
|
+
}
|
package/src/index.ts
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
import { Extractor, type FunctionDetails, type Schema } from "pg-extract";
|
2
|
+
import { rm, mkdir, writeFile } from "fs/promises";
|
3
|
+
import { Nodes, allowed_kind_names, type FolderStructure, type TruePGOpts, type createGenerator } from "./types.ts";
|
4
|
+
import { existsSync } from "fs";
|
5
|
+
import { join } from "./util.ts";
|
6
|
+
|
7
|
+
import { Kysely } from "./kysely/index.ts";
|
8
|
+
import { Zod } from "./zod/index.ts";
|
9
|
+
|
10
|
+
export const adapters: Record<string, createGenerator> = {
|
11
|
+
kysely: Kysely,
|
12
|
+
zod: Zod,
|
13
|
+
};
|
14
|
+
|
15
|
+
export * from "./consumer.ts";
|
16
|
+
|
17
|
+
const filter_function = (func: FunctionDetails, warnings: string[]) => {
|
18
|
+
const typesToFilter = [
|
19
|
+
"pg_catalog.trigger",
|
20
|
+
"pg_catalog.event_trigger",
|
21
|
+
"pg_catalog.internal",
|
22
|
+
"pg_catalog.language_handler",
|
23
|
+
"pg_catalog.fdw_handler",
|
24
|
+
"pg_catalog.index_am_handler",
|
25
|
+
"pg_catalog.tsm_handler",
|
26
|
+
];
|
27
|
+
|
28
|
+
const warn = (type: string) =>
|
29
|
+
warnings.push(`Skipping function ${func.name}: cannot represent ${type} (safe to ignore)`);
|
30
|
+
|
31
|
+
if (func.returnType.kind === "table") {
|
32
|
+
for (const col of func.returnType.columns) {
|
33
|
+
if (typesToFilter.includes(col.type.canonical_name)) {
|
34
|
+
warn(col.type.canonical_name);
|
35
|
+
return false;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
} else {
|
39
|
+
if (typesToFilter.includes(func.returnType.type.canonical_name)) {
|
40
|
+
warn(func.returnType.type.canonical_name);
|
41
|
+
return false;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
for (const param of func.parameters) {
|
46
|
+
if (typesToFilter.includes(param.type.canonical_name)) {
|
47
|
+
warn(param.type.canonical_name);
|
48
|
+
return false;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
return func;
|
53
|
+
};
|
54
|
+
|
55
|
+
const write = (filename: string, file: string) => writeFile(filename, file + "\n");
|
56
|
+
|
57
|
+
const multifile = async (generators: createGenerator[], schemas: Record<string, Schema>, opts: TruePGOpts) => {
|
58
|
+
const { out } = opts;
|
59
|
+
|
60
|
+
const warnings: string[] = [];
|
61
|
+
const gens = generators.map(g => g({ ...opts, warnings }));
|
62
|
+
const def_gen = gens[0]!;
|
63
|
+
|
64
|
+
const files: FolderStructure = {
|
65
|
+
name: out,
|
66
|
+
type: "root",
|
67
|
+
children: Object.fromEntries(
|
68
|
+
Object.values(schemas).map(schema => [
|
69
|
+
schema.name,
|
70
|
+
{
|
71
|
+
name: schema.name,
|
72
|
+
type: "schema",
|
73
|
+
children: Object.fromEntries(
|
74
|
+
allowed_kind_names.map(kind => [
|
75
|
+
kind,
|
76
|
+
{
|
77
|
+
kind: kind,
|
78
|
+
type: "kind",
|
79
|
+
children: Object.fromEntries(
|
80
|
+
schema[kind].map(item => [
|
81
|
+
item.name,
|
82
|
+
{
|
83
|
+
name: def_gen.formatSchemaType(item),
|
84
|
+
type: "type",
|
85
|
+
},
|
86
|
+
]),
|
87
|
+
),
|
88
|
+
},
|
89
|
+
]),
|
90
|
+
),
|
91
|
+
},
|
92
|
+
]),
|
93
|
+
),
|
94
|
+
};
|
95
|
+
|
96
|
+
const start = performance.now();
|
97
|
+
|
98
|
+
for (const schema of Object.values(schemas)) {
|
99
|
+
console.log("Selected schema '%s':\n", schema.name);
|
100
|
+
|
101
|
+
const schemaDir = `${out}/${schema.name}`;
|
102
|
+
|
103
|
+
// skip functions that cannot be represented in JavaScript
|
104
|
+
schema.functions = schema.functions.filter(f => filter_function(f, warnings));
|
105
|
+
|
106
|
+
for (const kind of allowed_kind_names) {
|
107
|
+
if (schema[kind].length < 1) continue;
|
108
|
+
|
109
|
+
await mkdir(`${schemaDir}/${kind}`, { recursive: true });
|
110
|
+
console.log(" Creating %s:\n", kind);
|
111
|
+
|
112
|
+
for (const [i, item] of schema[kind].entries()) {
|
113
|
+
const index = "[" + (i + 1 + "]").padEnd(3, " ");
|
114
|
+
const filename = `${schemaDir}/${kind}/${def_gen.formatSchemaType(item)}.ts`;
|
115
|
+
|
116
|
+
const exists = await existsSync(filename);
|
117
|
+
|
118
|
+
if (exists) {
|
119
|
+
warnings.push(
|
120
|
+
`Skipping ${item.kind} "${item.name}": formatted name clashes. Wanted to create ${filename}`,
|
121
|
+
);
|
122
|
+
continue;
|
123
|
+
}
|
124
|
+
|
125
|
+
const start = performance.now();
|
126
|
+
|
127
|
+
let file = "";
|
128
|
+
|
129
|
+
const imports = new Nodes.ImportList([]);
|
130
|
+
|
131
|
+
if (item.kind === "table") file += join(gens.map(gen => gen.table(imports, item)));
|
132
|
+
if (item.kind === "composite") file += join(gens.map(gen => gen.composite(imports, item)));
|
133
|
+
if (item.kind === "enum") file += join(gens.map(gen => gen.enum(imports, item)));
|
134
|
+
if (item.kind === "function") file += join(gens.map(gen => gen.function(imports, item)));
|
135
|
+
|
136
|
+
const parts: string[] = [];
|
137
|
+
parts.push(imports.stringify(filename, files));
|
138
|
+
parts.push(file);
|
139
|
+
file = join(parts);
|
140
|
+
|
141
|
+
await write(filename, file);
|
142
|
+
|
143
|
+
const end = performance.now();
|
144
|
+
console.log(" %s %s \x1b[32m(%sms)\x1B[0m", index, filename, (end - start).toFixed(2));
|
145
|
+
}
|
146
|
+
|
147
|
+
const kindIndex = join(gens.map(gen => gen.schemaKindIndex(schema, kind, def_gen)));
|
148
|
+
const kindIndexFilename = `${schemaDir}/${kind}/index.ts`;
|
149
|
+
await write(kindIndexFilename, kindIndex);
|
150
|
+
console.log(' ✅ Created "%s" %s index: %s\n', schema.name, kind, kindIndexFilename);
|
151
|
+
}
|
152
|
+
|
153
|
+
const index = join(gens.map(gen => gen.schemaIndex(schema, def_gen)));
|
154
|
+
const indexFilename = `${out}/${schema.name}/index.ts`;
|
155
|
+
await write(indexFilename, index);
|
156
|
+
console.log(" Created schema index: %s\n", indexFilename);
|
157
|
+
}
|
158
|
+
|
159
|
+
const fullIndex = join(gens.map(gen => gen.fullIndex(Object.values(schemas))));
|
160
|
+
const fullIndexFilename = `${out}/index.ts`;
|
161
|
+
await write(fullIndexFilename, fullIndex);
|
162
|
+
console.log("Created full index: %s", fullIndexFilename);
|
163
|
+
const end = performance.now();
|
164
|
+
console.log("Completed in \x1b[32m%sms\x1b[0m", (end - start).toFixed(2));
|
165
|
+
|
166
|
+
if (warnings.length > 0) {
|
167
|
+
console.log("\nWarnings generated:");
|
168
|
+
console.log(warnings.map(warning => "* " + warning).join("\n"));
|
169
|
+
}
|
170
|
+
};
|
171
|
+
|
172
|
+
export async function generate(opts: TruePGOpts, generators?: createGenerator[]) {
|
173
|
+
const out = opts.out || "./models";
|
174
|
+
const extractor = new Extractor(opts.uri);
|
175
|
+
const schemas = await extractor.extractSchemas();
|
176
|
+
generators ??= opts.adapters.map(adapter => {
|
177
|
+
const selected = adapters[adapter];
|
178
|
+
if (!selected) throw new Error(`Requested adapter ${adapter} not found`);
|
179
|
+
return selected;
|
180
|
+
});
|
181
|
+
console.log("Clearing directory and generating schemas at '%s'", out);
|
182
|
+
await rm(out, { recursive: true, force: true });
|
183
|
+
await mkdir(out, { recursive: true });
|
184
|
+
await multifile(generators, schemas, { ...opts, out });
|
185
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
// extended from https://github.com/kristiandupont/kanel/blob/e9332f03ff5e38f5b844dd7a4563580c0d9d1444/packages/kanel/src/defaultTypeMap.ts
|
2
|
+
|
3
|
+
export const builtins: Record<string, string> = {
|
4
|
+
"pg_catalog.int2": "number",
|
5
|
+
"pg_catalog.int4": "number",
|
6
|
+
|
7
|
+
// JS numbers are always floating point, so there is only 53 bits of precision
|
8
|
+
// for the integer part. Thus, storing a 64-bit integer in a JS number will
|
9
|
+
// result in potential data loss. We therefore use strings for 64-bit integers
|
10
|
+
// the same way that the pg driver does.
|
11
|
+
"pg_catalog.int8": "string",
|
12
|
+
|
13
|
+
"pg_catalog.float4": "number",
|
14
|
+
"pg_catalog.float8": "number",
|
15
|
+
"pg_catalog.numeric": "string",
|
16
|
+
"pg_catalog.bool": "boolean",
|
17
|
+
"pg_catalog.json": "unknown",
|
18
|
+
"pg_catalog.jsonb": "unknown",
|
19
|
+
"pg_catalog.char": "string",
|
20
|
+
"pg_catalog.bpchar": "string",
|
21
|
+
"pg_catalog.varchar": "string",
|
22
|
+
"pg_catalog.text": "string",
|
23
|
+
"pg_catalog.uuid": "string",
|
24
|
+
"pg_catalog.inet": "string",
|
25
|
+
"pg_catalog.date": "Date",
|
26
|
+
"pg_catalog.time": "Date",
|
27
|
+
"pg_catalog.timetz": "Date",
|
28
|
+
"pg_catalog.timestamp": "Date",
|
29
|
+
"pg_catalog.timestamptz": "Date",
|
30
|
+
"pg_catalog.int4range": "string",
|
31
|
+
"pg_catalog.int8range": "string",
|
32
|
+
"pg_catalog.numrange": "string",
|
33
|
+
"pg_catalog.tsrange": "string",
|
34
|
+
"pg_catalog.tstzrange": "string",
|
35
|
+
"pg_catalog.daterange": "string",
|
36
|
+
"pg_catalog.record": "Record<string, unknown>",
|
37
|
+
"pg_catalog.void": "void",
|
38
|
+
};
|