Skip to content

Commit

Permalink
Add support for literal arrays to block meta
Browse files Browse the repository at this point in the history
String, number, boolean, and JSON arrays can be defined by setting `array: true`.

**Example**

```ts
class NewsListBlockData {
    @BlockField({ type: "string", array: true })
    newsIds: string[];
}
```
  • Loading branch information
johnnyomair committed Oct 10, 2024
1 parent 6258182 commit 2e46354
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 12 deletions.
17 changes: 17 additions & 0 deletions .changeset/spicy-panthers-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"@comet/blocks-api": minor
"@comet/cli": minor
---

Add support for literal arrays to block meta

String, number, boolean, and JSON arrays can be defined by setting `array: true`.

**Example**

```ts
class NewsListBlockData {
@BlockField({ type: "string", array: true })
newsIds: string[];
}
```
10 changes: 6 additions & 4 deletions demo/api/block-meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -1194,15 +1194,17 @@
"fields": [
{
"name": "ids",
"kind": "Json",
"nullable": false
"kind": "String",
"nullable": false,
"array": true
}
],
"inputFields": [
{
"name": "ids",
"kind": "Json",
"nullable": false
"kind": "String",
"nullable": false,
"array": true
}
]
},
Expand Down
4 changes: 2 additions & 2 deletions demo/api/src/news/blocks/news-list.block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { BlockData, BlockField, BlockInput, createBlock, inputToData } from "@co
import { IsUUID } from "class-validator";

export class NewsListBlockData extends BlockData {
@BlockField({ type: "json" })
@BlockField({ type: "string", array: true })
ids: string[];
}

class NewsListBlockInput extends BlockInput {
@BlockField({ type: "json" })
@BlockField({ type: "string", array: true })
@IsUUID(undefined, { each: true })
ids: string[];

Expand Down
2 changes: 1 addition & 1 deletion demo/site/src/news/blocks/NewsListBlock.loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const loader: BlockLoader<NewsListBlockData> = async ({ blockData, graphQ
const newsList: LoadedData = [];

// TODO create a require that allows loading multiple news by IDs at once?
for (const id of blockData.ids as string[]) {
for (const id of blockData.ids) {
const data = await graphQLFetch<GQLNewsListBlockQuery, GQLNewsListBlockQueryVariables>(
gql`
query NewsListBlock($id: ID!) {
Expand Down
1 change: 1 addition & 0 deletions packages/api/blocks-api/src/blocks-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ function extractFromBlockMeta(blockMeta: BlockMetaInterface): BlockMetaField[] {
name: field.name,
kind: field.kind,
nullable: field.nullable,
array: field.array,
};
} else if (field.kind === BlockMetaFieldKind.Enum) {
return {
Expand Down
1 change: 1 addition & 0 deletions packages/api/blocks-api/src/blocks/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export type BlockMetaField =
name: string;
kind: BlockMetaLiteralFieldKind;
nullable: boolean;
array?: boolean;
}
| { name: string; kind: BlockMetaFieldKind.Enum; enum: string[]; nullable: boolean }
| { name: string; kind: BlockMetaFieldKind.Block; block: Block; nullable: boolean }
Expand Down
20 changes: 15 additions & 5 deletions packages/api/blocks-api/src/blocks/decorators/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ type BlockFieldOptions =
nullable?: boolean;
}
| {
type: "json";
type: "json" | "string" | "number" | "boolean";
nullable?: boolean;
array?: boolean;
}
| {
nullable?: boolean;
Expand Down Expand Up @@ -53,6 +54,7 @@ type BlockFieldData =
| {
kind: BlockMetaLiteralFieldKind;
nullable: boolean;
array?: boolean;
}
| { kind: BlockMetaFieldKind.Enum; enum: string[]; nullable: boolean }
| { kind: BlockMetaFieldKind.Block; block: Block; nullable: boolean }
Expand All @@ -68,13 +70,20 @@ export function getBlockFieldData(ctor: { prototype: any }, propertyKey: string)
const fieldType = Reflect.getMetadata(`data:fieldType`, ctor.prototype, propertyKey);

const nullable = !!(fieldType && fieldType.nullable);
const array: boolean | undefined = fieldType?.array ?? undefined;

if (fieldType && fieldType.type) {
if (fieldType.type === "enum") {
if (fieldType.type === "string") {
ret = { kind: BlockMetaFieldKind.String, nullable, array };
} else if (fieldType.type === "number") {
ret = { kind: BlockMetaFieldKind.Number, nullable, array };
} else if (fieldType.type === "boolean") {
ret = { kind: BlockMetaFieldKind.Boolean, nullable, array };
} else if (fieldType.type === "json") {
ret = { kind: BlockMetaFieldKind.Json, nullable, array };
} else if (fieldType.type === "enum") {
const enumValues = Array.isArray(fieldType.enum) ? fieldType.enum : Object.values(fieldType.enum);
ret = { kind: BlockMetaFieldKind.Enum, enum: enumValues, nullable };
} else if (fieldType.type === "json") {
ret = { kind: BlockMetaFieldKind.Json, nullable };
} else if (fieldType.type === "block") {
ret = { kind: BlockMetaFieldKind.Block, block: fieldType.block, nullable };
} else {
Expand Down Expand Up @@ -110,7 +119,7 @@ export function getBlockFieldData(ctor: { prototype: any }, propertyKey: string)
break;
case "Array":
if (!fieldType || !(isBlockDataInterface(fieldType.prototype) || isBlockInputInterface(fieldType.prototype))) {
throw new Error(`In ${designType.name} for ${propertyKey} only SubBlocks implementing BlockDataInterface are allowed`);
throw new Error(`Unknown array type for ${propertyKey}. An explicit type annotation is necessary.`);
}
ret = { kind: BlockMetaFieldKind.NestedObjectList, object: fieldType, nullable };

Expand Down Expand Up @@ -144,6 +153,7 @@ export class AnnotationBlockMeta implements BlockMetaInterface {
name,
kind: field.kind,
nullable: field.nullable,
array: field.array,
});
} else if (field.kind === BlockMetaFieldKind.Enum) {
ret.push({
Expand Down
17 changes: 17 additions & 0 deletions packages/cli/src/commands/generate-block-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type BlockMetaField =
name: string;
kind: "String" | "Number" | "Boolean" | "Json";
nullable: boolean;
array?: boolean;
}
| {
name: string;
Expand Down Expand Up @@ -48,12 +49,28 @@ let content = "";
function writeFieldType(field: BlockMetaField, blockNamePostfix: string) {
if (field.kind === "String") {
content += "string";

if (field.array) {
content += "[]";
}
} else if (field.kind === "Number") {
content += "number";

if (field.array) {
content += "[]";
}
} else if (field.kind === "Boolean") {
content += "boolean";

if (field.array) {
content += "[]";
}
} else if (field.kind === "Json") {
content += "unknown";

if (field.array) {
content += "[]";
}
} else if (field.kind === "Enum") {
content += `"${field.enum.join('" | "')}"`;
} else if (field.kind === "Block") {
Expand Down

0 comments on commit 2e46354

Please sign in to comment.