@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
|
@@ -1,101 +1,76 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* HTTP oRPC Plugin -
|
|
2
|
+
* HTTP oRPC Plugin - Generates oRPC routers from query symbols
|
|
3
3
|
*
|
|
4
|
-
* Consumes
|
|
5
|
-
*
|
|
4
|
+
* Consumes "queries" and "schema" capabilities (provider-agnostic).
|
|
5
|
+
* Works with any queries provider (kysely, drizzle, effect-sql, etc.)
|
|
6
|
+
* and any schema provider (zod, arktype, effect, etc.).
|
|
6
7
|
*
|
|
7
|
-
* Uses
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Uses the SymbolRegistry to resolve query functions and optionally
|
|
9
|
+
* schema symbols for request validation.
|
|
10
|
+
*
|
|
11
|
+
* Imports are resolved via the cross-reference system:
|
|
12
|
+
* - Calls registry.import(queryCapability).ref() during render
|
|
13
|
+
* - Emit phase generates imports from the recorded references
|
|
10
14
|
*/
|
|
11
|
-
import { Schema as S } from "effect";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
15
|
+
import { Effect, Schema as S } from "effect";
|
|
16
|
+
import { IR } from "../services/ir.js";
|
|
17
|
+
import { Inflection } from "../services/inflection.js";
|
|
18
|
+
import { SymbolRegistry } from "../runtime/registry.js";
|
|
19
|
+
import { isTableEntity } from "../ir/semantic-ir.js";
|
|
20
|
+
import { conjure, cast } from "../conjure/index.js";
|
|
21
|
+
import { normalizeFileNaming } from "../runtime/file-assignment.js";
|
|
22
|
+
const b = conjure.b;
|
|
23
|
+
const stmt = conjure.stmt;
|
|
24
|
+
const PLUGIN_NAME = "orpc-http";
|
|
16
25
|
// ============================================================================
|
|
17
|
-
// Configuration
|
|
26
|
+
// Configuration
|
|
18
27
|
// ============================================================================
|
|
28
|
+
const DEFAULT_OUTPUT_DIR = "";
|
|
29
|
+
const DEFAULT_ROUTES_FILE = "orpc.ts";
|
|
30
|
+
const DEFAULT_APP_FILE = "orpc.ts";
|
|
31
|
+
/**
|
|
32
|
+
* Schema-validated portion of the config (simple types only).
|
|
33
|
+
*/
|
|
19
34
|
const HttpOrpcConfigSchema = S.Struct({
|
|
20
|
-
|
|
21
|
-
outputDir: S.optionalWith(S.String, { default: () => "orpc" }),
|
|
22
|
-
/**
|
|
23
|
-
* Header content to prepend to each generated file.
|
|
24
|
-
* MUST import `os` from @orpc/server.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```typescript
|
|
28
|
-
* header: `import { os } from "@orpc/server";`
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
header: S.String,
|
|
35
|
+
outputDir: S.optionalWith(S.String, { default: () => DEFAULT_OUTPUT_DIR }),
|
|
32
36
|
/** Name of the aggregated router export. Default: "appRouter" */
|
|
33
37
|
aggregatorName: S.optionalWith(S.String, { default: () => "appRouter" }),
|
|
34
38
|
});
|
|
35
39
|
// ============================================================================
|
|
36
|
-
//
|
|
40
|
+
// Procedure Builders
|
|
37
41
|
// ============================================================================
|
|
38
42
|
/**
|
|
39
|
-
*
|
|
43
|
+
* Build Zod type expression for a param.
|
|
40
44
|
*/
|
|
41
|
-
|
|
42
|
-
const baseType = param.type.
|
|
43
|
-
let
|
|
45
|
+
function buildZodParamType(param) {
|
|
46
|
+
const baseType = param.type.toLowerCase();
|
|
47
|
+
let zodCall;
|
|
44
48
|
switch (baseType) {
|
|
45
49
|
case "number":
|
|
46
|
-
|
|
47
|
-
case "integer":
|
|
48
|
-
case "float":
|
|
49
|
-
case "double":
|
|
50
|
-
tsType = "number";
|
|
50
|
+
zodCall = b.callExpression(b.memberExpression(b.memberExpression(b.identifier("z"), b.identifier("coerce")), b.identifier("number")), []);
|
|
51
51
|
break;
|
|
52
52
|
case "boolean":
|
|
53
|
-
|
|
54
|
-
tsType = "boolean";
|
|
53
|
+
zodCall = b.callExpression(b.memberExpression(b.identifier("z"), b.identifier("boolean")), []);
|
|
55
54
|
break;
|
|
56
55
|
case "date":
|
|
57
|
-
|
|
56
|
+
zodCall = b.callExpression(b.memberExpression(b.memberExpression(b.identifier("z"), b.identifier("coerce")), b.identifier("date")), []);
|
|
58
57
|
break;
|
|
59
58
|
case "string":
|
|
60
59
|
default:
|
|
61
|
-
|
|
60
|
+
zodCall = b.callExpression(b.memberExpression(b.identifier("z"), b.identifier("string")), []);
|
|
62
61
|
break;
|
|
63
62
|
}
|
|
64
|
-
// Handle arrays
|
|
65
|
-
if (param.type.endsWith("[]")) {
|
|
66
|
-
tsType = `${tsType}[]`;
|
|
67
|
-
}
|
|
68
|
-
// Handle optionality
|
|
69
63
|
if (!param.required) {
|
|
70
|
-
|
|
64
|
+
zodCall = b.callExpression(b.memberExpression(cast.toExpr(zodCall), b.identifier("optional")), []);
|
|
71
65
|
}
|
|
72
|
-
return
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Build a TypeScript object type literal string for type<>().
|
|
76
|
-
* Returns something like "{ id: number; name?: string }"
|
|
77
|
-
*/
|
|
78
|
-
const buildTypeObjectString = (params) => {
|
|
79
|
-
if (params.length === 0)
|
|
80
|
-
return "{}";
|
|
81
|
-
const fields = params.map((param) => {
|
|
82
|
-
const typeStr = paramToTypeString(param);
|
|
83
|
-
const optional = !param.required ? "?" : "";
|
|
84
|
-
return `${param.name}${optional}: ${typeStr.replace(" | undefined", "")}`;
|
|
85
|
-
});
|
|
86
|
-
return `{ ${fields.join("; ")} }`;
|
|
87
|
-
};
|
|
88
|
-
// ============================================================================
|
|
89
|
-
// Procedure Builders
|
|
90
|
-
// ============================================================================
|
|
66
|
+
return zodCall;
|
|
67
|
+
}
|
|
91
68
|
/**
|
|
92
|
-
* Build the handler function body for
|
|
93
|
-
* oRPC handlers receive { input
|
|
69
|
+
* Build the handler function body for an oRPC procedure.
|
|
70
|
+
* oRPC handlers receive { input } and return data directly.
|
|
94
71
|
*/
|
|
95
|
-
|
|
72
|
+
function buildProcedureBody(method) {
|
|
96
73
|
const callSig = method.callSignature ?? { style: "named" };
|
|
97
|
-
const statements = [];
|
|
98
|
-
// Build the function call arguments based on callSignature
|
|
99
74
|
const args = [];
|
|
100
75
|
if (callSig.style === "positional") {
|
|
101
76
|
// Positional: fn(a, b, c)
|
|
@@ -104,7 +79,7 @@ const buildProcedureBody = (queryFnName, method) => {
|
|
|
104
79
|
}
|
|
105
80
|
}
|
|
106
81
|
else {
|
|
107
|
-
// Named
|
|
82
|
+
// Named style
|
|
108
83
|
const bodyParam = method.params.find((p) => p.source === "body");
|
|
109
84
|
if (bodyParam && callSig.bodyStyle === "spread") {
|
|
110
85
|
// Body fields spread directly: fn(input)
|
|
@@ -112,29 +87,19 @@ const buildProcedureBody = (queryFnName, method) => {
|
|
|
112
87
|
}
|
|
113
88
|
else if (bodyParam && callSig.bodyStyle === "property") {
|
|
114
89
|
// Body wrapped in property: fn({ id, data })
|
|
115
|
-
// Collect non-body params that need to be extracted from input
|
|
116
90
|
const nonBodyParams = method.params.filter((p) => p.source === "pk" || p.source === "fk" || p.source === "lookup" || p.source === "pagination");
|
|
117
91
|
if (nonBodyParams.length > 0) {
|
|
118
|
-
//
|
|
119
|
-
const destructureProps = nonBodyParams.map((p) => b.property.from({ kind: "init", key: b.identifier(p.name), value: b.identifier(p.name), shorthand: true }));
|
|
120
|
-
const restId = b.identifier(bodyParam.name);
|
|
121
|
-
const restElem = b.restElement(restId);
|
|
122
|
-
const pattern = b.objectPattern([...destructureProps, restElem]);
|
|
123
|
-
const destructureDecl = b.variableDeclaration("const", [
|
|
124
|
-
b.variableDeclarator(pattern, b.identifier("input")),
|
|
125
|
-
]);
|
|
126
|
-
statements.push(destructureDecl);
|
|
127
|
-
// Build: { id, data } using the destructured variables
|
|
92
|
+
// Build object with non-body params + body property
|
|
128
93
|
let objBuilder = conjure.obj();
|
|
129
94
|
for (const param of nonBodyParams) {
|
|
130
|
-
objBuilder = objBuilder.
|
|
95
|
+
objBuilder = objBuilder.prop(param.name, b.memberExpression(b.identifier("input"), b.identifier(param.name)));
|
|
131
96
|
}
|
|
132
|
-
objBuilder = objBuilder.
|
|
97
|
+
objBuilder = objBuilder.prop(bodyParam.name, b.memberExpression(b.identifier("input"), b.identifier(bodyParam.name)));
|
|
133
98
|
args.push(objBuilder.build());
|
|
134
99
|
}
|
|
135
100
|
else {
|
|
136
|
-
// No non-body params, just
|
|
137
|
-
args.push(
|
|
101
|
+
// No non-body params, just pass input
|
|
102
|
+
args.push(b.identifier("input"));
|
|
138
103
|
}
|
|
139
104
|
}
|
|
140
105
|
else if (method.params.length > 0) {
|
|
@@ -142,229 +107,352 @@ const buildProcedureBody = (queryFnName, method) => {
|
|
|
142
107
|
args.push(b.identifier("input"));
|
|
143
108
|
}
|
|
144
109
|
}
|
|
145
|
-
// Build:
|
|
146
|
-
const queryCall = b.callExpression(b.identifier(
|
|
147
|
-
|
|
110
|
+
// Build: queryFn(args)
|
|
111
|
+
const queryCall = b.callExpression(b.identifier(method.name), args.map(cast.toExpr));
|
|
112
|
+
// Add the appropriate .execute*() method based on query kind
|
|
113
|
+
const executeMethod = method.kind === "read" || (method.kind === "lookup" && method.isUniqueLookup)
|
|
114
|
+
? "executeTakeFirst"
|
|
115
|
+
: method.kind === "create" || method.kind === "update"
|
|
116
|
+
? "executeTakeFirstOrThrow"
|
|
117
|
+
: "execute";
|
|
118
|
+
const queryWithExecute = b.callExpression(b.memberExpression(queryCall, b.identifier(executeMethod)), []);
|
|
119
|
+
const awaitExpr = b.awaitExpression(queryWithExecute);
|
|
120
|
+
// For delete, return success object
|
|
148
121
|
if (method.kind === "delete") {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
122
|
+
return [
|
|
123
|
+
b.expressionStatement(awaitExpr),
|
|
124
|
+
b.returnStatement(conjure.obj().prop("success", b.booleanLiteral(true)).build()),
|
|
125
|
+
];
|
|
152
126
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
};
|
|
127
|
+
return [b.returnStatement(awaitExpr)];
|
|
128
|
+
}
|
|
156
129
|
/**
|
|
157
|
-
*
|
|
130
|
+
* Get the body schema name for a method if it needs validation.
|
|
158
131
|
*/
|
|
159
|
-
|
|
132
|
+
function getBodySchemaName(method, entityName) {
|
|
160
133
|
if (method.kind === "create") {
|
|
161
|
-
return
|
|
134
|
+
return `${entityName}Insert`;
|
|
162
135
|
}
|
|
163
136
|
if (method.kind === "update") {
|
|
164
|
-
return
|
|
137
|
+
return `${entityName}Update`;
|
|
165
138
|
}
|
|
166
139
|
return null;
|
|
167
|
-
}
|
|
140
|
+
}
|
|
168
141
|
/**
|
|
169
|
-
* Build
|
|
142
|
+
* Build input schema expression for a procedure.
|
|
143
|
+
* Returns the schema expression and whether we need z import.
|
|
170
144
|
*/
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
145
|
+
function buildInputSchema(method, entityName) {
|
|
146
|
+
const bodySchemaName = getBodySchemaName(method, entityName);
|
|
147
|
+
const nonBodyParams = method.params.filter((p) => p.source !== "body");
|
|
148
|
+
const callSig = method.callSignature ?? { style: "named" };
|
|
149
|
+
// For update with bodyStyle: "property", merge PK params with body schema
|
|
150
|
+
if (bodySchemaName && nonBodyParams.length > 0 && callSig.bodyStyle === "property") {
|
|
151
|
+
let objBuilder = conjure.obj();
|
|
152
|
+
for (const p of nonBodyParams) {
|
|
153
|
+
objBuilder = objBuilder.prop(p.name, buildZodParamType(p));
|
|
154
|
+
}
|
|
155
|
+
const zodObject = b.callExpression(b.memberExpression(b.identifier("z"), b.identifier("object")), [cast.toExpr(objBuilder.build())]);
|
|
156
|
+
const mergedSchema = b.callExpression(b.memberExpression(zodObject, b.identifier("merge")), [b.identifier(bodySchemaName)]);
|
|
157
|
+
return {
|
|
158
|
+
inputExpr: mergedSchema,
|
|
159
|
+
bodySchemaName,
|
|
160
|
+
needsZodImport: true,
|
|
161
|
+
needsTypeImport: false,
|
|
162
|
+
};
|
|
188
163
|
}
|
|
189
|
-
|
|
190
|
-
|
|
164
|
+
// Body params only use imported entity schemas
|
|
165
|
+
if (bodySchemaName) {
|
|
166
|
+
return {
|
|
167
|
+
inputExpr: b.identifier(bodySchemaName),
|
|
168
|
+
bodySchemaName,
|
|
169
|
+
needsZodImport: false,
|
|
170
|
+
needsTypeImport: false,
|
|
171
|
+
};
|
|
191
172
|
}
|
|
192
|
-
|
|
193
|
-
|
|
173
|
+
// Non-body params: build inline z.object
|
|
174
|
+
if (nonBodyParams.length === 0) {
|
|
175
|
+
return { inputExpr: null, bodySchemaName: null, needsZodImport: false, needsTypeImport: false };
|
|
176
|
+
}
|
|
177
|
+
let objBuilder = conjure.obj();
|
|
178
|
+
for (const param of nonBodyParams) {
|
|
179
|
+
const zodType = buildZodParamType(param);
|
|
180
|
+
objBuilder = objBuilder.prop(param.name, zodType);
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
inputExpr: b.callExpression(b.memberExpression(b.identifier("z"), b.identifier("object")), [cast.toExpr(objBuilder.build())]),
|
|
184
|
+
bodySchemaName: null,
|
|
185
|
+
needsZodImport: true,
|
|
186
|
+
needsTypeImport: false,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
194
189
|
/**
|
|
195
|
-
* Build a single oRPC procedure.
|
|
196
|
-
* Returns: os.input(type<InputType>()).handler(async ({ input }) => { ... })
|
|
197
|
-
* Or for body schemas: os.input(BodySchema).handler(...)
|
|
190
|
+
* Build a single oRPC procedure expression.
|
|
198
191
|
*/
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
let needsType = false;
|
|
202
|
-
let needsZMerge = false;
|
|
192
|
+
function buildProcedure(method, entityName) {
|
|
193
|
+
// Start with os
|
|
203
194
|
let chainExpr = b.identifier("os");
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (bodySchema && nonBodyParams.length > 0 && callSig.bodyStyle === "property") {
|
|
210
|
-
// For update-style operations with bodyStyle: "property", we need to merge
|
|
211
|
-
// the PK/FK params with the body schema: z.object({ id: z.number() }).merge(PostUpdate)
|
|
212
|
-
needsZMerge = true;
|
|
213
|
-
// Build: z.object({ id: z.coerce.number() })
|
|
214
|
-
let objBuilder = conjure.obj();
|
|
215
|
-
for (const p of nonBodyParams) {
|
|
216
|
-
objBuilder = objBuilder.prop(p.name, buildZodParamType(p));
|
|
217
|
-
}
|
|
218
|
-
const zodObject = b.callExpression(b.memberExpression(b.identifier("z"), b.identifier("object")), [cast.toExpr(objBuilder.build())]);
|
|
219
|
-
// Build: z.object({ id: ... }).merge(PostUpdate)
|
|
220
|
-
inputSchema = b.callExpression(b.memberExpression(zodObject, b.identifier("merge")), [b.identifier(bodySchema.schemaName)]);
|
|
221
|
-
}
|
|
222
|
-
else if (bodySchema) {
|
|
223
|
-
inputSchema = b.identifier(bodySchema.schemaName);
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
needsType = true;
|
|
227
|
-
const typeStr = buildTypeObjectString(method.params);
|
|
228
|
-
inputSchema = b.identifier(`type<${typeStr}>()`);
|
|
229
|
-
}
|
|
230
|
-
chainExpr = b.callExpression(b.memberExpression(cast.toExpr(chainExpr), b.identifier("input")), [cast.toExpr(inputSchema)]);
|
|
195
|
+
// Build input schema
|
|
196
|
+
const { inputExpr, bodySchemaName, needsZodImport, needsTypeImport } = buildInputSchema(method, entityName);
|
|
197
|
+
// Add .input(schema) if there are params
|
|
198
|
+
if (inputExpr) {
|
|
199
|
+
chainExpr = b.callExpression(b.memberExpression(cast.toExpr(chainExpr), b.identifier("input")), [cast.toExpr(inputExpr)]);
|
|
231
200
|
}
|
|
201
|
+
// Build the handler: async ({ input }) => { ... }
|
|
232
202
|
const handlerParams = [];
|
|
233
203
|
if (method.params.length > 0) {
|
|
234
204
|
const inputProp = b.objectProperty(b.identifier("input"), b.identifier("input"));
|
|
235
205
|
inputProp.shorthand = true;
|
|
236
206
|
handlerParams.push(inputProp);
|
|
237
207
|
}
|
|
238
|
-
const handlerBody = buildProcedureBody(
|
|
208
|
+
const handlerBody = buildProcedureBody(method);
|
|
239
209
|
const handler = b.arrowFunctionExpression([b.objectPattern(handlerParams)], b.blockStatement(handlerBody.map(cast.toStmt)));
|
|
240
210
|
handler.async = true;
|
|
211
|
+
// Add .handler()
|
|
241
212
|
chainExpr = b.callExpression(b.memberExpression(cast.toExpr(chainExpr), b.identifier("handler")), [handler]);
|
|
242
|
-
return { procedureExpr: chainExpr,
|
|
243
|
-
}
|
|
213
|
+
return { procedureExpr: chainExpr, bodySchemaName, needsZodImport, needsTypeImport };
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get the capability suffix for a query method.
|
|
217
|
+
*/
|
|
218
|
+
function getMethodCapabilitySuffix(method, inflection) {
|
|
219
|
+
switch (method.kind) {
|
|
220
|
+
case "read":
|
|
221
|
+
return "findById";
|
|
222
|
+
case "list":
|
|
223
|
+
return "list";
|
|
224
|
+
case "create":
|
|
225
|
+
return "create";
|
|
226
|
+
case "update":
|
|
227
|
+
return "update";
|
|
228
|
+
case "delete":
|
|
229
|
+
return "delete";
|
|
230
|
+
case "lookup":
|
|
231
|
+
if (method.lookupField) {
|
|
232
|
+
const pascalField = inflection.pascalCase(method.lookupField);
|
|
233
|
+
return `findBy${pascalField}`;
|
|
234
|
+
}
|
|
235
|
+
return "lookup";
|
|
236
|
+
case "function":
|
|
237
|
+
return method.name;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Generate oRPC router for an entity.
|
|
242
|
+
*/
|
|
243
|
+
function generateOrpcRouter(entityName, queries, config, registry, inflection) {
|
|
244
|
+
const routerName = inflection.variableName(entityName, "Router");
|
|
245
|
+
let needsZodImport = false;
|
|
246
|
+
let needsTypeImport = false;
|
|
247
|
+
const bodySchemaNames = [];
|
|
248
|
+
// Build router object
|
|
249
|
+
let routerObjBuilder = conjure.obj();
|
|
250
|
+
for (const method of queries.methods) {
|
|
251
|
+
// Record cross-reference for this query method
|
|
252
|
+
const methodCapability = `queries:${entityName}:${getMethodCapabilitySuffix(method, inflection)}`;
|
|
253
|
+
if (registry.has(methodCapability)) {
|
|
254
|
+
registry.import(methodCapability).ref();
|
|
255
|
+
}
|
|
256
|
+
const { procedureExpr, bodySchemaName, needsZodImport: methodNeedsZod, needsTypeImport: methodNeedsType } = buildProcedure(method, entityName);
|
|
257
|
+
if (bodySchemaName && !bodySchemaNames.includes(bodySchemaName)) {
|
|
258
|
+
bodySchemaNames.push(bodySchemaName);
|
|
259
|
+
// Import schema via cross-reference system
|
|
260
|
+
const schemaCapability = `schema:${bodySchemaName}`;
|
|
261
|
+
if (registry.has(schemaCapability)) {
|
|
262
|
+
registry.import(schemaCapability).ref();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (methodNeedsZod)
|
|
266
|
+
needsZodImport = true;
|
|
267
|
+
if (methodNeedsType)
|
|
268
|
+
needsTypeImport = true;
|
|
269
|
+
routerObjBuilder = routerObjBuilder.prop(method.name, procedureExpr);
|
|
270
|
+
}
|
|
271
|
+
// Build: export const userRouter = { ... }
|
|
272
|
+
const variableDeclarator = b.variableDeclarator(b.identifier(routerName), cast.toExpr(routerObjBuilder.build()));
|
|
273
|
+
const variableDeclaration = b.variableDeclaration("const", [variableDeclarator]);
|
|
274
|
+
const externalImports = [];
|
|
275
|
+
if (needsZodImport) {
|
|
276
|
+
externalImports.push({ from: "zod", names: ["z"] });
|
|
277
|
+
}
|
|
278
|
+
if (needsTypeImport) {
|
|
279
|
+
externalImports.push({ from: "@orpc/server", names: ["type"] });
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
statements: [variableDeclaration],
|
|
283
|
+
externalImports,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Generate aggregator router that combines all entity routers.
|
|
288
|
+
*/
|
|
289
|
+
function generateAggregator(entities, config, registry, inflection) {
|
|
290
|
+
const entityEntries = Array.from(entities.entries());
|
|
291
|
+
if (entityEntries.length === 0) {
|
|
292
|
+
return { statements: [], externalImports: [] };
|
|
293
|
+
}
|
|
294
|
+
// Build: { user: userRouter, post: postRouter, ... }
|
|
295
|
+
let routerObjBuilder = conjure.obj();
|
|
296
|
+
for (const [entityName] of entityEntries) {
|
|
297
|
+
const routerName = inflection.variableName(entityName, "Router");
|
|
298
|
+
const key = inflection.variableName(entityName, "");
|
|
299
|
+
routerObjBuilder = routerObjBuilder.prop(key, b.identifier(routerName));
|
|
300
|
+
// Record cross-reference to the entity's router capability
|
|
301
|
+
const routeCapability = `http-routes:orpc:${entityName}`;
|
|
302
|
+
if (registry.has(routeCapability)) {
|
|
303
|
+
registry.import(routeCapability).ref();
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const variableDeclarator = b.variableDeclarator(b.identifier(config.aggregatorName), cast.toExpr(routerObjBuilder.build()));
|
|
307
|
+
const variableDeclaration = b.variableDeclaration("const", [variableDeclarator]);
|
|
308
|
+
// Also export the type: export type AppRouter = typeof appRouter
|
|
309
|
+
const typeExport = b.exportNamedDeclaration(b.tsTypeAliasDeclaration(b.identifier("AppRouter"), b.tsTypeQuery(b.identifier(config.aggregatorName))));
|
|
310
|
+
return {
|
|
311
|
+
statements: [variableDeclaration, typeExport],
|
|
312
|
+
externalImports: [],
|
|
313
|
+
};
|
|
314
|
+
}
|
|
244
315
|
// ============================================================================
|
|
245
316
|
// Plugin Definition
|
|
246
317
|
// ============================================================================
|
|
247
318
|
/**
|
|
248
|
-
* Create an http-orpc
|
|
319
|
+
* Create an http-orpc plugin that generates oRPC routers.
|
|
249
320
|
*
|
|
250
321
|
* @example
|
|
251
322
|
* ```typescript
|
|
252
|
-
* import {
|
|
323
|
+
* import { orpc } from "pg-sourcerer"
|
|
253
324
|
*
|
|
254
325
|
* export default defineConfig({
|
|
255
326
|
* plugins: [
|
|
256
327
|
* zod(),
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
328
|
+
* kyselyQueries(),
|
|
329
|
+
* orpc({
|
|
330
|
+
* aggregatorName: "appRouter",
|
|
260
331
|
* }),
|
|
261
332
|
* ],
|
|
262
333
|
* })
|
|
263
334
|
* ```
|
|
264
335
|
*/
|
|
265
|
-
export function
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
336
|
+
export function orpc(config) {
|
|
337
|
+
const schemaConfig = S.decodeSync(HttpOrpcConfigSchema)(config ?? {});
|
|
338
|
+
const resolvedConfig = {
|
|
339
|
+
outputDir: schemaConfig.outputDir,
|
|
340
|
+
aggregatorName: schemaConfig.aggregatorName,
|
|
341
|
+
routesFile: normalizeFileNaming(config?.routesFile, DEFAULT_ROUTES_FILE),
|
|
342
|
+
appFile: normalizeFileNaming(config?.appFile, DEFAULT_APP_FILE),
|
|
343
|
+
orpcImport: config?.orpcImport,
|
|
344
|
+
};
|
|
345
|
+
return {
|
|
346
|
+
name: PLUGIN_NAME,
|
|
347
|
+
provides: [],
|
|
348
|
+
fileDefaults: [
|
|
349
|
+
// Entity routers use routesFile config
|
|
350
|
+
{
|
|
351
|
+
pattern: "http-routes:orpc:",
|
|
352
|
+
outputDir: resolvedConfig.outputDir,
|
|
353
|
+
fileNaming: resolvedConfig.routesFile,
|
|
354
|
+
},
|
|
355
|
+
// App aggregator uses appFile config (more specific pattern wins)
|
|
356
|
+
{
|
|
357
|
+
pattern: "http-routes:orpc:app",
|
|
358
|
+
outputDir: resolvedConfig.outputDir,
|
|
359
|
+
fileNaming: resolvedConfig.appFile,
|
|
360
|
+
},
|
|
275
361
|
],
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
// Track generated routers for aggregator
|
|
284
|
-
const generatedRouters = [];
|
|
285
|
-
// Generate router for each entity
|
|
286
|
-
for (const entityName of entityNames) {
|
|
287
|
-
const entityMethods = ctx.symbols.getEntityMethods(entityName);
|
|
288
|
-
if (!entityMethods || entityMethods.methods.length === 0)
|
|
362
|
+
declare: Effect.gen(function* () {
|
|
363
|
+
const ir = yield* IR;
|
|
364
|
+
const inflection = yield* Inflection;
|
|
365
|
+
const declarations = [];
|
|
366
|
+
// Declare routers for all table entities that might have queries
|
|
367
|
+
for (const entity of ir.entities.values()) {
|
|
368
|
+
if (!isTableEntity(entity))
|
|
289
369
|
continue;
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const bodySchemaImports = [];
|
|
302
|
-
let fileNeedsType = false;
|
|
303
|
-
let fileNeedsZod = false;
|
|
304
|
-
let routerObjBuilder = conjure.obj();
|
|
305
|
-
for (const method of entityMethods.methods) {
|
|
306
|
-
const queryFnName = `Queries.${method.name}`;
|
|
307
|
-
const { procedureExpr, bodySchema, needsType, needsZMerge } = buildProcedure(method, entityName, queryFnName);
|
|
308
|
-
if (bodySchema)
|
|
309
|
-
bodySchemaImports.push(bodySchema);
|
|
310
|
-
if (needsType)
|
|
311
|
-
fileNeedsType = true;
|
|
312
|
-
if (needsZMerge)
|
|
313
|
-
fileNeedsZod = true;
|
|
314
|
-
routerObjBuilder = routerObjBuilder.prop(method.name, procedureExpr);
|
|
315
|
-
}
|
|
316
|
-
// Import type utility if needed
|
|
317
|
-
if (fileNeedsType) {
|
|
318
|
-
file.import({ kind: "package", names: ["type"], from: "@orpc/server" });
|
|
319
|
-
}
|
|
320
|
-
// Import zod if needed for merged schemas
|
|
321
|
-
if (fileNeedsZod) {
|
|
322
|
-
file.import({ kind: "package", names: ["z"], from: "zod" });
|
|
323
|
-
}
|
|
324
|
-
// Import body schemas
|
|
325
|
-
for (const schemaImport of bodySchemaImports) {
|
|
326
|
-
file.import({
|
|
327
|
-
kind: "symbol",
|
|
328
|
-
ref: {
|
|
329
|
-
capability: "schemas",
|
|
330
|
-
entity: schemaImport.entity,
|
|
331
|
-
shape: schemaImport.shape,
|
|
332
|
-
},
|
|
370
|
+
if (entity.tags.omit === true)
|
|
371
|
+
continue;
|
|
372
|
+
const hasAnyPermissions = entity.permissions.canSelect ||
|
|
373
|
+
entity.permissions.canInsert ||
|
|
374
|
+
entity.permissions.canUpdate ||
|
|
375
|
+
entity.permissions.canDelete;
|
|
376
|
+
if (hasAnyPermissions) {
|
|
377
|
+
declarations.push({
|
|
378
|
+
name: inflection.variableName(entity.name, "Router"),
|
|
379
|
+
capability: `http-routes:orpc:${entity.name}`,
|
|
380
|
+
baseEntityName: entity.name,
|
|
333
381
|
});
|
|
334
382
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
383
|
+
}
|
|
384
|
+
// Also declare the aggregator
|
|
385
|
+
declarations.push({
|
|
386
|
+
name: resolvedConfig.aggregatorName,
|
|
387
|
+
capability: "http-routes:orpc:app",
|
|
388
|
+
});
|
|
389
|
+
return declarations;
|
|
390
|
+
}),
|
|
391
|
+
render: Effect.gen(function* () {
|
|
392
|
+
const ir = yield* IR;
|
|
393
|
+
const registry = yield* SymbolRegistry;
|
|
394
|
+
const inflection = yield* Inflection;
|
|
395
|
+
const rendered = [];
|
|
396
|
+
// Query the registry for all entity query capabilities
|
|
397
|
+
const entityQueries = new Map();
|
|
398
|
+
const queryCapabilities = registry.query("queries:");
|
|
399
|
+
for (const decl of queryCapabilities) {
|
|
400
|
+
// Only look at aggregate capabilities (queries:impl:EntityName, not queries:impl:EntityName:method)
|
|
401
|
+
const parts = decl.capability.split(":");
|
|
402
|
+
if (parts.length !== 3)
|
|
403
|
+
continue;
|
|
404
|
+
const entityName = parts[2];
|
|
405
|
+
const metadata = registry.getMetadata(decl.capability);
|
|
406
|
+
if (metadata && typeof metadata === "object" && "methods" in metadata) {
|
|
407
|
+
entityQueries.set(entityName, metadata);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
// User module imports for oRPC builder (if configured)
|
|
411
|
+
const orpcUserImports = resolvedConfig.orpcImport
|
|
412
|
+
? [resolvedConfig.orpcImport]
|
|
413
|
+
: undefined;
|
|
414
|
+
for (const [entityName, queries] of entityQueries) {
|
|
415
|
+
const entity = ir.entities.get(entityName);
|
|
416
|
+
if (!entity || !isTableEntity(entity))
|
|
417
|
+
continue;
|
|
418
|
+
const capability = `http-routes:orpc:${entityName}`;
|
|
419
|
+
// Scope cross-references to this specific capability
|
|
420
|
+
const { statements, externalImports } = registry.forSymbol(capability, () => generateOrpcRouter(entityName, queries, resolvedConfig, registry, inflection));
|
|
421
|
+
rendered.push({
|
|
422
|
+
name: inflection.variableName(entityName, "Router"),
|
|
423
|
+
capability,
|
|
424
|
+
node: statements[0],
|
|
425
|
+
exports: "named",
|
|
426
|
+
externalImports,
|
|
427
|
+
userImports: orpcUserImports,
|
|
341
428
|
});
|
|
342
429
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
const
|
|
347
|
-
//
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
430
|
+
if (entityQueries.size > 0) {
|
|
431
|
+
const appCapability = "http-routes:orpc:app";
|
|
432
|
+
// Scope cross-references to the app capability
|
|
433
|
+
const { statements, externalImports } = registry.forSymbol(appCapability, () => generateAggregator(entityQueries, resolvedConfig, registry, inflection));
|
|
434
|
+
// The aggregator has multiple statements (const + type export)
|
|
435
|
+
rendered.push({
|
|
436
|
+
name: resolvedConfig.aggregatorName,
|
|
437
|
+
capability: appCapability,
|
|
438
|
+
node: statements[0], // The const declaration
|
|
439
|
+
exports: "named",
|
|
440
|
+
externalImports,
|
|
441
|
+
userImports: orpcUserImports,
|
|
442
|
+
});
|
|
443
|
+
// Add the type export as a separate rendered symbol
|
|
444
|
+
if (statements[1]) {
|
|
445
|
+
rendered.push({
|
|
446
|
+
name: "AppRouter",
|
|
447
|
+
capability: "http-routes:orpc:app:type",
|
|
448
|
+
node: statements[1],
|
|
449
|
+
exports: false, // Already has export in the node
|
|
450
|
+
// No userImports needed for type export
|
|
354
451
|
});
|
|
355
452
|
}
|
|
356
|
-
// Build: export const appRouter = { user: userRouter, ... }
|
|
357
|
-
let routerObjBuilder = conjure.obj();
|
|
358
|
-
for (const route of generatedRouters) {
|
|
359
|
-
const key = route.routerName.replace(/Router$/, "");
|
|
360
|
-
routerObjBuilder = routerObjBuilder.prop(key, b.identifier(route.routerName));
|
|
361
|
-
}
|
|
362
|
-
const routerExport = conjure.export.const(aggregatorName, routerObjBuilder.build());
|
|
363
|
-
// Also export the type
|
|
364
|
-
const typeExport = b.exportNamedDeclaration(b.tsTypeAliasDeclaration(b.identifier("AppRouter"), b.tsTypeQuery(b.identifier(aggregatorName))));
|
|
365
|
-
indexFile.ast(conjure.program(routerExport, typeExport)).emit();
|
|
366
453
|
}
|
|
367
|
-
|
|
368
|
-
|
|
454
|
+
return rendered;
|
|
455
|
+
}),
|
|
456
|
+
};
|
|
369
457
|
}
|
|
370
458
|
//# sourceMappingURL=http-orpc.js.map
|