@lunora/codegen 1.0.0-alpha.32 → 1.0.0-alpha.320
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +6 -0
- package/README.md +1 -1
- package/dist/index.d.mts +4230 -2183
- package/dist/index.d.ts +4230 -2183
- package/dist/index.mjs +1 -35
- package/dist/packem_shared/AGENTS_FILENAME-B6-kjzM3.mjs +1 -0
- package/dist/packem_shared/CAPABILITY_PROBES-brcmKenl.mjs +25 -0
- package/dist/packem_shared/CONTAINERS_FILENAME-dFRtAyIe.mjs +1 -0
- package/dist/packem_shared/CodegenDiagnosticError-BUXlG3P-.mjs +1 -0
- package/dist/packem_shared/DEFAULT_TARGET-B0FkdiZq.mjs +1 -0
- package/dist/packem_shared/FLAGS_FILENAME-Bf0MSlHH.mjs +1 -0
- package/dist/packem_shared/GENERATED_HEADER-Ck_WOHzE.mjs +1 -0
- package/dist/packem_shared/LUNORA_ERROR_CODES-C2s0xWQD.mjs +1 -0
- package/dist/packem_shared/MUTATORS_FILENAME-Jkk8Zgkb.mjs +1 -0
- package/dist/packem_shared/NOTIFY_FILENAME-bAt7J3cs.mjs +1 -0
- package/dist/packem_shared/OPENRPC_VERSION-CCY7xqSL.mjs +3 -0
- package/dist/packem_shared/PROJECT_CONFIG_FILENAMES-DzOu-lSc.mjs +1 -0
- package/dist/packem_shared/QUEUES_FILENAME-CsRy4VTF.mjs +1 -0
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-Bo67h-3B.mjs +11 -0
- package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs +2 -0
- package/dist/packem_shared/SHAPES_FILENAME-DkBUN9dK.mjs +1 -0
- package/dist/packem_shared/SchemaSnapshotParseError-BRJT7c2k.mjs +18 -0
- package/dist/packem_shared/WORKFLOWS_FILENAME-CdeS224T.mjs +1 -0
- package/dist/packem_shared/attribution-hVBriwzy.mjs +1 -0
- package/dist/packem_shared/buildOpenApiDocument-DFv-RYZU.mjs +3 -0
- package/dist/packem_shared/capabilitiesUsedBy-QgSZyE0T.mjs +1 -0
- package/dist/packem_shared/chain-Cm6BMT8g.mjs +1 -0
- package/dist/packem_shared/classify-procedure-call-DVxdUhZt.mjs +1 -0
- package/dist/packem_shared/context-property-calls-Cn3upNgZ.mjs +1 -0
- package/dist/packem_shared/context-root-BdxINX-T.mjs +1 -0
- package/dist/packem_shared/createCodegenProject-V51_yBw3.mjs +1 -0
- package/dist/packem_shared/database-calls-BKozZUEW.mjs +1 -0
- package/dist/packem_shared/declared-output-Iaar469J.mjs +1 -0
- package/dist/packem_shared/describeErrorLevelFindings-vzaGS9KL.mjs +1 -0
- package/dist/packem_shared/discoverAuthApiCalls-xs0ONfI-.mjs +1 -0
- package/dist/packem_shared/discoverCrons-DBnCama4.mjs +1 -0
- package/dist/packem_shared/discoverFunctions-CZgLhsMn.mjs +1 -0
- package/dist/packem_shared/discoverHttpRoutes-WBAqBcfK.mjs +1 -0
- package/dist/packem_shared/discoverHyperdriveCalls-DV4IglLE.mjs +1 -0
- package/dist/packem_shared/discoverInserts-BjxXCACZ.mjs +1 -0
- package/dist/packem_shared/discoverMaskProcedures-DE-8CDen.mjs +1 -0
- package/dist/packem_shared/discoverMigrations-C9mLIhGZ.mjs +1 -0
- package/dist/packem_shared/discoverNondeterministicCalls-DvhyKM-f.mjs +1 -0
- package/dist/packem_shared/discoverQueries-C8E7TeRT.mjs +1 -0
- package/dist/packem_shared/discoverR2sqlCalls-DVcfMO6-.mjs +1 -0
- package/dist/packem_shared/discoverRlsMetadata-QRsWRQbM.mjs +1 -0
- package/dist/packem_shared/discoverRlsProcedures-Du7ITNTQ.mjs +1 -0
- package/dist/packem_shared/discoverSandboxUsage-w6Q3RvxZ.mjs +1 -0
- package/dist/packem_shared/discoverSchema-BtsX-CN9.mjs +1 -0
- package/dist/packem_shared/discoverStorageRulesMetadata-ClzKLdCV.mjs +1 -0
- package/dist/packem_shared/dispatch-namespace-DwTjD7BU.mjs +1 -0
- package/dist/packem_shared/emitAgents-CR2_X_ov.mjs +1 -0
- package/dist/packem_shared/emitApi-CDgIPAG2.mjs +147 -0
- package/dist/packem_shared/emitApp-BEe4wd3R.mjs +985 -0
- package/dist/packem_shared/emitCrons-BQW2lviZ.mjs +96 -0
- package/dist/packem_shared/emitDataModel-BskFt9Wv.mjs +114 -0
- package/dist/packem_shared/emitDrizzleSchema-DitcRZ1a.mjs +15 -0
- package/dist/packem_shared/emitFunctions-rjyb7h7k.mjs +422 -0
- package/dist/packem_shared/emitServer-D1vA5_X1.mjs +1 -0
- package/dist/packem_shared/emitShard-D3Po46nf.mjs +1 -0
- package/dist/packem_shared/exported-procedure-chains-BNBUkXui.mjs +1 -0
- package/dist/packem_shared/fingerprintSchemaSources-eVG9aVt0.mjs +1 -0
- package/dist/packem_shared/formatAdvisories-BCVASH7N.mjs +2 -0
- package/dist/packem_shared/handler-reference-vIeqkhV_.mjs +1 -0
- package/dist/packem_shared/index-JnqBWRYO.mjs +1 -0
- package/dist/packem_shared/isD1GlobalTable-udvHAAzD.mjs +1 -0
- package/dist/packem_shared/isTestPath-B81lOULB.mjs +1 -0
- package/dist/packem_shared/isTypedSchema-CKzc3ioR.mjs +4 -0
- package/dist/packem_shared/json-data-Chfs2Cz5.mjs +1 -0
- package/dist/packem_shared/loadProjectConfig-NO0dVJSl.mjs +1 -0
- package/dist/packem_shared/module-specifiers-WF8iAydP.mjs +1 -0
- package/dist/packem_shared/modules-CjOcuQnK.mjs +1 -0
- package/dist/packem_shared/parse-validator-IDBKIT7M.mjs +1 -0
- package/dist/packem_shared/platform-8oj7iXQy.mjs +1 -0
- package/dist/packem_shared/project-config-file-BV7RR-l6.mjs +1 -0
- package/dist/packem_shared/qualifiers-DEdXn5wP.mjs +1 -0
- package/dist/packem_shared/readPackageDependencies-RHhGiz0k.mjs +1 -0
- package/dist/packem_shared/readServiceBindings-DvqIThzd.mjs +1 -0
- package/dist/packem_shared/redact-Cy14LEnc.mjs +1 -0
- package/dist/packem_shared/reserved-words-CW1QFbTd.mjs +1 -0
- package/dist/packem_shared/schema-BgM8A3XV.mjs +1 -0
- package/dist/packem_shared/schemaFromIr-BWFnvCVg.mjs +1 -0
- package/dist/packem_shared/server-DAvi_bv_.mjs +368 -0
- package/dist/packem_shared/shard-CsOnD3Na.mjs +1601 -0
- package/dist/packem_shared/shard-runtime-BpoCV-aM.mjs +331 -0
- package/dist/packem_shared/shared-DnCokNcE.mjs +13 -0
- package/dist/packem_shared/unwrap-handler-return-CeaOifqX.mjs +1 -0
- package/dist/sdk/index.d.mts +288 -0
- package/dist/sdk/index.d.ts +288 -0
- package/dist/sdk/index.mjs +372 -0
- package/package.json +21 -8
- package/dist/packem_shared/CONTAINERS_FILENAME-DjpXMqhp.mjs +0 -224
- package/dist/packem_shared/CodegenDiagnosticError-DyQ5FwkM.mjs +0 -24
- package/dist/packem_shared/FLAGS_FILENAME-BjpS5w08.mjs +0 -139
- package/dist/packem_shared/GENERATED_HEADER-CLwPlCQe.mjs +0 -3
- package/dist/packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs +0 -61
- package/dist/packem_shared/MUTATORS_FILENAME-BZOfUhlY.mjs +0 -81
- package/dist/packem_shared/OPENRPC_VERSION-4YIeMkOI.mjs +0 -60
- package/dist/packem_shared/QUEUES_FILENAME-BF0iUmx7.mjs +0 -119
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-OBXQBJV0.mjs +0 -3520
- package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-D0ARY6rL.mjs +0 -249
- package/dist/packem_shared/SHAPES_FILENAME-DOhPGi-6.mjs +0 -94
- package/dist/packem_shared/WORKFLOWS_FILENAME-CCC_42o3.mjs +0 -124
- package/dist/packem_shared/buildOpenApiDocument-bp1pYSV6.mjs +0 -183
- package/dist/packem_shared/discover-ast-CT6BgBr4.mjs +0 -13
- package/dist/packem_shared/discoverAuthApiCalls-URDoTADN.mjs +0 -62
- package/dist/packem_shared/discoverCrons-DdZOeroL.mjs +0 -257
- package/dist/packem_shared/discoverFunctions-BJdF7lRs.mjs +0 -514
- package/dist/packem_shared/discoverHttpRoutes-CcwP-Rkr.mjs +0 -131
- package/dist/packem_shared/discoverInserts-BpFhM32L.mjs +0 -61
- package/dist/packem_shared/discoverMaskProcedures-DT-v8wvj.mjs +0 -273
- package/dist/packem_shared/discoverMigrations-cG1idBVM.mjs +0 -97
- package/dist/packem_shared/discoverNondeterministicCalls-CEOjmfk4.mjs +0 -122
- package/dist/packem_shared/discoverQueries-DeVBQVAG.mjs +0 -62
- package/dist/packem_shared/discoverR2sqlCalls-CWCAU-xJ.mjs +0 -80
- package/dist/packem_shared/discoverRlsMetadata-BL0oukaK.mjs +0 -280
- package/dist/packem_shared/discoverSchema-CeXJWVKV.mjs +0 -874
- package/dist/packem_shared/discoverStorageRulesMetadata-CFHByjIl.mjs +0 -97
- package/dist/packem_shared/emit-CBwEvCXQ.mjs +0 -3451
- package/dist/packem_shared/emitApp-nQ2oC-8G.mjs +0 -668
- package/dist/packem_shared/formatAdvisories-C9wNBNvL.mjs +0 -113
- package/dist/packem_shared/parse-validator-D6zI2i85.mjs +0 -134
- package/dist/packem_shared/paths-BRd6JHuF.mjs +0 -11
- package/dist/packem_shared/redact-oTmsol5A.mjs +0 -33
- package/dist/packem_shared/schemaFromIr-DTYsLBaA.mjs +0 -57
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { LanguageName } from 'quicktype-core';
|
|
2
|
+
/**
|
|
3
|
+
* Language-agnostic half of SDK generation: turn an OpenRPC document
|
|
4
|
+
* (`_generated/openrpc.json`, see {@link file://../openrpc.ts}) into the parsed
|
|
5
|
+
* shape every per-language target renders from.
|
|
6
|
+
*
|
|
7
|
+
* Nothing here knows about a target language. A target supplies its own member
|
|
8
|
+
* naming and templates (see {@link file://./targets}); everything that would
|
|
9
|
+
* otherwise be re-derived per language — how a `functionPath` splits, which
|
|
10
|
+
* runtime verb a kind maps to, whether a schema is real or the untyped
|
|
11
|
+
* placeholder, how namespaces group and sort — lives here exactly once.
|
|
12
|
+
*
|
|
13
|
+
* That single-source rule is not stylistic. `paths.ts` documents the same
|
|
14
|
+
* discipline for namespaces ("if these ever disagree, runtime dispatch silently
|
|
15
|
+
* misses functions"), and the failure mode here is the same in a new costume: a
|
|
16
|
+
* target that re-derives a model name renders an import pointing at a class
|
|
17
|
+
* quicktype never emitted.
|
|
18
|
+
*
|
|
19
|
+
* Deriving names in one place is necessary but NOT sufficient, because only
|
|
20
|
+
* half the decision is ours: quicktype chooses whether a predicted name becomes
|
|
21
|
+
* a declared type, and different backends answer differently for the same
|
|
22
|
+
* schema. {@link withDeclaredModels} reconciles the two halves before a target
|
|
23
|
+
* renders anything.
|
|
24
|
+
*/
|
|
25
|
+
/** One OpenRPC method as {@link file://../openrpc.ts} emits it. */
|
|
26
|
+
interface OpenRpcMethod {
|
|
27
|
+
name: string;
|
|
28
|
+
params?: ReadonlyArray<{
|
|
29
|
+
name: string;
|
|
30
|
+
schema?: Record<string, unknown>;
|
|
31
|
+
}>;
|
|
32
|
+
result?: {
|
|
33
|
+
name: string;
|
|
34
|
+
schema?: Record<string, unknown>;
|
|
35
|
+
};
|
|
36
|
+
summary?: string;
|
|
37
|
+
"x-lunora-function-kind"?: string;
|
|
38
|
+
}
|
|
39
|
+
/** The `_generated/openrpc.json` document. */
|
|
40
|
+
interface OpenRpcDocument {
|
|
41
|
+
info?: {
|
|
42
|
+
title?: string;
|
|
43
|
+
version?: string;
|
|
44
|
+
};
|
|
45
|
+
methods: ReadonlyArray<OpenRpcMethod>;
|
|
46
|
+
}
|
|
47
|
+
/** The runtime verbs a generated SDK can call. Mirrors the client transports. */
|
|
48
|
+
type RuntimeVerb = "action" | "mutation" | "query";
|
|
49
|
+
/** One RPC function, parsed and language-neutral. */
|
|
50
|
+
interface SdkMethod {
|
|
51
|
+
/**
|
|
52
|
+
* Where this function's ARGUMENT nulls mean "unset" and where they mean
|
|
53
|
+
* "null" — see {@link ModelNullPaths}.
|
|
54
|
+
*
|
|
55
|
+
* On the method rather than on a shared render input because it is a
|
|
56
|
+
* per-method fact and the parser already holds the schema it comes from. Read
|
|
57
|
+
* by the three targets whose rendered models cannot tell the two apart
|
|
58
|
+
* (ruby, rust, swift); the other five have a marker of their own and ignore
|
|
59
|
+
* it.
|
|
60
|
+
*/
|
|
61
|
+
argsNullPaths: ModelNullPaths;
|
|
62
|
+
/**
|
|
63
|
+
* Generated args model name, or `undefined` when NO model could be named for
|
|
64
|
+
* this function's arguments.
|
|
65
|
+
*
|
|
66
|
+
* `undefined` does NOT mean "takes no arguments" — see {@link SdkMethod.takesArgs}.
|
|
67
|
+
* A schema carrying a `v.bigint()` or `v.bytes()` gets no model deliberately
|
|
68
|
+
* (`hasUnrepresentableWireType`), and a backend that cannot name a shape leaves
|
|
69
|
+
* it undeclared. Both still take arguments, just untyped ones.
|
|
70
|
+
*/
|
|
71
|
+
argsType: string | undefined;
|
|
72
|
+
/** Raw exported function name (`"list"`), before any naming convention. */
|
|
73
|
+
functionName: string;
|
|
74
|
+
/** The wire identifier (`"messages:list"`), emitted verbatim into calls. */
|
|
75
|
+
functionPath: string;
|
|
76
|
+
/** Raw file namespace (`"messages"`), before any naming convention. */
|
|
77
|
+
namespace: string;
|
|
78
|
+
/** Generated result model name, or `undefined` while the result is untyped. */
|
|
79
|
+
resultType: string | undefined;
|
|
80
|
+
/** Human summary for the doc comment. */
|
|
81
|
+
summary: string;
|
|
82
|
+
/**
|
|
83
|
+
* Whether this function declares arguments at all, independent of whether a
|
|
84
|
+
* model could be named for them.
|
|
85
|
+
*
|
|
86
|
+
* A target emits three shapes from this: a TYPED parameter when `argsType` is
|
|
87
|
+
* set, an UNTYPED wire-shaped parameter when it is not but this is true, and no
|
|
88
|
+
* parameter at all when this is false. Collapsing the middle case into the last
|
|
89
|
+
* is what made `v.bigint()` functions uncallable with arguments.
|
|
90
|
+
*/
|
|
91
|
+
takesArgs: boolean;
|
|
92
|
+
/** Which runtime verb this dispatches to. */
|
|
93
|
+
verb: RuntimeVerb;
|
|
94
|
+
}
|
|
95
|
+
/** One namespace's functions, sorted. */
|
|
96
|
+
interface SdkNamespace {
|
|
97
|
+
methods: ReadonlyArray<SdkMethod>;
|
|
98
|
+
/** Raw namespace (`"messages"`); a target applies its own casing. */
|
|
99
|
+
name: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* True when a schema actually describes a shape.
|
|
103
|
+
*
|
|
104
|
+
* `openrpc.ts` emits a description-only placeholder for any function without a
|
|
105
|
+
* declared `.output()` (the return type is TS-inferred and absent from the IR).
|
|
106
|
+
* A placeholder must never become a generated model: quicktype would render an
|
|
107
|
+
* empty type, and the surface would decode every response into it — silently
|
|
108
|
+
* discarding the real payload rather than leaving it untyped.
|
|
109
|
+
*/
|
|
110
|
+
declare const isTypedSchema: (schema: Record<string, unknown> | undefined) => boolean;
|
|
111
|
+
/**
|
|
112
|
+
* A path from a model's root to one property. `*` stands for every element of an
|
|
113
|
+
* array or every value of a record, neither of which has named positions.
|
|
114
|
+
*/
|
|
115
|
+
type SchemaPath = ReadonlyArray<string>;
|
|
116
|
+
/**
|
|
117
|
+
* Where a model's nulls mean different things — the one fact a generated model
|
|
118
|
+
* flattens away, and the reason three ports could not send a `v.nullable()`
|
|
119
|
+
* argument at all.
|
|
120
|
+
*
|
|
121
|
+
* An unset `v.optional()` and a `v.nullable()` set to null are the SAME value in
|
|
122
|
+
* every generated model (a nil field), and opposite things on the wire: the
|
|
123
|
+
* validator rejects an explicit null for the first and requires the key present
|
|
124
|
+
* for the second. Neither Ruby, Rust nor Swift renders a marker telling them
|
|
125
|
+
* apart, so the distinction is computed here, from the schema, where `required`
|
|
126
|
+
* still exists — and handed to the targets that need it.
|
|
127
|
+
*
|
|
128
|
+
* Two lists rather than one because the ports need opposite operations. Ruby and
|
|
129
|
+
* Rust project a whole value tree and prune nulls, so they prune at
|
|
130
|
+
* {@link ModelNullPaths.optional} and nowhere else — which also stops them
|
|
131
|
+
* dropping a legitimate null inside a record or an array, as a blanket prune
|
|
132
|
+
* does. Swift's `JSONEncoder` has already dropped every struct-property nil
|
|
133
|
+
* before the transport sees a tree, so it restores nulls at
|
|
134
|
+
* {@link ModelNullPaths.nullable} instead: an absent key at a required path can
|
|
135
|
+
* only have been a nil, so putting the null back is exact.
|
|
136
|
+
*
|
|
137
|
+
* A `$ref` is NOT resolved. `openrpc.ts` inlines everything it emits, so this
|
|
138
|
+
* never comes up for a generated document — but `--spec` accepts a hand-written
|
|
139
|
+
* one, and there a `$ref`'d sub-object contributes no paths at all: the ports
|
|
140
|
+
* that prune would send its unset optionals as null, and Swift would not restore
|
|
141
|
+
* its nullables. Inline the schema, or teach this to follow the pointer.
|
|
142
|
+
*
|
|
143
|
+
* Both lists name PROPERTIES only. A record's values and an array's elements can
|
|
144
|
+
* be null too, but no port drops one: the pruning ports prune at `optional`
|
|
145
|
+
* paths, which a `*` position can never be, and `JSONEncoder` drops a nil only
|
|
146
|
+
* from a struct property — a nil inside a dictionary or array encodes as null.
|
|
147
|
+
* Listing a `*` leaf would also make Swift's restore INVENT record keys that
|
|
148
|
+
* were never there, which is why the walk records the path it descends through
|
|
149
|
+
* but never the `*` position itself.
|
|
150
|
+
*/
|
|
151
|
+
interface ModelNullPaths {
|
|
152
|
+
/** Required properties that permit null — a null there is a VALUE and must survive. */
|
|
153
|
+
nullable: ReadonlyArray<SchemaPath>;
|
|
154
|
+
/** Properties absent from their object's `required` — a null there means UNSET. */
|
|
155
|
+
optional: ReadonlyArray<SchemaPath>;
|
|
156
|
+
}
|
|
157
|
+
/** What a target renders from. */
|
|
158
|
+
interface SdkRenderInput {
|
|
159
|
+
/**
|
|
160
|
+
* The rendered model source, to be written as the target's model file.
|
|
161
|
+
*
|
|
162
|
+
* Empty for a target that emits its own model FILES via
|
|
163
|
+
* {@link SdkTarget.renderModels} — those are already written, and this string
|
|
164
|
+
* exists only so the declared-model reconciliation reads one shape.
|
|
165
|
+
*/
|
|
166
|
+
models: string;
|
|
167
|
+
/** Namespaces and their functions, already sorted. */
|
|
168
|
+
namespaces: ReadonlyArray<SdkNamespace>;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* One directory or file of the hand-written transport, and where it lands in the
|
|
172
|
+
* output.
|
|
173
|
+
*
|
|
174
|
+
* `from` is relative to `sdks/<target id>/` and `to` is relative to `--out`. The
|
|
175
|
+
* two differ because a repo layout and a consumable layout are not the same
|
|
176
|
+
* shape: the Ruby transport lives under `lib/` so `ruby -Ilib` works in the
|
|
177
|
+
* repo, while a vendored copy has no `lib` to point at, and the Rust transport
|
|
178
|
+
* is the repo's root crate but a nested one in the output.
|
|
179
|
+
*
|
|
180
|
+
* Only the runtime is listed. A transport's own conformance suite and its
|
|
181
|
+
* `generated_check/` sample are deliberately absent — they assert against
|
|
182
|
+
* `protocol/fixtures/`, which is not copied, so vendoring them would ship a user
|
|
183
|
+
* a test suite that cannot run.
|
|
184
|
+
*/
|
|
185
|
+
interface SdkVendorEntry {
|
|
186
|
+
/** Path under `sdks/<id>/`. A directory is copied recursively. */
|
|
187
|
+
from: string;
|
|
188
|
+
/** Destination path under `--out`. */
|
|
189
|
+
to: string;
|
|
190
|
+
}
|
|
191
|
+
/** A language target. One per `--lang` value. */
|
|
192
|
+
interface SdkTarget {
|
|
193
|
+
/** The `--lang` value (`"python"`, `"go"`, …). */
|
|
194
|
+
id: string;
|
|
195
|
+
/**
|
|
196
|
+
* The quicktype backend + renderer options that produce this target's
|
|
197
|
+
* models, or absent when the target emits its own (see
|
|
198
|
+
* {@link SdkTarget.renderModels}) or none at all.
|
|
199
|
+
*
|
|
200
|
+
* `LanguageName` is quicktype's own union, so a target naming a backend
|
|
201
|
+
* quicktype does not ship fails to compile rather than at run time.
|
|
202
|
+
*/
|
|
203
|
+
quicktype?: {
|
|
204
|
+
lang: LanguageName;
|
|
205
|
+
rendererOptions?: Record<string, string>;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Render the SDK. Returns file contents keyed by path relative to the
|
|
209
|
+
* output directory (nested paths are created as needed).
|
|
210
|
+
*
|
|
211
|
+
* This includes the BUILD MANIFEST the layout needs — `go.mod`, `Cargo.toml`,
|
|
212
|
+
* `Package.swift`, a crate root — because those name the vendored transport
|
|
213
|
+
* and are therefore part of "how this language resolves the copy", not
|
|
214
|
+
* something a consumer should have to write. Languages that resolve by
|
|
215
|
+
* directory (Python, Ruby, Java, Kotlin) emit no manifest.
|
|
216
|
+
*/
|
|
217
|
+
render: (input: SdkRenderInput) => Record<string, string>;
|
|
218
|
+
/**
|
|
219
|
+
* Emit this target's models from the schema directly, INSTEAD of quicktype,
|
|
220
|
+
* as file contents keyed by path relative to the output directory.
|
|
221
|
+
*
|
|
222
|
+
* Present only for the two JVM targets, and the exception is earned rather
|
|
223
|
+
* than a preference: quicktype's Java and Kotlin backends rename properties
|
|
224
|
+
* and, under `just-types`, emit no mapping metadata, so a model they render
|
|
225
|
+
* cannot be projected back onto the wire — and the only complete mapping
|
|
226
|
+
* they offer requires a Jackson / Klaxon / kotlinx dependency, which is the
|
|
227
|
+
* one thing these JDK-only transports are defined not to have.
|
|
228
|
+
* `targets/java.ts` records every option that was measured.
|
|
229
|
+
*
|
|
230
|
+
* A MAP rather than the single string quicktype returns, because Java takes
|
|
231
|
+
* one file per class: its single-file render is not compilable Java at all.
|
|
232
|
+
* The values are still joined for {@link SdkRenderInput.models}, so the
|
|
233
|
+
* declared-model reconciliation is the same code for every target.
|
|
234
|
+
*/
|
|
235
|
+
renderModels?: (document: OpenRpcDocument) => Record<string, string>;
|
|
236
|
+
/**
|
|
237
|
+
* THIRD-PARTY packages a consuming project must still install, reported by
|
|
238
|
+
* the CLI. Empty for six of the eight — the transport is vendored and those
|
|
239
|
+
* six reach the wire with only their standard library.
|
|
240
|
+
*
|
|
241
|
+
* A list, and not derivable from the transport, because a target's MODELS can
|
|
242
|
+
* carry a dependency the transport does not: quicktype's Ruby backend emits
|
|
243
|
+
* `Dry::Struct` types with no renderer option to avoid them, so a Ruby SDK
|
|
244
|
+
* needs the gems even though `sdks/ruby` itself is dependency-free.
|
|
245
|
+
*/
|
|
246
|
+
requires: ReadonlyArray<string>;
|
|
247
|
+
/**
|
|
248
|
+
* Which parts of `sdks/<id>/` are the transport, and where they land under
|
|
249
|
+
* `--out`. See {@link SdkVendorEntry}.
|
|
250
|
+
*/
|
|
251
|
+
vendor: ReadonlyArray<SdkVendorEntry>;
|
|
252
|
+
}
|
|
253
|
+
/** Every language `lunora sdk generate --lang` accepts, keyed by id. */
|
|
254
|
+
declare const SDK_TARGETS: Readonly<Record<string, SdkTarget>>;
|
|
255
|
+
/** The accepted `--lang` values, sorted — for help text and error messages. */
|
|
256
|
+
declare const SDK_LANGUAGES: ReadonlyArray<string>;
|
|
257
|
+
/** The files a generation run writes, keyed by path relative to the output directory. */
|
|
258
|
+
type SdkFiles = Record<string, string>;
|
|
259
|
+
/** What a generation run produced, plus what it had to weaken and why. */
|
|
260
|
+
interface SdkResult {
|
|
261
|
+
files: SdkFiles;
|
|
262
|
+
/**
|
|
263
|
+
* Model names predicted from the schema that the chosen backend did not
|
|
264
|
+
* declare, so their call sites fell back to an untyped return. Surfaced
|
|
265
|
+
* rather than swallowed — silently weaker types are how an SDK looks
|
|
266
|
+
* finished while returning `Any` everywhere.
|
|
267
|
+
*/
|
|
268
|
+
undeclared: ReadonlyArray<string>;
|
|
269
|
+
/**
|
|
270
|
+
* Functions whose args or result carry a `v.bigint()` or `v.bytes()`. No
|
|
271
|
+
* typed model can represent those — the wire needs a tagged value that no
|
|
272
|
+
* generated field produces — so their parameters stay untyped and the
|
|
273
|
+
* caller passes wire values directly.
|
|
274
|
+
*/
|
|
275
|
+
unrepresentable: ReadonlyArray<string>;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Generate the SDK for `document` in `target`'s language.
|
|
279
|
+
*
|
|
280
|
+
* Async only because the model layer is: quicktype's renderer is promise-based.
|
|
281
|
+
* The surface itself is pure, so a target's `render` stays synchronous and
|
|
282
|
+
* unit-testable without touching quicktype.
|
|
283
|
+
*
|
|
284
|
+
* Models are rendered BEFORE the surface because the surface's model references
|
|
285
|
+
* depend on what the backend actually declared — see {@link withDeclaredModels}.
|
|
286
|
+
*/
|
|
287
|
+
declare const generateSdk: (document: OpenRpcDocument, target: SdkTarget) => Promise<SdkResult>;
|
|
288
|
+
export { type OpenRpcDocument, type OpenRpcMethod, type RuntimeVerb, SDK_LANGUAGES, SDK_TARGETS, type SdkFiles, type SdkMethod, type SdkNamespace, type SdkRenderInput, type SdkResult, type SdkTarget, generateSdk, isTypedSchema };
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { LanguageName } from 'quicktype-core';
|
|
2
|
+
/**
|
|
3
|
+
* Language-agnostic half of SDK generation: turn an OpenRPC document
|
|
4
|
+
* (`_generated/openrpc.json`, see {@link file://../openrpc.ts}) into the parsed
|
|
5
|
+
* shape every per-language target renders from.
|
|
6
|
+
*
|
|
7
|
+
* Nothing here knows about a target language. A target supplies its own member
|
|
8
|
+
* naming and templates (see {@link file://./targets}); everything that would
|
|
9
|
+
* otherwise be re-derived per language — how a `functionPath` splits, which
|
|
10
|
+
* runtime verb a kind maps to, whether a schema is real or the untyped
|
|
11
|
+
* placeholder, how namespaces group and sort — lives here exactly once.
|
|
12
|
+
*
|
|
13
|
+
* That single-source rule is not stylistic. `paths.ts` documents the same
|
|
14
|
+
* discipline for namespaces ("if these ever disagree, runtime dispatch silently
|
|
15
|
+
* misses functions"), and the failure mode here is the same in a new costume: a
|
|
16
|
+
* target that re-derives a model name renders an import pointing at a class
|
|
17
|
+
* quicktype never emitted.
|
|
18
|
+
*
|
|
19
|
+
* Deriving names in one place is necessary but NOT sufficient, because only
|
|
20
|
+
* half the decision is ours: quicktype chooses whether a predicted name becomes
|
|
21
|
+
* a declared type, and different backends answer differently for the same
|
|
22
|
+
* schema. {@link withDeclaredModels} reconciles the two halves before a target
|
|
23
|
+
* renders anything.
|
|
24
|
+
*/
|
|
25
|
+
/** One OpenRPC method as {@link file://../openrpc.ts} emits it. */
|
|
26
|
+
interface OpenRpcMethod {
|
|
27
|
+
name: string;
|
|
28
|
+
params?: ReadonlyArray<{
|
|
29
|
+
name: string;
|
|
30
|
+
schema?: Record<string, unknown>;
|
|
31
|
+
}>;
|
|
32
|
+
result?: {
|
|
33
|
+
name: string;
|
|
34
|
+
schema?: Record<string, unknown>;
|
|
35
|
+
};
|
|
36
|
+
summary?: string;
|
|
37
|
+
"x-lunora-function-kind"?: string;
|
|
38
|
+
}
|
|
39
|
+
/** The `_generated/openrpc.json` document. */
|
|
40
|
+
interface OpenRpcDocument {
|
|
41
|
+
info?: {
|
|
42
|
+
title?: string;
|
|
43
|
+
version?: string;
|
|
44
|
+
};
|
|
45
|
+
methods: ReadonlyArray<OpenRpcMethod>;
|
|
46
|
+
}
|
|
47
|
+
/** The runtime verbs a generated SDK can call. Mirrors the client transports. */
|
|
48
|
+
type RuntimeVerb = "action" | "mutation" | "query";
|
|
49
|
+
/** One RPC function, parsed and language-neutral. */
|
|
50
|
+
interface SdkMethod {
|
|
51
|
+
/**
|
|
52
|
+
* Where this function's ARGUMENT nulls mean "unset" and where they mean
|
|
53
|
+
* "null" — see {@link ModelNullPaths}.
|
|
54
|
+
*
|
|
55
|
+
* On the method rather than on a shared render input because it is a
|
|
56
|
+
* per-method fact and the parser already holds the schema it comes from. Read
|
|
57
|
+
* by the three targets whose rendered models cannot tell the two apart
|
|
58
|
+
* (ruby, rust, swift); the other five have a marker of their own and ignore
|
|
59
|
+
* it.
|
|
60
|
+
*/
|
|
61
|
+
argsNullPaths: ModelNullPaths;
|
|
62
|
+
/**
|
|
63
|
+
* Generated args model name, or `undefined` when NO model could be named for
|
|
64
|
+
* this function's arguments.
|
|
65
|
+
*
|
|
66
|
+
* `undefined` does NOT mean "takes no arguments" — see {@link SdkMethod.takesArgs}.
|
|
67
|
+
* A schema carrying a `v.bigint()` or `v.bytes()` gets no model deliberately
|
|
68
|
+
* (`hasUnrepresentableWireType`), and a backend that cannot name a shape leaves
|
|
69
|
+
* it undeclared. Both still take arguments, just untyped ones.
|
|
70
|
+
*/
|
|
71
|
+
argsType: string | undefined;
|
|
72
|
+
/** Raw exported function name (`"list"`), before any naming convention. */
|
|
73
|
+
functionName: string;
|
|
74
|
+
/** The wire identifier (`"messages:list"`), emitted verbatim into calls. */
|
|
75
|
+
functionPath: string;
|
|
76
|
+
/** Raw file namespace (`"messages"`), before any naming convention. */
|
|
77
|
+
namespace: string;
|
|
78
|
+
/** Generated result model name, or `undefined` while the result is untyped. */
|
|
79
|
+
resultType: string | undefined;
|
|
80
|
+
/** Human summary for the doc comment. */
|
|
81
|
+
summary: string;
|
|
82
|
+
/**
|
|
83
|
+
* Whether this function declares arguments at all, independent of whether a
|
|
84
|
+
* model could be named for them.
|
|
85
|
+
*
|
|
86
|
+
* A target emits three shapes from this: a TYPED parameter when `argsType` is
|
|
87
|
+
* set, an UNTYPED wire-shaped parameter when it is not but this is true, and no
|
|
88
|
+
* parameter at all when this is false. Collapsing the middle case into the last
|
|
89
|
+
* is what made `v.bigint()` functions uncallable with arguments.
|
|
90
|
+
*/
|
|
91
|
+
takesArgs: boolean;
|
|
92
|
+
/** Which runtime verb this dispatches to. */
|
|
93
|
+
verb: RuntimeVerb;
|
|
94
|
+
}
|
|
95
|
+
/** One namespace's functions, sorted. */
|
|
96
|
+
interface SdkNamespace {
|
|
97
|
+
methods: ReadonlyArray<SdkMethod>;
|
|
98
|
+
/** Raw namespace (`"messages"`); a target applies its own casing. */
|
|
99
|
+
name: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* True when a schema actually describes a shape.
|
|
103
|
+
*
|
|
104
|
+
* `openrpc.ts` emits a description-only placeholder for any function without a
|
|
105
|
+
* declared `.output()` (the return type is TS-inferred and absent from the IR).
|
|
106
|
+
* A placeholder must never become a generated model: quicktype would render an
|
|
107
|
+
* empty type, and the surface would decode every response into it — silently
|
|
108
|
+
* discarding the real payload rather than leaving it untyped.
|
|
109
|
+
*/
|
|
110
|
+
declare const isTypedSchema: (schema: Record<string, unknown> | undefined) => boolean;
|
|
111
|
+
/**
|
|
112
|
+
* A path from a model's root to one property. `*` stands for every element of an
|
|
113
|
+
* array or every value of a record, neither of which has named positions.
|
|
114
|
+
*/
|
|
115
|
+
type SchemaPath = ReadonlyArray<string>;
|
|
116
|
+
/**
|
|
117
|
+
* Where a model's nulls mean different things — the one fact a generated model
|
|
118
|
+
* flattens away, and the reason three ports could not send a `v.nullable()`
|
|
119
|
+
* argument at all.
|
|
120
|
+
*
|
|
121
|
+
* An unset `v.optional()` and a `v.nullable()` set to null are the SAME value in
|
|
122
|
+
* every generated model (a nil field), and opposite things on the wire: the
|
|
123
|
+
* validator rejects an explicit null for the first and requires the key present
|
|
124
|
+
* for the second. Neither Ruby, Rust nor Swift renders a marker telling them
|
|
125
|
+
* apart, so the distinction is computed here, from the schema, where `required`
|
|
126
|
+
* still exists — and handed to the targets that need it.
|
|
127
|
+
*
|
|
128
|
+
* Two lists rather than one because the ports need opposite operations. Ruby and
|
|
129
|
+
* Rust project a whole value tree and prune nulls, so they prune at
|
|
130
|
+
* {@link ModelNullPaths.optional} and nowhere else — which also stops them
|
|
131
|
+
* dropping a legitimate null inside a record or an array, as a blanket prune
|
|
132
|
+
* does. Swift's `JSONEncoder` has already dropped every struct-property nil
|
|
133
|
+
* before the transport sees a tree, so it restores nulls at
|
|
134
|
+
* {@link ModelNullPaths.nullable} instead: an absent key at a required path can
|
|
135
|
+
* only have been a nil, so putting the null back is exact.
|
|
136
|
+
*
|
|
137
|
+
* A `$ref` is NOT resolved. `openrpc.ts` inlines everything it emits, so this
|
|
138
|
+
* never comes up for a generated document — but `--spec` accepts a hand-written
|
|
139
|
+
* one, and there a `$ref`'d sub-object contributes no paths at all: the ports
|
|
140
|
+
* that prune would send its unset optionals as null, and Swift would not restore
|
|
141
|
+
* its nullables. Inline the schema, or teach this to follow the pointer.
|
|
142
|
+
*
|
|
143
|
+
* Both lists name PROPERTIES only. A record's values and an array's elements can
|
|
144
|
+
* be null too, but no port drops one: the pruning ports prune at `optional`
|
|
145
|
+
* paths, which a `*` position can never be, and `JSONEncoder` drops a nil only
|
|
146
|
+
* from a struct property — a nil inside a dictionary or array encodes as null.
|
|
147
|
+
* Listing a `*` leaf would also make Swift's restore INVENT record keys that
|
|
148
|
+
* were never there, which is why the walk records the path it descends through
|
|
149
|
+
* but never the `*` position itself.
|
|
150
|
+
*/
|
|
151
|
+
interface ModelNullPaths {
|
|
152
|
+
/** Required properties that permit null — a null there is a VALUE and must survive. */
|
|
153
|
+
nullable: ReadonlyArray<SchemaPath>;
|
|
154
|
+
/** Properties absent from their object's `required` — a null there means UNSET. */
|
|
155
|
+
optional: ReadonlyArray<SchemaPath>;
|
|
156
|
+
}
|
|
157
|
+
/** What a target renders from. */
|
|
158
|
+
interface SdkRenderInput {
|
|
159
|
+
/**
|
|
160
|
+
* The rendered model source, to be written as the target's model file.
|
|
161
|
+
*
|
|
162
|
+
* Empty for a target that emits its own model FILES via
|
|
163
|
+
* {@link SdkTarget.renderModels} — those are already written, and this string
|
|
164
|
+
* exists only so the declared-model reconciliation reads one shape.
|
|
165
|
+
*/
|
|
166
|
+
models: string;
|
|
167
|
+
/** Namespaces and their functions, already sorted. */
|
|
168
|
+
namespaces: ReadonlyArray<SdkNamespace>;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* One directory or file of the hand-written transport, and where it lands in the
|
|
172
|
+
* output.
|
|
173
|
+
*
|
|
174
|
+
* `from` is relative to `sdks/<target id>/` and `to` is relative to `--out`. The
|
|
175
|
+
* two differ because a repo layout and a consumable layout are not the same
|
|
176
|
+
* shape: the Ruby transport lives under `lib/` so `ruby -Ilib` works in the
|
|
177
|
+
* repo, while a vendored copy has no `lib` to point at, and the Rust transport
|
|
178
|
+
* is the repo's root crate but a nested one in the output.
|
|
179
|
+
*
|
|
180
|
+
* Only the runtime is listed. A transport's own conformance suite and its
|
|
181
|
+
* `generated_check/` sample are deliberately absent — they assert against
|
|
182
|
+
* `protocol/fixtures/`, which is not copied, so vendoring them would ship a user
|
|
183
|
+
* a test suite that cannot run.
|
|
184
|
+
*/
|
|
185
|
+
interface SdkVendorEntry {
|
|
186
|
+
/** Path under `sdks/<id>/`. A directory is copied recursively. */
|
|
187
|
+
from: string;
|
|
188
|
+
/** Destination path under `--out`. */
|
|
189
|
+
to: string;
|
|
190
|
+
}
|
|
191
|
+
/** A language target. One per `--lang` value. */
|
|
192
|
+
interface SdkTarget {
|
|
193
|
+
/** The `--lang` value (`"python"`, `"go"`, …). */
|
|
194
|
+
id: string;
|
|
195
|
+
/**
|
|
196
|
+
* The quicktype backend + renderer options that produce this target's
|
|
197
|
+
* models, or absent when the target emits its own (see
|
|
198
|
+
* {@link SdkTarget.renderModels}) or none at all.
|
|
199
|
+
*
|
|
200
|
+
* `LanguageName` is quicktype's own union, so a target naming a backend
|
|
201
|
+
* quicktype does not ship fails to compile rather than at run time.
|
|
202
|
+
*/
|
|
203
|
+
quicktype?: {
|
|
204
|
+
lang: LanguageName;
|
|
205
|
+
rendererOptions?: Record<string, string>;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Render the SDK. Returns file contents keyed by path relative to the
|
|
209
|
+
* output directory (nested paths are created as needed).
|
|
210
|
+
*
|
|
211
|
+
* This includes the BUILD MANIFEST the layout needs — `go.mod`, `Cargo.toml`,
|
|
212
|
+
* `Package.swift`, a crate root — because those name the vendored transport
|
|
213
|
+
* and are therefore part of "how this language resolves the copy", not
|
|
214
|
+
* something a consumer should have to write. Languages that resolve by
|
|
215
|
+
* directory (Python, Ruby, Java, Kotlin) emit no manifest.
|
|
216
|
+
*/
|
|
217
|
+
render: (input: SdkRenderInput) => Record<string, string>;
|
|
218
|
+
/**
|
|
219
|
+
* Emit this target's models from the schema directly, INSTEAD of quicktype,
|
|
220
|
+
* as file contents keyed by path relative to the output directory.
|
|
221
|
+
*
|
|
222
|
+
* Present only for the two JVM targets, and the exception is earned rather
|
|
223
|
+
* than a preference: quicktype's Java and Kotlin backends rename properties
|
|
224
|
+
* and, under `just-types`, emit no mapping metadata, so a model they render
|
|
225
|
+
* cannot be projected back onto the wire — and the only complete mapping
|
|
226
|
+
* they offer requires a Jackson / Klaxon / kotlinx dependency, which is the
|
|
227
|
+
* one thing these JDK-only transports are defined not to have.
|
|
228
|
+
* `targets/java.ts` records every option that was measured.
|
|
229
|
+
*
|
|
230
|
+
* A MAP rather than the single string quicktype returns, because Java takes
|
|
231
|
+
* one file per class: its single-file render is not compilable Java at all.
|
|
232
|
+
* The values are still joined for {@link SdkRenderInput.models}, so the
|
|
233
|
+
* declared-model reconciliation is the same code for every target.
|
|
234
|
+
*/
|
|
235
|
+
renderModels?: (document: OpenRpcDocument) => Record<string, string>;
|
|
236
|
+
/**
|
|
237
|
+
* THIRD-PARTY packages a consuming project must still install, reported by
|
|
238
|
+
* the CLI. Empty for six of the eight — the transport is vendored and those
|
|
239
|
+
* six reach the wire with only their standard library.
|
|
240
|
+
*
|
|
241
|
+
* A list, and not derivable from the transport, because a target's MODELS can
|
|
242
|
+
* carry a dependency the transport does not: quicktype's Ruby backend emits
|
|
243
|
+
* `Dry::Struct` types with no renderer option to avoid them, so a Ruby SDK
|
|
244
|
+
* needs the gems even though `sdks/ruby` itself is dependency-free.
|
|
245
|
+
*/
|
|
246
|
+
requires: ReadonlyArray<string>;
|
|
247
|
+
/**
|
|
248
|
+
* Which parts of `sdks/<id>/` are the transport, and where they land under
|
|
249
|
+
* `--out`. See {@link SdkVendorEntry}.
|
|
250
|
+
*/
|
|
251
|
+
vendor: ReadonlyArray<SdkVendorEntry>;
|
|
252
|
+
}
|
|
253
|
+
/** Every language `lunora sdk generate --lang` accepts, keyed by id. */
|
|
254
|
+
declare const SDK_TARGETS: Readonly<Record<string, SdkTarget>>;
|
|
255
|
+
/** The accepted `--lang` values, sorted — for help text and error messages. */
|
|
256
|
+
declare const SDK_LANGUAGES: ReadonlyArray<string>;
|
|
257
|
+
/** The files a generation run writes, keyed by path relative to the output directory. */
|
|
258
|
+
type SdkFiles = Record<string, string>;
|
|
259
|
+
/** What a generation run produced, plus what it had to weaken and why. */
|
|
260
|
+
interface SdkResult {
|
|
261
|
+
files: SdkFiles;
|
|
262
|
+
/**
|
|
263
|
+
* Model names predicted from the schema that the chosen backend did not
|
|
264
|
+
* declare, so their call sites fell back to an untyped return. Surfaced
|
|
265
|
+
* rather than swallowed — silently weaker types are how an SDK looks
|
|
266
|
+
* finished while returning `Any` everywhere.
|
|
267
|
+
*/
|
|
268
|
+
undeclared: ReadonlyArray<string>;
|
|
269
|
+
/**
|
|
270
|
+
* Functions whose args or result carry a `v.bigint()` or `v.bytes()`. No
|
|
271
|
+
* typed model can represent those — the wire needs a tagged value that no
|
|
272
|
+
* generated field produces — so their parameters stay untyped and the
|
|
273
|
+
* caller passes wire values directly.
|
|
274
|
+
*/
|
|
275
|
+
unrepresentable: ReadonlyArray<string>;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Generate the SDK for `document` in `target`'s language.
|
|
279
|
+
*
|
|
280
|
+
* Async only because the model layer is: quicktype's renderer is promise-based.
|
|
281
|
+
* The surface itself is pure, so a target's `render` stays synchronous and
|
|
282
|
+
* unit-testable without touching quicktype.
|
|
283
|
+
*
|
|
284
|
+
* Models are rendered BEFORE the surface because the surface's model references
|
|
285
|
+
* depend on what the backend actually declared — see {@link withDeclaredModels}.
|
|
286
|
+
*/
|
|
287
|
+
declare const generateSdk: (document: OpenRpcDocument, target: SdkTarget) => Promise<SdkResult>;
|
|
288
|
+
export { type OpenRpcDocument, type OpenRpcMethod, type RuntimeVerb, SDK_LANGUAGES, SDK_TARGETS, type SdkFiles, type SdkMethod, type SdkNamespace, type SdkRenderInput, type SdkResult, type SdkTarget, generateSdk, isTypedSchema };
|