Skip to content

Commit

Permalink
cleanup and no more circular source references
Browse files Browse the repository at this point in the history
  • Loading branch information
sparecycles committed Jan 3, 2025
1 parent 2fbc30b commit ea1de2e
Show file tree
Hide file tree
Showing 30 changed files with 300 additions and 290 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/core/app-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export async function createPardonApplicationContext(
const {
rc: {
collections,
samples: samples,
samples,
example,
database: databaseLocation = "./pardon.db",
},
Expand Down
67 changes: 48 additions & 19 deletions packages/core/src/core/request/body-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/

import { jsonSchemaTransform, syncEvaluation } from "../expression.js";
import { JSON } from "../json.js";
import { Schematic, Template } from "../schema/core/types.js";
import { datums } from "../schema/definition/datum.js";
import { base64Encoding } from "../schema/definition/encodings/base64-encoding.js";
import { jsonEncoding } from "../schema/definition/encodings/json-encoding.js";
import {
encodingTemplate,
EncodingType,
} from "../schema/definition/encodings/encoding.js";
import { textTemplate } from "../schema/definition/encodings/text-encoding.js";
import { urlEncodedFormTemplate } from "../schema/definition/encodings/url-encoded.js";
import { createNumber } from "../schema/definition/scalar.js";
Expand All @@ -29,6 +32,7 @@ import {
mixTemplate,
matchTemplate,
} from "../schema/scheming.js";
import { evalTemplate } from "./eval-template.js";

const encodings = {
json(value: unknown | Template<unknown>) {
Expand Down Expand Up @@ -75,25 +79,50 @@ export const bodyGlobals: Record<string, any> = {
},
};

export function evalTemplate(schemaSource: string): Schematic<unknown> {
return syncEvaluation(`${schemaSource}`, {
binding(name) {
if (name in bodyGlobals) {
return bodyGlobals[name];
}

if (name.startsWith("$")) {
const ref = name.slice(1);

return referenceTemplate({ ref });
}

return undefined;
},
transform: jsonSchemaTransform,
}) as Schematic<unknown>;
export function evalBodyTemplate(source: string) {
return evalTemplate(source, bodyGlobals);
}

export function getContentEncoding(encoding: EncodingTypes) {
return encodings[encoding]!;
}

export function jsonEncoding(template?: Template<unknown>): Schematic<string> {
return encodingTemplate(jsonEncodingType, template);
}

export const jsonEncodingType: EncodingType<string, unknown> = {
as: "string",
decode({ mode, template }) {
if ((template ?? "") == "") {
return undefined;
}

if (typeof template !== "string") {
throw new Error("json cannot parse non-string");
}

if (mode === "match") {
return JSON.parse(template, (_, value, { source }) => {
if (typeof value === "number") {
return createNumber(source, value);
}

return value;
});
}

return evalBodyTemplate(template);
},
encode(output, context) {
if (output === undefined) {
return undefined;
}

if (context.environment.option("pretty-print")) {
return JSON.stringify(output, null, 2);
}

return JSON.stringify(output, null, 0);
},
};
37 changes: 37 additions & 0 deletions packages/core/src/core/request/eval-template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright 2025 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

import { jsonSchemaTransform, syncEvaluation } from "../expression.js";
import { Schematic } from "../schema/core/types.js";
import { referenceTemplate } from "../schema/definition/structures/reference.js";

export function evalTemplate(
schemaSource: string,
globals: Record<string, unknown>,
): Schematic<unknown> {
return syncEvaluation(`${schemaSource}`, {
binding(name) {
if (name in globals) {
return globals[name];
}

if (name.startsWith("$")) {
const ref = name.slice(1);

return referenceTemplate({ ref });
}

return undefined;
},
transform: jsonSchemaTransform,
}) as Schematic<unknown>;
}
10 changes: 5 additions & 5 deletions packages/core/src/core/request/https-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import MIME from "whatwg-mimetype";
import { jsonEncoding } from "../schema/definition/encodings/json-encoding.js";
import { referenceTemplate } from "../schema/definition/structures/reference.js";
import { FetchObject, ResponseObject } from "./fetch-pattern.js";
import { mixing } from "../schema/template.js";
import {
urlEncodedTemplate,
urlEncodedFormTemplate,
Expand All @@ -37,8 +36,9 @@ import {
executeOp,
merge,
} from "../schema/core/schema-ops.js";
import { EncodingTypes, evalTemplate } from "./body-template.js";
import { EncodingTypes, evalBodyTemplate } from "./body-template.js";
import { JSON } from "../json.js";
import { mixing } from "../schema/core/contexts.js";

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

return merged && bodySchema(encoding, merged);
Expand All @@ -172,7 +172,7 @@ export function bodySchema(
) {
const merged = merge(schema ?? stubSchema(), {
...context,
template: evalTemplate(`json(${source})`),
template: evalBodyTemplate(`json(${source})`),
}) as Schema<string>;
return merged && bodySchema(encoding, merged);
}
Expand All @@ -185,7 +185,7 @@ export function bodySchema(
const effectiveEncoding = encoding ?? "json";
const merged = merge(schema ?? stubSchema(), {
...context,
template: evalTemplate(
template: evalBodyTemplate(
`${effectiveEncoding}(${effectiveEncoding === "json" ? source : JSON.stringify(source)})`,
) as Template<string>,
});
Expand Down
109 changes: 108 additions & 1 deletion packages/core/src/core/schema/core/context-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,37 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/
import { DEBUG } from "./debugging.js";
import { SchemaContext } from "./types.js";
import {
SchemaContext,
SchemaMergingContext,
SchemaRenderContext,
SchemaScope,
} from "./types.js";

export type DereferenceType<
M,
Parameters extends (string | number)[],
> = Parameters extends [
infer H extends string | number,
...infer Rest extends (string | number)[],
]
? H extends keyof M
? DereferenceType<M[H], Rest>
: H extends number
? M extends (infer O)[]
? O
: never
: never
: M;

export type KeyedContext<
C extends SchemaContext,
Parameters extends (string | number)[],
> = C extends SchemaRenderContext
? SchemaRenderContext
: C extends SchemaMergingContext<infer M>
? SchemaMergingContext<DereferenceType<M, Parameters>>
: C;

export function diagnostic(
context: SchemaContext<unknown>,
Expand Down Expand Up @@ -51,3 +81,80 @@ export function isAbstractContext(context: SchemaContext<unknown>) {
(part) => part.endsWith("[]") || part.endsWith("{}"),
);
}

export function keyContext<
C extends SchemaContext | SchemaMergingContext<unknown>,
Parameters extends (string | number)[],
O = KeyedContext<C, Parameters>,
>(context: C, ...keys: Parameters): O {
const template = keys.reduce(
(template, key) => template?.[key],
(context as SchemaMergingContext<unknown>).template,
);

return {
...context,
template,
keys: [...context.keys, ...keys],
} as O;
}

export function elementScopeContext<
C extends SchemaContext,
Key extends number,
O = KeyedContext<C, [Key]>,
>(context: C, key: Key): O {
context = keyContext(context, key === -1 ? "[]" : key) as C;

const subscope = context.scope.subscope(context.keys.join("."), {
context,
type: "element",
key: key === -1 ? undefined : key,
struts: [],
});

return { ...context, scope: subscope, scopes: subscope.path, keys: [] } as O;
}

export function fieldScopeContext<
C extends SchemaContext,
Key extends string | undefined,
O = KeyedContext<C, [Key extends undefined ? string : Key]>,
>(context: C, key: Key): O {
context = keyContext(context, key ?? "{}") as C;

const subscope = context.scope.subscope(context.keys.join("."), {
context,
type: "field",
key,
struts: [],
});

return { ...context, scope: subscope, scopes: subscope.path, keys: [] } as O;
}

export function tempContext<C extends SchemaContext>(context: C): C {
const { scope } = context as SchemaContext;

return { ...context, scope: scope?.tempscope() };
}

export function rescope<T extends SchemaContext>(
context: T,
scope: SchemaScope,
): T {
return {
...context,
scope: scope.rescope(context.scope),
scopes: [...scope.scopePath()],
};
}

export function metaScopeContext<C extends SchemaContext>(
context: C,
meta: string,
): C {
const subscope = context.scope.subscope([...context.keys, meta].join("."));

return { ...context, scope: subscope, scopes: subscope.path, keys: [] } as C;
}
Loading

0 comments on commit ea1de2e

Please sign in to comment.