Skip to content

Commit ea1de2e

Browse files
committed
cleanup and no more circular source references
1 parent 2fbc30b commit ea1de2e

30 files changed

+300
-290
lines changed

packages/core/src/core/app-context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ export async function createPardonApplicationContext(
198198
const {
199199
rc: {
200200
collections,
201-
samples: samples,
201+
samples,
202202
example,
203203
database: databaseLocation = "./pardon.db",
204204
},

packages/core/src/core/request/body-template.ts

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ OF ANY KIND, either express or implied. See the License for the specific languag
1010
governing permissions and limitations under the License.
1111
*/
1212

13-
import { jsonSchemaTransform, syncEvaluation } from "../expression.js";
13+
import { JSON } from "../json.js";
1414
import { Schematic, Template } from "../schema/core/types.js";
1515
import { datums } from "../schema/definition/datum.js";
1616
import { base64Encoding } from "../schema/definition/encodings/base64-encoding.js";
17-
import { jsonEncoding } from "../schema/definition/encodings/json-encoding.js";
17+
import {
18+
encodingTemplate,
19+
EncodingType,
20+
} from "../schema/definition/encodings/encoding.js";
1821
import { textTemplate } from "../schema/definition/encodings/text-encoding.js";
1922
import { urlEncodedFormTemplate } from "../schema/definition/encodings/url-encoded.js";
2023
import { createNumber } from "../schema/definition/scalar.js";
@@ -29,6 +32,7 @@ import {
2932
mixTemplate,
3033
matchTemplate,
3134
} from "../schema/scheming.js";
35+
import { evalTemplate } from "./eval-template.js";
3236

3337
const encodings = {
3438
json(value: unknown | Template<unknown>) {
@@ -75,25 +79,50 @@ export const bodyGlobals: Record<string, any> = {
7579
},
7680
};
7781

78-
export function evalTemplate(schemaSource: string): Schematic<unknown> {
79-
return syncEvaluation(`${schemaSource}`, {
80-
binding(name) {
81-
if (name in bodyGlobals) {
82-
return bodyGlobals[name];
83-
}
84-
85-
if (name.startsWith("$")) {
86-
const ref = name.slice(1);
87-
88-
return referenceTemplate({ ref });
89-
}
90-
91-
return undefined;
92-
},
93-
transform: jsonSchemaTransform,
94-
}) as Schematic<unknown>;
82+
export function evalBodyTemplate(source: string) {
83+
return evalTemplate(source, bodyGlobals);
9584
}
9685

9786
export function getContentEncoding(encoding: EncodingTypes) {
9887
return encodings[encoding]!;
9988
}
89+
90+
export function jsonEncoding(template?: Template<unknown>): Schematic<string> {
91+
return encodingTemplate(jsonEncodingType, template);
92+
}
93+
94+
export const jsonEncodingType: EncodingType<string, unknown> = {
95+
as: "string",
96+
decode({ mode, template }) {
97+
if ((template ?? "") == "") {
98+
return undefined;
99+
}
100+
101+
if (typeof template !== "string") {
102+
throw new Error("json cannot parse non-string");
103+
}
104+
105+
if (mode === "match") {
106+
return JSON.parse(template, (_, value, { source }) => {
107+
if (typeof value === "number") {
108+
return createNumber(source, value);
109+
}
110+
111+
return value;
112+
});
113+
}
114+
115+
return evalBodyTemplate(template);
116+
},
117+
encode(output, context) {
118+
if (output === undefined) {
119+
return undefined;
120+
}
121+
122+
if (context.environment.option("pretty-print")) {
123+
return JSON.stringify(output, null, 2);
124+
}
125+
126+
return JSON.stringify(output, null, 0);
127+
},
128+
};
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
Copyright 2025 Adobe. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
Unless required by applicable law or agreed to in writing, software distributed under
8+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
OF ANY KIND, either express or implied. See the License for the specific language
10+
governing permissions and limitations under the License.
11+
*/
12+
13+
import { jsonSchemaTransform, syncEvaluation } from "../expression.js";
14+
import { Schematic } from "../schema/core/types.js";
15+
import { referenceTemplate } from "../schema/definition/structures/reference.js";
16+
17+
export function evalTemplate(
18+
schemaSource: string,
19+
globals: Record<string, unknown>,
20+
): Schematic<unknown> {
21+
return syncEvaluation(`${schemaSource}`, {
22+
binding(name) {
23+
if (name in globals) {
24+
return globals[name];
25+
}
26+
27+
if (name.startsWith("$")) {
28+
const ref = name.slice(1);
29+
30+
return referenceTemplate({ ref });
31+
}
32+
33+
return undefined;
34+
},
35+
transform: jsonSchemaTransform,
36+
}) as Schematic<unknown>;
37+
}

packages/core/src/core/request/https-template.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import MIME from "whatwg-mimetype";
1313
import { jsonEncoding } from "../schema/definition/encodings/json-encoding.js";
1414
import { referenceTemplate } from "../schema/definition/structures/reference.js";
1515
import { FetchObject, ResponseObject } from "./fetch-pattern.js";
16-
import { mixing } from "../schema/template.js";
1716
import {
1817
urlEncodedTemplate,
1918
urlEncodedFormTemplate,
@@ -37,8 +36,9 @@ import {
3736
executeOp,
3837
merge,
3938
} from "../schema/core/schema-ops.js";
40-
import { EncodingTypes, evalTemplate } from "./body-template.js";
39+
import { EncodingTypes, evalBodyTemplate } from "./body-template.js";
4140
import { JSON } from "../json.js";
41+
import { mixing } from "../schema/core/contexts.js";
4242

4343
function looksLikeJson(template: unknown): template is string {
4444
if (typeof template !== "string") {
@@ -155,7 +155,7 @@ export function bodySchema(
155155
if (/^[a-z]+(?<!^mix|^mux|^match)\s*[(]/i.test(source.trim())) {
156156
const merged = merge(stubSchema(), {
157157
...context,
158-
template: evalTemplate(`${source}`),
158+
template: evalBodyTemplate(`${source}`),
159159
}) as Schema<string>;
160160

161161
return merged && bodySchema(encoding, merged);
@@ -172,7 +172,7 @@ export function bodySchema(
172172
) {
173173
const merged = merge(schema ?? stubSchema(), {
174174
...context,
175-
template: evalTemplate(`json(${source})`),
175+
template: evalBodyTemplate(`json(${source})`),
176176
}) as Schema<string>;
177177
return merged && bodySchema(encoding, merged);
178178
}
@@ -185,7 +185,7 @@ export function bodySchema(
185185
const effectiveEncoding = encoding ?? "json";
186186
const merged = merge(schema ?? stubSchema(), {
187187
...context,
188-
template: evalTemplate(
188+
template: evalBodyTemplate(
189189
`${effectiveEncoding}(${effectiveEncoding === "json" ? source : JSON.stringify(source)})`,
190190
) as Template<string>,
191191
});

packages/core/src/core/schema/core/context-util.ts

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,37 @@ OF ANY KIND, either express or implied. See the License for the specific languag
1010
governing permissions and limitations under the License.
1111
*/
1212
import { DEBUG } from "./debugging.js";
13-
import { SchemaContext } from "./types.js";
13+
import {
14+
SchemaContext,
15+
SchemaMergingContext,
16+
SchemaRenderContext,
17+
SchemaScope,
18+
} from "./types.js";
19+
20+
export type DereferenceType<
21+
M,
22+
Parameters extends (string | number)[],
23+
> = Parameters extends [
24+
infer H extends string | number,
25+
...infer Rest extends (string | number)[],
26+
]
27+
? H extends keyof M
28+
? DereferenceType<M[H], Rest>
29+
: H extends number
30+
? M extends (infer O)[]
31+
? O
32+
: never
33+
: never
34+
: M;
35+
36+
export type KeyedContext<
37+
C extends SchemaContext,
38+
Parameters extends (string | number)[],
39+
> = C extends SchemaRenderContext
40+
? SchemaRenderContext
41+
: C extends SchemaMergingContext<infer M>
42+
? SchemaMergingContext<DereferenceType<M, Parameters>>
43+
: C;
1444

1545
export function diagnostic(
1646
context: SchemaContext<unknown>,
@@ -51,3 +81,80 @@ export function isAbstractContext(context: SchemaContext<unknown>) {
5181
(part) => part.endsWith("[]") || part.endsWith("{}"),
5282
);
5383
}
84+
85+
export function keyContext<
86+
C extends SchemaContext | SchemaMergingContext<unknown>,
87+
Parameters extends (string | number)[],
88+
O = KeyedContext<C, Parameters>,
89+
>(context: C, ...keys: Parameters): O {
90+
const template = keys.reduce(
91+
(template, key) => template?.[key],
92+
(context as SchemaMergingContext<unknown>).template,
93+
);
94+
95+
return {
96+
...context,
97+
template,
98+
keys: [...context.keys, ...keys],
99+
} as O;
100+
}
101+
102+
export function elementScopeContext<
103+
C extends SchemaContext,
104+
Key extends number,
105+
O = KeyedContext<C, [Key]>,
106+
>(context: C, key: Key): O {
107+
context = keyContext(context, key === -1 ? "[]" : key) as C;
108+
109+
const subscope = context.scope.subscope(context.keys.join("."), {
110+
context,
111+
type: "element",
112+
key: key === -1 ? undefined : key,
113+
struts: [],
114+
});
115+
116+
return { ...context, scope: subscope, scopes: subscope.path, keys: [] } as O;
117+
}
118+
119+
export function fieldScopeContext<
120+
C extends SchemaContext,
121+
Key extends string | undefined,
122+
O = KeyedContext<C, [Key extends undefined ? string : Key]>,
123+
>(context: C, key: Key): O {
124+
context = keyContext(context, key ?? "{}") as C;
125+
126+
const subscope = context.scope.subscope(context.keys.join("."), {
127+
context,
128+
type: "field",
129+
key,
130+
struts: [],
131+
});
132+
133+
return { ...context, scope: subscope, scopes: subscope.path, keys: [] } as O;
134+
}
135+
136+
export function tempContext<C extends SchemaContext>(context: C): C {
137+
const { scope } = context as SchemaContext;
138+
139+
return { ...context, scope: scope?.tempscope() };
140+
}
141+
142+
export function rescope<T extends SchemaContext>(
143+
context: T,
144+
scope: SchemaScope,
145+
): T {
146+
return {
147+
...context,
148+
scope: scope.rescope(context.scope),
149+
scopes: [...scope.scopePath()],
150+
};
151+
}
152+
153+
export function metaScopeContext<C extends SchemaContext>(
154+
context: C,
155+
meta: string,
156+
): C {
157+
const subscope = context.scope.subscope([...context.keys, meta].join("."));
158+
159+
return { ...context, scope: subscope, scopes: subscope.path, keys: [] } as C;
160+
}

0 commit comments

Comments
 (0)