Page MenuHomeSealhub

No OneTemporary

diff --git a/src/component-arguments/structured.test.ts b/src/component-arguments/structured.test.ts
index b4e1122..251aa33 100644
--- a/src/component-arguments/structured.test.ts
+++ b/src/component-arguments/structured.test.ts
@@ -1,37 +1,57 @@
+import { FileManager } from "@sealcode/file-manager";
+import { makeSimpleEnglishJDDContext } from "../jdd-context.js";
import { ExtractParsed } from "./component-argument.js";
import { List } from "./list.js";
import { ShortText } from "./short-text.js";
import { Structured } from "./structured.js";
+import assert from "assert";
describe("structured argument", () => {
it("properly extracts parsed type", () => {
const args = new Structured({
value: new ShortText().setExampleValues([""]),
tags: new List(new ShortText()).setExampleValues([["okazja"]]),
});
const values = {
value: "test",
tags: ["tag1", "tag2"],
} as ExtractParsed<typeof args>;
values.tags.map((tag) => tag.padStart(10)); // if the types are OK, this will typecheck OK
});
it("properly extracts parsed type within a list", () => {
const arg = new List(
new Structured({
value: new ShortText().setExampleValues([""]),
tags: new List(new ShortText()).setExampleValues([["okazja"]]),
})
);
const values = [
{
value: "test",
tags: ["tag1", "tag2"],
},
] as ExtractParsed<typeof arg>;
values[0].tags.map((tag) => tag.padStart(10)); // if the types are OK, this will typecheck OK
});
+
+ it("uses the provided object as an example value if set", () => {
+ const arg = new Structured({
+ value: new ShortText().setExampleValues([""]),
+ tags: new List(new ShortText()).setExampleValues([["okazja"]]),
+ }).setExampleValues([{ value: "override", tags: ["override"] }]);
+
+ const example_value = arg.getExampleValue(
+ makeSimpleEnglishJDDContext(
+ new FileManager("/tmp", "/uploaded_files")
+ )
+ );
+ assert.deepStrictEqual(example_value, {
+ value: "override",
+ tags: ["override"],
+ });
+ });
});
diff --git a/src/component-arguments/structured.ts b/src/component-arguments/structured.ts
index 75d5de5..03517d3 100644
--- a/src/component-arguments/structured.ts
+++ b/src/component-arguments/structured.ts
@@ -1,147 +1,152 @@
import { is, predicates } from "@sealcode/ts-predicates";
import { JDDContext } from "../index.js";
import {
ComponentArgument,
ExtractParsed,
ExtractStorage,
} from "./component-argument.js";
import { ContainerArgument } from "./container-argument.js";
export class Structured<
T extends Record<string, ComponentArgument<unknown>>
> extends ContainerArgument<
{
[property in keyof T]: ExtractParsed<T[property]>;
},
{
[property in keyof T]: ExtractStorage<T[property]>;
}
> {
constructor(public structure: T) {
super();
Object.values(structure).forEach((arg) => (arg.parent_argument = this));
}
getTypeName() {
return "structured";
}
getSubArgument(
[key, ...rest]: string[],
value: {
[property in keyof T]: ExtractParsed<T[property]>;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): readonly [ComponentArgument<any> | null, string[], unknown] {
return <const>[this.structure[key] || null, rest, value[key]];
}
countWords(value: {
[property in keyof T]: ExtractParsed<T[property]>;
}): number {
return Object.entries(value).reduce((acc, [key, val]) => {
if (!this.structure[key]) {
console.warn(`Key ${key} doesn't exist in structured argument`);
return acc + 0;
}
return acc + this.structure[key].countWords(val);
}, 0);
}
async getEmptyValue(context: JDDContext): Promise<{
[property in keyof T]: ExtractParsed<T[property]>;
}> {
return Object.fromEntries(
await Promise.all(
Object.entries(this.structure).map(async ([name, arg]) => [
name,
await arg.getEmptyValue(context),
])
)
) as {
[property in keyof T]: ExtractParsed<T[property]>;
};
}
async getExampleValue(context: JDDContext) {
+ if (this.example_values.length) {
+ return super.getExampleValue(context) as {
+ [property in keyof T]: ExtractParsed<T[property]>;
+ };
+ }
return Object.fromEntries(
await Promise.all(
Object.entries(this.structure).map(async ([name, arg]) => [
name,
await arg.getExampleValue(context),
])
)
) as {
[property in keyof T]: ExtractParsed<T[property]>;
};
}
async processAllSubarguments<
SingleObject extends {
[property in keyof T]: ExtractParsed<T[property]>;
}
>(
_context: JDDContext,
input: unknown,
processing_function: (
argument: ComponentArgument<unknown>,
value: unknown
) => Promise<unknown>
): Promise<SingleObject | SingleObject[] | null> {
if (!is(input, predicates.object)) {
throw new Error(`Not an object: ${input as string}`);
}
const result: Record<string, unknown> = {};
await Promise.all(
Object.entries(input).map(async ([obj_key, obj_value]) => {
const nested_arg_type: ComponentArgument<unknown> =
this.structure[obj_key];
if (!nested_arg_type) {
return [obj_key, null];
}
const new_value = await processing_function(
nested_arg_type,
obj_value
);
result[obj_key] = new_value;
})
);
// if we're in a list and any of the values return an array, we will multiply the object
if (this.hasParent("list")) {
const keys_with_unexpected_arrays = Object.entries(result)
.filter(([key, value]) => {
const nested_arg_type: ComponentArgument<unknown> =
this.structure[key];
return (
nested_arg_type.getTypeName() !== "list" &&
Array.isArray(value)
);
})
.map(([key]) => key);
if (keys_with_unexpected_arrays.length > 1) {
throw new Error(
"Multiplying on more than one field at the same time is not implemented yet"
);
}
if (keys_with_unexpected_arrays.length == 1) {
const key = keys_with_unexpected_arrays[0];
const old_result = result;
const array = old_result[key];
if (!Array.isArray(array)) {
throw new Error("expected an array");
}
return array.map((value: unknown) => ({
...old_result,
[key]: value,
})) as SingleObject[];
} else {
return result as SingleObject;
}
} else {
return result as SingleObject;
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Dec 23, 11:45 (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
556263
Default Alt Text
(6 KB)

Event Timeline