Page MenuHomeSealhub

No OneTemporary

diff --git a/src/component-arguments/component-argument.ts b/src/component-arguments/component-argument.ts
index e8beed9..4d3fe7c 100644
--- a/src/component-arguments/component-argument.ts
+++ b/src/component-arguments/component-argument.ts
@@ -1,89 +1,90 @@
-import { JDDContext, List } from "../index.js";
-
-export type ExtractComponentArgumentValue<C> = C extends List<infer S>
- ? S[]
- : C extends ComponentArgument<infer T>
- ? T
- : never;
+import { JDDContext } from "../index.js";
+import { List } from "./list.js";
export type ExtractStructuredComponentArgumentsParsed<C> = {
- [property in keyof C]: ExtractComponentArgumentValue<C[property]>;
+ [property in keyof C]: ExtractParsed<C[property]>;
};
export type ExtractStructuredComponentArgumentsStorage<C> = {
[property in keyof C]: ExtractStorage<C[property]>;
};
export type ExtractStructuredComponentArgumentsReceived<C> = {
[property in keyof C]: ExtractReceived<C[property]>;
};
-export type ExtractParsed<C> = C extends ComponentArgument<infer T> ? T : never;
+export type ExtractParsed<C> = C extends List<infer T>
+ ? T[]
+ : C extends ComponentArgument<infer T2>
+ ? T2
+ : never;
+
export type ExtractStorage<C> = C extends ComponentArgument<infer _, infer T>
? T
: never;
+
export type ExtractReceived<C> = C extends ComponentArgument<
infer _,
infer __,
infer T
>
? T
: never;
export abstract class ComponentArgument<
ParsedType,
StorageType = ParsedType,
ReceivedDataType = StorageType
> {
public example_values: ParsedType[] = [];
public parent_argument: ComponentArgument<unknown> | null = null;
abstract getTypeName(): string;
abstract getEmptyValue(): ParsedType;
abstract countWords(value: ParsedType): number;
abstract getSubArgument(
key: string,
value: ParsedType
): ComponentArgument<unknown> | null;
// Received - what we get on the server side when receiveing the request
// Parsed - the useful form of the value, ready for processing
// Storage - how it's represented when storing in a JSON form
// Formdata - how it's represented when it needs to be sent to the server
abstract receivedToParsed(
context: JDDContext,
value: ReceivedDataType
): Promise<ParsedType | ParsedType[]>;
abstract parsedToStorage(
context: JDDContext,
value: ParsedType
): Promise<StorageType>;
abstract storageToParsed(
context: JDDContext,
value: StorageType
): Promise<ParsedType>;
getExampleValue(_context: JDDContext): Promise<ParsedType> | ParsedType {
return this.example_values[
Math.floor(this.example_values.length * Math.random())
];
}
setExampleValues(values: ParsedType[]): this {
this.example_values = values;
return this;
}
hasParent(type: string) {
let parent = this.parent_argument;
while (parent) {
if (parent.getTypeName() == type) {
return true;
}
parent = parent.parent_argument;
}
return false;
}
}
diff --git a/src/component-arguments/list.test.ts b/src/component-arguments/list.test.ts
index 58d64a3..556f466 100644
--- a/src/component-arguments/list.test.ts
+++ b/src/component-arguments/list.test.ts
@@ -1,8 +1,15 @@
+import { ExtractParsed } from "./component-argument.js";
import { Image } from "./image.js";
import { List } from "./list.js";
describe("list", () => {
it("allows for creating a list of images", () => {
new List(new Image());
});
+
+ it("properly parses list arguments", () => {
+ const images_arg = new List(new Image());
+ const images = [] as ExtractParsed<typeof images_arg>;
+ images.map((e) => e?.file_manager); // if the types are right, this should typecheck OK
+ });
});
diff --git a/src/component-arguments/list.ts b/src/component-arguments/list.ts
index becdcb9..5ed4382 100644
--- a/src/component-arguments/list.ts
+++ b/src/component-arguments/list.ts
@@ -1,94 +1,90 @@
import { is, predicates } from "@sealcode/ts-predicates";
-import { JDDContext } from "../index.js";
import { MaybePromise } from "../utils/util-types.js";
-import { ComponentArgument, ExtractParsed } from "./component-argument.js";
+import { ComponentArgument } from "./component-argument.js";
import { ContainerArgument } from "./container-argument.js";
+import { JDDContext } from "../jdd-context.js";
-export class List<
- T extends ComponentArgument<unknown>
-> extends ContainerArgument<ExtractParsed<T>[], unknown, unknown> {
+export class List<T> extends ContainerArgument<T[], unknown, unknown> {
constructor(
- public item_type: ComponentArgument<ExtractParsed<T>, unknown, unknown>,
+ public item_type: ComponentArgument<T, unknown, unknown>,
public example_count: number | null = null
) {
super();
item_type.parent_argument = this;
}
getTypeName() {
return "list";
}
getEmptyValue() {
return [];
}
getSubArgument(key: string) {
if (isNaN(parseInt(key))) {
return null;
}
return this.item_type;
}
getExampleCount() {
if (this.example_count === null) {
return Math.floor(Math.random() * 5);
} else {
return this.example_count;
}
}
- async getExampleValue(context: JDDContext) {
+ async getExampleValue(context: JDDContext): Promise<T[]> {
if (this.example_values.length) {
return super.getExampleValue(context);
} else {
const count = this.getExampleCount();
- const result = [] as Array<MaybePromise<ExtractParsed<T>>>;
+ const result = [] as Array<MaybePromise<T>>;
for (let i = 0; i < count; i++) {
result.push(
- this.item_type.getExampleValue(context) as Promise<
- ExtractParsed<T>
- >
+ this.item_type.getExampleValue(context) as Promise<T>
);
}
return await Promise.all(result);
}
}
- countWords(value: Array<ExtractParsed<T>>): number {
+ countWords(value: Array<T>): number {
return value.reduce(
(acc, item) => acc + this.item_type.countWords(item),
0
);
}
async processAllSubarguments(
_context: JDDContext,
values: unknown,
processing_function: (
argument: ComponentArgument<unknown>,
value: unknown
) => Promise<unknown>
): Promise<T[] | null> {
if (
!is(values, predicates.array(predicates.object)) &&
!is(values, predicates.object)
) {
throw new Error(`Not a list or object: ${values as string}`);
}
const values_array = Array.isArray(values)
? values
: Object.values(values);
let array_result = (await Promise.all(
values_array.map(async (value) => {
const result = await processing_function(this.item_type, value);
return result;
})
)) as Array<T | T[] | null>;
if (this.item_type.getTypeName() != "list") {
array_result = array_result.flat() as T[];
}
const result = array_result.filter((e) => e !== null) as T[];
return result;
}
}
diff --git a/src/component-arguments/structured.ts b/src/component-arguments/structured.ts
index 58254de..07be295 100644
--- a/src/component-arguments/structured.ts
+++ b/src/component-arguments/structured.ts
@@ -1,137 +1,137 @@
import { is, predicates } from "@sealcode/ts-predicates";
import { JDDContext } from "../index.js";
import {
ComponentArgument,
- ExtractComponentArgumentValue,
+ 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]: ExtractComponentArgumentValue<T[property]>;
+ [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: string) {
return this.structure[key] || null;
}
countWords(value: {
- [property in keyof T]: ExtractComponentArgumentValue<T[property]>;
+ [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);
}
getEmptyValue() {
return Object.fromEntries(
Object.entries(this.structure).map(([name, arg]) => [
name,
arg.getEmptyValue(),
])
) as {
- [property in keyof T]: ExtractComponentArgumentValue<T[property]>;
+ [property in keyof T]: ExtractParsed<T[property]>;
};
}
async getExampleValue(context: JDDContext) {
return Object.fromEntries(
await Promise.all(
Object.entries(this.structure).map(async ([name, arg]) => [
name,
await arg.getExampleValue(context),
])
)
) as {
- [property in keyof T]: ExtractComponentArgumentValue<T[property]>;
+ [property in keyof T]: ExtractParsed<T[property]>;
};
}
async processAllSubarguments<
SingleObject extends {
- [property in keyof T]: ExtractComponentArgumentValue<T[property]>;
+ [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
Tue, Dec 24, 07:37 (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
557039
Default Alt Text
(10 KB)

Event Timeline