Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F995647
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
R130 jdd
Attached
Detach File
Event Timeline
Log In to Comment