@typed-sql/schema 1.0.0-beta.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/CHANGELOG.md +10 -0
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/packages/schema/src/generator.d.ts +22 -0
- package/dist/packages/schema/src/generator.d.ts.map +1 -0
- package/dist/packages/schema/src/generator.js +63 -0
- package/dist/packages/schema/src/generator.js.map +1 -0
- package/dist/packages/schema/src/index.d.ts +6 -0
- package/dist/packages/schema/src/index.d.ts.map +1 -0
- package/dist/packages/schema/src/index.js +4 -0
- package/dist/packages/schema/src/index.js.map +1 -0
- package/dist/packages/schema/src/loader.d.ts +12 -0
- package/dist/packages/schema/src/loader.d.ts.map +1 -0
- package/dist/packages/schema/src/loader.js +172 -0
- package/dist/packages/schema/src/loader.js.map +1 -0
- package/dist/packages/schema/src/model.d.ts +58 -0
- package/dist/packages/schema/src/model.d.ts.map +1 -0
- package/dist/packages/schema/src/model.js +2 -0
- package/dist/packages/schema/src/model.js.map +1 -0
- package/dist/packages/schema/src/postgres-provider.d.ts +84 -0
- package/dist/packages/schema/src/postgres-provider.d.ts.map +1 -0
- package/dist/packages/schema/src/postgres-provider.js +196 -0
- package/dist/packages/schema/src/postgres-provider.js.map +1 -0
- package/dist/packages/schema/src/resolver.d.ts +22 -0
- package/dist/packages/schema/src/resolver.d.ts.map +1 -0
- package/dist/packages/schema/src/resolver.js +196 -0
- package/dist/packages/schema/src/resolver.js.map +1 -0
- package/dist/packages/schema/src/type-policy.d.ts +4 -0
- package/dist/packages/schema/src/type-policy.d.ts.map +1 -0
- package/dist/packages/schema/src/type-policy.js +46 -0
- package/dist/packages/schema/src/type-policy.js.map +1 -0
- package/package.json +40 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# @typed-sql/schema
|
|
2
|
+
|
|
3
|
+
## 1.0.0-beta.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- Release the first public typed-sql beta: exact TypeScript 7 row inference from static PostgreSQL and
|
|
8
|
+
MySQL, versioned schema introspection, application-owned drivers, config-driven grammar plugins,
|
|
9
|
+
CLI verification, editor language-server integration, versioned diagnostics, bounded parsing, and
|
|
10
|
+
real-database plus packed-tarball verification.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 typed-sql contributors
|
|
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,33 @@
|
|
|
1
|
+
# @typed-sql/schema
|
|
2
|
+
|
|
3
|
+
Versioned database snapshots, deterministic generation, migrations, hashes, and drift detection for
|
|
4
|
+
[typed-sql](https://github.com/Lojhan/typed-sql).
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
pnpm add @typed-sql/schema@next
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import {
|
|
12
|
+
SCHEMA_FORMAT_VERSION,
|
|
13
|
+
calculateSchemaHash,
|
|
14
|
+
checkSchemaDrift,
|
|
15
|
+
generateSchemaPackage,
|
|
16
|
+
loadSchemaSnapshot,
|
|
17
|
+
migrateSchemaSnapshot,
|
|
18
|
+
parseSchemaSnapshot,
|
|
19
|
+
} from "@typed-sql/schema";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Schema format `1` records the dialect, dialect version, server version, tables, columns, views,
|
|
23
|
+
enums, domains, arrays, database functions, nullability, TypeScript mappings, and deterministic
|
|
24
|
+
hashes. Unknown future snapshot versions fail explicitly instead of being interpreted optimistically.
|
|
25
|
+
|
|
26
|
+
Generated TypeScript is metadata for inspection and editor tooling. Applications do not import
|
|
27
|
+
their `sql` tag or runtime policy from the generated directory.
|
|
28
|
+
|
|
29
|
+
Most applications use this package indirectly through `@typed-sql/cli`. Grammar and tooling authors
|
|
30
|
+
use it to validate snapshots and implement providers. See the
|
|
31
|
+
[architecture](https://github.com/Lojhan/typed-sql/blob/main/docs/ARCHITECTURE.md).
|
|
32
|
+
|
|
33
|
+
MIT © typed-sql contributors
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GeneratedSchemaMetadata, GeneratedSchemaSnapshot, SchemaSnapshot } from "./model.js";
|
|
2
|
+
export interface GenerateSchemaOptions {
|
|
3
|
+
readonly outDir: string;
|
|
4
|
+
readonly typePolicy?: unknown;
|
|
5
|
+
readonly generatorVersion?: string;
|
|
6
|
+
readonly dialectVersion?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function calculateSchemaHash(schema: SchemaSnapshot): string;
|
|
9
|
+
export declare function calculateTypePolicyHash(policy: unknown): string;
|
|
10
|
+
export interface SchemaDriftResult {
|
|
11
|
+
readonly drifted: boolean;
|
|
12
|
+
readonly schemaChanged: boolean;
|
|
13
|
+
readonly typePolicyChanged: boolean;
|
|
14
|
+
readonly expectedSchemaHash: string;
|
|
15
|
+
readonly actualSchemaHash: string;
|
|
16
|
+
readonly expectedTypePolicyHash: string;
|
|
17
|
+
readonly actualTypePolicyHash: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function checkSchemaDrift(generated: GeneratedSchemaSnapshot, current: SchemaSnapshot, policy?: unknown): SchemaDriftResult;
|
|
20
|
+
export declare function generateSchemaPackage(schema: SchemaSnapshot, options: GenerateSchemaOptions): Promise<GeneratedSchemaMetadata>;
|
|
21
|
+
export type { GeneratedSchemaMetadata } from "./model.js";
|
|
22
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../../src/generator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGnG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAUD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAElE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAE/D;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACvC;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,uBAAuB,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAE,OAAY,GAAG,iBAAiB,CAmBrI;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAuBpI;AAED,YAAY,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { SCHEMA_FORMAT_VERSION } from "./model.js";
|
|
5
|
+
function canonicalize(value) {
|
|
6
|
+
if (Array.isArray(value))
|
|
7
|
+
return value.map(canonicalize);
|
|
8
|
+
if (typeof value !== "object" || value === null)
|
|
9
|
+
return value;
|
|
10
|
+
return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => [key, canonicalize(item)]));
|
|
11
|
+
}
|
|
12
|
+
const hash = (value) => createHash("sha256").update(JSON.stringify(canonicalize(value))).digest("hex");
|
|
13
|
+
export function calculateSchemaHash(schema) {
|
|
14
|
+
return hash(schema);
|
|
15
|
+
}
|
|
16
|
+
export function calculateTypePolicyHash(policy) {
|
|
17
|
+
return hash(policy);
|
|
18
|
+
}
|
|
19
|
+
export function checkSchemaDrift(generated, current, policy = {}) {
|
|
20
|
+
const comparableCurrent = {
|
|
21
|
+
...current,
|
|
22
|
+
...(generated.formatVersion === undefined ? {} : { formatVersion: generated.formatVersion }),
|
|
23
|
+
...(generated.dialectVersion === undefined ? {} : { dialectVersion: generated.dialectVersion }),
|
|
24
|
+
};
|
|
25
|
+
const actualSchemaHash = calculateSchemaHash(comparableCurrent);
|
|
26
|
+
const actualTypePolicyHash = calculateTypePolicyHash(policy);
|
|
27
|
+
const schemaChanged = generated.metadata.schemaHash !== actualSchemaHash;
|
|
28
|
+
const typePolicyChanged = generated.metadata.typePolicyHash !== actualTypePolicyHash;
|
|
29
|
+
return {
|
|
30
|
+
drifted: schemaChanged || typePolicyChanged,
|
|
31
|
+
schemaChanged,
|
|
32
|
+
typePolicyChanged,
|
|
33
|
+
expectedSchemaHash: generated.metadata.schemaHash,
|
|
34
|
+
actualSchemaHash,
|
|
35
|
+
expectedTypePolicyHash: generated.metadata.typePolicyHash,
|
|
36
|
+
actualTypePolicyHash,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export async function generateSchemaPackage(schema, options) {
|
|
40
|
+
const policy = options.typePolicy ?? {};
|
|
41
|
+
const versionedSchema = {
|
|
42
|
+
...schema,
|
|
43
|
+
formatVersion: SCHEMA_FORMAT_VERSION,
|
|
44
|
+
...(options.dialectVersion === undefined ? {} : { dialectVersion: options.dialectVersion }),
|
|
45
|
+
};
|
|
46
|
+
const metadata = {
|
|
47
|
+
generatorVersion: options.generatorVersion ?? "1.0.0",
|
|
48
|
+
schemaHash: calculateSchemaHash(versionedSchema),
|
|
49
|
+
typePolicyHash: calculateTypePolicyHash(policy),
|
|
50
|
+
};
|
|
51
|
+
await mkdir(options.outDir, { recursive: true });
|
|
52
|
+
await writeFile(join(options.outDir, "schema.json"), `${JSON.stringify({ ...versionedSchema, metadata }, null, 2)}\n`, "utf8");
|
|
53
|
+
const moduleSource = [
|
|
54
|
+
`// Generated by @typed-sql/cli ${metadata.generatorVersion}. Schema metadata only; do not edit.`,
|
|
55
|
+
`export const schema = ${JSON.stringify(versionedSchema, null, 2)} as const;`,
|
|
56
|
+
`export const metadata = ${JSON.stringify(metadata, null, 2)} as const;`,
|
|
57
|
+
"export type DatabaseSchema = typeof schema;",
|
|
58
|
+
"",
|
|
59
|
+
].join("\n");
|
|
60
|
+
await writeFile(join(options.outDir, "index.ts"), moduleSource, "utf8");
|
|
61
|
+
return metadata;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../src/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { calculateSchemaHash, calculateTypePolicyHash, checkSchemaDrift, generateSchemaPackage } from "./generator.js";
|
|
2
|
+
export { SCHEMA_FORMAT_VERSION } from "./model.js";
|
|
3
|
+
export { loadGeneratedSchemaSnapshot, loadSchemaSnapshot, loadTypePolicy, migrateSchemaSnapshot, parseSchemaSnapshot, parseTypePolicy } from "./loader.js";
|
|
4
|
+
export type * from "./generator.js";
|
|
5
|
+
export type * from "./model.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvH,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,cAAc,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3J,mBAAmB,gBAAgB,CAAC;AACpC,mBAAmB,YAAY,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { calculateSchemaHash, calculateTypePolicyHash, checkSchemaDrift, generateSchemaPackage } from "./generator.js";
|
|
2
|
+
export { SCHEMA_FORMAT_VERSION } from "./model.js";
|
|
3
|
+
export { loadGeneratedSchemaSnapshot, loadSchemaSnapshot, loadTypePolicy, migrateSchemaSnapshot, parseSchemaSnapshot, parseTypePolicy } from "./loader.js";
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvH,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,cAAc,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GeneratedSchemaSnapshot, SchemaSnapshot, TypePolicy } from "./model.js";
|
|
2
|
+
export declare function parseSchemaSnapshot(value: unknown): SchemaSnapshot;
|
|
3
|
+
/**
|
|
4
|
+
* Migrates an unversioned pre-1.0 snapshot to the stable v1 format and validates
|
|
5
|
+
* already-versioned input. Future format migrations are added here.
|
|
6
|
+
*/
|
|
7
|
+
export declare function migrateSchemaSnapshot(value: unknown): SchemaSnapshot;
|
|
8
|
+
export declare function loadSchemaSnapshot(path: string): Promise<SchemaSnapshot>;
|
|
9
|
+
export declare function loadGeneratedSchemaSnapshot(path: string): Promise<GeneratedSchemaSnapshot>;
|
|
10
|
+
export declare function parseTypePolicy(value: unknown): TypePolicy;
|
|
11
|
+
export declare function loadTypePolicy(path: string): Promise<TypePolicy>;
|
|
12
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../src/loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAKV,uBAAuB,EACvB,cAAc,EAEd,UAAU,EACX,MAAM,YAAY,CAAC;AA2FpB,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAuBlE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAEpE;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAG9E;AAUD,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAKhG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAG1D;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAEtE"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { SCHEMA_FORMAT_VERSION } from "./model.js";
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function parseColumn(value, path) {
|
|
7
|
+
if (!isRecord(value))
|
|
8
|
+
throw new TypeError(`${path} must be an object`);
|
|
9
|
+
if (typeof value.name !== "string")
|
|
10
|
+
throw new TypeError(`${path}.name must be a string`);
|
|
11
|
+
if (typeof value.databaseType !== "string")
|
|
12
|
+
throw new TypeError(`${path}.databaseType must be a string`);
|
|
13
|
+
if (typeof value.tsType !== "string")
|
|
14
|
+
throw new TypeError(`${path}.tsType must be a string`);
|
|
15
|
+
if (typeof value.nullable !== "boolean")
|
|
16
|
+
throw new TypeError(`${path}.nullable must be a boolean`);
|
|
17
|
+
if (value.array !== undefined && typeof value.array !== "boolean")
|
|
18
|
+
throw new TypeError(`${path}.array must be a boolean`);
|
|
19
|
+
if (value.defaultExpression !== undefined && typeof value.defaultExpression !== "string") {
|
|
20
|
+
throw new TypeError(`${path}.defaultExpression must be a string`);
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
name: value.name,
|
|
24
|
+
databaseType: value.databaseType,
|
|
25
|
+
tsType: value.tsType,
|
|
26
|
+
nullable: value.nullable,
|
|
27
|
+
...(value.array === undefined ? {} : { array: value.array }),
|
|
28
|
+
...(value.defaultExpression === undefined ? {} : { defaultExpression: value.defaultExpression }),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function parseTable(value, path) {
|
|
32
|
+
if (!isRecord(value))
|
|
33
|
+
throw new TypeError(`${path} must be an object`);
|
|
34
|
+
if (typeof value.name !== "string")
|
|
35
|
+
throw new TypeError(`${path}.name must be a string`);
|
|
36
|
+
if (value.schema !== undefined && typeof value.schema !== "string")
|
|
37
|
+
throw new TypeError(`${path}.schema must be a string`);
|
|
38
|
+
if (!isRecord(value.columns))
|
|
39
|
+
throw new TypeError(`${path}.columns must be an object`);
|
|
40
|
+
const columns = {};
|
|
41
|
+
for (const [name, column] of Object.entries(value.columns))
|
|
42
|
+
columns[name] = parseColumn(column, `${path}.columns.${name}`);
|
|
43
|
+
return { name: value.name, columns, ...(value.schema === undefined ? {} : { schema: value.schema }) };
|
|
44
|
+
}
|
|
45
|
+
function parseDomain(value, path) {
|
|
46
|
+
if (!isRecord(value))
|
|
47
|
+
throw new TypeError(`${path} must be an object`);
|
|
48
|
+
if (typeof value.name !== "string")
|
|
49
|
+
throw new TypeError(`${path}.name must be a string`);
|
|
50
|
+
if (typeof value.databaseType !== "string")
|
|
51
|
+
throw new TypeError(`${path}.databaseType must be a string`);
|
|
52
|
+
if (typeof value.tsType !== "string")
|
|
53
|
+
throw new TypeError(`${path}.tsType must be a string`);
|
|
54
|
+
if (typeof value.nullable !== "boolean")
|
|
55
|
+
throw new TypeError(`${path}.nullable must be a boolean`);
|
|
56
|
+
return { name: value.name, databaseType: value.databaseType, tsType: value.tsType, nullable: value.nullable };
|
|
57
|
+
}
|
|
58
|
+
function parseFunction(value, path) {
|
|
59
|
+
if (!isRecord(value))
|
|
60
|
+
throw new TypeError(`${path} must be an object`);
|
|
61
|
+
if (typeof value.name !== "string")
|
|
62
|
+
throw new TypeError(`${path}.name must be a string`);
|
|
63
|
+
if (!Array.isArray(value.argumentTypes) || value.argumentTypes.some((item) => typeof item !== "string")) {
|
|
64
|
+
throw new TypeError(`${path}.argumentTypes must be a string array`);
|
|
65
|
+
}
|
|
66
|
+
if (typeof value.returnType !== "string")
|
|
67
|
+
throw new TypeError(`${path}.returnType must be a string`);
|
|
68
|
+
if (typeof value.nullable !== "boolean")
|
|
69
|
+
throw new TypeError(`${path}.nullable must be a boolean`);
|
|
70
|
+
if (value.schema !== undefined && typeof value.schema !== "string")
|
|
71
|
+
throw new TypeError(`${path}.schema must be a string`);
|
|
72
|
+
if (value.databaseReturnType !== undefined && typeof value.databaseReturnType !== "string") {
|
|
73
|
+
throw new TypeError(`${path}.databaseReturnType must be a string`);
|
|
74
|
+
}
|
|
75
|
+
if (value.setReturning !== undefined && typeof value.setReturning !== "boolean") {
|
|
76
|
+
throw new TypeError(`${path}.setReturning must be a boolean`);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
name: value.name,
|
|
80
|
+
argumentTypes: value.argumentTypes,
|
|
81
|
+
returnType: value.returnType,
|
|
82
|
+
nullable: value.nullable,
|
|
83
|
+
...(value.schema === undefined ? {} : { schema: value.schema }),
|
|
84
|
+
...(value.databaseReturnType === undefined ? {} : { databaseReturnType: value.databaseReturnType }),
|
|
85
|
+
...(value.setReturning === undefined ? {} : { setReturning: value.setReturning }),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function parseStringArrays(value, path) {
|
|
89
|
+
if (!isRecord(value))
|
|
90
|
+
throw new TypeError(`${path} must be an object`);
|
|
91
|
+
const result = {};
|
|
92
|
+
for (const [name, labels] of Object.entries(value)) {
|
|
93
|
+
if (!Array.isArray(labels) || labels.some((label) => typeof label !== "string")) {
|
|
94
|
+
throw new TypeError(`${path}.${name} must be a string array`);
|
|
95
|
+
}
|
|
96
|
+
result[name] = labels;
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
function parseObjectMap(value, path, parser) {
|
|
101
|
+
if (!isRecord(value))
|
|
102
|
+
throw new TypeError(`${path} must be an object`);
|
|
103
|
+
const result = {};
|
|
104
|
+
for (const [name, item] of Object.entries(value))
|
|
105
|
+
result[name] = parser(item, `${path}.${name}`);
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
export function parseSchemaSnapshot(value) {
|
|
109
|
+
if (!isRecord(value))
|
|
110
|
+
throw new TypeError("Schema snapshot must be an object");
|
|
111
|
+
if (value.dialect !== "postgres" && value.dialect !== "mysql" && value.dialect !== "sqlite") {
|
|
112
|
+
throw new TypeError("schema.dialect must be postgres, mysql, or sqlite");
|
|
113
|
+
}
|
|
114
|
+
if (!isRecord(value.tables))
|
|
115
|
+
throw new TypeError("schema.tables must be an object");
|
|
116
|
+
const tables = {};
|
|
117
|
+
for (const [name, table] of Object.entries(value.tables))
|
|
118
|
+
tables[name] = parseTable(table, `schema.tables.${name}`);
|
|
119
|
+
const snapshot = {
|
|
120
|
+
formatVersion: value.formatVersion === undefined
|
|
121
|
+
? SCHEMA_FORMAT_VERSION
|
|
122
|
+
: value.formatVersion === SCHEMA_FORMAT_VERSION
|
|
123
|
+
? SCHEMA_FORMAT_VERSION
|
|
124
|
+
: (() => { throw new TypeError(`Unsupported schema.formatVersion ${String(value.formatVersion)}; this release supports format ${SCHEMA_FORMAT_VERSION}`); })(),
|
|
125
|
+
dialect: value.dialect,
|
|
126
|
+
...(typeof value.dialectVersion === "string" ? { dialectVersion: value.dialectVersion } : {}),
|
|
127
|
+
tables,
|
|
128
|
+
...(typeof value.version === "string" ? { version: value.version } : {}),
|
|
129
|
+
...(value.enums === undefined ? {} : { enums: parseStringArrays(value.enums, "schema.enums") }),
|
|
130
|
+
...(value.domains === undefined ? {} : { domains: parseObjectMap(value.domains, "schema.domains", parseDomain) }),
|
|
131
|
+
...(value.functions === undefined ? {} : { functions: parseObjectMap(value.functions, "schema.functions", parseFunction) }),
|
|
132
|
+
};
|
|
133
|
+
return snapshot;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Migrates an unversioned pre-1.0 snapshot to the stable v1 format and validates
|
|
137
|
+
* already-versioned input. Future format migrations are added here.
|
|
138
|
+
*/
|
|
139
|
+
export function migrateSchemaSnapshot(value) {
|
|
140
|
+
return parseSchemaSnapshot(value);
|
|
141
|
+
}
|
|
142
|
+
export async function loadSchemaSnapshot(path) {
|
|
143
|
+
const source = await readFile(path, "utf8");
|
|
144
|
+
return parseSchemaSnapshot(JSON.parse(source));
|
|
145
|
+
}
|
|
146
|
+
function parseMetadata(value) {
|
|
147
|
+
if (!isRecord(value))
|
|
148
|
+
throw new TypeError("schema.metadata must be an object");
|
|
149
|
+
if (typeof value.generatorVersion !== "string")
|
|
150
|
+
throw new TypeError("schema.metadata.generatorVersion must be a string");
|
|
151
|
+
if (typeof value.schemaHash !== "string")
|
|
152
|
+
throw new TypeError("schema.metadata.schemaHash must be a string");
|
|
153
|
+
if (typeof value.typePolicyHash !== "string")
|
|
154
|
+
throw new TypeError("schema.metadata.typePolicyHash must be a string");
|
|
155
|
+
return { generatorVersion: value.generatorVersion, schemaHash: value.schemaHash, typePolicyHash: value.typePolicyHash };
|
|
156
|
+
}
|
|
157
|
+
export async function loadGeneratedSchemaSnapshot(path) {
|
|
158
|
+
const source = await readFile(path, "utf8");
|
|
159
|
+
const value = JSON.parse(source);
|
|
160
|
+
if (!isRecord(value))
|
|
161
|
+
throw new TypeError("Generated schema snapshot must be an object");
|
|
162
|
+
return { ...parseSchemaSnapshot(value), metadata: parseMetadata(value.metadata) };
|
|
163
|
+
}
|
|
164
|
+
export function parseTypePolicy(value) {
|
|
165
|
+
if (!isRecord(value))
|
|
166
|
+
throw new TypeError("Type policy must be an object");
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
export async function loadTypePolicy(path) {
|
|
170
|
+
return parseTypePolicy(JSON.parse(await readFile(path, "utf8")));
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../../src/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export type SqlDialect = string;
|
|
2
|
+
export declare const SCHEMA_FORMAT_VERSION: 1;
|
|
3
|
+
export interface SchemaSnapshot {
|
|
4
|
+
readonly formatVersion: typeof SCHEMA_FORMAT_VERSION;
|
|
5
|
+
readonly dialect: SqlDialect;
|
|
6
|
+
readonly dialectVersion?: string;
|
|
7
|
+
readonly version?: string;
|
|
8
|
+
readonly tables: Readonly<Record<string, TableSnapshot>>;
|
|
9
|
+
readonly enums?: Readonly<Record<string, readonly string[]>>;
|
|
10
|
+
readonly domains?: Readonly<Record<string, DomainSnapshot>>;
|
|
11
|
+
readonly functions?: Readonly<Record<string, FunctionSnapshot>>;
|
|
12
|
+
}
|
|
13
|
+
export interface GeneratedSchemaMetadata {
|
|
14
|
+
readonly generatorVersion: string;
|
|
15
|
+
readonly schemaHash: string;
|
|
16
|
+
readonly typePolicyHash: string;
|
|
17
|
+
}
|
|
18
|
+
export interface GeneratedSchemaSnapshot extends SchemaSnapshot {
|
|
19
|
+
readonly metadata: GeneratedSchemaMetadata;
|
|
20
|
+
}
|
|
21
|
+
export interface TableSnapshot {
|
|
22
|
+
readonly schema?: string;
|
|
23
|
+
readonly name: string;
|
|
24
|
+
readonly columns: Readonly<Record<string, ColumnSnapshot>>;
|
|
25
|
+
}
|
|
26
|
+
export interface ColumnSnapshot {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly databaseType: string;
|
|
29
|
+
readonly tsType: string;
|
|
30
|
+
readonly nullable: boolean;
|
|
31
|
+
readonly array?: boolean;
|
|
32
|
+
readonly defaultExpression?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface DomainSnapshot {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly databaseType: string;
|
|
37
|
+
readonly tsType: string;
|
|
38
|
+
readonly nullable: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface FunctionSnapshot {
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly schema?: string;
|
|
43
|
+
readonly argumentTypes: readonly string[];
|
|
44
|
+
readonly databaseReturnType?: string;
|
|
45
|
+
readonly returnType: string;
|
|
46
|
+
readonly nullable: boolean;
|
|
47
|
+
readonly setReturning?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export type TypePolicy = Readonly<Record<string, unknown>>;
|
|
50
|
+
export interface SchemaInput {
|
|
51
|
+
readonly url?: string;
|
|
52
|
+
readonly snapshot?: string;
|
|
53
|
+
readonly migrations?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface SchemaProvider {
|
|
56
|
+
introspect(input: SchemaInput): Promise<SchemaSnapshot>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../../src/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../src/model.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAU,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { SchemaInput, SchemaProvider, SchemaSnapshot, TypePolicy } from "./model.js";
|
|
2
|
+
export interface PostgresQueryResult<Row> {
|
|
3
|
+
readonly rows: readonly Row[];
|
|
4
|
+
}
|
|
5
|
+
export interface PostgresQueryable {
|
|
6
|
+
query<Row extends Record<string, unknown>>(text: string, values?: readonly unknown[]): Promise<PostgresQueryResult<Row>>;
|
|
7
|
+
}
|
|
8
|
+
export interface PostgresSchemaProviderOptions {
|
|
9
|
+
readonly client?: PostgresQueryable;
|
|
10
|
+
readonly includeSchemas?: readonly string[];
|
|
11
|
+
readonly typePolicy?: TypePolicy;
|
|
12
|
+
}
|
|
13
|
+
export declare const postgresCatalogQueries: {
|
|
14
|
+
readonly version: "SELECT current_setting('server_version') AS server_version";
|
|
15
|
+
readonly columns: `
|
|
16
|
+
SELECT
|
|
17
|
+
n.nspname AS schema_name,
|
|
18
|
+
c.relname AS table_name,
|
|
19
|
+
a.attname AS column_name,
|
|
20
|
+
format_type(a.atttypid, a.atttypmod) AS database_type,
|
|
21
|
+
a.attnotnull AS not_null,
|
|
22
|
+
(t.typcategory = 'A') AS is_array,
|
|
23
|
+
pg_get_expr(ad.adbin, ad.adrelid) AS default_expression
|
|
24
|
+
FROM pg_catalog.pg_attribute AS a
|
|
25
|
+
JOIN pg_catalog.pg_class AS c ON c.oid = a.attrelid
|
|
26
|
+
JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace
|
|
27
|
+
JOIN pg_catalog.pg_type AS t ON t.oid = a.atttypid
|
|
28
|
+
LEFT JOIN pg_catalog.pg_attrdef AS ad ON ad.adrelid = a.attrelid AND ad.adnum = a.attnum
|
|
29
|
+
WHERE a.attnum > 0
|
|
30
|
+
AND NOT a.attisdropped
|
|
31
|
+
AND c.relkind IN ('r', 'p', 'v', 'm', 'f')
|
|
32
|
+
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
33
|
+
AND n.nspname NOT LIKE 'pg_toast%'
|
|
34
|
+
AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
|
|
35
|
+
ORDER BY n.nspname, c.relname, a.attnum
|
|
36
|
+
`;
|
|
37
|
+
readonly enums: `
|
|
38
|
+
SELECT n.nspname AS schema_name, t.typname AS type_name, e.enumlabel AS enum_label
|
|
39
|
+
FROM pg_catalog.pg_type AS t
|
|
40
|
+
JOIN pg_catalog.pg_namespace AS n ON n.oid = t.typnamespace
|
|
41
|
+
JOIN pg_catalog.pg_enum AS e ON e.enumtypid = t.oid
|
|
42
|
+
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
43
|
+
AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
|
|
44
|
+
ORDER BY n.nspname, t.typname, e.enumsortorder
|
|
45
|
+
`;
|
|
46
|
+
readonly domains: `
|
|
47
|
+
SELECT
|
|
48
|
+
n.nspname AS schema_name,
|
|
49
|
+
t.typname AS domain_name,
|
|
50
|
+
format_type(t.typbasetype, t.typtypmod) AS database_type,
|
|
51
|
+
t.typnotnull AS not_null
|
|
52
|
+
FROM pg_catalog.pg_type AS t
|
|
53
|
+
JOIN pg_catalog.pg_namespace AS n ON n.oid = t.typnamespace
|
|
54
|
+
WHERE t.typtype = 'd'
|
|
55
|
+
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
56
|
+
AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
|
|
57
|
+
ORDER BY n.nspname, t.typname
|
|
58
|
+
`;
|
|
59
|
+
readonly functions: `
|
|
60
|
+
SELECT
|
|
61
|
+
n.nspname AS schema_name,
|
|
62
|
+
p.proname AS function_name,
|
|
63
|
+
ARRAY(
|
|
64
|
+
SELECT format_type(argument_oid, NULL)
|
|
65
|
+
FROM unnest(p.proargtypes::oid[]) WITH ORDINALITY AS arguments(argument_oid, position)
|
|
66
|
+
ORDER BY position
|
|
67
|
+
) AS argument_types,
|
|
68
|
+
format_type(p.prorettype, NULL) AS database_return_type,
|
|
69
|
+
p.proretset AS set_returning
|
|
70
|
+
FROM pg_catalog.pg_proc AS p
|
|
71
|
+
JOIN pg_catalog.pg_namespace AS n ON n.oid = p.pronamespace
|
|
72
|
+
WHERE p.prokind = 'f'
|
|
73
|
+
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
74
|
+
AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
|
|
75
|
+
ORDER BY n.nspname, p.proname, p.oid
|
|
76
|
+
`;
|
|
77
|
+
};
|
|
78
|
+
export declare class PostgresSchemaProvider implements SchemaProvider {
|
|
79
|
+
#private;
|
|
80
|
+
constructor(options?: PostgresSchemaProviderOptions);
|
|
81
|
+
introspect(input: SchemaInput): Promise<SchemaSnapshot>;
|
|
82
|
+
}
|
|
83
|
+
export declare function introspectPostgres(input: SchemaInput, options?: PostgresSchemaProviderOptions): Promise<SchemaSnapshot>;
|
|
84
|
+
//# sourceMappingURL=postgres-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-provider.d.ts","sourceRoot":"","sources":["../../../../src/postgres-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,WAAW,EACX,cAAc,EACd,cAAc,EAEd,UAAU,EACX,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,mBAAmB,CAAC,GAAG;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,GAAG,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;CAC1H;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CAClC;AAqCD,eAAO,MAAM,sBAAsB;aACjC,OAAO,EAAE,4DAA4D;aACrE,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;GAqBR;aACD,KAAK,EAAE;;;;;;;;GAQN;aACD,OAAO,EAAE;;;;;;;;;;;;GAYR;aACD,SAAS,EAAE;;;;;;;;;;;;;;;;;GAiBV;CACO,CAAC;AAgDX,qBAAa,sBAAuB,YAAW,cAAc;;IAG3D,YAAY,OAAO,GAAE,6BAAkC,EAEtD;IAEK,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAuE5D;CACF;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,6BAAkC,GAAG,OAAO,CAAC,cAAc,CAAC,CAEjI"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { defaultPostgresTypePolicy } from "./model.js";
|
|
2
|
+
import { mapPostgresType } from "./type-policy.js";
|
|
3
|
+
export const postgresCatalogQueries = {
|
|
4
|
+
version: "SELECT current_setting('server_version') AS server_version",
|
|
5
|
+
columns: `
|
|
6
|
+
SELECT
|
|
7
|
+
n.nspname AS schema_name,
|
|
8
|
+
c.relname AS table_name,
|
|
9
|
+
a.attname AS column_name,
|
|
10
|
+
format_type(a.atttypid, a.atttypmod) AS database_type,
|
|
11
|
+
a.attnotnull AS not_null,
|
|
12
|
+
(t.typcategory = 'A') AS is_array,
|
|
13
|
+
pg_get_expr(ad.adbin, ad.adrelid) AS default_expression
|
|
14
|
+
FROM pg_catalog.pg_attribute AS a
|
|
15
|
+
JOIN pg_catalog.pg_class AS c ON c.oid = a.attrelid
|
|
16
|
+
JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace
|
|
17
|
+
JOIN pg_catalog.pg_type AS t ON t.oid = a.atttypid
|
|
18
|
+
LEFT JOIN pg_catalog.pg_attrdef AS ad ON ad.adrelid = a.attrelid AND ad.adnum = a.attnum
|
|
19
|
+
WHERE a.attnum > 0
|
|
20
|
+
AND NOT a.attisdropped
|
|
21
|
+
AND c.relkind IN ('r', 'p', 'v', 'm', 'f')
|
|
22
|
+
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
23
|
+
AND n.nspname NOT LIKE 'pg_toast%'
|
|
24
|
+
AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
|
|
25
|
+
ORDER BY n.nspname, c.relname, a.attnum
|
|
26
|
+
`,
|
|
27
|
+
enums: `
|
|
28
|
+
SELECT n.nspname AS schema_name, t.typname AS type_name, e.enumlabel AS enum_label
|
|
29
|
+
FROM pg_catalog.pg_type AS t
|
|
30
|
+
JOIN pg_catalog.pg_namespace AS n ON n.oid = t.typnamespace
|
|
31
|
+
JOIN pg_catalog.pg_enum AS e ON e.enumtypid = t.oid
|
|
32
|
+
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
33
|
+
AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
|
|
34
|
+
ORDER BY n.nspname, t.typname, e.enumsortorder
|
|
35
|
+
`,
|
|
36
|
+
domains: `
|
|
37
|
+
SELECT
|
|
38
|
+
n.nspname AS schema_name,
|
|
39
|
+
t.typname AS domain_name,
|
|
40
|
+
format_type(t.typbasetype, t.typtypmod) AS database_type,
|
|
41
|
+
t.typnotnull AS not_null
|
|
42
|
+
FROM pg_catalog.pg_type AS t
|
|
43
|
+
JOIN pg_catalog.pg_namespace AS n ON n.oid = t.typnamespace
|
|
44
|
+
WHERE t.typtype = 'd'
|
|
45
|
+
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
46
|
+
AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
|
|
47
|
+
ORDER BY n.nspname, t.typname
|
|
48
|
+
`,
|
|
49
|
+
functions: `
|
|
50
|
+
SELECT
|
|
51
|
+
n.nspname AS schema_name,
|
|
52
|
+
p.proname AS function_name,
|
|
53
|
+
ARRAY(
|
|
54
|
+
SELECT format_type(argument_oid, NULL)
|
|
55
|
+
FROM unnest(p.proargtypes::oid[]) WITH ORDINALITY AS arguments(argument_oid, position)
|
|
56
|
+
ORDER BY position
|
|
57
|
+
) AS argument_types,
|
|
58
|
+
format_type(p.prorettype, NULL) AS database_return_type,
|
|
59
|
+
p.proretset AS set_returning
|
|
60
|
+
FROM pg_catalog.pg_proc AS p
|
|
61
|
+
JOIN pg_catalog.pg_namespace AS n ON n.oid = p.pronamespace
|
|
62
|
+
WHERE p.prokind = 'f'
|
|
63
|
+
AND n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
64
|
+
AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
|
|
65
|
+
ORDER BY n.nspname, p.proname, p.oid
|
|
66
|
+
`,
|
|
67
|
+
};
|
|
68
|
+
function qualifiedKey(schema, name) {
|
|
69
|
+
return schema === "public" ? name : `${schema}.${name}`;
|
|
70
|
+
}
|
|
71
|
+
function redactError(error, connectionString) {
|
|
72
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
73
|
+
return new Error(message.replaceAll(connectionString, "[REDACTED_DATABASE_URL]"));
|
|
74
|
+
}
|
|
75
|
+
async function withConnection(input, options, fn) {
|
|
76
|
+
if (options.client !== undefined)
|
|
77
|
+
return fn(options.client);
|
|
78
|
+
if (input.url === undefined)
|
|
79
|
+
throw new TypeError("PostgreSQL introspection requires SchemaInput.url");
|
|
80
|
+
let Pool;
|
|
81
|
+
try {
|
|
82
|
+
({ Pool } = await import("pg"));
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof Error && "code" in error && error.code === "ERR_MODULE_NOT_FOUND") {
|
|
86
|
+
throw new Error("PostgreSQL introspection requires the application-owned pg driver. Install it with: pnpm add pg", { cause: error });
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
const pool = new Pool({ connectionString: input.url });
|
|
91
|
+
const client = await pool.connect().catch(async (error) => {
|
|
92
|
+
await pool.end();
|
|
93
|
+
throw redactError(error, input.url);
|
|
94
|
+
});
|
|
95
|
+
const queryable = {
|
|
96
|
+
async query(text, values) {
|
|
97
|
+
const result = await client.query(text, values === undefined ? [] : [...values]);
|
|
98
|
+
return { rows: result.rows };
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
try {
|
|
102
|
+
await client.query("BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY");
|
|
103
|
+
const result = await fn(queryable);
|
|
104
|
+
await client.query("COMMIT");
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
try {
|
|
109
|
+
await client.query("ROLLBACK");
|
|
110
|
+
}
|
|
111
|
+
catch { /* Preserve the introspection error. */ }
|
|
112
|
+
throw redactError(error, input.url);
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
client.release();
|
|
116
|
+
await pool.end();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export class PostgresSchemaProvider {
|
|
120
|
+
#options;
|
|
121
|
+
constructor(options = {}) {
|
|
122
|
+
this.#options = options;
|
|
123
|
+
}
|
|
124
|
+
async introspect(input) {
|
|
125
|
+
return withConnection(input, this.#options, async (client) => {
|
|
126
|
+
const schemaFilter = this.#options.includeSchemas === undefined ? null : [...this.#options.includeSchemas];
|
|
127
|
+
const values = [schemaFilter];
|
|
128
|
+
const [versionResult, enumResult, domainResult, columnResult, functionResult] = await Promise.all([
|
|
129
|
+
client.query(postgresCatalogQueries.version),
|
|
130
|
+
client.query(postgresCatalogQueries.enums, values),
|
|
131
|
+
client.query(postgresCatalogQueries.domains, values),
|
|
132
|
+
client.query(postgresCatalogQueries.columns, values),
|
|
133
|
+
client.query(postgresCatalogQueries.functions, values),
|
|
134
|
+
]);
|
|
135
|
+
const enums = {};
|
|
136
|
+
for (const row of enumResult.rows)
|
|
137
|
+
(enums[qualifiedKey(row.schema_name, row.type_name)] ??= []).push(row.enum_label);
|
|
138
|
+
const policy = this.#options.typePolicy ?? defaultPostgresTypePolicy;
|
|
139
|
+
const domains = {};
|
|
140
|
+
for (const row of domainResult.rows) {
|
|
141
|
+
const key = qualifiedKey(row.schema_name, row.domain_name);
|
|
142
|
+
domains[key] = {
|
|
143
|
+
name: row.domain_name,
|
|
144
|
+
databaseType: row.database_type,
|
|
145
|
+
tsType: mapPostgresType(row.database_type, policy),
|
|
146
|
+
nullable: !row.not_null,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const partialSchema = { dialect: "postgres", tables: {}, enums, domains };
|
|
150
|
+
const tables = {};
|
|
151
|
+
for (const row of columnResult.rows) {
|
|
152
|
+
const tableKey = qualifiedKey(row.schema_name, row.table_name);
|
|
153
|
+
const existing = tables[tableKey];
|
|
154
|
+
const columns = existing === undefined ? {} : { ...existing.columns };
|
|
155
|
+
const domain = domains[row.database_type];
|
|
156
|
+
columns[row.column_name] = {
|
|
157
|
+
name: row.column_name,
|
|
158
|
+
databaseType: row.database_type,
|
|
159
|
+
tsType: mapPostgresType(row.database_type, policy, partialSchema),
|
|
160
|
+
nullable: !row.not_null && (domain?.nullable ?? true),
|
|
161
|
+
...(row.is_array ? { array: true } : {}),
|
|
162
|
+
...(row.default_expression === null ? {} : { defaultExpression: row.default_expression }),
|
|
163
|
+
};
|
|
164
|
+
tables[tableKey] = { schema: row.schema_name, name: row.table_name, columns };
|
|
165
|
+
}
|
|
166
|
+
const schemaForFunctions = { ...partialSchema, tables };
|
|
167
|
+
const functions = {};
|
|
168
|
+
for (const row of functionResult.rows) {
|
|
169
|
+
const name = qualifiedKey(row.schema_name, row.function_name);
|
|
170
|
+
const key = `${name}(${row.argument_types.join(",")})`;
|
|
171
|
+
functions[key] = {
|
|
172
|
+
name: row.function_name,
|
|
173
|
+
schema: row.schema_name,
|
|
174
|
+
argumentTypes: row.argument_types,
|
|
175
|
+
databaseReturnType: row.database_return_type,
|
|
176
|
+
returnType: mapPostgresType(row.database_return_type, policy, schemaForFunctions),
|
|
177
|
+
nullable: true,
|
|
178
|
+
...(row.set_returning ? { setReturning: true } : {}),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const version = versionResult.rows[0]?.server_version;
|
|
182
|
+
return {
|
|
183
|
+
dialect: "postgres",
|
|
184
|
+
...(version === undefined ? {} : { version }),
|
|
185
|
+
tables,
|
|
186
|
+
...(Object.keys(enums).length === 0 ? {} : { enums }),
|
|
187
|
+
...(Object.keys(domains).length === 0 ? {} : { domains }),
|
|
188
|
+
...(Object.keys(functions).length === 0 ? {} : { functions }),
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export async function introspectPostgres(input, options = {}) {
|
|
194
|
+
return new PostgresSchemaProvider(options).introspect(input);
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=postgres-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-provider.js","sourceRoot":"","sources":["../../../../src/postgres-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SelectStatement, SourceRange, SqlDiagnostic } from "@typed-sql/ast";
|
|
2
|
+
import type { SchemaSnapshot, TypePolicy } from "./model.js";
|
|
3
|
+
interface ResolvedType {
|
|
4
|
+
readonly tsType: string;
|
|
5
|
+
readonly nullable: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ResolvedColumn extends ResolvedType {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly range: SourceRange;
|
|
10
|
+
}
|
|
11
|
+
export interface ResolvedQuery {
|
|
12
|
+
readonly columns: readonly ResolvedColumn[];
|
|
13
|
+
readonly diagnostics: readonly SqlDiagnostic[];
|
|
14
|
+
}
|
|
15
|
+
export interface ResolveOptions {
|
|
16
|
+
readonly typePolicy?: TypePolicy;
|
|
17
|
+
readonly strictExpressions?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function resolveSelect(statement: SelectStatement, schema: SchemaSnapshot, options?: ResolveOptions): ResolvedQuery;
|
|
20
|
+
export declare function rowTypeLiteral(columns: readonly ResolvedColumn[]): string;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,eAAe,EACf,WAAW,EACX,aAAa,EAEd,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAkB,cAAc,EAAiB,UAAU,EAAE,MAAM,YAAY,CAAC;AAU5F,UAAU,YAAY;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,QAAQ,CAAC,WAAW,EAAE,SAAS,aAAa,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC;AA6LD,wBAAgB,aAAa,CAAC,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CAE7H;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAGzE"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { defaultPostgresTypePolicy } from "./model.js";
|
|
2
|
+
import { isKnownPostgresType, mapPostgresType } from "./type-policy.js";
|
|
3
|
+
const comparable = new Set(["=", "!=", "<>", "<", "<=", ">", ">=", "IS", "IS NOT", "LIKE", "AND", "OR"]);
|
|
4
|
+
function sqlName(identifier) {
|
|
5
|
+
return identifier.quoted ? identifier.name : identifier.name.toLowerCase();
|
|
6
|
+
}
|
|
7
|
+
function distance(a, b) {
|
|
8
|
+
const rows = Array.from({ length: a.length + 1 }, (_, index) => index);
|
|
9
|
+
for (let column = 1; column <= b.length; column += 1) {
|
|
10
|
+
let diagonal = rows[0];
|
|
11
|
+
rows[0] = column;
|
|
12
|
+
for (let row = 1; row <= a.length; row += 1) {
|
|
13
|
+
const above = rows[row];
|
|
14
|
+
rows[row] = Math.min(rows[row] + 1, rows[row - 1] + 1, diagonal + (a[row - 1] === b[column - 1] ? 0 : 1));
|
|
15
|
+
diagonal = above;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return rows[a.length];
|
|
19
|
+
}
|
|
20
|
+
function suggestion(name, candidates) {
|
|
21
|
+
const candidate = [...candidates].sort((a, b) => distance(name, a) - distance(name, b))[0];
|
|
22
|
+
if (candidate === undefined || distance(name, candidate) > Math.max(2, Math.floor(name.length / 2)))
|
|
23
|
+
return undefined;
|
|
24
|
+
return `Did you mean ${candidate}?`;
|
|
25
|
+
}
|
|
26
|
+
class Resolver {
|
|
27
|
+
#schema;
|
|
28
|
+
#policy;
|
|
29
|
+
#strictExpressions;
|
|
30
|
+
#relations = [];
|
|
31
|
+
#diagnostics = [];
|
|
32
|
+
constructor(schema, options) {
|
|
33
|
+
this.#schema = schema;
|
|
34
|
+
this.#policy = options.typePolicy ?? defaultPostgresTypePolicy;
|
|
35
|
+
this.#strictExpressions = options.strictExpressions ?? true;
|
|
36
|
+
}
|
|
37
|
+
resolve(statement) {
|
|
38
|
+
if (this.#schema.dialect !== "postgres")
|
|
39
|
+
this.#diagnostic("TSQ007", `MVP resolver only supports PostgreSQL, not ${this.#schema.dialect}`, statement.range);
|
|
40
|
+
if (statement.from !== undefined)
|
|
41
|
+
this.#addRelation(statement.from, false);
|
|
42
|
+
for (const join of statement.joins) {
|
|
43
|
+
if (join.kind === "right" || join.kind === "full")
|
|
44
|
+
for (const relation of this.#relations)
|
|
45
|
+
relation.nullable = true;
|
|
46
|
+
const relation = this.#addRelation(join.table, join.kind === "left" || join.kind === "full");
|
|
47
|
+
if (relation !== undefined)
|
|
48
|
+
this.#resolveExpression(join.on);
|
|
49
|
+
}
|
|
50
|
+
const columns = [];
|
|
51
|
+
const names = new Set();
|
|
52
|
+
for (const item of statement.columns) {
|
|
53
|
+
const type = this.#resolveExpression(item.expression);
|
|
54
|
+
const name = item.alias?.name ?? (item.expression.kind === "column" ? item.expression.column.name : undefined);
|
|
55
|
+
if (name === undefined) {
|
|
56
|
+
if (this.#strictExpressions)
|
|
57
|
+
this.#diagnostic("TSQ104", "Expressions in SELECT require an explicit alias", item.range, "Add AS <name>.");
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (names.has(name)) {
|
|
61
|
+
this.#diagnostic("TSQ105", `Duplicate output property ${name}`, item.range, "Give one expression a unique alias.");
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
names.add(name);
|
|
65
|
+
columns.push({ name, tsType: type.tsType, nullable: type.nullable, range: item.range });
|
|
66
|
+
}
|
|
67
|
+
return { columns, diagnostics: this.#diagnostics };
|
|
68
|
+
}
|
|
69
|
+
#addRelation(reference, nullable) {
|
|
70
|
+
const requested = sqlName(reference.name);
|
|
71
|
+
const requestedSchema = reference.schema === undefined ? undefined : sqlName(reference.schema);
|
|
72
|
+
const tableEntries = Object.entries(this.#schema.tables).filter(([key, table]) => {
|
|
73
|
+
const nameMatches = key.toLowerCase() === requested || key.toLowerCase().endsWith(`.${requested}`) || table.name.toLowerCase() === requested;
|
|
74
|
+
const schemaMatches = requestedSchema === undefined || table.schema?.toLowerCase() === requestedSchema || key.toLowerCase() === `${requestedSchema}.${requested}`;
|
|
75
|
+
return nameMatches && schemaMatches;
|
|
76
|
+
});
|
|
77
|
+
if (tableEntries.length === 0) {
|
|
78
|
+
this.#diagnostic("TSQ100", `Unknown table ${reference.name.name}`, reference.name.range, suggestion(requested, Object.keys(this.#schema.tables)));
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
if (requestedSchema === undefined && tableEntries.length > 1) {
|
|
82
|
+
this.#diagnostic("TSQ107", `Ambiguous table ${reference.name.name}`, reference.name.range, "Qualify the table with a schema name.");
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const relation = { alias: reference.alias === undefined ? requested : sqlName(reference.alias), table: tableEntries[0][1], nullable };
|
|
86
|
+
this.#relations.push(relation);
|
|
87
|
+
return relation;
|
|
88
|
+
}
|
|
89
|
+
#resolveExpression(expression) {
|
|
90
|
+
switch (expression.kind) {
|
|
91
|
+
case "column": return this.#resolveColumn(expression.relation, expression.column);
|
|
92
|
+
case "literal": {
|
|
93
|
+
if (expression.value === null)
|
|
94
|
+
return { tsType: "unknown", nullable: true };
|
|
95
|
+
return { tsType: typeof expression.value, nullable: false };
|
|
96
|
+
}
|
|
97
|
+
case "parameter": return { tsType: "unknown", nullable: true };
|
|
98
|
+
case "star": return { tsType: "unknown", nullable: false };
|
|
99
|
+
case "cast": {
|
|
100
|
+
const source = this.#resolveExpression(expression.expression);
|
|
101
|
+
if (!isKnownPostgresType(expression.databaseType.name, this.#schema)) {
|
|
102
|
+
this.#diagnostic("TSQ106", `Invalid or unknown PostgreSQL cast type ${expression.databaseType.name}`, expression.databaseType.range);
|
|
103
|
+
}
|
|
104
|
+
return { tsType: mapPostgresType(expression.databaseType.name, this.#policy, this.#schema), nullable: source.nullable };
|
|
105
|
+
}
|
|
106
|
+
case "unary": {
|
|
107
|
+
const operand = this.#resolveExpression(expression.expression);
|
|
108
|
+
return expression.operator === "NOT" ? { tsType: "boolean", nullable: operand.nullable } : operand;
|
|
109
|
+
}
|
|
110
|
+
case "binary": {
|
|
111
|
+
const left = this.#resolveExpression(expression.left);
|
|
112
|
+
const right = this.#resolveExpression(expression.right);
|
|
113
|
+
if (comparable.has(expression.operator))
|
|
114
|
+
return { tsType: "boolean", nullable: expression.operator.startsWith("IS") ? false : left.nullable || right.nullable };
|
|
115
|
+
const tsType = left.tsType === right.tsType ? left.tsType : left.tsType === "number" || right.tsType === "number" ? "number" : `${left.tsType} | ${right.tsType}`;
|
|
116
|
+
return { tsType, nullable: left.nullable || right.nullable };
|
|
117
|
+
}
|
|
118
|
+
case "call": return this.#resolveCall(expression.name, expression.arguments, expression.range);
|
|
119
|
+
case "case": {
|
|
120
|
+
const results = expression.branches.map((branch) => this.#resolveExpression(branch.then));
|
|
121
|
+
if (expression.elseExpression !== undefined)
|
|
122
|
+
results.push(this.#resolveExpression(expression.elseExpression));
|
|
123
|
+
const types = [...new Set(results.map((result) => result.tsType))];
|
|
124
|
+
return { tsType: types.join(" | ") || "unknown", nullable: expression.elseExpression === undefined || results.some((result) => result.nullable) };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
#resolveColumn(relationIdentifier, columnIdentifier) {
|
|
129
|
+
const columnName = sqlName(columnIdentifier);
|
|
130
|
+
let matches;
|
|
131
|
+
if (relationIdentifier !== undefined) {
|
|
132
|
+
const alias = sqlName(relationIdentifier);
|
|
133
|
+
const relation = this.#relations.find((candidate) => candidate.alias === alias);
|
|
134
|
+
if (relation === undefined) {
|
|
135
|
+
this.#diagnostic("TSQ103", `Unknown relation alias ${relationIdentifier.name}`, relationIdentifier.range, suggestion(alias, this.#relations.map((item) => item.alias)));
|
|
136
|
+
return { tsType: "unknown", nullable: true };
|
|
137
|
+
}
|
|
138
|
+
matches = [relation];
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
if (this.#relations.length === 0 && this.#diagnostics.some((diagnostic) => diagnostic.code === "TSQ100")) {
|
|
142
|
+
return { tsType: "unknown", nullable: true };
|
|
143
|
+
}
|
|
144
|
+
matches = this.#relations.filter((relation) => this.#findColumn(relation.table, columnName) !== undefined);
|
|
145
|
+
if (matches.length > 1) {
|
|
146
|
+
this.#diagnostic("TSQ102", `Ambiguous column ${columnIdentifier.name}`, columnIdentifier.range, "Qualify the column with a table alias.");
|
|
147
|
+
return { tsType: "unknown", nullable: true };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const relation = matches[0];
|
|
151
|
+
const column = relation === undefined ? undefined : this.#findColumn(relation.table, columnName);
|
|
152
|
+
if (column === undefined) {
|
|
153
|
+
const candidates = relation === undefined
|
|
154
|
+
? this.#relations.flatMap((item) => Object.keys(item.table.columns))
|
|
155
|
+
: Object.keys(relation.table.columns);
|
|
156
|
+
this.#diagnostic("TSQ101", `Unknown column ${columnIdentifier.name}`, columnIdentifier.range, suggestion(columnName, candidates));
|
|
157
|
+
return { tsType: "unknown", nullable: true };
|
|
158
|
+
}
|
|
159
|
+
return { tsType: column.tsType, nullable: column.nullable || relation.nullable };
|
|
160
|
+
}
|
|
161
|
+
#findColumn(table, name) {
|
|
162
|
+
return Object.entries(table.columns).find(([key, column]) => key.toLowerCase() === name || column.name.toLowerCase() === name)?.[1];
|
|
163
|
+
}
|
|
164
|
+
#resolveCall(nameIdentifier, args, range) {
|
|
165
|
+
const name = nameIdentifier.name.toUpperCase();
|
|
166
|
+
const resolved = args.map((argument) => this.#resolveExpression(argument));
|
|
167
|
+
if (name === "COUNT")
|
|
168
|
+
return { tsType: this.#policy.bigint, nullable: false };
|
|
169
|
+
if (name === "COALESCE") {
|
|
170
|
+
const types = [...new Set(resolved.map((result) => result.tsType).filter((type) => type !== "unknown"))];
|
|
171
|
+
return { tsType: types.join(" | ") || "unknown", nullable: resolved.every((result) => result.nullable) };
|
|
172
|
+
}
|
|
173
|
+
if (name === "MIN" || name === "MAX")
|
|
174
|
+
return { tsType: resolved[0]?.tsType ?? "unknown", nullable: true };
|
|
175
|
+
if (name === "SUM")
|
|
176
|
+
return { tsType: resolved[0]?.tsType ?? this.#policy.numeric, nullable: true };
|
|
177
|
+
const declared = this.#schema.functions?.[nameIdentifier.name]
|
|
178
|
+
?? this.#schema.functions?.[nameIdentifier.name.toLowerCase()]
|
|
179
|
+
?? Object.values(this.#schema.functions ?? {}).find((candidate) => candidate.name.toLowerCase() === nameIdentifier.name.toLowerCase() && candidate.argumentTypes.length === args.length);
|
|
180
|
+
if (declared !== undefined)
|
|
181
|
+
return { tsType: declared.returnType, nullable: declared.nullable };
|
|
182
|
+
this.#diagnostic("TSQ202", `Unknown function ${nameIdentifier.name}`, range, undefined, "warning");
|
|
183
|
+
return { tsType: "unknown", nullable: true };
|
|
184
|
+
}
|
|
185
|
+
#diagnostic(code, message, range, suggestionText, severity = "error") {
|
|
186
|
+
this.#diagnostics.push({ code, message, range, severity, ...(suggestionText === undefined ? {} : { suggestion: suggestionText }) });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
export function resolveSelect(statement, schema, options = {}) {
|
|
190
|
+
return new Resolver(schema, options).resolve(statement);
|
|
191
|
+
}
|
|
192
|
+
export function rowTypeLiteral(columns) {
|
|
193
|
+
const properties = columns.map((column) => `${JSON.stringify(column.name)}: ${column.tsType}${column.nullable ? " | null" : ""};`);
|
|
194
|
+
return `{ ${properties.join(" ")} }`;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../../src/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SchemaSnapshot, TypePolicy } from "./model.js";
|
|
2
|
+
export declare function isKnownPostgresType(databaseType: string, schema?: SchemaSnapshot): boolean;
|
|
3
|
+
export declare function mapPostgresType(databaseType: string, policy: TypePolicy, schema?: SchemaSnapshot): string;
|
|
4
|
+
//# sourceMappingURL=type-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-policy.d.ts","sourceRoot":"","sources":["../../../../src/type-policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAK7D,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAS1F;AAED,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,CAoBzG"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const normalized = (databaseType) => databaseType.trim().toLowerCase().replace(/\s+/g, " ");
|
|
2
|
+
const withoutModifiers = (databaseType) => databaseType.replace(/\(\d+(?:,\s*\d+)?\)/g, "");
|
|
3
|
+
export function isKnownPostgresType(databaseType, schema) {
|
|
4
|
+
const type = withoutModifiers(normalized(databaseType).replace(/\[\]$/, ""));
|
|
5
|
+
if ([
|
|
6
|
+
"smallint", "int2", "integer", "int", "int4", "bigint", "int8", "numeric", "decimal",
|
|
7
|
+
"real", "float4", "double precision", "float8", "boolean", "bool", "text", "varchar",
|
|
8
|
+
"character varying", "char", "uuid", "date", "timestamp", "timestamp without time zone",
|
|
9
|
+
"timestamptz", "timestamp with time zone", "json", "jsonb", "bytea",
|
|
10
|
+
].includes(type))
|
|
11
|
+
return true;
|
|
12
|
+
return schema?.enums?.[type] !== undefined || schema?.domains?.[type] !== undefined;
|
|
13
|
+
}
|
|
14
|
+
export function mapPostgresType(databaseType, policy, schema) {
|
|
15
|
+
const normalizedType = normalized(databaseType);
|
|
16
|
+
const array = normalizedType.endsWith("[]");
|
|
17
|
+
const unmodifiedType = normalizedType.replace(/\[\]$/, "");
|
|
18
|
+
const type = withoutModifiers(unmodifiedType);
|
|
19
|
+
let mapped;
|
|
20
|
+
if (["smallint", "int2", "integer", "int", "int4", "real", "float4", "double precision", "float8"].includes(type))
|
|
21
|
+
mapped = "number";
|
|
22
|
+
else if (["bigint", "int8"].includes(type))
|
|
23
|
+
mapped = policy.bigint;
|
|
24
|
+
else if (["numeric", "decimal"].includes(type))
|
|
25
|
+
mapped = policy.numeric;
|
|
26
|
+
else if (["boolean", "bool"].includes(type))
|
|
27
|
+
mapped = "boolean";
|
|
28
|
+
else if (["text", "varchar", "character varying", "char", "uuid"].includes(type))
|
|
29
|
+
mapped = "string";
|
|
30
|
+
else if (["date", "timestamp", "timestamp without time zone", "timestamptz", "timestamp with time zone"].includes(type))
|
|
31
|
+
mapped = policy.date;
|
|
32
|
+
else if (["json", "jsonb"].includes(type))
|
|
33
|
+
mapped = policy.json;
|
|
34
|
+
else if (type === "bytea")
|
|
35
|
+
mapped = "Uint8Array";
|
|
36
|
+
else if (schema?.domains?.[unmodifiedType] !== undefined || schema?.domains?.[type] !== undefined)
|
|
37
|
+
mapped = (schema.domains[unmodifiedType] ?? schema.domains[type]).tsType;
|
|
38
|
+
else if (schema?.enums?.[unmodifiedType] !== undefined || schema?.enums?.[type] !== undefined) {
|
|
39
|
+
const values = schema.enums[unmodifiedType] ?? schema.enums[type];
|
|
40
|
+
mapped = policy.enums === "string" ? "string" : values.map((value) => JSON.stringify(value)).join(" | ");
|
|
41
|
+
}
|
|
42
|
+
else
|
|
43
|
+
mapped = policy.unknown;
|
|
44
|
+
return array ? `readonly (${mapped})[]` : mapped;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=type-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-policy.js","sourceRoot":"","sources":["../../../../src/type-policy.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@typed-sql/schema",
|
|
3
|
+
"version": "1.0.0-beta.0",
|
|
4
|
+
"description": "Versioned typed-sql schema snapshots, deterministic generation, and drift checks.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Lojhan",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Lojhan/typed-sql.git",
|
|
10
|
+
"directory": "packages/schema"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/Lojhan/typed-sql#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/Lojhan/typed-sql/issues"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.11"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist/**/*.js",
|
|
21
|
+
"dist/**/*.d.ts",
|
|
22
|
+
"dist/**/*.map",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"CHANGELOG.md"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"sideEffects": false,
|
|
31
|
+
"type": "module",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": "./dist/packages/schema/src/index.js"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"test": "poku test --reporter=compact --enforce",
|
|
38
|
+
"coverage": "poku test --coverage=@pokujs/c8 --coverageConfig=.c8rc.json --reporter=compact --enforce"
|
|
39
|
+
}
|
|
40
|
+
}
|