@danielfgray/pg-sourcerer 0.2.2 → 0.4.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/bin/pgsourcerer +2 -0
- package/dist/__tests__/fixtures/index.d.ts +15 -0
- package/dist/__tests__/fixtures/index.d.ts.map +1 -0
- package/dist/__tests__/fixtures/index.js +19 -0
- package/dist/__tests__/fixtures/index.js.map +1 -0
- package/dist/__tests__/fixtures/introspection.json +40522 -0
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +7 -46
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +38 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -2
- package/dist/config.js.map +1 -1
- package/dist/{lib/conjure.d.ts → conjure/index.d.ts} +62 -3
- package/dist/conjure/index.d.ts.map +1 -0
- package/dist/{lib/conjure.js → conjure/index.js} +124 -3
- package/dist/conjure/index.js.map +1 -0
- package/dist/conjure/signature.d.ts +85 -0
- package/dist/conjure/signature.d.ts.map +1 -0
- package/dist/conjure/signature.js +130 -0
- package/dist/conjure/signature.js.map +1 -0
- package/dist/conjure/types.d.ts +97 -0
- package/dist/conjure/types.d.ts.map +1 -0
- package/dist/conjure/types.js +206 -0
- package/dist/conjure/types.js.map +1 -0
- package/dist/errors.d.ts +114 -139
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +82 -36
- package/dist/errors.js.map +1 -1
- package/dist/generate.d.ts +45 -46
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +86 -59
- package/dist/generate.js.map +1 -1
- package/dist/hex/builder.d.ts +12 -0
- package/dist/hex/builder.d.ts.map +1 -0
- package/dist/hex/builder.js +64 -0
- package/dist/hex/builder.js.map +1 -0
- package/dist/hex/ddl.d.ts +53 -0
- package/dist/hex/ddl.d.ts.map +1 -0
- package/dist/hex/ddl.js +306 -0
- package/dist/hex/ddl.js.map +1 -0
- package/dist/hex/index.d.ts +105 -0
- package/dist/hex/index.d.ts.map +1 -0
- package/dist/hex/index.js +81 -0
- package/dist/hex/index.js.map +1 -0
- package/dist/hex/primitives.d.ts +23 -0
- package/dist/hex/primitives.d.ts.map +1 -0
- package/dist/hex/primitives.js +38 -0
- package/dist/hex/primitives.js.map +1 -0
- package/dist/hex/query.d.ts +116 -0
- package/dist/hex/query.d.ts.map +1 -0
- package/dist/hex/query.js +219 -0
- package/dist/hex/query.js.map +1 -0
- package/dist/hex/types.d.ts +287 -0
- package/dist/hex/types.d.ts.map +1 -0
- package/dist/hex/types.js +431 -0
- package/dist/hex/types.js.map +1 -0
- package/dist/index.d.ts +17 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -44
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +76 -140
- package/dist/init.js.map +1 -1
- package/dist/ir/extensions/queries.d.ts +6 -6
- package/dist/ir/extensions/queries.d.ts.map +1 -1
- package/dist/ir/extensions/queries.js +6 -4
- package/dist/ir/extensions/queries.js.map +1 -1
- package/dist/ir/extensions/schema-builder.d.ts.map +1 -1
- package/dist/ir/extensions/schema-builder.js.map +1 -1
- package/dist/ir/index.d.ts.map +1 -1
- package/dist/ir/index.js.map +1 -1
- package/dist/ir/relation-graph.d.ts.map +1 -1
- package/dist/ir/relation-graph.js +8 -8
- package/dist/ir/relation-graph.js.map +1 -1
- package/dist/ir/semantic-ir.d.ts +38 -0
- package/dist/ir/semantic-ir.d.ts.map +1 -1
- package/dist/ir/semantic-ir.js +50 -2
- package/dist/ir/semantic-ir.js.map +1 -1
- package/dist/ir/smart-tags.d.ts.map +1 -1
- package/dist/ir/smart-tags.js.map +1 -1
- package/dist/lib/field-utils.d.ts.map +1 -1
- package/dist/lib/field-utils.js +7 -7
- package/dist/lib/field-utils.js.map +1 -1
- package/dist/lib/join-graph.d.ts +95 -0
- package/dist/lib/join-graph.d.ts.map +1 -0
- package/dist/lib/join-graph.js +305 -0
- package/dist/lib/join-graph.js.map +1 -0
- package/dist/lib/picker.d.ts +60 -0
- package/dist/lib/picker.d.ts.map +1 -0
- package/dist/lib/picker.js +325 -0
- package/dist/lib/picker.js.map +1 -0
- package/dist/plugins/arktype.d.ts +20 -24
- package/dist/plugins/arktype.d.ts.map +1 -1
- package/dist/plugins/arktype.js +462 -386
- package/dist/plugins/arktype.js.map +1 -1
- package/dist/plugins/effect/http.d.ts +7 -0
- package/dist/plugins/effect/http.d.ts.map +1 -0
- package/dist/plugins/effect/http.js +460 -0
- package/dist/plugins/effect/http.js.map +1 -0
- package/dist/plugins/effect/index.d.ts +22 -0
- package/dist/plugins/effect/index.d.ts.map +1 -0
- package/dist/plugins/effect/index.js +65 -0
- package/dist/plugins/effect/index.js.map +1 -0
- package/dist/plugins/effect/models.d.ts +6 -0
- package/dist/plugins/effect/models.d.ts.map +1 -0
- package/dist/plugins/effect/models.js +116 -0
- package/dist/plugins/effect/models.js.map +1 -0
- package/dist/plugins/effect/repos.d.ts +21 -0
- package/dist/plugins/effect/repos.d.ts.map +1 -0
- package/dist/plugins/effect/repos.js +131 -0
- package/dist/plugins/effect/repos.js.map +1 -0
- package/dist/plugins/effect/schemas.d.ts +7 -0
- package/dist/plugins/effect/schemas.d.ts.map +1 -0
- package/dist/plugins/effect/schemas.js +75 -0
- package/dist/plugins/effect/schemas.js.map +1 -0
- package/dist/plugins/effect/shared.d.ts +116 -0
- package/dist/plugins/effect/shared.d.ts.map +1 -0
- package/dist/plugins/effect/shared.js +164 -0
- package/dist/plugins/effect/shared.js.map +1 -0
- package/dist/plugins/http-elysia.d.ts +20 -27
- package/dist/plugins/http-elysia.d.ts.map +1 -1
- package/dist/plugins/http-elysia.js +350 -475
- package/dist/plugins/http-elysia.js.map +1 -1
- package/dist/plugins/http-express.d.ts +20 -31
- package/dist/plugins/http-express.d.ts.map +1 -1
- package/dist/plugins/http-express.js +281 -268
- package/dist/plugins/http-express.js.map +1 -1
- package/dist/plugins/http-hono.d.ts +17 -33
- package/dist/plugins/http-hono.d.ts.map +1 -1
- package/dist/plugins/http-hono.js +317 -341
- package/dist/plugins/http-hono.js.map +1 -1
- package/dist/plugins/http-orpc.d.ts +34 -33
- package/dist/plugins/http-orpc.d.ts.map +1 -1
- package/dist/plugins/http-orpc.js +345 -257
- package/dist/plugins/http-orpc.js.map +1 -1
- package/dist/plugins/http-trpc.d.ts +33 -35
- package/dist/plugins/http-trpc.d.ts.map +1 -1
- package/dist/plugins/http-trpc.js +337 -241
- package/dist/plugins/http-trpc.js.map +1 -1
- package/dist/plugins/kysely.d.ts +54 -59
- package/dist/plugins/kysely.d.ts.map +1 -1
- package/dist/plugins/kysely.js +826 -687
- package/dist/plugins/kysely.js.map +1 -1
- package/dist/plugins/sql-queries.d.ts +38 -44
- package/dist/plugins/sql-queries.d.ts.map +1 -1
- package/dist/plugins/sql-queries.js +497 -897
- package/dist/plugins/sql-queries.js.map +1 -1
- package/dist/plugins/types.d.ts +12 -20
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/plugins/types.js +84 -227
- package/dist/plugins/types.js.map +1 -1
- package/dist/plugins/valibot.d.ts +7 -44
- package/dist/plugins/valibot.d.ts.map +1 -1
- package/dist/plugins/valibot.js +376 -382
- package/dist/plugins/valibot.js.map +1 -1
- package/dist/plugins/zod.d.ts +20 -24
- package/dist/plugins/zod.d.ts.map +1 -1
- package/dist/plugins/zod.js +370 -367
- package/dist/plugins/zod.js.map +1 -1
- package/dist/runtime/emit.d.ts +64 -0
- package/dist/runtime/emit.d.ts.map +1 -0
- package/dist/runtime/emit.js +445 -0
- package/dist/runtime/emit.js.map +1 -0
- package/dist/runtime/errors.d.ts +36 -0
- package/dist/runtime/errors.d.ts.map +1 -0
- package/dist/runtime/errors.js +29 -0
- package/dist/runtime/errors.js.map +1 -0
- package/dist/runtime/file-assignment.d.ts +161 -0
- package/dist/runtime/file-assignment.d.ts.map +1 -0
- package/dist/runtime/file-assignment.js +195 -0
- package/dist/runtime/file-assignment.js.map +1 -0
- package/dist/runtime/orchestrator.d.ts +62 -0
- package/dist/runtime/orchestrator.d.ts.map +1 -0
- package/dist/runtime/orchestrator.js +99 -0
- package/dist/runtime/orchestrator.js.map +1 -0
- package/dist/runtime/registry.d.ts +268 -0
- package/dist/runtime/registry.d.ts.map +1 -0
- package/dist/runtime/registry.js +436 -0
- package/dist/runtime/registry.js.map +1 -0
- package/dist/runtime/types.d.ts +182 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/validation.d.ts +41 -0
- package/dist/runtime/validation.d.ts.map +1 -0
- package/dist/runtime/validation.js +70 -0
- package/dist/runtime/validation.js.map +1 -0
- package/dist/services/config-loader.d.ts.map +1 -1
- package/dist/services/config-loader.js +15 -6
- package/dist/services/config-loader.js.map +1 -1
- package/dist/services/config.d.ts +55 -25
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +60 -34
- package/dist/services/config.js.map +1 -1
- package/dist/services/file-writer.d.ts +3 -3
- package/dist/services/file-writer.d.ts.map +1 -1
- package/dist/services/file-writer.js +6 -8
- package/dist/services/file-writer.js.map +1 -1
- package/dist/services/inflection.d.ts +126 -27
- package/dist/services/inflection.d.ts.map +1 -1
- package/dist/services/inflection.js +300 -72
- package/dist/services/inflection.js.map +1 -1
- package/dist/services/introspection.d.ts.map +1 -1
- package/dist/services/introspection.js +6 -6
- package/dist/services/introspection.js.map +1 -1
- package/dist/services/ir-builder.d.ts.map +1 -1
- package/dist/services/ir-builder.js +73 -77
- package/dist/services/ir-builder.js.map +1 -1
- package/dist/services/ir.d.ts.map +1 -1
- package/dist/services/ir.js.map +1 -1
- package/dist/services/pg-types.d.ts.map +1 -1
- package/dist/services/pg-types.js +3 -3
- package/dist/services/pg-types.js.map +1 -1
- package/dist/services/smart-tags-parser.d.ts.map +1 -1
- package/dist/services/smart-tags-parser.js +4 -4
- package/dist/services/smart-tags-parser.js.map +1 -1
- package/dist/services/type-hints.d.ts.map +1 -1
- package/dist/services/type-hints.js +1 -1
- package/dist/services/type-hints.js.map +1 -1
- package/dist/services/user-module-parser.d.ts +46 -0
- package/dist/services/user-module-parser.d.ts.map +1 -0
- package/dist/services/user-module-parser.js +181 -0
- package/dist/services/user-module-parser.js.map +1 -0
- package/dist/shared/converters.d.ts +60 -0
- package/dist/shared/converters.d.ts.map +1 -0
- package/dist/shared/converters.js +168 -0
- package/dist/shared/converters.js.map +1 -0
- package/dist/shared/query-types.d.ts +95 -0
- package/dist/shared/query-types.d.ts.map +1 -0
- package/dist/shared/query-types.js +9 -0
- package/dist/shared/query-types.js.map +1 -0
- package/dist/testing.d.ts +125 -37
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +134 -42
- package/dist/testing.js.map +1 -1
- package/dist/user-module.d.ts +86 -0
- package/dist/user-module.d.ts.map +1 -0
- package/dist/user-module.js +55 -0
- package/dist/user-module.js.map +1 -0
- package/package.json +10 -6
- package/dist/lib/conjure.d.ts.map +0 -1
- package/dist/lib/conjure.js.map +0 -1
- package/dist/lib/hex.d.ts +0 -119
- package/dist/lib/hex.d.ts.map +0 -1
- package/dist/lib/hex.js +0 -188
- package/dist/lib/hex.js.map +0 -1
- package/dist/plugins/effect.d.ts +0 -53
- package/dist/plugins/effect.d.ts.map +0 -1
- package/dist/plugins/effect.js +0 -1074
- package/dist/plugins/effect.js.map +0 -1
- package/dist/plugins/kysely/queries.d.ts +0 -92
- package/dist/plugins/kysely/queries.d.ts.map +0 -1
- package/dist/plugins/kysely/queries.js +0 -1169
- package/dist/plugins/kysely/queries.js.map +0 -1
- package/dist/plugins/kysely/shared.d.ts +0 -59
- package/dist/plugins/kysely/shared.d.ts.map +0 -1
- package/dist/plugins/kysely/shared.js +0 -247
- package/dist/plugins/kysely/shared.js.map +0 -1
- package/dist/plugins/kysely/types.d.ts +0 -22
- package/dist/plugins/kysely/types.d.ts.map +0 -1
- package/dist/plugins/kysely/types.js +0 -428
- package/dist/plugins/kysely/types.js.map +0 -1
- package/dist/services/artifact-store.d.ts +0 -65
- package/dist/services/artifact-store.d.ts.map +0 -1
- package/dist/services/artifact-store.js +0 -57
- package/dist/services/artifact-store.js.map +0 -1
- package/dist/services/core-providers.d.ts +0 -15
- package/dist/services/core-providers.d.ts.map +0 -1
- package/dist/services/core-providers.js +0 -23
- package/dist/services/core-providers.js.map +0 -1
- package/dist/services/emissions.d.ts +0 -103
- package/dist/services/emissions.d.ts.map +0 -1
- package/dist/services/emissions.js +0 -241
- package/dist/services/emissions.js.map +0 -1
- package/dist/services/execution.d.ts +0 -35
- package/dist/services/execution.d.ts.map +0 -1
- package/dist/services/execution.js +0 -86
- package/dist/services/execution.js.map +0 -1
- package/dist/services/file-builder.d.ts +0 -85
- package/dist/services/file-builder.d.ts.map +0 -1
- package/dist/services/file-builder.js +0 -112
- package/dist/services/file-builder.js.map +0 -1
- package/dist/services/plugin-meta.d.ts +0 -33
- package/dist/services/plugin-meta.d.ts.map +0 -1
- package/dist/services/plugin-meta.js +0 -24
- package/dist/services/plugin-meta.js.map +0 -1
- package/dist/services/plugin-runner.d.ts +0 -42
- package/dist/services/plugin-runner.d.ts.map +0 -1
- package/dist/services/plugin-runner.js +0 -84
- package/dist/services/plugin-runner.js.map +0 -1
- package/dist/services/plugin.d.ts +0 -421
- package/dist/services/plugin.d.ts.map +0 -1
- package/dist/services/plugin.js +0 -197
- package/dist/services/plugin.js.map +0 -1
- package/dist/services/resolution.d.ts +0 -38
- package/dist/services/resolution.d.ts.map +0 -1
- package/dist/services/resolution.js +0 -242
- package/dist/services/resolution.js.map +0 -1
- package/dist/services/service-registry.d.ts +0 -74
- package/dist/services/service-registry.d.ts.map +0 -1
- package/dist/services/service-registry.js +0 -61
- package/dist/services/service-registry.js.map +0 -1
- package/dist/services/symbols.d.ts +0 -144
- package/dist/services/symbols.d.ts.map +0 -1
- package/dist/services/symbols.js +0 -144
- package/dist/services/symbols.js.map +0 -1
package/dist/plugins/arktype.js
CHANGED
|
@@ -1,422 +1,498 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ArkType Plugin -
|
|
2
|
+
* ArkType Plugin - Generates ArkType schemas for entities
|
|
3
3
|
*
|
|
4
|
-
* Generates ArkType
|
|
5
|
-
* with inferred TypeScript types.
|
|
4
|
+
* Generates ArkType schemas for Row, Insert, Update, and Patch shapes,
|
|
5
|
+
* with optional inferred TypeScript types.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* - `
|
|
9
|
-
* - `
|
|
10
|
-
* - `
|
|
11
|
-
* -
|
|
7
|
+
* Capabilities provided:
|
|
8
|
+
* - `schema:arktype:EntityName` for each table entity (Row schema)
|
|
9
|
+
* - `schema:arktype:EntityName:insert` for Insert shape
|
|
10
|
+
* - `schema:arktype:EntityName:update` for Update shape
|
|
11
|
+
* - `schema:arktype:EnumName` for enum entities
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { SCHEMA_BUILDER_KIND, } from "../ir/extensions/schema-builder.js";
|
|
20
|
-
const { ts, exp, obj } = conjure;
|
|
21
|
-
const ArkTypeConfigSchema = S.Struct({
|
|
22
|
-
outputDir: S.optionalWith(S.String, { default: () => "arktype" }),
|
|
23
|
-
exportTypes: S.optionalWith(S.Boolean, { default: () => true }),
|
|
24
|
-
enumStyle: S.optionalWith(S.Union(S.Literal("strings"), S.Literal("enum")), {
|
|
25
|
-
default: () => "strings",
|
|
26
|
-
}),
|
|
27
|
-
typeReferences: S.optionalWith(S.Union(S.Literal("inline"), S.Literal("separate")), {
|
|
28
|
-
default: () => "separate",
|
|
29
|
-
}),
|
|
30
|
-
});
|
|
31
|
-
// ============================================================================
|
|
32
|
-
// ArkType Schema Builders (pure functions)
|
|
33
|
-
// ============================================================================
|
|
13
|
+
import { Effect, Schema as S } from "effect";
|
|
14
|
+
import { normalizeFileNaming } from "../runtime/file-assignment.js";
|
|
15
|
+
import { SymbolRegistry } from "../runtime/registry.js";
|
|
16
|
+
import { IR } from "../services/ir.js";
|
|
17
|
+
import { isTableEntity, isEnumEntity, } from "../ir/semantic-ir.js";
|
|
18
|
+
import { conjure, cast } from "../conjure/index.js";
|
|
34
19
|
/**
|
|
35
|
-
*
|
|
20
|
+
* Creates a consume callback for ArkType schemas.
|
|
21
|
+
* Generates: `SchemaName.assert(input)` (throws on validation error)
|
|
36
22
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* - `"Date"` for Date objects
|
|
40
|
-
* - `"string?"` for optional
|
|
41
|
-
* - `"string | null"` for nullable
|
|
42
|
-
* - `"string[]"` for arrays
|
|
43
|
-
*/
|
|
44
|
-
const buildArkTypeString = (baseType, modifiers) => {
|
|
45
|
-
let result = baseType;
|
|
46
|
-
// Apply array first (before nullable/optional)
|
|
47
|
-
if (modifiers.isArray) {
|
|
48
|
-
result = `${result}[]`;
|
|
49
|
-
}
|
|
50
|
-
// For nullable, use union with null
|
|
51
|
-
if (modifiers.nullable) {
|
|
52
|
-
result = `${result} | null`;
|
|
53
|
-
}
|
|
54
|
-
// Optional uses ? suffix in object keys, not in the type string itself
|
|
55
|
-
// We handle this at the property level
|
|
56
|
-
return result;
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Build ArkType enum as union of string literals: `"'a' | 'b' | 'c'"`
|
|
23
|
+
* @param schemaName - The name of the ArkType schema
|
|
24
|
+
* @returns A function that generates assert AST for an input expression
|
|
60
25
|
*/
|
|
61
|
-
|
|
26
|
+
function createArkTypeConsumeCallback(schemaName) {
|
|
27
|
+
return (input) => {
|
|
28
|
+
return conjure.id(schemaName).method("assert", [cast.toExpr(input)]).build();
|
|
29
|
+
};
|
|
30
|
+
}
|
|
62
31
|
/**
|
|
63
|
-
*
|
|
32
|
+
* Convert a param type to an ArkType type string.
|
|
64
33
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
case
|
|
70
|
-
|
|
71
|
-
case
|
|
72
|
-
|
|
73
|
-
case
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
case
|
|
78
|
-
|
|
34
|
+
function paramToArkTypeString(param) {
|
|
35
|
+
const baseType = param.type.replace(/\[\]$/, "").replace(/\?$/, "").toLowerCase();
|
|
36
|
+
let arkType;
|
|
37
|
+
switch (baseType) {
|
|
38
|
+
case "number":
|
|
39
|
+
case "int":
|
|
40
|
+
case "integer":
|
|
41
|
+
case "float":
|
|
42
|
+
case "double":
|
|
43
|
+
arkType = "number";
|
|
44
|
+
break;
|
|
45
|
+
case "boolean":
|
|
46
|
+
case "bool":
|
|
47
|
+
arkType = "boolean";
|
|
48
|
+
break;
|
|
49
|
+
case "date":
|
|
50
|
+
arkType = "Date";
|
|
51
|
+
break;
|
|
52
|
+
case "string":
|
|
79
53
|
default:
|
|
80
|
-
|
|
54
|
+
arkType = "string";
|
|
55
|
+
break;
|
|
81
56
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return
|
|
57
|
+
if (!param.required) {
|
|
58
|
+
arkType = `${arkType}?`;
|
|
59
|
+
}
|
|
60
|
+
return arkType;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* ArkType SchemaBuilder implementation.
|
|
64
|
+
* Builds ArkType schemas for path/query parameters.
|
|
65
|
+
*/
|
|
66
|
+
const arkTypeSchemaBuilder = {
|
|
67
|
+
build(request) {
|
|
68
|
+
if (request.params.length === 0) {
|
|
69
|
+
return undefined;
|
|
95
70
|
}
|
|
96
|
-
//
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
|
|
71
|
+
// Build type({ field: "string", ... })
|
|
72
|
+
const typeObj = {};
|
|
73
|
+
for (const param of request.params) {
|
|
74
|
+
typeObj[param.name] = paramToArkTypeString(param);
|
|
75
|
+
}
|
|
76
|
+
// Generate: type({ id: "number", email: "string" })
|
|
77
|
+
let objBuilder = conjure.obj();
|
|
78
|
+
for (const [name, arkType] of Object.entries(typeObj)) {
|
|
79
|
+
objBuilder = objBuilder.prop(name, conjure.str(arkType));
|
|
80
|
+
}
|
|
81
|
+
const ast = conjure.id("type").call([objBuilder.build()]).build();
|
|
100
82
|
return {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
isArray: field.isArray,
|
|
104
|
-
}),
|
|
105
|
-
isReference: false,
|
|
83
|
+
ast,
|
|
84
|
+
importSpec: { from: "arktype", names: ["type"] },
|
|
106
85
|
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
const ArkTypeSchemaConfig = S.Struct({
|
|
89
|
+
exportTypes: S.optionalWith(S.Boolean, { default: () => true }),
|
|
90
|
+
});
|
|
91
|
+
function toExpr(node) {
|
|
92
|
+
return node;
|
|
93
|
+
}
|
|
94
|
+
// =============================================================================
|
|
95
|
+
// PostgreSQL Type to ArkType String Mapping
|
|
96
|
+
// =============================================================================
|
|
97
|
+
const PG_STRING_TYPES = new Set([
|
|
98
|
+
"uuid",
|
|
99
|
+
"text",
|
|
100
|
+
"varchar",
|
|
101
|
+
"char",
|
|
102
|
+
"character",
|
|
103
|
+
"name",
|
|
104
|
+
"bpchar",
|
|
105
|
+
"citext",
|
|
106
|
+
]);
|
|
107
|
+
const PG_NUMBER_TYPES = new Set([
|
|
108
|
+
"int2",
|
|
109
|
+
"int4",
|
|
110
|
+
"int8",
|
|
111
|
+
"integer",
|
|
112
|
+
"smallint",
|
|
113
|
+
"bigint",
|
|
114
|
+
"numeric",
|
|
115
|
+
"decimal",
|
|
116
|
+
"real",
|
|
117
|
+
"float4",
|
|
118
|
+
"float8",
|
|
119
|
+
"double",
|
|
120
|
+
]);
|
|
121
|
+
const PG_BOOLEAN_TYPES = new Set(["bool", "boolean"]);
|
|
122
|
+
const PG_DATE_TYPES = new Set(["timestamp", "timestamptz", "date", "time", "timetz"]);
|
|
123
|
+
const PG_JSON_TYPES = new Set(["json", "jsonb"]);
|
|
124
|
+
function fieldToArkType(field, enums) {
|
|
125
|
+
const pgType = field.pgAttribute.getType();
|
|
126
|
+
if (!pgType) {
|
|
127
|
+
return { kind: "string", typeString: "unknown" };
|
|
107
128
|
}
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
isReference: false,
|
|
116
|
-
};
|
|
129
|
+
// For arrays, use element type; for domains, use base type; otherwise use pgType
|
|
130
|
+
let typeName;
|
|
131
|
+
let typeInfo;
|
|
132
|
+
if (pgType.typcategory === "A") {
|
|
133
|
+
// Array type - use element type name
|
|
134
|
+
typeName = field.elementTypeName ?? "unknown";
|
|
135
|
+
typeInfo = pgType;
|
|
117
136
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
nullable: field.nullable,
|
|
123
|
-
isArray: field.isArray,
|
|
124
|
-
}),
|
|
125
|
-
isReference: false,
|
|
126
|
-
};
|
|
137
|
+
else if (pgType.typtype === "d" && field.domainBaseType) {
|
|
138
|
+
// Domain type - resolve to underlying base type
|
|
139
|
+
typeName = field.domainBaseType.typeName;
|
|
140
|
+
typeInfo = { typcategory: field.domainBaseType.category };
|
|
127
141
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
142
|
+
else {
|
|
143
|
+
typeName = pgType.typname;
|
|
144
|
+
typeInfo = pgType;
|
|
145
|
+
}
|
|
146
|
+
const baseResult = baseTypeToArkType(typeName, typeInfo, enums);
|
|
147
|
+
// For enum references, we can't easily add modifiers in string form,
|
|
148
|
+
// so we handle them specially in shapeToArkTypeObject
|
|
149
|
+
if (baseResult.kind === "enumRef") {
|
|
150
|
+
return baseResult;
|
|
151
|
+
}
|
|
152
|
+
let typeStr = baseResult.typeString;
|
|
153
|
+
if (field.isArray) {
|
|
154
|
+
typeStr = `${typeStr}[]`;
|
|
155
|
+
}
|
|
156
|
+
if (field.nullable) {
|
|
157
|
+
typeStr = `${typeStr} | null`;
|
|
158
|
+
}
|
|
159
|
+
if (field.optional) {
|
|
160
|
+
typeStr = `${typeStr}?`;
|
|
161
|
+
}
|
|
162
|
+
return { kind: "string", typeString: typeStr };
|
|
163
|
+
}
|
|
164
|
+
function baseTypeToArkType(typeName, pgType, enums) {
|
|
165
|
+
const normalized = typeName.toLowerCase();
|
|
166
|
+
if (PG_STRING_TYPES.has(normalized)) {
|
|
167
|
+
if (normalized === "uuid") {
|
|
168
|
+
return { kind: "string", typeString: "string.uuid" };
|
|
154
169
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return conjure.id("type").call([objBuilder.build()]).build();
|
|
159
|
-
};
|
|
160
|
-
/**
|
|
161
|
-
* Generate schema const + optional inferred type for a shape
|
|
162
|
-
*/
|
|
163
|
-
const generateShapeStatements = (shape, entityName, shapeKind, ctx, exportTypes) => {
|
|
164
|
-
const schemaSymbolCtx = { capability: "schemas", entity: entityName, shape: shapeKind };
|
|
165
|
-
const schemaExpr = buildShapeArkTypeObject(shape, ctx);
|
|
166
|
-
const schemaStatement = exp.const(shape.name, schemaSymbolCtx, schemaExpr);
|
|
167
|
-
if (!exportTypes) {
|
|
168
|
-
return [schemaStatement];
|
|
170
|
+
// citext is case-insensitive text, but ArkType doesn't have a specific validator
|
|
171
|
+
// Just treat it as a regular string
|
|
172
|
+
return { kind: "string", typeString: "string" };
|
|
169
173
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
*/
|
|
188
|
-
const generateEntityStatements = (entity, ctx, exportTypes) => collectShapes(entity).flatMap(([kind, shape]) => generateShapeStatements(shape, entity.name, kind, ctx, exportTypes));
|
|
189
|
-
// ============================================================================
|
|
190
|
-
// Composite Type Generation
|
|
191
|
-
// ============================================================================
|
|
192
|
-
/**
|
|
193
|
-
* Build type({ ... }) expression from composite fields
|
|
194
|
-
*/
|
|
195
|
-
const buildCompositeArkTypeObject = (composite, ctx) => {
|
|
196
|
-
const objBuilder = composite.fields.reduce((builder, field) => {
|
|
197
|
-
const result = resolveFieldArkType(field, ctx);
|
|
198
|
-
const value = result.isReference
|
|
199
|
-
? conjure.id(result.typeString).build()
|
|
200
|
-
: conjure.str(result.typeString);
|
|
201
|
-
// Use "key?" syntax for optional fields
|
|
202
|
-
if (field.optional) {
|
|
203
|
-
return builder.stringProp(`${field.name}?`, value);
|
|
174
|
+
if (PG_NUMBER_TYPES.has(normalized)) {
|
|
175
|
+
return { kind: "string", typeString: "number" };
|
|
176
|
+
}
|
|
177
|
+
if (PG_BOOLEAN_TYPES.has(normalized)) {
|
|
178
|
+
return { kind: "string", typeString: "boolean" };
|
|
179
|
+
}
|
|
180
|
+
if (PG_DATE_TYPES.has(normalized)) {
|
|
181
|
+
return { kind: "string", typeString: "Date" };
|
|
182
|
+
}
|
|
183
|
+
if (PG_JSON_TYPES.has(normalized)) {
|
|
184
|
+
return { kind: "string", typeString: "unknown" };
|
|
185
|
+
}
|
|
186
|
+
if (pgType.typtype === "e" || pgType.typcategory === "E") {
|
|
187
|
+
const enumEntity = enums.find(e => e.pgType.typname === typeName);
|
|
188
|
+
if (enumEntity) {
|
|
189
|
+
// Return reference to the enum schema instead of inlining
|
|
190
|
+
return { kind: "enumRef", enumRef: enumEntity.name };
|
|
204
191
|
}
|
|
205
|
-
return
|
|
206
|
-
}, obj());
|
|
207
|
-
return conjure.id("type").call([objBuilder.build()]).build();
|
|
208
|
-
};
|
|
209
|
-
/**
|
|
210
|
-
* Generate schema const + optional inferred type for a composite type
|
|
211
|
-
*/
|
|
212
|
-
const generateCompositeStatements = (composite, ctx, exportTypes) => {
|
|
213
|
-
const schemaSymbolCtx = { capability: "schemas", entity: composite.name };
|
|
214
|
-
const schemaExpr = buildCompositeArkTypeObject(composite, ctx);
|
|
215
|
-
const schemaStatement = exp.const(composite.name, schemaSymbolCtx, schemaExpr);
|
|
216
|
-
if (!exportTypes) {
|
|
217
|
-
return [schemaStatement];
|
|
192
|
+
return { kind: "string", typeString: "unknown" };
|
|
218
193
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
194
|
+
return { kind: "string", typeString: "unknown" };
|
|
195
|
+
}
|
|
196
|
+
// =============================================================================
|
|
197
|
+
// Shape to ArkType Object
|
|
198
|
+
// =============================================================================
|
|
199
|
+
function shapeToArkTypeObject(shape, enums, registry) {
|
|
200
|
+
let objBuilder = conjure.obj();
|
|
201
|
+
for (const field of shape.fields) {
|
|
202
|
+
const mapping = fieldToArkType(field, enums);
|
|
203
|
+
if (mapping.kind === "enumRef") {
|
|
204
|
+
// Get handle and track cross-reference
|
|
205
|
+
const enumHandle = registry.import(`schema:arktype:${mapping.enumRef}`);
|
|
206
|
+
let enumExpr = enumHandle.ref();
|
|
207
|
+
if (field.isArray) {
|
|
208
|
+
enumExpr = conjure.chain(enumExpr).method("array").build();
|
|
209
|
+
}
|
|
210
|
+
if (field.nullable) {
|
|
211
|
+
enumExpr = conjure.chain(enumExpr).method("or", [conjure.id("type").call([conjure.str("null")]).build()]).build();
|
|
212
|
+
}
|
|
213
|
+
// Note: ArkType doesn't have a direct .optional() method like Zod
|
|
214
|
+
// Optional is typically handled at the object level with "key?" syntax
|
|
215
|
+
// For now, we'll treat optional enum fields the same as required
|
|
216
|
+
// This is a limitation - may need scope() for full support
|
|
217
|
+
objBuilder = objBuilder.prop(field.name, enumExpr);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
objBuilder = objBuilder.prop(field.name, conjure.str(mapping.typeString));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return conjure.id("type").call([objBuilder.build()]).build();
|
|
224
|
+
}
|
|
228
225
|
/**
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
226
|
+
* Build an UpdateInput schema: PK fields required, non-PK update fields optional.
|
|
227
|
+
* This is used for update operations where we need to identify the row (PK) and
|
|
228
|
+
* specify which fields to change (non-PK).
|
|
232
229
|
*/
|
|
233
|
-
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
// For arktype with native enums: type("keyof", typeof EnumName)
|
|
239
|
-
const schemaName = `${enumEntity.name}Type`;
|
|
240
|
-
const typeofExpr = conjure.b.unaryExpression("typeof", conjure.id(enumEntity.name).build(), true);
|
|
241
|
-
const schemaExpr = conjure
|
|
242
|
-
.id("type")
|
|
243
|
-
.call([conjure.str("keyof"), typeofExpr])
|
|
244
|
-
.build();
|
|
245
|
-
const schemaStatement = exp.const(schemaName, schemaSymbolCtx, schemaExpr);
|
|
246
|
-
return [enumStatement, schemaStatement];
|
|
230
|
+
function buildUpdateInputSchema(entity, enums, registry) {
|
|
231
|
+
const updateShape = entity.shapes.update;
|
|
232
|
+
const primaryKey = entity.primaryKey;
|
|
233
|
+
if (!updateShape || !primaryKey) {
|
|
234
|
+
return null;
|
|
247
235
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
.
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
236
|
+
const pkColumnSet = new Set(primaryKey.columns);
|
|
237
|
+
let objBuilder = conjure.obj();
|
|
238
|
+
// First, add PK fields as REQUIRED (from row shape to get correct types)
|
|
239
|
+
for (const pkColName of primaryKey.columns) {
|
|
240
|
+
// Find the field in the row shape (PK fields always exist in row)
|
|
241
|
+
const pkField = entity.shapes.row.fields.find(f => f.name === pkColName);
|
|
242
|
+
if (!pkField)
|
|
243
|
+
continue;
|
|
244
|
+
// Get the base type without optional/nullable modifiers for PK
|
|
245
|
+
const mapping = fieldToArkType({ ...pkField, optional: false, nullable: false }, enums);
|
|
246
|
+
if (mapping.kind === "enumRef") {
|
|
247
|
+
const enumHandle = registry.import(`schema:arktype:${mapping.enumRef}`);
|
|
248
|
+
objBuilder = objBuilder.prop(pkField.name, enumHandle.ref());
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
objBuilder = objBuilder.prop(pkField.name, conjure.str(mapping.typeString));
|
|
252
|
+
}
|
|
257
253
|
}
|
|
258
|
-
//
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// ============================================================================
|
|
282
|
-
/**
|
|
283
|
-
* Map TypeScript type string to ArkType string for params.
|
|
284
|
-
* URL params are strings, so we use string.integer for numbers (coerces).
|
|
285
|
-
*/
|
|
286
|
-
const paramTypeToArkTypeString = (tsType) => {
|
|
287
|
-
switch (tsType.toLowerCase()) {
|
|
288
|
-
case "number":
|
|
289
|
-
// string.integer parses string to integer
|
|
290
|
-
return "string.integer.parse";
|
|
291
|
-
case "boolean":
|
|
292
|
-
return "string"; // ArkType doesn't have built-in boolean coercion from string
|
|
293
|
-
case "bigint":
|
|
294
|
-
return "string"; // Handle as string, parse manually
|
|
295
|
-
case "string":
|
|
296
|
-
default:
|
|
297
|
-
return "string";
|
|
254
|
+
// Then add non-PK fields from update shape as OPTIONAL
|
|
255
|
+
for (const field of updateShape.fields) {
|
|
256
|
+
if (pkColumnSet.has(field.name)) {
|
|
257
|
+
continue; // Skip PK fields, already added above
|
|
258
|
+
}
|
|
259
|
+
// Force optional for non-PK fields (partial updates)
|
|
260
|
+
const mapping = fieldToArkType({ ...field, optional: true }, enums);
|
|
261
|
+
if (mapping.kind === "enumRef") {
|
|
262
|
+
const enumHandle = registry.import(`schema:arktype:${mapping.enumRef}`);
|
|
263
|
+
let enumExpr = enumHandle.ref();
|
|
264
|
+
if (field.isArray) {
|
|
265
|
+
enumExpr = conjure.chain(enumExpr).method("array").build();
|
|
266
|
+
}
|
|
267
|
+
if (field.nullable) {
|
|
268
|
+
enumExpr = conjure.chain(enumExpr).method("or", [conjure.id("type").call([conjure.str("null")]).build()]).build();
|
|
269
|
+
}
|
|
270
|
+
// For optional enum fields, we need to use .optional() method
|
|
271
|
+
enumExpr = conjure.chain(enumExpr).method("optional").build();
|
|
272
|
+
objBuilder = objBuilder.prop(field.name, enumExpr);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
objBuilder = objBuilder.prop(field.name, conjure.str(mapping.typeString));
|
|
276
|
+
}
|
|
298
277
|
}
|
|
299
|
-
};
|
|
300
|
-
/**
|
|
301
|
-
* Build type({ ... }) expression from QueryMethodParam[].
|
|
302
|
-
* For path/query parameter validation in HTTP handlers.
|
|
303
|
-
*/
|
|
304
|
-
const buildParamArkTypeObject = (params) => {
|
|
305
|
-
const objBuilder = params.reduce((builder, param) => {
|
|
306
|
-
const arkType = paramTypeToArkTypeString(param.type);
|
|
307
|
-
// Use "key?" syntax for optional params
|
|
308
|
-
const key = param.required ? param.name : `${param.name}?`;
|
|
309
|
-
return builder.stringProp(key, conjure.str(arkType));
|
|
310
|
-
}, obj());
|
|
311
278
|
return conjure.id("type").call([objBuilder.build()]).build();
|
|
312
|
-
}
|
|
279
|
+
}
|
|
280
|
+
// =============================================================================
|
|
281
|
+
// ArkType Plugin Definition
|
|
282
|
+
// =============================================================================
|
|
313
283
|
/**
|
|
314
|
-
*
|
|
284
|
+
* Get the UpdateInput schema name for an entity.
|
|
285
|
+
* Convention: EntityNameUpdateInput (e.g., CommentUpdateInput)
|
|
315
286
|
*/
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
287
|
+
function getUpdateInputName(entity) {
|
|
288
|
+
return `${entity.name}UpdateInput`;
|
|
289
|
+
}
|
|
290
|
+
function getShapeDeclarations(entity) {
|
|
291
|
+
const declarations = [];
|
|
292
|
+
const baseEntityName = entity.name;
|
|
293
|
+
declarations.push({
|
|
294
|
+
name: entity.shapes.row.name,
|
|
295
|
+
capability: `schema:arktype:${entity.shapes.row.name}`,
|
|
296
|
+
baseEntityName,
|
|
297
|
+
});
|
|
298
|
+
if (entity.shapes.insert) {
|
|
299
|
+
const insertName = entity.shapes.insert.name;
|
|
300
|
+
declarations.push({
|
|
301
|
+
name: insertName,
|
|
302
|
+
capability: `schema:arktype:${insertName}`,
|
|
303
|
+
baseEntityName,
|
|
304
|
+
});
|
|
305
|
+
declarations.push({
|
|
306
|
+
name: insertName,
|
|
307
|
+
capability: `schema:arktype:${insertName}:type`,
|
|
308
|
+
baseEntityName,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
if (entity.shapes.update) {
|
|
312
|
+
const updateName = entity.shapes.update.name;
|
|
313
|
+
declarations.push({
|
|
314
|
+
name: updateName,
|
|
315
|
+
capability: `schema:arktype:${updateName}`,
|
|
316
|
+
baseEntityName,
|
|
317
|
+
});
|
|
318
|
+
declarations.push({
|
|
319
|
+
name: updateName,
|
|
320
|
+
capability: `schema:arktype:${updateName}:type`,
|
|
321
|
+
baseEntityName,
|
|
322
|
+
});
|
|
323
|
+
// UpdateInput schema: required PK + optional non-PK fields
|
|
324
|
+
// Only declare if entity has both update shape AND primary key
|
|
325
|
+
if (entity.primaryKey) {
|
|
326
|
+
const updateInputName = getUpdateInputName(entity);
|
|
327
|
+
declarations.push({
|
|
328
|
+
name: updateInputName,
|
|
329
|
+
capability: `schema:arktype:${updateInputName}`,
|
|
330
|
+
baseEntityName,
|
|
331
|
+
});
|
|
332
|
+
declarations.push({
|
|
333
|
+
name: updateInputName,
|
|
334
|
+
capability: `schema:arktype:${updateInputName}:type`,
|
|
335
|
+
baseEntityName,
|
|
336
|
+
});
|
|
320
337
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// ============================================================================
|
|
332
|
-
// Provider Definition
|
|
333
|
-
// ============================================================================
|
|
334
|
-
/**
|
|
335
|
-
* Create an arktype provider that generates ArkType schemas.
|
|
336
|
-
*
|
|
337
|
-
* @example
|
|
338
|
-
* ```typescript
|
|
339
|
-
* import { arktype } from "pg-sourcerer"
|
|
340
|
-
*
|
|
341
|
-
* export default defineConfig({
|
|
342
|
-
* plugins: [
|
|
343
|
-
* arktype(),
|
|
344
|
-
* arktype({ outputDir: "schemas", exportTypes: false }),
|
|
345
|
-
* ],
|
|
346
|
-
* })
|
|
347
|
-
* ```
|
|
348
|
-
*/
|
|
349
|
-
export function arktype(config = {}) {
|
|
350
|
-
const parsed = S.decodeUnknownSync(ArkTypeConfigSchema)(config);
|
|
351
|
-
return definePlugin({
|
|
338
|
+
}
|
|
339
|
+
return declarations;
|
|
340
|
+
}
|
|
341
|
+
export function arktype(config) {
|
|
342
|
+
const schemaConfig = S.decodeSync(ArkTypeSchemaConfig)(config ?? {});
|
|
343
|
+
const resolvedConfig = {
|
|
344
|
+
...schemaConfig,
|
|
345
|
+
schemasFile: normalizeFileNaming(config?.schemasFile, "schemas.ts"),
|
|
346
|
+
};
|
|
347
|
+
return {
|
|
352
348
|
name: "arktype",
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
.
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
.
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
.emit();
|
|
380
|
-
});
|
|
349
|
+
provides: ["schema"],
|
|
350
|
+
fileDefaults: [
|
|
351
|
+
{
|
|
352
|
+
pattern: "schema:",
|
|
353
|
+
fileNaming: resolvedConfig.schemasFile,
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
declare: Effect.gen(function* () {
|
|
357
|
+
const ir = yield* IR;
|
|
358
|
+
const declarations = [];
|
|
359
|
+
for (const entity of ir.entities.values()) {
|
|
360
|
+
if (isTableEntity(entity)) {
|
|
361
|
+
declarations.push(...getShapeDeclarations(entity));
|
|
362
|
+
}
|
|
363
|
+
else if (isEnumEntity(entity)) {
|
|
364
|
+
declarations.push({
|
|
365
|
+
name: entity.name,
|
|
366
|
+
capability: `schema:arktype:${entity.name}`,
|
|
367
|
+
baseEntityName: entity.name,
|
|
368
|
+
});
|
|
369
|
+
declarations.push({
|
|
370
|
+
name: entity.name,
|
|
371
|
+
capability: `schema:arktype:${entity.name}:type`,
|
|
372
|
+
baseEntityName: entity.name,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
381
375
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const entityName = inflection.entityName(entity.pgClass, entity.tags);
|
|
387
|
-
// Collect all fields for enum detection
|
|
388
|
-
const allFields = [
|
|
389
|
-
...entity.shapes.row.fields,
|
|
390
|
-
...(entity.shapes.insert?.fields ?? []),
|
|
391
|
-
...(entity.shapes.update?.fields ?? []),
|
|
392
|
-
];
|
|
393
|
-
const usedEnums = parsed.typeReferences === "separate"
|
|
394
|
-
? collectUsedEnums(allFields, Arr.fromIterable(fieldCtx.enums))
|
|
395
|
-
: new Set();
|
|
396
|
-
const fileBuilder = ctx
|
|
397
|
-
.file(buildFilePath(entityName))
|
|
398
|
-
.import({ kind: "package", names: ["type"], from: "arktype" });
|
|
399
|
-
// Add enum imports when using separate files
|
|
400
|
-
buildEnumImports(usedEnums).forEach(ref => fileBuilder.import(ref));
|
|
401
|
-
fileBuilder.ast(conjure.symbolProgram(...statements)).emit();
|
|
376
|
+
// Declare the schema builder capability
|
|
377
|
+
declarations.push({
|
|
378
|
+
name: "arkTypeSchemaBuilder",
|
|
379
|
+
capability: "schema:arktype:builder",
|
|
402
380
|
});
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
381
|
+
return declarations;
|
|
382
|
+
}),
|
|
383
|
+
render: Effect.gen(function* () {
|
|
384
|
+
const ir = yield* IR;
|
|
385
|
+
const registry = yield* SymbolRegistry;
|
|
386
|
+
const enums = [...ir.entities.values()].filter(isEnumEntity);
|
|
387
|
+
const rendered = [];
|
|
388
|
+
for (const entity of ir.entities.values()) {
|
|
389
|
+
if (isTableEntity(entity)) {
|
|
390
|
+
const shapes = [
|
|
391
|
+
entity.shapes.row,
|
|
392
|
+
];
|
|
393
|
+
if (entity.shapes.insert)
|
|
394
|
+
shapes.push(entity.shapes.insert);
|
|
395
|
+
if (entity.shapes.update)
|
|
396
|
+
shapes.push(entity.shapes.update);
|
|
397
|
+
for (const shape of shapes) {
|
|
398
|
+
const isRow = shape.kind === "row";
|
|
399
|
+
const capability = `schema:arktype:${shape.name}`;
|
|
400
|
+
// Scope cross-references to this specific capability
|
|
401
|
+
const schemaNode = registry.forSymbol(capability, () => shapeToArkTypeObject(shape, enums, registry));
|
|
402
|
+
const schemaDecl = conjure.export.const(shape.name, schemaNode);
|
|
403
|
+
rendered.push({
|
|
404
|
+
name: shape.name,
|
|
405
|
+
capability,
|
|
406
|
+
node: schemaDecl,
|
|
407
|
+
exports: "named",
|
|
408
|
+
externalImports: [{ from: "arktype", names: ["type"] }],
|
|
409
|
+
metadata: {
|
|
410
|
+
consume: createArkTypeConsumeCallback(shape.name),
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
if (resolvedConfig.exportTypes && !isRow) {
|
|
414
|
+
const inferType = conjure.ts.typeof(`${shape.name}.infer`);
|
|
415
|
+
const typeDecl = conjure.export.type(shape.name, inferType);
|
|
416
|
+
rendered.push({
|
|
417
|
+
name: shape.name,
|
|
418
|
+
capability: `schema:arktype:${shape.name}:type`,
|
|
419
|
+
node: typeDecl,
|
|
420
|
+
exports: "named",
|
|
421
|
+
externalImports: [{ from: "arktype", names: ["type"] }],
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// Render UpdateInput schema if entity has update shape AND primary key
|
|
426
|
+
if (entity.shapes.update && entity.primaryKey) {
|
|
427
|
+
const updateInputName = getUpdateInputName(entity);
|
|
428
|
+
const capability = `schema:arktype:${updateInputName}`;
|
|
429
|
+
const schemaNode = registry.forSymbol(capability, () => buildUpdateInputSchema(entity, enums, registry));
|
|
430
|
+
if (schemaNode) {
|
|
431
|
+
const schemaDecl = conjure.export.const(updateInputName, schemaNode);
|
|
432
|
+
rendered.push({
|
|
433
|
+
name: updateInputName,
|
|
434
|
+
capability,
|
|
435
|
+
node: schemaDecl,
|
|
436
|
+
exports: "named",
|
|
437
|
+
externalImports: [{ from: "arktype", names: ["type"] }],
|
|
438
|
+
metadata: {
|
|
439
|
+
consume: createArkTypeConsumeCallback(updateInputName),
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
if (resolvedConfig.exportTypes) {
|
|
443
|
+
const inferType = conjure.ts.typeof(`${updateInputName}.infer`);
|
|
444
|
+
const typeDecl = conjure.export.type(updateInputName, inferType);
|
|
445
|
+
rendered.push({
|
|
446
|
+
name: updateInputName,
|
|
447
|
+
capability: `schema:arktype:${updateInputName}:type`,
|
|
448
|
+
node: typeDecl,
|
|
449
|
+
exports: "named",
|
|
450
|
+
externalImports: [{ from: "arktype", names: ["type"] }],
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
else if (isEnumEntity(entity)) {
|
|
457
|
+
const enumString = entity.values.map(v => `'${v}'`).join(" | ");
|
|
458
|
+
const schemaNode = conjure.id("type").call([conjure.str(enumString)]).build();
|
|
459
|
+
const schemaDecl = conjure.export.const(entity.name, schemaNode);
|
|
460
|
+
const inferType = conjure.ts.typeof(`${entity.name}.infer`);
|
|
461
|
+
const typeDecl = conjure.export.type(entity.name, inferType);
|
|
462
|
+
rendered.push({
|
|
463
|
+
name: entity.name,
|
|
464
|
+
capability: `schema:arktype:${entity.name}`,
|
|
465
|
+
node: schemaDecl,
|
|
466
|
+
exports: "named",
|
|
467
|
+
externalImports: [{ from: "arktype", names: ["type"] }],
|
|
468
|
+
metadata: {
|
|
469
|
+
consume: createArkTypeConsumeCallback(entity.name),
|
|
470
|
+
},
|
|
471
|
+
});
|
|
472
|
+
if (resolvedConfig.exportTypes) {
|
|
473
|
+
rendered.push({
|
|
474
|
+
name: entity.name,
|
|
475
|
+
capability: `schema:arktype:${entity.name}:type`,
|
|
476
|
+
node: typeDecl,
|
|
477
|
+
exports: "named",
|
|
478
|
+
externalImports: [{ from: "arktype", names: ["type"] }],
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
// Render the schema builder (virtual symbol - no node, just metadata)
|
|
484
|
+
// The builder is used by HTTP plugins to generate inline param schemas
|
|
485
|
+
rendered.push({
|
|
486
|
+
name: "arkTypeSchemaBuilder",
|
|
487
|
+
capability: "schema:arktype:builder",
|
|
488
|
+
node: null, // Virtual symbol - no emitted code
|
|
489
|
+
exports: false, // Not exported
|
|
490
|
+
metadata: {
|
|
491
|
+
builder: arkTypeSchemaBuilder,
|
|
492
|
+
},
|
|
417
493
|
});
|
|
418
|
-
return
|
|
419
|
-
},
|
|
420
|
-
}
|
|
494
|
+
return rendered;
|
|
495
|
+
}),
|
|
496
|
+
};
|
|
421
497
|
}
|
|
422
498
|
//# sourceMappingURL=arktype.js.map
|