Skip to content

Commit

Permalink
reduce config selection via defaults if needed
Browse files Browse the repository at this point in the history
  • Loading branch information
sparecycles committed Jan 2, 2025
1 parent f3aaba9 commit 2fbc30b
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 10 deletions.
8 changes: 3 additions & 5 deletions packages/core/src/config/collection-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ governing permissions and limitations under the License.
*/
import { type HttpsSteps } from "../core/formats/https-fmt.js";
import { EncodingTypes } from "../core/request/body-template.js";
import { type ConfigMapping } from "../core/schema/core/config-space.js";

export type Config = Record<string, string | ConfigMapping>;
import { type ConfigMap } from "../core/schema/core/config-space.js";

export type Helper = {
config: string;
Expand All @@ -28,8 +26,8 @@ export type AssetParseError = { path: string; error: any };
export type Configuration = {
name: string;
path: string;
config?: Config;
defaults?: Record<string, string | ConfigMapping>;
config?: ConfigMap;
defaults?: ConfigMap;
mixin?: string | string[];
import?: ConfigurationImports;
export?: string;
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/core/endpoint-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export function createEndpointEnvironment({
const environment = new ScriptEnvironment({
name: endpoint.configuration.name,
config: endpoint.configuration.config,
defaults: endpoint.configuration.defaults,
input: values,
runtime: {
false: false,
Expand Down
43 changes: 39 additions & 4 deletions packages/core/src/core/schema/core/config-space.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,24 @@ import {
import { arrayIntoObject, mapObject } from "../../../util/mapping.js";
import { uniqReducer } from "../../../util/uniq-reducer.js";

export type ConfigMap = Record<string, ConfigMapping>;

export type ConfigMapping =
| string
| {
[key: string]: Record<string, ConfigMapping>;
[key: string]: ConfigMap;
};

export class ConfigSpace {
options: Record<string, string>[];
possibilities: Record<string, string>[];
mapping: Record<string, ConfigMapping>;
mapping: ConfigMap;
defaults: ConfigMap;
chosen: Record<string, string> = {};

constructor(mapping: Record<string, ConfigMapping>) {
constructor(mapping: ConfigMap, defaults?: ConfigMap) {
this.options = enumerateConfigs((this.mapping = mapping));
this.defaults = defaults ?? {};

this.possibilities = this.options.slice();
}
Expand All @@ -43,6 +48,7 @@ export class ConfigSpace {
}

choose(config: Record<string, unknown>) {
Object.assign(this.chosen, config);
this.possibilities = this.possibilities.filter((possibility) =>
compatible(possibility, config),
);
Expand Down Expand Up @@ -184,14 +190,29 @@ export class ConfigSpace {

// reduce alternatives down to those that are compatible with the
// current possibilities and don't override any data in the natural interpretation.
const selected = alternatives.filter(
let selected = alternatives.filter(
({ option }) =>
compatible(option, compatibleNature) &&
this.possibilities.some((possibility) =>
compatible({ ...option, ...compatibleNature }, possibility),
),
);

if (selected.length > 1) {
const inferred = {
...this.chosen,
...implied(...selected.map(({ option }) => option)),
};

selected = selected.filter(({ option }) =>
Object.entries(option).every(
([k, v]) =>
inferred[k] ??
(resolveDefault(this.defaults[k], inferred) ?? v) == v,
),
);
}

// rewrite any other mappings from the natural interpretation to the selected one.
const rewritten = other.flatMap((pattern) =>
naturally.flatMap(({ pattern: from }) =>
Expand Down Expand Up @@ -418,3 +439,17 @@ function related(keys: string[], options: Record<string, string>[]) {

return keys;
}

function resolveDefault(
defaulted: ConfigMapping,
values: Record<string, string>,
): string | undefined {
while (defaulted !== undefined) {
if (typeof defaulted === "string") {
return defaulted;
}

const [k, v] = Object.entries(defaulted)[0];
defaulted = v[values[k] ?? "default"];
}
}
4 changes: 3 additions & 1 deletion packages/core/src/core/schema/core/script-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class ScriptEnvironment implements SchemaScriptEnvironment {
constructor({
name,
config,
defaults,
input,
runtime,
resolve,
Expand All @@ -86,6 +87,7 @@ export class ScriptEnvironment implements SchemaScriptEnvironment {
}: {
name?: string;
config?: Record<string, ConfigMapping>;
defaults?: Record<string, ConfigMapping>;
input?: Record<string, unknown>;
runtime?: Record<string, unknown>;
resolve?: ScriptDataResolver;
Expand All @@ -97,7 +99,7 @@ export class ScriptEnvironment implements SchemaScriptEnvironment {
} = {}) {
this.name = () => name;
this.input = input ?? {};
this.space = new ConfigSpace(config ?? {});
this.space = new ConfigSpace(config ?? {}, defaults);
this.space.choose(input ?? {});

this.resolver = (identifier, context) => {
Expand Down

0 comments on commit 2fbc30b

Please sign in to comment.