Page MenuHomeSealhub

No OneTemporary

diff --git a/src/component-arguments/component-argument.ts b/src/component-arguments/component-argument.ts
index d83ced7..a690992 100644
--- a/src/component-arguments/component-argument.ts
+++ b/src/component-arguments/component-argument.ts
@@ -1,91 +1,93 @@
-import { JDDContext } from "../index.js";
+import { JDDContext, Table, TableData } from "../index.js";
import { List } from "./list.js";
export type ExtractStructuredComponentArgumentsParsed<C> = {
[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 List<infer T>
? T[]
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
C extends ComponentArgument<infer T2, any, any>
? T2
+ : C extends Table<infer TT1, infer TT2>
+ ? TableData<TT1, TT2>
: 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 556f466..284b6fd 100644
--- a/src/component-arguments/list.test.ts
+++ b/src/component-arguments/list.test.ts
@@ -1,15 +1,22 @@
import { ExtractParsed } from "./component-argument.js";
import { Image } from "./image.js";
import { List } from "./list.js";
+import { ShortText } from "./short-text.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
+
+ const strings_arg = new List(new ShortText()).setExampleValues([
+ ["a tag"],
+ ]);
+ const strings = [] as ExtractParsed<typeof strings_arg>;
+ strings.map((e) => e?.padStart(0)); // if the types are right, this should typecheck OK
});
});
diff --git a/src/component-arguments/structured.test.ts b/src/component-arguments/structured.test.ts
new file mode 100644
index 0000000..3c76294
--- /dev/null
+++ b/src/component-arguments/structured.test.ts
@@ -0,0 +1,36 @@
+import { ExtractParsed } from "./component-argument.js";
+import { List } from "./list.js";
+import { ShortText } from "./short-text.js";
+import { Structured } from "./structured.js";
+
+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
+ });
+});
diff --git a/src/component-arguments/table.test.ts b/src/component-arguments/table.test.ts
new file mode 100644
index 0000000..0ebca4a
--- /dev/null
+++ b/src/component-arguments/table.test.ts
@@ -0,0 +1,34 @@
+import { Table } from "./table.js";
+import { Structured } from "./structured.js";
+import { List } from "./list.js";
+import { ShortText } from "./short-text.js";
+import { ExtractParsed } from "./component-argument.js";
+
+describe("table argument", () => {
+ it("properly parses type value", () => {
+ const table_arg = new Table(
+ new Structured(<const>{
+ value: new ShortText().setExampleValues([""]),
+ tags: new List(new ShortText()),
+ }),
+ new Structured({
+ tags: new List(new ShortText()).setExampleValues([["okazja"]]),
+ })
+ );
+
+ const table_value = {
+ rows: [
+ { type: "row", cells: [] },
+ { type: "header", value: "", tags: [] },
+ ],
+ } as ExtractParsed<typeof table_arg>;
+
+ table_value.rows.map((row) => {
+ if (row.type == "row") {
+ row.cells.map((cell) => {
+ cell.tags.map((tag) => tag); // if the types are written correctly, this will typecheck OK
+ });
+ }
+ });
+ });
+});
diff --git a/src/component-arguments/table.ts b/src/component-arguments/table.ts
index 7e58544..6338f35 100644
--- a/src/component-arguments/table.ts
+++ b/src/component-arguments/table.ts
@@ -1,209 +1,209 @@
import { hasShape, predicates } from "@sealcode/ts-predicates";
import { JDDContext } from "../index.js";
import { ComponentArgument } from "./component-argument.js";
import { ContainerArgument } from "./container-argument.js";
type TableHeader<HeaderType> = { type: "header"; header_content: HeaderType };
type TableRegularRow<CellType> = { type: "row"; cells: CellType[] };
export type TableRow<CellType, HeaderType> =
| TableHeader<HeaderType>
| TableRegularRow<CellType>;
export type TableData<CellType, HeaderType> = {
rows: TableRow<CellType, HeaderType>[];
};
export function isTableHeader(x: unknown): x is TableHeader<unknown> {
return hasShape(
{
type: predicates.const("header"),
header_content: predicates.unknown,
},
x
);
}
export function isTableRegularRow<CellType = unknown>(
x: unknown
): x is TableRegularRow<CellType> {
return hasShape(
{
type: predicates.const("row"),
cells: predicates.array(predicates.unknown),
},
x
);
}
export function isTableData<CellType = unknown, HeaderType = unknown>(
x: unknown
): x is TableData<CellType, HeaderType> {
return hasShape(
{
rows: predicates.array(predicates.object),
},
x
);
}
export class Table<CellType, HeaderType> extends ContainerArgument<
TableData<CellType, HeaderType>
> {
constructor(
- public header_type: ComponentArgument<HeaderType>,
- public cell_type: ComponentArgument<CellType>
+ public header_type: ComponentArgument<HeaderType, unknown, unknown>,
+ public cell_type: ComponentArgument<CellType, unknown, unknown>
) {
super();
cell_type.parent_argument = this;
header_type.parent_argument = this;
}
getSubArgument(key: string, value: TableData<CellType, HeaderType>) {
if (isNaN(parseInt(key))) {
return null;
}
const key_n = parseInt(key);
const row = value.rows[key_n];
if (!row) {
return null;
} else if (row.type == "header") {
return this.header_type;
} else {
return this.cell_type;
}
}
getTypeName() {
return "table";
}
getEmptyValue() {
return {
rows: [
{
type: <const>"header",
header_content: this.header_type.getEmptyValue(),
},
{
type: <const>"row",
cells: [this.cell_type.getEmptyValue()],
},
],
};
}
async getExampleValue(context: JDDContext) {
const rows = Math.round(Math.random() * 5);
const columns = Math.round(Math.random() * 5);
const result: TableData<CellType, HeaderType> = {
rows: [
{
type: "header",
header_content: await this.header_type.getExampleValue(
context
),
},
],
};
for (let i = 0; i < rows; i++) {
const cells: CellType[] = [];
for (let j = 0; j < columns; j++) {
// eslint-disable-next-line no-await-in-loop
cells.push(await this.cell_type.getExampleValue(context));
}
result.rows.push({ type: "row", cells });
}
return result;
}
countWords(value: TableData<CellType, HeaderType>): number {
let result = 0;
for (let i = 0; i < value.rows.length; i++) {
const row = value.rows[i];
if (isTableHeader(row)) {
result += this.header_type.countWords(row.header_content);
} else {
for (let j = 0; j < row.cells.length; j++) {
result += this.cell_type.countWords(row.cells[j]);
}
}
}
return result;
}
async processAllSubarguments(
context: JDDContext,
input: unknown,
processing_function: (
argument: ComponentArgument<unknown>,
value: unknown
) => Promise<unknown>
) {
if (!hasShape({ rows: predicates.array(predicates.object) }, input)) {
return { rows: [] };
} else {
const result: TableData<CellType, HeaderType> = { rows: [] };
const row_promises = input.rows.map(async (row, row_index) => {
let new_row: TableRow<CellType, HeaderType>;
if (hasShape({ header_content: predicates.unknown }, row)) {
let header_content = (await processing_function(
this.header_type,
row.header_content
)) as HeaderType | HeaderType[] | null;
if (Array.isArray(header_content)) {
header_content = header_content[0];
}
if (header_content == null) {
header_content = this.header_type.getEmptyValue();
}
new_row = {
type: "header",
header_content,
};
result.rows[row_index] = new_row;
} else if (
hasShape(
{ cells: predicates.array(predicates.unknown) },
row
)
) {
new_row = {
type: "row",
cells: await Promise.all(
row.cells.map(async (cell) => {
const value = (await processing_function(
this.cell_type,
cell
)) as CellType | CellType[] | null;
if (value === null) {
return this.cell_type.getEmptyValue();
} else if (Array.isArray(value)) {
return value[0];
} else {
return value;
}
})
),
};
result.rows[row_index] = new_row;
}
});
await Promise.all(row_promises);
return result;
}
}
getColumnsCount(value: TableData<CellType, HeaderType>) {
return (
(
(
value.rows.filter((row) => row.type == "row")[0] as
| TableRegularRow<CellType>
| undefined
)?.cells || []
).length || 1
);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 23, 00:01 (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
547467
Default Alt Text
(11 KB)

Event Timeline