@sjcx/vorma 0.0.0-pre.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/LICENSE +20 -0
- package/dist/build/assemble-artifacts.d.ts +23 -0
- package/dist/build/browser-contracts.d.ts +8 -0
- package/dist/build/bundle-client.d.ts +29 -0
- package/dist/build/cli.d.ts +2 -0
- package/dist/build/cli.js +1256 -0
- package/dist/build/client-inputs.d.ts +11 -0
- package/dist/build/client-output-hashing.d.ts +3 -0
- package/dist/build/client-public-urls.d.ts +20 -0
- package/dist/build/compare-text.d.ts +5 -0
- package/dist/build/compile-application.d.ts +40 -0
- package/dist/build/compile-server.d.ts +42 -0
- package/dist/build/contained-path.d.ts +29 -0
- package/dist/build/critical-css.d.ts +7 -0
- package/dist/build/css-public-assets.d.ts +15 -0
- package/dist/build/development-artifacts.d.ts +35 -0
- package/dist/build/development-browser-source.d.ts +3 -0
- package/dist/build/development-build.d.ts +30 -0
- package/dist/build/development-changes.d.ts +14 -0
- package/dist/build/development-client.d.ts +21 -0
- package/dist/build/development-generation.d.ts +20 -0
- package/dist/build/development-listener.d.ts +14 -0
- package/dist/build/development-patterns.d.ts +5 -0
- package/dist/build/development-protocol.d.ts +20 -0
- package/dist/build/development-server-process.d.ts +30 -0
- package/dist/build/development-sources.d.ts +23 -0
- package/dist/build/development-stylesheet.d.ts +15 -0
- package/dist/build/development-watcher.d.ts +15 -0
- package/dist/build/development-work.d.ts +32 -0
- package/dist/build/development.d.ts +3 -0
- package/dist/build/generate-application.d.ts +62 -0
- package/dist/build/index.d.ts +15 -0
- package/dist/build/index.js +2 -0
- package/dist/build/inspect-css-artifacts.d.ts +11 -0
- package/dist/build/inspect-projects.d.ts +69 -0
- package/dist/build/load-config.d.ts +56 -0
- package/dist/build/output-files.d.ts +8 -0
- package/dist/build/output-ownership.d.ts +21 -0
- package/dist/build/public-assets.d.ts +32 -0
- package/dist/build/publish-artifacts.d.ts +23 -0
- package/dist/build/render-client-contracts.d.ts +10 -0
- package/dist/build/render-client-transport.d.ts +11 -0
- package/dist/build/render-server-generated.d.ts +33 -0
- package/dist/build/render-source-text.d.ts +24 -0
- package/dist/build/render-types.d.ts +31 -0
- package/dist/build/resolve-config.d.ts +50 -0
- package/dist/build/source-layout.d.ts +24 -0
- package/dist/build/typescript-projects.d.ts +36 -0
- package/dist/build-JgARonaY.js +3214 -0
- package/dist/build-invocation-D7Fu8gBK.js +4 -0
- package/dist/client/assembly.d.ts +40 -0
- package/dist/client/browser-http-client.d.ts +10 -0
- package/dist/client/client-loaders.d.ts +93 -0
- package/dist/client/commit.d.ts +41 -0
- package/dist/client/contracts.d.ts +192 -0
- package/dist/client/core.d.ts +45 -0
- package/dist/client/development.d.ts +16 -0
- package/dist/client/document-recovery.d.ts +4 -0
- package/dist/client/endpoints.d.ts +54 -0
- package/dist/client/errors.d.ts +87 -0
- package/dist/client/freshness.d.ts +51 -0
- package/dist/client/head.d.ts +14 -0
- package/dist/client/history.d.ts +25 -0
- package/dist/client/index.d.ts +80 -0
- package/dist/client/index.js +150 -0
- package/dist/client/links.d.ts +48 -0
- package/dist/client/materialize.d.ts +21 -0
- package/dist/client/modules.d.ts +2 -0
- package/dist/client/navigation.d.ts +47 -0
- package/dist/client/payload.d.ts +54 -0
- package/dist/client/prefetch.d.ts +28 -0
- package/dist/client/prepare.d.ts +47 -0
- package/dist/client/projections.d.ts +26 -0
- package/dist/client/queries.d.ts +33 -0
- package/dist/client/react/application.d.ts +87 -0
- package/dist/client/react/hooks.d.ts +36 -0
- package/dist/client/react/index.d.ts +5 -0
- package/dist/client/react/index.js +3237 -0
- package/dist/client/react/link.d.ts +27 -0
- package/dist/client/react/view.d.ts +86 -0
- package/dist/client/request.d.ts +16 -0
- package/dist/client/route-context.d.ts +31 -0
- package/dist/client/route-matching.d.ts +22 -0
- package/dist/client/route-synchronization.d.ts +30 -0
- package/dist/client/route-url.d.ts +5 -0
- package/dist/client/runtime.d.ts +82 -0
- package/dist/client/scroll.d.ts +16 -0
- package/dist/client/services.d.ts +34 -0
- package/dist/client/state.d.ts +102 -0
- package/dist/client/static-assets.d.ts +3 -0
- package/dist/client/stylesheets.d.ts +7 -0
- package/dist/client/transport-type-entries.d.ts +2 -0
- package/dist/client/types.d.ts +152 -0
- package/dist/client/view-definition.d.ts +24 -0
- package/dist/client/work-indicator.d.ts +18 -0
- package/dist/compile-Me8EOyMK.js +870 -0
- package/dist/development-B_rxuwY7.js +128 -0
- package/dist/hash-set-BPx3iXec.js +141 -0
- package/dist/href-Cqyax8Y0.js +357 -0
- package/dist/materialize-DZ7VSLFk.js +739 -0
- package/dist/metadata-BoPKo-G2.js +32 -0
- package/dist/primitives/tasks/index.d.ts +1 -0
- package/dist/primitives/tasks/index.js +1 -0
- package/dist/route-context-CtY_9U_W.js +559 -0
- package/dist/route-matching-D_uSG2P9.js +33 -0
- package/dist/search-parse-0f7oqVsG.js +375 -0
- package/dist/server/config/index.d.ts +36 -0
- package/dist/server/config/index.js +30 -0
- package/dist/server/development/metadata.d.ts +11 -0
- package/dist/server/document.d.ts +37 -0
- package/dist/server/form-data.d.ts +21 -0
- package/dist/server/graph/compile.d.ts +118 -0
- package/dist/server/graph/declarations.d.ts +117 -0
- package/dist/server/graph/literal-error-tag.d.ts +14 -0
- package/dist/server/graph/pattern-conflicts.d.ts +36 -0
- package/dist/server/graph/search-schema.d.ts +13 -0
- package/dist/server/graph/transport-schema.d.ts +11 -0
- package/dist/server/index.d.ts +310 -0
- package/dist/server/index.js +2311 -0
- package/dist/server/public-assets.d.ts +18 -0
- package/dist/server/runtime/application.d.ts +15 -0
- package/dist/server/runtime/assets.d.ts +15 -0
- package/dist/server/runtime/context.d.ts +96 -0
- package/dist/server/runtime/domain-errors.d.ts +11 -0
- package/dist/server/runtime/effects.d.ts +83 -0
- package/dist/server/runtime/execute.d.ts +13 -0
- package/dist/server/runtime/finalize.d.ts +44 -0
- package/dist/server/runtime/handler.d.ts +106 -0
- package/dist/server/runtime/head.d.ts +22 -0
- package/dist/server/runtime/payload.d.ts +50 -0
- package/dist/server/runtime/pipeline.d.ts +27 -0
- package/dist/server/runtime/plan.d.ts +98 -0
- package/dist/server/runtime/render-document.d.ts +16 -0
- package/dist/server/runtime/startup-error.d.ts +11 -0
- package/dist/server/runtime/transport-type-entries.d.ts +2 -0
- package/dist/server/runtime/vercel-deployment.d.ts +2 -0
- package/dist/server/url-pathname.d.ts +13 -0
- package/dist/static-assets-BrH3O0M8.js +199 -0
- package/dist/universal/content-digest.d.ts +7 -0
- package/dist/universal/generated-types.d.ts +9 -0
- package/dist/universal/href.d.ts +17 -0
- package/dist/universal/http-method.d.ts +4 -0
- package/dist/universal/json-transport.d.ts +14 -0
- package/dist/universal/null-prototype-record.d.ts +7 -0
- package/dist/universal/path-wire.d.ts +71 -0
- package/dist/universal/pattern-language.d.ts +4 -0
- package/dist/universal/protocol-schemas.d.ts +99 -0
- package/dist/universal/protocol.d.ts +162 -0
- package/dist/universal/search-grammar.d.ts +7 -0
- package/dist/universal/search-parse.d.ts +22 -0
- package/dist/universal/search-serialize.d.ts +16 -0
- package/dist/universal/search-shape.d.ts +32 -0
- package/dist/universal/static-assets.d.ts +2 -0
- package/dist/universal/transport-types/big-decimal.d.ts +13 -0
- package/dist/universal/transport-types/chunk.d.ts +8 -0
- package/dist/universal/transport-types/date-time-utc.d.ts +13 -0
- package/dist/universal/transport-types/date-time-zoned.d.ts +13 -0
- package/dist/universal/transport-types/duration.d.ts +13 -0
- package/dist/universal/transport-types/hash-map.d.ts +8 -0
- package/dist/universal/transport-types/hash-set.d.ts +8 -0
- package/dist/universal/transport-types/option.d.ts +10 -0
- package/dist/universal/transport-types/redacted.d.ts +9 -0
- package/dist/universal/value-transport.d.ts +117 -0
- package/dist/value-transport-Bst4Hk-n.js +864 -0
- package/dist/vite/build-invocation.d.ts +4 -0
- package/dist/vite/index.d.ts +3 -0
- package/dist/vite/index.js +15 -0
- package/package.json +84 -0
|
@@ -0,0 +1,870 @@
|
|
|
1
|
+
import { c as compileUiPattern, p as makeNullPrototypeRecord, s as compileEndpointPattern, t as EFFECT_TRANSPORT_TYPES, v as FRAMEWORK_ERROR_TAGS } from "./value-transport-Bst4Hk-n.js";
|
|
2
|
+
import { Result, Schema, SchemaAST, SchemaRepresentation } from "effect";
|
|
3
|
+
import * as NativeHttpMethod from "effect/unstable/http/HttpMethod";
|
|
4
|
+
import { Multipart } from "effect/unstable/http";
|
|
5
|
+
//#region src/universal/http-method.ts
|
|
6
|
+
function matchesHttpMethod(method) {
|
|
7
|
+
return NativeHttpMethod.isHttpMethod(method) && method !== "HEAD" && method !== "TRACE";
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/server/form-data.ts
|
|
11
|
+
const FORM_DATA_IDENTIFIER = "vorma/server/FormData";
|
|
12
|
+
/** Marks an endpoint's form transport; handlers receive Effect's parsed form record. */
|
|
13
|
+
const FormData = Schema.Record(Schema.String, Schema.Union([
|
|
14
|
+
Schema.String,
|
|
15
|
+
Schema.Array(Schema.String),
|
|
16
|
+
Multipart.FilesSchema
|
|
17
|
+
])).annotate({ identifier: FORM_DATA_IDENTIFIER });
|
|
18
|
+
/** The schema at the end of an encoding chain: the form the wire carries. */
|
|
19
|
+
function getEncodedLeaf(ast) {
|
|
20
|
+
let leaf = ast;
|
|
21
|
+
let encoding = leaf.encoding;
|
|
22
|
+
while (encoding !== void 0) {
|
|
23
|
+
for (const link of encoding) leaf = link.to;
|
|
24
|
+
encoding = leaf.encoding;
|
|
25
|
+
}
|
|
26
|
+
return leaf;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Whether an input schema reads the request's form data. `FormData` and
|
|
30
|
+
* every schema derived from it, such as `FormData.pipe(Schema.decodeTo(...))`,
|
|
31
|
+
* encode to the native form record at the end of their chain, which
|
|
32
|
+
* carries this module's identifier.
|
|
33
|
+
*/
|
|
34
|
+
function matchesFormInput(schema) {
|
|
35
|
+
return getEncodedLeaf(schema.ast).annotations?.["identifier"] === FORM_DATA_IDENTIFIER;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region src/server/graph/declarations.ts
|
|
39
|
+
function getInputTransport(declaration) {
|
|
40
|
+
if (declaration.input === void 0) return { kind: "none" };
|
|
41
|
+
if (declaration.method === "GET") return {
|
|
42
|
+
kind: "search",
|
|
43
|
+
schema: declaration.input
|
|
44
|
+
};
|
|
45
|
+
return matchesFormInput(declaration.input) ? {
|
|
46
|
+
kind: "formData",
|
|
47
|
+
schema: declaration.input
|
|
48
|
+
} : {
|
|
49
|
+
kind: "json",
|
|
50
|
+
schema: declaration.input
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/server/graph/literal-error-tag.ts
|
|
55
|
+
/**
|
|
56
|
+
* The literal tag a schema discriminates on, when it carries exactly one
|
|
57
|
+
* usable one. A `_tag` field wins when several string literals are present,
|
|
58
|
+
* which is the `Schema.TaggedError` shape; anything else ambiguous, and a
|
|
59
|
+
* schema with no required string literal, has no static tag. Runtime matching
|
|
60
|
+
* validates values against the declared schemas, so this is only the static
|
|
61
|
+
* identity the build checks and the envelope carries.
|
|
62
|
+
*/
|
|
63
|
+
function getLiteralErrorTag(schema) {
|
|
64
|
+
const ast = schema.ast;
|
|
65
|
+
const nodes = ast._tag === "Declaration" ? ast.typeParameters : [ast];
|
|
66
|
+
const literals = [];
|
|
67
|
+
for (const node of nodes) {
|
|
68
|
+
if (node._tag !== "Objects") continue;
|
|
69
|
+
for (const property of node.propertySignatures) {
|
|
70
|
+
if (typeof property.name === "symbol") continue;
|
|
71
|
+
if (property.type.context?.isOptional === true) continue;
|
|
72
|
+
if (property.type._tag === "Literal" && typeof property.type.literal === "string") literals.push({
|
|
73
|
+
field: String(property.name),
|
|
74
|
+
tag: property.type.literal
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (literals.length === 1) return literals[0];
|
|
79
|
+
return literals.find((literal) => literal.field === "_tag");
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/server/graph/pattern-conflicts.ts
|
|
83
|
+
function createPatternConflictIndex() {
|
|
84
|
+
return {
|
|
85
|
+
staticBranches: /* @__PURE__ */ new Map(),
|
|
86
|
+
dynamicBranch: void 0
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/** Attributes each shared dynamic-branch name clash to the authored pattern identities that produce it. */
|
|
90
|
+
function findConflictingDynamicParameterNames(input) {
|
|
91
|
+
const root = createPatternConflictIndex();
|
|
92
|
+
const seenMatcherPatterns = /* @__PURE__ */ new Set();
|
|
93
|
+
const conflicts = [];
|
|
94
|
+
for (const pattern of input.patterns) {
|
|
95
|
+
const matcherPattern = input.getMatcherPattern(pattern);
|
|
96
|
+
if (seenMatcherPatterns.has(matcherPattern)) continue;
|
|
97
|
+
let index = root;
|
|
98
|
+
const dynamicBranches = [];
|
|
99
|
+
let rejected = false;
|
|
100
|
+
for (const segment of input.getSegments(pattern)) {
|
|
101
|
+
if (segment.kind === "splat" || segment.kind === "index") break;
|
|
102
|
+
if (segment.kind === "static") {
|
|
103
|
+
let branch = index.staticBranches.get(segment.value);
|
|
104
|
+
if (branch === void 0) {
|
|
105
|
+
branch = createPatternConflictIndex();
|
|
106
|
+
index.staticBranches.set(segment.value, branch);
|
|
107
|
+
}
|
|
108
|
+
index = branch;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
let branch = index.dynamicBranch;
|
|
112
|
+
if (branch === void 0) {
|
|
113
|
+
branch = {
|
|
114
|
+
parameterName: segment.parameterName,
|
|
115
|
+
patterns: [],
|
|
116
|
+
next: createPatternConflictIndex()
|
|
117
|
+
};
|
|
118
|
+
index.dynamicBranch = branch;
|
|
119
|
+
} else if (branch.parameterName !== segment.parameterName) {
|
|
120
|
+
conflicts.push({
|
|
121
|
+
patterns: [...branch.patterns, pattern],
|
|
122
|
+
attemptedPattern: pattern,
|
|
123
|
+
cause: input.makeCause({
|
|
124
|
+
conflict: {
|
|
125
|
+
existingParameterName: branch.parameterName,
|
|
126
|
+
attemptedParameterName: segment.parameterName
|
|
127
|
+
},
|
|
128
|
+
attemptedPattern: pattern
|
|
129
|
+
})
|
|
130
|
+
});
|
|
131
|
+
rejected = true;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
dynamicBranches.push(branch);
|
|
135
|
+
index = branch.next;
|
|
136
|
+
}
|
|
137
|
+
if (rejected) continue;
|
|
138
|
+
for (const branch of dynamicBranches) branch.patterns.push(pattern);
|
|
139
|
+
seenMatcherPatterns.add(matcherPattern);
|
|
140
|
+
}
|
|
141
|
+
return conflicts;
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/server/graph/search-schema.ts
|
|
145
|
+
const SCALAR_DECLARATIONS = /* @__PURE__ */ new Map([
|
|
146
|
+
["effect/schema/Date", "date"],
|
|
147
|
+
["effect/schema/URL", "url"],
|
|
148
|
+
["effect/schema/URLSearchParams", "url-search-params"],
|
|
149
|
+
["effect/schema/RegExp", "regexp"]
|
|
150
|
+
]);
|
|
151
|
+
const EFFECT_KIND_BY_DECLARATION_ID = new Map(EFFECT_TRANSPORT_TYPES.map((type) => [type.representationId, type.name]));
|
|
152
|
+
function deriveSearchContract(schema) {
|
|
153
|
+
const ast = schema.ast;
|
|
154
|
+
if (ast._tag !== "Objects") return failUnsupported({
|
|
155
|
+
path: "",
|
|
156
|
+
reason: "the search schema root must be a structural object; transformations belong on its fields"
|
|
157
|
+
});
|
|
158
|
+
const live = SchemaRepresentation.toRepresentation(SchemaAST.toType(ast));
|
|
159
|
+
return Result.map(projectNode({
|
|
160
|
+
node: live.representation,
|
|
161
|
+
references: live.references,
|
|
162
|
+
path: "",
|
|
163
|
+
visiting: /* @__PURE__ */ new Set()
|
|
164
|
+
}), (document) => {
|
|
165
|
+
return {
|
|
166
|
+
document,
|
|
167
|
+
fields: new Set(ast.propertySignatures.map((property) => String(property.name)))
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function projectNode(input) {
|
|
172
|
+
if (input.visiting.has(input.node)) return failUnsupported({
|
|
173
|
+
path: input.path,
|
|
174
|
+
reason: "recursive schemas cannot be search parameters"
|
|
175
|
+
});
|
|
176
|
+
input.visiting.add(input.node);
|
|
177
|
+
const result = projectKnown(input);
|
|
178
|
+
input.visiting.delete(input.node);
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
function projectKnown(input) {
|
|
182
|
+
const { node, path } = input;
|
|
183
|
+
function child(node, childPath = path) {
|
|
184
|
+
return projectNode({
|
|
185
|
+
...input,
|
|
186
|
+
node,
|
|
187
|
+
path: childPath
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
switch (node._tag) {
|
|
191
|
+
case "Reference": {
|
|
192
|
+
const target = input.references[node.$ref];
|
|
193
|
+
return target === void 0 ? failUnsupported({
|
|
194
|
+
path,
|
|
195
|
+
reason: "the schema has a missing reference"
|
|
196
|
+
}) : child(target);
|
|
197
|
+
}
|
|
198
|
+
case "Suspend": return child(node.thunk);
|
|
199
|
+
case "String":
|
|
200
|
+
case "TemplateLiteral": return Result.succeed({
|
|
201
|
+
kind: "scalar",
|
|
202
|
+
type: "string"
|
|
203
|
+
});
|
|
204
|
+
case "Number": return Result.succeed({
|
|
205
|
+
kind: "scalar",
|
|
206
|
+
type: "number"
|
|
207
|
+
});
|
|
208
|
+
case "Boolean": return Result.succeed({
|
|
209
|
+
kind: "scalar",
|
|
210
|
+
type: "boolean"
|
|
211
|
+
});
|
|
212
|
+
case "BigInt": return Result.succeed({
|
|
213
|
+
kind: "scalar",
|
|
214
|
+
type: "bigint"
|
|
215
|
+
});
|
|
216
|
+
case "Literal": return typeof node.literal === "string" ? Result.succeed({
|
|
217
|
+
kind: "scalar",
|
|
218
|
+
type: "string",
|
|
219
|
+
values: [node.literal]
|
|
220
|
+
}) : failUnsupported({
|
|
221
|
+
path,
|
|
222
|
+
reason: "only string literals can be search parameters"
|
|
223
|
+
});
|
|
224
|
+
case "Enum": {
|
|
225
|
+
const values = node.enums.map(([, value]) => value);
|
|
226
|
+
return values.every((value) => typeof value === "string") ? Result.succeed({
|
|
227
|
+
kind: "scalar",
|
|
228
|
+
type: "string",
|
|
229
|
+
values
|
|
230
|
+
}) : failUnsupported({
|
|
231
|
+
path,
|
|
232
|
+
reason: "only string enums can be search parameters"
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
case "Union": {
|
|
236
|
+
const carried = node.types.filter((member) => member._tag !== "Undefined" && member._tag !== "Null");
|
|
237
|
+
const first = carried[0];
|
|
238
|
+
if (first === void 0) return failUnsupported({
|
|
239
|
+
path,
|
|
240
|
+
reason: "a union of only null and undefined carries nothing"
|
|
241
|
+
});
|
|
242
|
+
const values = [];
|
|
243
|
+
if (carried.length > 1) for (const member of carried) {
|
|
244
|
+
if (member._tag !== "Literal" || typeof member.literal !== "string") return failUnsupported({
|
|
245
|
+
path,
|
|
246
|
+
reason: "unions other than string literal enums cannot be search parameters"
|
|
247
|
+
});
|
|
248
|
+
values.push(member.literal);
|
|
249
|
+
}
|
|
250
|
+
const shape = carried.length === 1 ? child(first) : Result.succeed({
|
|
251
|
+
kind: "scalar",
|
|
252
|
+
type: "string",
|
|
253
|
+
values
|
|
254
|
+
});
|
|
255
|
+
return Result.map(shape, (value) => {
|
|
256
|
+
return {
|
|
257
|
+
...value,
|
|
258
|
+
...node.types.some((member) => member._tag === "Undefined") ? { optional: true } : {},
|
|
259
|
+
...node.types.some((member) => member._tag === "Null") ? { nullable: true } : {}
|
|
260
|
+
};
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
case "Arrays": {
|
|
264
|
+
const [item, ...more] = node.rest;
|
|
265
|
+
if (node.elements.length !== 0 || item === void 0 || more.length !== 0) return failUnsupported({
|
|
266
|
+
path,
|
|
267
|
+
reason: "only homogeneous arrays can be search parameters"
|
|
268
|
+
});
|
|
269
|
+
return Result.flatMap(child(item), (shape) => {
|
|
270
|
+
return Result.map(toScalar(shape, path), (item) => {
|
|
271
|
+
return {
|
|
272
|
+
kind: "array",
|
|
273
|
+
collection: "array",
|
|
274
|
+
item
|
|
275
|
+
};
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
case "Objects": {
|
|
280
|
+
const [index, ...more] = node.indexSignatures;
|
|
281
|
+
if (index !== void 0) {
|
|
282
|
+
if (node.propertySignatures.length !== 0 || more.length !== 0) return failUnsupported({
|
|
283
|
+
path,
|
|
284
|
+
reason: "a map cannot also have named fields"
|
|
285
|
+
});
|
|
286
|
+
return projectRecord({
|
|
287
|
+
...input,
|
|
288
|
+
key: index.parameter,
|
|
289
|
+
value: index.type,
|
|
290
|
+
collection: "record"
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
const fields = makeNullPrototypeRecord();
|
|
294
|
+
for (const property of node.propertySignatures) {
|
|
295
|
+
if (typeof property.name !== "string") return failUnsupported({
|
|
296
|
+
path,
|
|
297
|
+
reason: "field names must be strings"
|
|
298
|
+
});
|
|
299
|
+
const projected = child(property.type, path === "" ? property.name : `${path}.${property.name}`);
|
|
300
|
+
if (Result.isFailure(projected)) return projected;
|
|
301
|
+
fields[property.name] = property.isOptional ? {
|
|
302
|
+
...projected.success,
|
|
303
|
+
optional: true
|
|
304
|
+
} : projected.success;
|
|
305
|
+
}
|
|
306
|
+
return Result.succeed({
|
|
307
|
+
kind: "object",
|
|
308
|
+
fields
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
case "Declaration": return projectDeclaration(input, node);
|
|
312
|
+
default: return failUnsupported({
|
|
313
|
+
path,
|
|
314
|
+
reason: `${node._tag} has no URL spelling`
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function projectDeclaration(input, node) {
|
|
319
|
+
const { path } = input;
|
|
320
|
+
const id = node.representation?.id;
|
|
321
|
+
const effectKind = id === void 0 ? void 0 : EFFECT_KIND_BY_DECLARATION_ID.get(id);
|
|
322
|
+
const type = (id === void 0 ? void 0 : SCALAR_DECLARATIONS.get(id)) ?? (effectKind === "duration" || effectKind === "big-decimal" || effectKind === "date-time-utc" || effectKind === "date-time-zoned" ? effectKind : void 0);
|
|
323
|
+
if (type !== void 0) return node.typeParameters.length === 0 ? Result.succeed({
|
|
324
|
+
kind: "scalar",
|
|
325
|
+
type
|
|
326
|
+
}) : failUnsupported({
|
|
327
|
+
path,
|
|
328
|
+
reason: `${id} has unexpected type parameters`
|
|
329
|
+
});
|
|
330
|
+
if (id === "effect/schema/ReadonlyMap" || effectKind === "hash-map") {
|
|
331
|
+
const [key, value, ...more] = node.typeParameters;
|
|
332
|
+
return key === void 0 || value === void 0 || more.length !== 0 ? failUnsupported({
|
|
333
|
+
path,
|
|
334
|
+
reason: `${id} needs key and value types`
|
|
335
|
+
}) : projectRecord({
|
|
336
|
+
...input,
|
|
337
|
+
key,
|
|
338
|
+
value,
|
|
339
|
+
collection: effectKind === "hash-map" ? "hash-map" : "map"
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
if (effectKind === "option" || effectKind === "redacted" || effectKind === "chunk" || effectKind === "hash-set" || id === "effect/schema/ReadonlySet") {
|
|
343
|
+
const [parameter, ...more] = node.typeParameters;
|
|
344
|
+
if (parameter === void 0 || more.length !== 0) return failUnsupported({
|
|
345
|
+
path,
|
|
346
|
+
reason: `${id} needs one value type`
|
|
347
|
+
});
|
|
348
|
+
return Result.flatMap(projectNode({
|
|
349
|
+
...input,
|
|
350
|
+
node: parameter
|
|
351
|
+
}), (value) => {
|
|
352
|
+
if (effectKind === "option") return Result.succeed({
|
|
353
|
+
kind: "option",
|
|
354
|
+
value
|
|
355
|
+
});
|
|
356
|
+
if (effectKind === "redacted") {
|
|
357
|
+
const payload = node.representation?.payload;
|
|
358
|
+
const label = payload !== null && typeof payload === "object" && "label" in payload ? payload["label"] : void 0;
|
|
359
|
+
if (label !== void 0 && typeof label !== "string") return failUnsupported({
|
|
360
|
+
path,
|
|
361
|
+
reason: "a Redacted label must be a string"
|
|
362
|
+
});
|
|
363
|
+
return Result.succeed({
|
|
364
|
+
kind: "redacted",
|
|
365
|
+
value,
|
|
366
|
+
...label === void 0 ? {} : { label }
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
return Result.map(toScalar(value, path), (item) => {
|
|
370
|
+
return {
|
|
371
|
+
kind: "array",
|
|
372
|
+
collection: effectKind === "chunk" || effectKind === "hash-set" ? effectKind : "set",
|
|
373
|
+
item
|
|
374
|
+
};
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
return failUnsupported({
|
|
379
|
+
path,
|
|
380
|
+
reason: `the declaration ${id ?? "without a representation identity"} has no URL spelling`
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
function projectRecord(input) {
|
|
384
|
+
const key = projectNode({
|
|
385
|
+
...input,
|
|
386
|
+
node: input.key
|
|
387
|
+
});
|
|
388
|
+
if (Result.isFailure(key)) return key;
|
|
389
|
+
if (key.success.kind !== "scalar" || key.success.type !== "string" || key.success.nullable || key.success.optional) return failUnsupported({
|
|
390
|
+
path: input.path,
|
|
391
|
+
reason: "record and map keys must be strings or string enums"
|
|
392
|
+
});
|
|
393
|
+
const keyShape = key.success;
|
|
394
|
+
return Result.map(projectNode({
|
|
395
|
+
...input,
|
|
396
|
+
node: input.value,
|
|
397
|
+
path: `${input.path}.*`
|
|
398
|
+
}), (value) => {
|
|
399
|
+
return {
|
|
400
|
+
kind: "record",
|
|
401
|
+
collection: input.collection,
|
|
402
|
+
key: keyShape,
|
|
403
|
+
value
|
|
404
|
+
};
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
function toScalar(shape, path) {
|
|
408
|
+
return shape.kind === "scalar" ? Result.succeed(shape) : failUnsupported({
|
|
409
|
+
path,
|
|
410
|
+
reason: "array and set items must have one scalar URL spelling"
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
function failUnsupported(input) {
|
|
414
|
+
return Result.fail({
|
|
415
|
+
_tag: "UnsupportedSearchSchema",
|
|
416
|
+
...input
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region src/server/graph/transport-schema.ts
|
|
421
|
+
/** The representation identities of the declarations the transport carries by value. */
|
|
422
|
+
const VOCABULARY_REPRESENTATION_IDS = /* @__PURE__ */ new Set([
|
|
423
|
+
"effect/schema/Date",
|
|
424
|
+
"effect/schema/URL",
|
|
425
|
+
"effect/schema/URLSearchParams",
|
|
426
|
+
"effect/schema/RegExp"
|
|
427
|
+
]);
|
|
428
|
+
/** Declarations whose type parameters are the member types the transport walks. */
|
|
429
|
+
const COLLECTION_REPRESENTATION_IDS = /* @__PURE__ */ new Set(["effect/schema/ReadonlyMap", "effect/schema/ReadonlySet"]);
|
|
430
|
+
const EFFECT_TRANSPORT_REPRESENTATION_IDS = new Set(EFFECT_TRANSPORT_TYPES.map((type) => type.representationId));
|
|
431
|
+
function checkTransportSchema$1(input) {
|
|
432
|
+
const root = SchemaAST.toType(input.schema.ast);
|
|
433
|
+
const pending = input.allowClassRoot && root._tag === "Declaration" ? root.typeParameters.map((ast) => {
|
|
434
|
+
return {
|
|
435
|
+
ast,
|
|
436
|
+
path: ""
|
|
437
|
+
};
|
|
438
|
+
}) : [{
|
|
439
|
+
ast: root,
|
|
440
|
+
path: ""
|
|
441
|
+
}];
|
|
442
|
+
const visited = /* @__PURE__ */ new Set();
|
|
443
|
+
for (let next = pending.pop(); next !== void 0; next = pending.pop()) {
|
|
444
|
+
const { ast, path } = next;
|
|
445
|
+
if (visited.has(ast)) continue;
|
|
446
|
+
visited.add(ast);
|
|
447
|
+
switch (ast._tag) {
|
|
448
|
+
case "Null":
|
|
449
|
+
case "Undefined":
|
|
450
|
+
case "Void":
|
|
451
|
+
case "String":
|
|
452
|
+
case "Number":
|
|
453
|
+
case "Boolean":
|
|
454
|
+
case "BigInt":
|
|
455
|
+
case "Literal":
|
|
456
|
+
case "Enum":
|
|
457
|
+
case "TemplateLiteral":
|
|
458
|
+
case "Never": break;
|
|
459
|
+
case "Declaration": {
|
|
460
|
+
const id = readRepresentationId(ast);
|
|
461
|
+
if (id !== void 0 && EFFECT_TRANSPORT_REPRESENTATION_IDS.has(id)) {
|
|
462
|
+
for (const parameter of ast.typeParameters) pending.push({
|
|
463
|
+
ast: parameter,
|
|
464
|
+
path
|
|
465
|
+
});
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
468
|
+
if (id !== void 0 && VOCABULARY_REPRESENTATION_IDS.has(id)) break;
|
|
469
|
+
if (id !== void 0 && COLLECTION_REPRESENTATION_IDS.has(id)) {
|
|
470
|
+
for (const parameter of ast.typeParameters) pending.push({
|
|
471
|
+
ast: parameter,
|
|
472
|
+
path
|
|
473
|
+
});
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
return refuseAt(path, "a class or an opaque declaration has no wire form; declare the value's structure");
|
|
477
|
+
}
|
|
478
|
+
case "Suspend":
|
|
479
|
+
pending.push({
|
|
480
|
+
ast: ast.thunk(),
|
|
481
|
+
path
|
|
482
|
+
});
|
|
483
|
+
break;
|
|
484
|
+
case "Union":
|
|
485
|
+
for (const member of ast.types) pending.push({
|
|
486
|
+
ast: member,
|
|
487
|
+
path
|
|
488
|
+
});
|
|
489
|
+
break;
|
|
490
|
+
case "Arrays":
|
|
491
|
+
for (const [index, element] of ast.elements.entries()) pending.push({
|
|
492
|
+
ast: element,
|
|
493
|
+
path: `${path}[${index}]`
|
|
494
|
+
});
|
|
495
|
+
for (const rest of ast.rest) pending.push({
|
|
496
|
+
ast: rest,
|
|
497
|
+
path: `${path}[]`
|
|
498
|
+
});
|
|
499
|
+
break;
|
|
500
|
+
case "Objects":
|
|
501
|
+
for (const property of ast.propertySignatures) {
|
|
502
|
+
if (typeof property.name === "symbol") return refuseAt(path, "a symbol-keyed property has no wire form");
|
|
503
|
+
const name = String(property.name);
|
|
504
|
+
pending.push({
|
|
505
|
+
ast: property.type,
|
|
506
|
+
path: path === "" ? name : `${path}.${name}`
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
for (const signature of ast.indexSignatures) {
|
|
510
|
+
if (!matchesStringKey(signature.parameter)) return refuseAt(path, "an index signature must be keyed by strings");
|
|
511
|
+
pending.push({
|
|
512
|
+
ast: signature.type,
|
|
513
|
+
path: `${path}[*]`
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
break;
|
|
517
|
+
case "Unknown":
|
|
518
|
+
case "Any":
|
|
519
|
+
case "ObjectKeyword":
|
|
520
|
+
case "Symbol":
|
|
521
|
+
case "UniqueSymbol": return refuseAt(path, `${ast._tag} leaves the value's structure open; declare it`);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return Result.succeed(void 0);
|
|
525
|
+
}
|
|
526
|
+
function refuseAt(path, reason) {
|
|
527
|
+
return Result.fail({
|
|
528
|
+
_tag: "UntransportableSchema",
|
|
529
|
+
path,
|
|
530
|
+
reason
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
function matchesStringKey(ast) {
|
|
534
|
+
return ast._tag === "String" || ast._tag === "TemplateLiteral" || ast._tag === "Literal" && typeof ast.literal === "string";
|
|
535
|
+
}
|
|
536
|
+
function readRepresentationId(ast) {
|
|
537
|
+
const representation = ast.annotations?.["representation"];
|
|
538
|
+
return typeof representation === "object" && representation !== null && "id" in representation && typeof representation.id === "string" ? representation.id : void 0;
|
|
539
|
+
}
|
|
540
|
+
//#endregion
|
|
541
|
+
//#region src/server/graph/compile.ts
|
|
542
|
+
function compileUiLoader(declaration, errors) {
|
|
543
|
+
const registered = compileUiPattern(declaration.pattern);
|
|
544
|
+
if (Result.isFailure(registered)) {
|
|
545
|
+
errors.push({
|
|
546
|
+
_tag: "InvalidPattern",
|
|
547
|
+
role: "uiLoader",
|
|
548
|
+
pattern: declaration.pattern,
|
|
549
|
+
cause: registered.failure
|
|
550
|
+
});
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
let search = null;
|
|
554
|
+
if (declaration.input !== void 0) {
|
|
555
|
+
const derived = deriveSearchContract(declaration.input);
|
|
556
|
+
if (Result.isFailure(derived)) errors.push({
|
|
557
|
+
_tag: "UnsupportedSearchSchema",
|
|
558
|
+
role: "uiLoader",
|
|
559
|
+
pattern: declaration.pattern,
|
|
560
|
+
path: derived.failure.path,
|
|
561
|
+
reason: derived.failure.reason
|
|
562
|
+
});
|
|
563
|
+
else search = {
|
|
564
|
+
schema: declaration.input,
|
|
565
|
+
...derived.success
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
checkTransportSchema({
|
|
569
|
+
schema: declaration.output,
|
|
570
|
+
role: "uiLoader",
|
|
571
|
+
pattern: declaration.pattern,
|
|
572
|
+
field: "output",
|
|
573
|
+
errors
|
|
574
|
+
});
|
|
575
|
+
return {
|
|
576
|
+
declaration,
|
|
577
|
+
registered: registered.success,
|
|
578
|
+
search
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
function compileEndpoint(declaration, errors) {
|
|
582
|
+
if (!(declaration.kind === "stream" ? declaration.method === "GET" : matchesHttpMethod(declaration.method))) {
|
|
583
|
+
errors.push({
|
|
584
|
+
_tag: "InvalidEndpointMethod",
|
|
585
|
+
pattern: declaration.pattern,
|
|
586
|
+
method: String(declaration.method),
|
|
587
|
+
kind: declaration.kind
|
|
588
|
+
});
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
const registered = compileEndpointPattern(declaration.pattern);
|
|
592
|
+
if (Result.isFailure(registered)) {
|
|
593
|
+
errors.push({
|
|
594
|
+
_tag: "InvalidPattern",
|
|
595
|
+
role: "endpoint",
|
|
596
|
+
pattern: declaration.pattern,
|
|
597
|
+
cause: registered.failure
|
|
598
|
+
});
|
|
599
|
+
return null;
|
|
600
|
+
}
|
|
601
|
+
const transport = getInputTransport(declaration);
|
|
602
|
+
if (transport.kind === "json") checkTransportSchema({
|
|
603
|
+
schema: transport.schema,
|
|
604
|
+
role: "endpoint",
|
|
605
|
+
pattern: declaration.pattern,
|
|
606
|
+
field: "input",
|
|
607
|
+
errors
|
|
608
|
+
});
|
|
609
|
+
if (declaration.output !== void 0) checkTransportSchema({
|
|
610
|
+
schema: declaration.output,
|
|
611
|
+
role: "endpoint",
|
|
612
|
+
pattern: declaration.pattern,
|
|
613
|
+
field: "output",
|
|
614
|
+
errors
|
|
615
|
+
});
|
|
616
|
+
if (declaration.event !== void 0) checkTransportSchema({
|
|
617
|
+
schema: declaration.event,
|
|
618
|
+
role: "endpoint",
|
|
619
|
+
pattern: declaration.pattern,
|
|
620
|
+
field: "event",
|
|
621
|
+
errors
|
|
622
|
+
});
|
|
623
|
+
checkEndpointErrors(declaration, errors);
|
|
624
|
+
let search = null;
|
|
625
|
+
if (declaration.method === "GET" && declaration.input !== void 0) {
|
|
626
|
+
const derived = deriveSearchContract(declaration.input);
|
|
627
|
+
if (Result.isFailure(derived)) errors.push({
|
|
628
|
+
_tag: "UnsupportedSearchSchema",
|
|
629
|
+
role: "endpoint",
|
|
630
|
+
pattern: declaration.pattern,
|
|
631
|
+
path: derived.failure.path,
|
|
632
|
+
reason: derived.failure.reason
|
|
633
|
+
});
|
|
634
|
+
else search = {
|
|
635
|
+
schema: declaration.input,
|
|
636
|
+
document: derived.success.document
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
return {
|
|
640
|
+
declaration,
|
|
641
|
+
registered: registered.success,
|
|
642
|
+
search
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
function compileMiddleware(declaration, index, errors) {
|
|
646
|
+
let ok = true;
|
|
647
|
+
if (declaration.patterns.length === 0) {
|
|
648
|
+
errors.push({
|
|
649
|
+
_tag: "EmptyMiddlewareSelector",
|
|
650
|
+
index,
|
|
651
|
+
field: "patterns"
|
|
652
|
+
});
|
|
653
|
+
ok = false;
|
|
654
|
+
}
|
|
655
|
+
if (declaration.methods.length === 0) {
|
|
656
|
+
errors.push({
|
|
657
|
+
_tag: "EmptyMiddlewareSelector",
|
|
658
|
+
index,
|
|
659
|
+
field: "methods"
|
|
660
|
+
});
|
|
661
|
+
ok = false;
|
|
662
|
+
}
|
|
663
|
+
const registered = [];
|
|
664
|
+
const patternIdentities = [];
|
|
665
|
+
for (const pattern of declaration.patterns) {
|
|
666
|
+
const result = compileEndpointPattern(pattern);
|
|
667
|
+
if (Result.isFailure(result)) {
|
|
668
|
+
errors.push({
|
|
669
|
+
_tag: "InvalidPattern",
|
|
670
|
+
role: "middleware",
|
|
671
|
+
pattern,
|
|
672
|
+
cause: result.failure
|
|
673
|
+
});
|
|
674
|
+
ok = false;
|
|
675
|
+
} else {
|
|
676
|
+
registered.push(result.success);
|
|
677
|
+
patternIdentities.push({
|
|
678
|
+
authoredPattern: pattern,
|
|
679
|
+
registered: result.success
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
for (const conflict of findFlatPatternRegistrationConflicts(patternIdentities)) {
|
|
684
|
+
errors.push({
|
|
685
|
+
_tag: "ConflictingMiddlewareParameters",
|
|
686
|
+
index,
|
|
687
|
+
patterns: conflict.patterns,
|
|
688
|
+
cause: conflict.cause
|
|
689
|
+
});
|
|
690
|
+
ok = false;
|
|
691
|
+
}
|
|
692
|
+
return ok ? {
|
|
693
|
+
declaration,
|
|
694
|
+
registered
|
|
695
|
+
} : null;
|
|
696
|
+
}
|
|
697
|
+
/** Groups endpoint nodes by method, preserving declaration order within each method. */
|
|
698
|
+
function groupEndpointsByMethod(endpoints) {
|
|
699
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
700
|
+
for (const endpoint of endpoints) {
|
|
701
|
+
const method = endpoint.declaration.method;
|
|
702
|
+
const entries = grouped.get(method);
|
|
703
|
+
if (entries === void 0) grouped.set(method, [endpoint]);
|
|
704
|
+
else entries.push(endpoint);
|
|
705
|
+
}
|
|
706
|
+
return grouped;
|
|
707
|
+
}
|
|
708
|
+
function checkEndpointPatternRegistrations(endpoints, errors) {
|
|
709
|
+
for (const [method, entries] of groupEndpointsByMethod(endpoints)) {
|
|
710
|
+
const conflicts = findFlatPatternRegistrationConflicts(entries.map((entry) => {
|
|
711
|
+
return {
|
|
712
|
+
authoredPattern: entry.declaration.pattern,
|
|
713
|
+
registered: entry.registered
|
|
714
|
+
};
|
|
715
|
+
}));
|
|
716
|
+
for (const conflict of conflicts) errors.push({
|
|
717
|
+
_tag: "ConflictingEndpointParameters",
|
|
718
|
+
method,
|
|
719
|
+
patterns: conflict.patterns,
|
|
720
|
+
cause: conflict.cause
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
function findFlatPatternRegistrationConflicts(patterns) {
|
|
725
|
+
return findConflictingDynamicParameterNames({
|
|
726
|
+
patterns,
|
|
727
|
+
getMatcherPattern: (pattern) => pattern.registered.pattern,
|
|
728
|
+
getSegments: (pattern) => pattern.registered.segments,
|
|
729
|
+
makeCause: ({ conflict, attemptedPattern }) => {
|
|
730
|
+
return {
|
|
731
|
+
_tag: "ConflictingDynamicParameterName",
|
|
732
|
+
...conflict,
|
|
733
|
+
pattern: attemptedPattern.authoredPattern
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
}).map((conflict) => {
|
|
737
|
+
return {
|
|
738
|
+
patterns: conflict.patterns.map((pattern) => pattern.authoredPattern),
|
|
739
|
+
cause: conflict.cause
|
|
740
|
+
};
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
/** Materializes each target's registered outer-to-inner route chain in time proportional to route depth. */
|
|
744
|
+
function createNestedRouteChains(input) {
|
|
745
|
+
const branches = /* @__PURE__ */ new Map();
|
|
746
|
+
const exact = new Map(input.nodes.map((node) => [node.registered.pattern, node]));
|
|
747
|
+
for (const node of input.nodes) {
|
|
748
|
+
const terminal = node.registered.segments.at(-1)?.kind;
|
|
749
|
+
if (terminal !== "index" && terminal !== "splat") branches.set(getNestedRoutePathKey(node.registered.segments), node);
|
|
750
|
+
}
|
|
751
|
+
return input.nodes.map((target) => {
|
|
752
|
+
const consumingSegments = target.registered.segments.filter((segment) => segment.kind !== "index" && segment.kind !== "splat");
|
|
753
|
+
const chain = [];
|
|
754
|
+
for (let depth = 0; depth <= consumingSegments.length; depth++) {
|
|
755
|
+
const branch = branches.get(getNestedRoutePathKey(consumingSegments.slice(0, depth)));
|
|
756
|
+
if (branch !== void 0) chain.push(branch);
|
|
757
|
+
}
|
|
758
|
+
const terminal = target.registered.segments.at(-1)?.kind;
|
|
759
|
+
if (terminal === "index" || terminal === "splat") {
|
|
760
|
+
const leaf = exact.get(target.registered.pattern);
|
|
761
|
+
if (leaf !== void 0) chain.push(leaf);
|
|
762
|
+
}
|
|
763
|
+
return {
|
|
764
|
+
target,
|
|
765
|
+
chain
|
|
766
|
+
};
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
function getNestedRoutePathKey(segments) {
|
|
770
|
+
return JSON.stringify(segments.map((segment) => {
|
|
771
|
+
return segment.kind === "static" ? ["static", segment.value] : segment.kind === "dynamic" ? ["dynamic", segment.parameterName] : [segment.kind];
|
|
772
|
+
}));
|
|
773
|
+
}
|
|
774
|
+
function checkDuplicates(uiLoaders, endpoints, errors) {
|
|
775
|
+
reportDuplicateRegistrations({
|
|
776
|
+
nodes: uiLoaders,
|
|
777
|
+
readKeyFn: (node) => node.registered.pattern,
|
|
778
|
+
makeErrorFn: (node) => {
|
|
779
|
+
return {
|
|
780
|
+
_tag: "DuplicateUiLoader",
|
|
781
|
+
pattern: node.declaration.pattern
|
|
782
|
+
};
|
|
783
|
+
},
|
|
784
|
+
errors
|
|
785
|
+
});
|
|
786
|
+
reportDuplicateRegistrations({
|
|
787
|
+
nodes: endpoints,
|
|
788
|
+
readKeyFn: (node) => {
|
|
789
|
+
return `${node.declaration.method} ${node.registered.pattern}`;
|
|
790
|
+
},
|
|
791
|
+
makeErrorFn: (node) => {
|
|
792
|
+
return {
|
|
793
|
+
_tag: "DuplicateEndpoint",
|
|
794
|
+
method: node.declaration.method,
|
|
795
|
+
pattern: node.declaration.pattern
|
|
796
|
+
};
|
|
797
|
+
},
|
|
798
|
+
errors
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
function reportDuplicateRegistrations(input) {
|
|
802
|
+
const seen = /* @__PURE__ */ new Set();
|
|
803
|
+
for (const node of input.nodes) {
|
|
804
|
+
const key = input.readKeyFn(node);
|
|
805
|
+
if (seen.has(key)) input.errors.push(input.makeErrorFn(node));
|
|
806
|
+
seen.add(key);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
/** Declared error entries need transport structure, a real error status, and distinct usable tags. */
|
|
810
|
+
function checkEndpointErrors(declaration, errors) {
|
|
811
|
+
const tags = /* @__PURE__ */ new Set();
|
|
812
|
+
for (const [index, entry] of declaration.errors.entries()) {
|
|
813
|
+
checkTransportSchema({
|
|
814
|
+
schema: entry.schema,
|
|
815
|
+
role: "endpoint",
|
|
816
|
+
pattern: declaration.pattern,
|
|
817
|
+
field: "errors",
|
|
818
|
+
errors
|
|
819
|
+
});
|
|
820
|
+
if (!Number.isInteger(entry.status) || entry.status < 400 || entry.status > 599) errors.push({
|
|
821
|
+
_tag: "InvalidErrorStatus",
|
|
822
|
+
role: "endpoint",
|
|
823
|
+
pattern: declaration.pattern,
|
|
824
|
+
status: entry.status
|
|
825
|
+
});
|
|
826
|
+
const tag = getLiteralErrorTag(entry.schema);
|
|
827
|
+
if (tag === void 0) {
|
|
828
|
+
errors.push({
|
|
829
|
+
_tag: "ErrorSchemaWithoutLiteralTag",
|
|
830
|
+
role: "endpoint",
|
|
831
|
+
pattern: declaration.pattern,
|
|
832
|
+
index
|
|
833
|
+
});
|
|
834
|
+
continue;
|
|
835
|
+
}
|
|
836
|
+
if (FRAMEWORK_ERROR_TAGS.includes(tag.tag)) errors.push({
|
|
837
|
+
_tag: "FrameworkErrorTagCollision",
|
|
838
|
+
role: "endpoint",
|
|
839
|
+
pattern: declaration.pattern,
|
|
840
|
+
tag: tag.tag
|
|
841
|
+
});
|
|
842
|
+
else if (tags.has(tag.tag)) errors.push({
|
|
843
|
+
_tag: "DuplicateErrorTag",
|
|
844
|
+
role: "endpoint",
|
|
845
|
+
pattern: declaration.pattern,
|
|
846
|
+
tag: tag.tag
|
|
847
|
+
});
|
|
848
|
+
else tags.add(tag.tag);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
/** A contract crosses the wire by value, so its decoded side must be JSON plus the transport's vocabulary; an error's class root travels as its fields. */
|
|
852
|
+
function checkTransportSchema(input) {
|
|
853
|
+
const checked = checkTransportSchema$1({
|
|
854
|
+
schema: input.schema,
|
|
855
|
+
allowClassRoot: input.field === "errors"
|
|
856
|
+
});
|
|
857
|
+
if (Result.isFailure(checked)) {
|
|
858
|
+
input.errors.push({
|
|
859
|
+
_tag: "UntransportableSchema",
|
|
860
|
+
role: input.role,
|
|
861
|
+
pattern: input.pattern,
|
|
862
|
+
field: input.field,
|
|
863
|
+
path: checked.failure.path,
|
|
864
|
+
reason: checked.failure.reason
|
|
865
|
+
});
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
//#endregion
|
|
870
|
+
export { compileUiLoader as a, findConflictingDynamicParameterNames as c, FormData as d, matchesHttpMethod as f, compileMiddleware as i, getLiteralErrorTag as l, checkEndpointPatternRegistrations as n, createNestedRouteChains as o, compileEndpoint as r, groupEndpointsByMethod as s, checkDuplicates as t, getInputTransport as u };
|