@avocadostudio-ai/shared 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blocks/_registry.d.ts +2 -4
- package/dist/blocks/_registry.js +76 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +12 -2
|
@@ -97,10 +97,8 @@ export type BlockRegistration = {
|
|
|
97
97
|
schema: z.ZodObject<any>;
|
|
98
98
|
meta: BlockMeta;
|
|
99
99
|
};
|
|
100
|
-
/**
|
|
101
|
-
|
|
102
|
-
* Re-registering the same type overwrites the previous registration.
|
|
103
|
-
*/
|
|
100
|
+
/** Test seam: forget what has already been warned about. */
|
|
101
|
+
export declare function resetListFieldWarnings(): void;
|
|
104
102
|
export declare function registerBlock(type: string, config: BlockRegistration): void;
|
|
105
103
|
/** Get metadata for a registered block type, or undefined. */
|
|
106
104
|
export declare function getBlockMeta(type: string): BlockMeta | undefined;
|
package/dist/blocks/_registry.js
CHANGED
|
@@ -23,6 +23,74 @@ const _blockMeta = G.__ase_blockMeta ?? (G.__ase_blockMeta = {});
|
|
|
23
23
|
* Register a block type. Can be called at module load time.
|
|
24
24
|
* Re-registering the same type overwrites the previous registration.
|
|
25
25
|
*/
|
|
26
|
+
/*
|
|
27
|
+
* `meta.listFields` and the props schema are two halves of one declaration, and
|
|
28
|
+
* only the schema is load-bearing: the property panel renders rows from the
|
|
29
|
+
* schema's array, and `listFields` only says how to label them. So a list named
|
|
30
|
+
* in the meta and missing from the schema produces no rows, no Add control, and
|
|
31
|
+
* no error — the one outcome that carries no information.
|
|
32
|
+
*
|
|
33
|
+
* That is not hypothetical. An integration declared six accordion items, four
|
|
34
|
+
* contact rows, a price table's tiers and every block's buttons this way, and
|
|
35
|
+
* the whole run passed: validation succeeded, operations applied, the preview
|
|
36
|
+
* rendered, the publisher diffed the rows correctly. The only symptom was an
|
|
37
|
+
* absence in one panel — and it was invisible precisely because the block's
|
|
38
|
+
* schema carried `.catchall(z.unknown())`, which every CMS integration needs
|
|
39
|
+
* because our own publish guidance tells it to stash a `__source` snapshot in
|
|
40
|
+
* block props. The catchall swallowed the undeclared arrays as extras.
|
|
41
|
+
*
|
|
42
|
+
* The loop below was already standing on the contradiction: it walks
|
|
43
|
+
* `listFields` against the schema to derive `required`, finds no array, and
|
|
44
|
+
* steps over it. This is that step, saying so.
|
|
45
|
+
*
|
|
46
|
+
* A warning rather than a throw: `registerBlocks` re-runs on every `/blocks`
|
|
47
|
+
* request, and a registry that can fail a request is worse than a panel with a
|
|
48
|
+
* missing list. Deduped for the same reason.
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* Strip the wrappers that make a schema optional, so the shape underneath can be
|
|
52
|
+
* inspected. `z.array(z.object({…})).optional()` is a `ZodOptional` holding the
|
|
53
|
+
* array, and reaching for `.element` on the wrapper finds nothing.
|
|
54
|
+
*
|
|
55
|
+
* Follows `def.innerType`, which is what `ZodOptional`, `ZodDefault` and
|
|
56
|
+
* `ZodNullable` carry, and deliberately **not** `.unwrap()`: in Zod 4 an array
|
|
57
|
+
* has that method too and it returns the array's *element*, so a generic
|
|
58
|
+
* unwrapper walks `ZodOptional → ZodArray → ZodObject` and lands one step past
|
|
59
|
+
* the array it was looking for.
|
|
60
|
+
*/
|
|
61
|
+
function unwrapZod(schema) {
|
|
62
|
+
let current = schema;
|
|
63
|
+
for (let depth = 0; depth < 5 && current; depth += 1) {
|
|
64
|
+
const inner = current.def?.innerType ?? current._def?.innerType;
|
|
65
|
+
if (!inner)
|
|
66
|
+
return current;
|
|
67
|
+
current = inner;
|
|
68
|
+
}
|
|
69
|
+
return current;
|
|
70
|
+
}
|
|
71
|
+
const warnedListFields = new Set();
|
|
72
|
+
function warnUnbackedListField(type, listKey, present) {
|
|
73
|
+
const key = `${type}.${listKey}`;
|
|
74
|
+
if (warnedListFields.has(key))
|
|
75
|
+
return;
|
|
76
|
+
warnedListFields.add(key);
|
|
77
|
+
const because = present
|
|
78
|
+
? `the schema's \`${listKey}\` is not an array of objects`
|
|
79
|
+
: `the schema has no \`${listKey}\``;
|
|
80
|
+
try {
|
|
81
|
+
console.warn(`[avocado] ${type}: meta.listFields declares "${listKey}" but ${because}. ` +
|
|
82
|
+
`The property panel renders list rows from the schema, so this list will show ` +
|
|
83
|
+
`no rows and no Add control. Declare it alongside the meta, e.g. ` +
|
|
84
|
+
`${listKey}: z.array(z.object({ … })).optional()`);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// A host with no console is not a reason to fail a registration.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Test seam: forget what has already been warned about. */
|
|
91
|
+
export function resetListFieldWarnings() {
|
|
92
|
+
warnedListFields.clear();
|
|
93
|
+
}
|
|
26
94
|
export function registerBlock(type, config) {
|
|
27
95
|
_blockSchemas[type] = config.schema;
|
|
28
96
|
// Auto-derive `required` on each FieldMeta from the Zod schema shape
|
|
@@ -40,10 +108,15 @@ export function registerBlock(type, config) {
|
|
|
40
108
|
if (config.meta.listFields) {
|
|
41
109
|
for (const [listKey, listMeta] of Object.entries(config.meta.listFields)) {
|
|
42
110
|
const listZod = shape[listKey];
|
|
43
|
-
// Unwrap ZodArray → element
|
|
44
|
-
|
|
45
|
-
|
|
111
|
+
// Unwrap ZodOptional / ZodDefault / ZodNullable → ZodArray → element.
|
|
112
|
+
// Without the outer unwrap, `z.array(...).optional()` — which is how a
|
|
113
|
+
// list should be declared — looked like no array at all, so every
|
|
114
|
+
// optional list silently skipped its own `required` derivation.
|
|
115
|
+
const elementShape = unwrapZod(listZod)?.element?.shape;
|
|
116
|
+
if (!elementShape) {
|
|
117
|
+
warnUnbackedListField(type, listKey, listZod !== undefined);
|
|
46
118
|
continue;
|
|
119
|
+
}
|
|
47
120
|
for (const [itemKey, itemField] of Object.entries(listMeta.itemFields)) {
|
|
48
121
|
if (itemField.required !== undefined)
|
|
49
122
|
continue;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { isImagePath, toAltPath, setPropAtPath } from "./editable-path.ts";
|
|
|
5
5
|
export { parseInline, parseRichText, parseRichTextBlocks, normalizeRichTextBody, resolveRichTextHeadingLevel, clampMarkdownHeadings, unescapeMarkdownText, isRichTextDoc, fromMarkdown, toMarkdown, mergeRichTextDoc, NODE, MARK, type InlineToken, type RichTextBlock, type RichTextList, type RichTextListItem, type RichTextDoc, type RichTextNode, type RichTextMark } from "@avocadostudio-ai/richtext";
|
|
6
6
|
export { blockDefinitionSchema, blockManifestSchema, buildBlockManifest, jsonSchemaLikeSchema, validateByJsonSchemaLike, findManifestSchemaIssue, type ManifestSchemaIssue, validateManifestDefaultProps, deriveFieldMetaFromSchema, resolveManifestFieldMeta, isProseMirrorDocSchema, type BlockDefinition, type BlockManifest } from "./block-manifest.ts";
|
|
7
7
|
export { z } from "zod";
|
|
8
|
-
export { type FieldKind, type ImageSpec, type FieldMeta, type ListFieldMeta, type BlockMeta, type BlockType, type BlockInstance, type BlockRegistration, IMAGE_PLACEHOLDER, isImagePlaceholder, registerBlock, getBlockMeta, getAllBlockMeta, getImageFields, getListImageFields, isFieldInlineEditable, getImageSpec, isChrome, getChromeTypes, blockSchemas, allowedBlockTypes, declareBlockCatalogue, getBlockCatalogue, isInBlockCatalogue, catalogueBlockTypes, undeclaredBlockTypes, getPropDisplayName, defaultListItemForBlock, blockInstanceSchema, blockInstanceSchemaLenient, validateBlockProps, getBlockJsonSchema, } from "./blocks/_registry.ts";
|
|
8
|
+
export { type FieldKind, type ImageSpec, type FieldMeta, type ListFieldMeta, type BlockMeta, type BlockType, type BlockInstance, type BlockRegistration, IMAGE_PLACEHOLDER, isImagePlaceholder, registerBlock, resetListFieldWarnings, getBlockMeta, getAllBlockMeta, getImageFields, getListImageFields, isFieldInlineEditable, getImageSpec, isChrome, getChromeTypes, blockSchemas, allowedBlockTypes, declareBlockCatalogue, getBlockCatalogue, isInBlockCatalogue, catalogueBlockTypes, undeclaredBlockTypes, getPropDisplayName, defaultListItemForBlock, blockInstanceSchema, blockInstanceSchemaLenient, validateBlockProps, getBlockJsonSchema, } from "./blocks/_registry.ts";
|
|
9
9
|
export { defaultPropsForType, declaredDefaultPropsForType, resolveHeadingTag, resolveItemHeadingTag, DEFAULT_HEADING_LEVELS, } from "./blocks/index.ts";
|
|
10
10
|
export { blockTypeToCamel, camelToBlockType, blockTypeToLower, lowerToBlockType, } from "./block-names.ts";
|
|
11
11
|
export { makeAddBlock, generateBlockId, makeAddItem, generateItemId, ensureItemIds, type AddBlockOp, type MakeAddBlockOptions, type AddItemOp, type MakeAddItemOptions, } from "./ops/builders.ts";
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ export {
|
|
|
33
33
|
// Constants & helpers
|
|
34
34
|
IMAGE_PLACEHOLDER, isImagePlaceholder,
|
|
35
35
|
// Registry functions
|
|
36
|
-
registerBlock, getBlockMeta, getAllBlockMeta, getImageFields, getListImageFields, isFieldInlineEditable, getImageSpec, isChrome, getChromeTypes,
|
|
36
|
+
registerBlock, resetListFieldWarnings, getBlockMeta, getAllBlockMeta, getImageFields, getListImageFields, isFieldInlineEditable, getImageSpec, isChrome, getChromeTypes,
|
|
37
37
|
// Backwards-compatible exports
|
|
38
38
|
blockSchemas, allowedBlockTypes,
|
|
39
39
|
// The catalogue a site actually renders — see `declareBlockCatalogue`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@avocadostudio-ai/shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,13 +19,23 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"zod": "^4.3.6",
|
|
22
|
-
"@avocadostudio-ai/richtext": "0.
|
|
22
|
+
"@avocadostudio-ai/richtext": "^0.3.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"tsx": "^4.21.0",
|
|
26
26
|
"typescript": "^5.7.3"
|
|
27
27
|
},
|
|
28
28
|
"description": "Shared Zod schemas, block registry, and operation types for Avocado Studio",
|
|
29
|
+
"keywords": [
|
|
30
|
+
"avocado",
|
|
31
|
+
"avocado-studio",
|
|
32
|
+
"cms",
|
|
33
|
+
"blocks",
|
|
34
|
+
"zod",
|
|
35
|
+
"schema",
|
|
36
|
+
"page-builder",
|
|
37
|
+
"visual-editing"
|
|
38
|
+
],
|
|
29
39
|
"license": "Apache-2.0",
|
|
30
40
|
"homepage": "https://github.com/avocadostudio-ai/avocado/tree/main/packages/shared#readme",
|
|
31
41
|
"bugs": {
|