@beechcms/core 0.6.0 → 0.6.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ddl.d.ts","sourceRoot":"","sources":["../../src/engine/ddl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EACJ,MAAM,EAOP,MAAM,YAAY,CAAC;AA6BpB;;GAEG;AACH,eAAO,MAAM,cAAc,aAAgE,CAAA;AAG3F;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5C;AAcD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE/C;AAGD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAG9D;AAGD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAI5D;AAgCD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAwBtD;AAGD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAwB5D;AAGD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGpE;AAGD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAoBpD;AAGD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAc1D;AAGD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAgCxD;AAGD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,2BAA2B;IAC3B,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACpC,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,6CAA6C;IAC7C,IAAI,EAAE,OAAO,CAAA;CACd;AAGD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,YAAY,EAAE,CAgB7D;AAGD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/E;AAGD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAkBxE;AAGD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAM5E;AAGD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAapF;AAGD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAwBtD;AAGD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBtE;AAGD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBnF;AAGD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBzE"}
1
+ {"version":3,"file":"ddl.d.ts","sourceRoot":"","sources":["../../src/engine/ddl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EACJ,MAAM,EAOP,MAAM,YAAY,CAAC;AA8BpB;;GAEG;AACH,eAAO,MAAM,cAAc,aAAgE,CAAA;AAG3F;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5C;AAcD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE/C;AAGD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAG9D;AAGD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAM5D;AAgCD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAwBtD;AAGD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAwB5D;AAGD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGpE;AAGD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAoBpD;AAGD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAc1D;AAGD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAgCxD;AAGD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,2BAA2B;IAC3B,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACpC,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,6CAA6C;IAC7C,IAAI,EAAE,OAAO,CAAA;CACd;AAGD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,YAAY,EAAE,CAgB7D;AAGD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/E;AAGD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAkBxE;AAGD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAM5E;AAGD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAapF;AAGD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAwBtD;AAGD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBtE;AAGD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBnF;AAGD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBzE"}
@@ -1,3 +1,4 @@
1
+ import { resolvePolicies } from './policies.js';
1
2
  /**
2
3
  * Mapping of core branch types to SQLite column types.
3
4
  */
@@ -63,7 +64,12 @@ export function isValidColumn(seed, col) {
63
64
  * @returns An array of indexable branches.
64
65
  */
65
66
  export function indexableSearchBranches(seed) {
66
- return seed.branches.filter(b => (b.type === 'text' || b.type === 'richtext') && b.policies?.search !== false);
67
+ return seed.branches.filter(b => {
68
+ if (b.type !== 'text' && b.type !== 'richtext')
69
+ return false;
70
+ const { search, public: isPublic } = resolvePolicies(b);
71
+ return search && isPublic;
72
+ });
67
73
  }
68
74
  /**
69
75
  * The default ON DELETE referential integrity rule for single-value relations.
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/engine/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EAMJ,aAAa,EACb,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,aAAkB,GAAG,kBAAkB,CA2E5F"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/engine/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EAMJ,aAAa,EACb,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,aAAkB,GAAG,kBAAkB,CAoF5F"}
@@ -43,17 +43,26 @@ export function buildSelectQuery(seed, options = {}) {
43
43
  whereClauses.push(`${table}.status = ?`);
44
44
  bindings.push(status);
45
45
  }
46
+ const groupClauses = [];
46
47
  for (const group of filters) {
47
48
  if (!isValidColumn(seed, group.column))
48
49
  continue;
49
50
  const col = SYSTEM_COLUMNS.has(group.column)
50
51
  ? `${table}.${group.column}`
51
52
  : group.column;
53
+ const condClauses = [];
52
54
  for (const cond of group.conditions) {
53
55
  const clause = buildFilterCondition(col, group.type, cond, bindings);
54
56
  if (clause)
55
- whereClauses.push(clause);
57
+ condClauses.push(clause);
56
58
  }
59
+ if (condClauses.length > 0) {
60
+ groupClauses.push(condClauses.length > 1 ? `(${condClauses.join(' AND ')})` : condClauses[0]);
61
+ }
62
+ }
63
+ if (groupClauses.length > 0) {
64
+ const joiner = options.filterLogic === 'OR' ? ' OR ' : ' AND ';
65
+ whereClauses.push(groupClauses.length > 1 ? `(${groupClauses.join(joiner)})` : groupClauses[0]);
57
66
  }
58
67
  let selectCols = options.isCount ? 'COUNT(*) as total' : `${table}.*`;
59
68
  if (!options.isCount && fields && fields.length > 0) {
@@ -235,8 +235,10 @@ export interface FilterGroup {
235
235
  conditions: FilterCondition[];
236
236
  }
237
237
  export interface SelectOptions {
238
- /** Filter groups, ANDed together. */
238
+ /** Filter groups. Joined by `filterLogic` (default AND); conditions within a group are always ANDed. */
239
239
  filters?: FilterGroup[];
240
+ /** How top-level `filters` groups are combined. Defaults to 'AND'. */
241
+ filterLogic?: 'AND' | 'OR';
240
242
  /** Sort column and direction. Ignored when `kanbanOrder` is set. */
241
243
  orderBy?: {
242
244
  column: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/cache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAsB,IAAI,EAAwC,MAAM,aAAa,CAAA;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAoHjD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CA2BjH"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/cache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAsB,IAAI,EAAwC,MAAM,aAAa,CAAA;AAEjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAgIjD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAsCjH"}
@@ -2,37 +2,46 @@
2
2
  // Copyright (c) 2024–2026 Flavio De Musso
3
3
  import { z } from 'zod';
4
4
  import { schemaForBranch } from './schema-builders.js';
5
- /** Max entries kept in {@link seedSchemaCache} before evicting the least recently used. */
5
+ /** Max entries kept per cache map before evicting the least recently used. */
6
6
  const SEED_SCHEMA_CACHE_MAX_SIZE = 150;
7
- /** Cache storing compiled Zod schemas for seeds to optimize validation runs. */
7
+ /** Cache storing compiled Zod schemas for relation-free seeds. */
8
8
  const seedSchemaCache = new Map();
9
+ /**
10
+ * Per-`idGenerator`-instance caches for seeds with relation branches.
11
+ * Partitioning by instance identity keeps schemas compiled with different
12
+ * generators (and thus different `isValid()` semantics) from colliding,
13
+ * without needing a stable identifier on {@link IIdGenerator}.
14
+ */
15
+ const relationSchemaCacheByGenerator = new WeakMap();
9
16
  /**
10
17
  * Retrieves a cache entry and marks it as most recently used.
11
18
  *
19
+ * @param cache - The cache map to read from.
12
20
  * @param key - The cache key.
13
21
  * @returns The cached schema, or undefined if absent.
14
22
  */
15
- function getCachedSchema(key) {
16
- const cached = seedSchemaCache.get(key);
23
+ function getCachedSchema(cache, key) {
24
+ const cached = cache.get(key);
17
25
  if (cached) {
18
- seedSchemaCache.delete(key);
19
- seedSchemaCache.set(key, cached);
26
+ cache.delete(key);
27
+ cache.set(key, cached);
20
28
  }
21
29
  return cached;
22
30
  }
23
31
  /**
24
32
  * Stores a cache entry, evicting the least recently used one if over capacity.
25
33
  *
34
+ * @param cache - The cache map to write to.
26
35
  * @param key - The cache key.
27
36
  * @param value - The compiled schema to cache.
28
37
  */
29
- function setCachedSchema(key, value) {
30
- if (seedSchemaCache.size >= SEED_SCHEMA_CACHE_MAX_SIZE) {
31
- const oldestKey = seedSchemaCache.keys().next().value;
38
+ function setCachedSchema(cache, key, value) {
39
+ if (cache.size >= SEED_SCHEMA_CACHE_MAX_SIZE) {
40
+ const oldestKey = cache.keys().next().value;
32
41
  if (oldestKey !== undefined)
33
- seedSchemaCache.delete(oldestKey);
42
+ cache.delete(oldestKey);
34
43
  }
35
- seedSchemaCache.set(key, value);
44
+ cache.set(key, value);
36
45
  }
37
46
  /**
38
47
  * Recursively generates a typesafe fingerprint object for a branch and its sub-branches.
@@ -89,13 +98,27 @@ function buildCacheKey(seed, options) {
89
98
  * @returns The compiled strict Zod object schema.
90
99
  */
91
100
  export function compileSeedSchema(seed, options) {
92
- // Seeds with relation branches cannot be safely cached because the schema
93
- // captures the idGenerator by closure, and different generators (e.g.
94
- // SystemIdGenerator vs SequentialIdGenerator) have different isValid() semantics.
101
+ // Seeds with relation branches capture the idGenerator by closure, so their
102
+ // schemas are cached per generator instance instead of in the shared cache
103
+ // (different generators, e.g. SystemIdGenerator vs a test double, have
104
+ // different isValid() semantics).
95
105
  const hasRelation = seed.branches.some((b) => b.type === 'relation');
96
- if (!hasRelation) {
97
- const key = buildCacheKey(seed, options);
98
- const cached = getCachedSchema(key);
106
+ const key = buildCacheKey(seed, options);
107
+ let cache;
108
+ if (hasRelation) {
109
+ if (options.idGenerator) {
110
+ cache = relationSchemaCacheByGenerator.get(options.idGenerator);
111
+ if (!cache) {
112
+ cache = new Map();
113
+ relationSchemaCacheByGenerator.set(options.idGenerator, cache);
114
+ }
115
+ }
116
+ }
117
+ else {
118
+ cache = seedSchemaCache;
119
+ }
120
+ if (cache) {
121
+ const cached = getCachedSchema(cache, key);
99
122
  if (cached)
100
123
  return cached;
101
124
  }
@@ -107,9 +130,7 @@ export function compileSeedSchema(seed, options) {
107
130
  shape[branch.alias] = isRequired ? branchSchema : branchSchema.optional();
108
131
  }
109
132
  const compiled = z.object(shape).strict();
110
- if (!hasRelation) {
111
- const key = buildCacheKey(seed, options);
112
- setCachedSchema(key, compiled);
113
- }
133
+ if (cache)
134
+ setCachedSchema(cache, key, compiled);
114
135
  return compiled;
115
136
  }
@@ -42,7 +42,7 @@ export declare function extractFileCandidate(candidate: unknown): FileCandidate
42
42
  * input representing an asset list.
43
43
  *
44
44
  * @param raw - The raw input data (can be array, JSON string, or single item).
45
- * @returns The list of unique file candidates, or null if any item is invalid.
45
+ * @returns The list of unique file candidates, or null if any item is invalid or the list exceeds the cap.
46
46
  */
47
47
  export declare function collectAssetListItems(raw: unknown): FileCandidate[] | null;
48
48
  //# sourceMappingURL=file-branch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-branch.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/file-branch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAoB3D;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAW1D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAM1F;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AA6BD,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAI7E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,EAAE,GAAG,IAAI,CAe1E"}
1
+ {"version":3,"file":"file-branch.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/file-branch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAoB3D;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAW1D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAM1F;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AA6BD,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAI7E;AAKD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,EAAE,GAAG,IAAI,CAiB1E"}
@@ -100,16 +100,22 @@ export function extractFileCandidate(candidate) {
100
100
  return null;
101
101
  return { url, size: extractSizeFromCandidate(candidate) };
102
102
  }
103
+ /** Maximum number of items accepted in an asset list to prevent unbounded processing. */
104
+ const MAX_ASSET_LIST_ITEMS = 100;
103
105
  /**
104
106
  * Collects and deduplicates valid file candidates (url + optional size) from a raw
105
107
  * input representing an asset list.
106
108
  *
107
109
  * @param raw - The raw input data (can be array, JSON string, or single item).
108
- * @returns The list of unique file candidates, or null if any item is invalid.
110
+ * @returns The list of unique file candidates, or null if any item is invalid or the list exceeds the cap.
109
111
  */
110
112
  export function collectAssetListItems(raw) {
113
+ if (raw === null)
114
+ return null;
111
115
  const source = typeof raw === 'string' ? tryParseJson(raw) : raw;
112
116
  const items = Array.isArray(source) ? source : [source];
117
+ if (items.length > MAX_ASSET_LIST_ITEMS)
118
+ return null;
113
119
  const seen = new Set();
114
120
  const out = [];
115
121
  for (const item of items) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAOhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,0GAA0G;IAC1G,QAAQ,EAAE,MAAM,CAAA;IAChB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAA;IAChB,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC/B;;;OAGG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,YAAY,CAAA;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,+EAA+E;IAC/E,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,8FAA8F;IAC9F,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,4FAA4F;IAC5F,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,sEAAsE;IACtE,qBAAqB,EAAE,MAAM,EAAE,CAAA;IAC/B,uFAAuF;IACvF,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC9B,2BAA2B,EAAE,OAAO,CAAA;IACpC,qBAAqB,EAAE,OAAO,CAAA;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,YAAY,GAAG,SAAS,CAAA;CACtC,CAAA;AAKD,0CAA0C;AAC1C,QAAA,MAAM,aAAa,YAAI,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAA;AAkR/D;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,GAAE,0BAA+B,GACvC,yBAAyB,CAqD3B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAE5F"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAOhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,0GAA0G;IAC1G,QAAQ,EAAE,MAAM,CAAA;IAChB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAA;IAChB,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC/B;;;OAGG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,YAAY,CAAA;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,+EAA+E;IAC/E,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,8FAA8F;IAC9F,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,4FAA4F;IAC5F,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,sEAAsE;IACtE,qBAAqB,EAAE,MAAM,EAAE,CAAA;IAC/B,uFAAuF;IACvF,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC9B,2BAA2B,EAAE,OAAO,CAAA;IACpC,qBAAqB,EAAE,OAAO,CAAA;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,YAAY,GAAG,SAAS,CAAA;CACtC,CAAA;AAKD,0CAA0C;AAC1C,QAAA,MAAM,aAAa,YAAI,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAA;AAqR/D;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,GAAE,0BAA+B,GACvC,yBAAyB,CAqD3B;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAE5F"}
@@ -17,9 +17,10 @@ const statusSchema = z.enum(STATUS_VALUES);
17
17
  * Checks if a value is effectively empty (e.g. null, undefined, empty string, empty array, or empty rich text).
18
18
  *
19
19
  * @param value - The value to check.
20
+ * @param branchType - The type of the branch being checked.
20
21
  * @returns True if effectively empty, false otherwise.
21
22
  */
22
- function isEffectivelyEmpty(value) {
23
+ function isEffectivelyEmpty(value, branchType) {
23
24
  if (value === null || value === undefined)
24
25
  return true;
25
26
  if (typeof value === 'string')
@@ -27,10 +28,12 @@ function isEffectivelyEmpty(value) {
27
28
  if (Array.isArray(value))
28
29
  return value.length === 0;
29
30
  if (isPlainObject(value)) {
31
+ // Richtext envelope: delegate to the richtext emptiness check.
30
32
  if (isRichtextEnvelopeV1(value))
31
33
  return isRichtextDocEmpty(value.doc);
32
- if (isRichtextDocEmpty(value))
33
- return true;
34
+ // Raw TipTap doc root: only delegate for richtext branches to avoid misclassifying generic json fields.
35
+ if (branchType === 'richtext' && value.type === 'doc')
36
+ return isRichtextDocEmpty(value);
34
37
  return Object.keys(value).length === 0;
35
38
  }
36
39
  return false;
@@ -65,7 +68,7 @@ function detectMissingRequired(seed, rawPayload, filtered, parsedData, parseSucc
65
68
  continue;
66
69
  }
67
70
  const candidate = parseSucceeded ? parsedData[branch.alias] : filtered[branch.alias];
68
- if (isEffectivelyEmpty(candidate)) {
71
+ if (isEffectivelyEmpty(candidate, branch.type)) {
69
72
  missing.push(branch.alias);
70
73
  details.push({
71
74
  field: branch.alias,
@@ -310,7 +313,7 @@ export function validateAndSanitizeSeedPayload(seed, payload, options = {}) {
310
313
  field: 'data',
311
314
  expected: 'at-least-one-valid-field',
312
315
  received: 'empty',
313
- message: 'Payload does not contain any valid fields for this operation',
316
+ message: 'Payload contains no valid fields after validation; check field types and values',
314
317
  });
315
318
  }
316
319
  return {
@@ -15,7 +15,8 @@ export declare function stripControlChars(input: string): string;
15
15
  */
16
16
  export declare function cleanString(input: string): string;
17
17
  /**
18
- * Type-guard checking if a value is a plain object (excluding arrays and null).
18
+ * Type-guard checking if a value is a plain object (excluding arrays, null, and class instances).
19
+ * Accepts only objects whose prototype is `Object.prototype` or `null` (created via `Object.create(null)`).
19
20
  *
20
21
  * @param input - The value to check.
21
22
  * @returns True if the value is a plain object, false otherwise.
@@ -1 +1 @@
1
- {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/primitives.ts"],"names":[],"mappings":"AAGA,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,QAAoD,CAAA;AAEpF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAID;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD"}
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/primitives.ts"],"names":[],"mappings":"AAGA,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,QAAoD,CAAA;AAEpF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAI9E;AAID;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD"}
@@ -21,13 +21,17 @@ export function cleanString(input) {
21
21
  return stripControlChars(input).trim();
22
22
  }
23
23
  /**
24
- * Type-guard checking if a value is a plain object (excluding arrays and null).
24
+ * Type-guard checking if a value is a plain object (excluding arrays, null, and class instances).
25
+ * Accepts only objects whose prototype is `Object.prototype` or `null` (created via `Object.create(null)`).
25
26
  *
26
27
  * @param input - The value to check.
27
28
  * @returns True if the value is a plain object, false otherwise.
28
29
  */
29
30
  export function isPlainObject(input) {
30
- return typeof input === 'object' && input !== null && !Array.isArray(input);
31
+ if (typeof input !== 'object' || input === null || Array.isArray(input))
32
+ return false;
33
+ const proto = Object.getPrototypeOf(input);
34
+ return proto === Object.prototype || proto === null;
31
35
  }
32
36
  const byteLengthEncoder = new TextEncoder();
33
37
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"richtext-sanitizer.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/richtext-sanitizer.ts"],"names":[],"mappings":"AA0BA,+DAA+D;AAC/D,UAAU,sBAAsB;IAC9B,2CAA2C;IAC3C,KAAK,EAAE,OAAO,CAAA;IACd,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAA;IAClB,mEAAmE;IACnE,KAAK,EAAE,OAAO,CAAA;IACd,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAsGD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,sBAAsB,CAgCvF;AAyBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAS1D"}
1
+ {"version":3,"file":"richtext-sanitizer.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/richtext-sanitizer.ts"],"names":[],"mappings":"AA0BA,+DAA+D;AAC/D,UAAU,sBAAsB;IAC9B,2CAA2C;IAC3C,KAAK,EAAE,OAAO,CAAA;IACd,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAA;IAClB,mEAAmE;IACnE,KAAK,EAAE,OAAO,CAAA;IACd,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AA4GD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,sBAAsB,CAgCvF;AA2BD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAS1D"}
@@ -108,7 +108,14 @@ function sanitizeRichtextJson(raw) {
108
108
  const cleaned = walkRichtextNode(raw, state);
109
109
  const asObject = isPlainObject(cleaned) ? cleaned : {};
110
110
  const valid = asObject.type === 'doc';
111
- return { value: asObject, dangerous: state.dangerous, valid, size: byteLength(JSON.stringify(asObject)) };
111
+ let serialized;
112
+ try {
113
+ serialized = JSON.stringify(asObject);
114
+ }
115
+ catch {
116
+ return { value: asObject, dangerous: state.dangerous, valid: false, size: 0 };
117
+ }
118
+ return { value: asObject, dangerous: state.dangerous, valid, size: byteLength(serialized) };
112
119
  }
113
120
  /**
114
121
  * Main entrance helper to sanitize rich text, handling both v1 envelope formats and raw JSON payloads.
@@ -153,11 +160,14 @@ export function sanitizeRichtext(raw, maxBytes) {
153
160
  *
154
161
  * @param node - The rich text node to inspect.
155
162
  * @param sink - Accumulated text chunks.
163
+ * @param depth - Current recursion depth (guard against pathological structures).
156
164
  */
157
- function gatherRichtextText(node, sink) {
165
+ function gatherRichtextText(node, sink, depth = 0) {
166
+ if (depth > RICHTEXT_MAX_DEPTH)
167
+ return;
158
168
  if (Array.isArray(node)) {
159
169
  for (const child of node)
160
- gatherRichtextText(child, sink);
170
+ gatherRichtextText(child, sink, depth + 1);
161
171
  return;
162
172
  }
163
173
  if (!isPlainObject(node))
@@ -170,7 +180,7 @@ function gatherRichtextText(node, sink) {
170
180
  }
171
181
  if (Array.isArray(node.content)) {
172
182
  for (const child of node.content)
173
- gatherRichtextText(child, sink);
183
+ gatherRichtextText(child, sink, depth + 1);
174
184
  }
175
185
  }
176
186
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"schema-builders.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/schema-builders.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,aAAa,CAAA;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAsUjD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,CAAC,CAAC,UAAU,CAMtF"}
1
+ {"version":3,"file":"schema-builders.d.ts","sourceRoot":"","sources":["../../../src/engine/validation/schema-builders.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,aAAa,CAAA;AAErD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAmajD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,CAAC,CAAC,UAAU,CAMtF"}
@@ -2,7 +2,7 @@
2
2
  // Copyright (c) 2024–2026 Flavio De Musso
3
3
  import { z } from 'zod';
4
4
  import { extensionFromUrl, isExtensionAccepted } from '../../media/file-types.js';
5
- import { cleanString, byteLength } from './primitives.js';
5
+ import { cleanString, stripControlChars, byteLength, isPlainObject } from './primitives.js';
6
6
  import { sanitizeRichtext } from './richtext-sanitizer.js';
7
7
  import { resolveFileOptions, isAssetListBranch, collectAssetListItems, extractFileCandidate } from './file-branch.js';
8
8
  /**
@@ -12,12 +12,19 @@ import { resolveFileOptions, isAssetListBranch, collectAssetListItems, extractFi
12
12
  * @returns True if the string is a valid ISO date, false otherwise.
13
13
  */
14
14
  function isValidIsoDate(value) {
15
- if (!/^\d{4}-\d{2}-\d{2}/.test(value))
15
+ if (!/^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}(?::?\d{2})?)?)?$/.test(value)) {
16
16
  return false;
17
+ }
17
18
  const ts = Date.parse(value);
18
19
  if (Number.isNaN(ts))
19
20
  return false;
20
- return new Date(ts).toISOString().startsWith(value.slice(0, 10));
21
+ const y = parseInt(value.slice(0, 4), 10);
22
+ const m = parseInt(value.slice(5, 7), 10);
23
+ const d = parseInt(value.slice(8, 10), 10);
24
+ const date = new Date(Date.UTC(y, m - 1, d));
25
+ return (date.getUTCFullYear() === y &&
26
+ date.getUTCMonth() === m - 1 &&
27
+ date.getUTCDate() === d);
21
28
  }
22
29
  /**
23
30
  * Wraps a Zod schema to allow null values if `allowNull` is enabled.
@@ -39,7 +46,13 @@ function withNullable(schema, allowNull) {
39
46
  function withEmptyPreprocessing(schema, allowNull) {
40
47
  const fallback = allowNull ? null : undefined;
41
48
  const wrapped = allowNull ? schema.optional().nullable() : schema.optional();
42
- return z.preprocess((val) => (val === '' || val === null ? fallback : val), wrapped);
49
+ return z.preprocess((val) => {
50
+ if (val === '')
51
+ return fallback;
52
+ if (val === null)
53
+ return allowNull ? null : val;
54
+ return val;
55
+ }, wrapped);
43
56
  }
44
57
  /**
45
58
  * Compiles a Zod validation schema for a text branch.
@@ -165,14 +178,91 @@ function dateSchema(allowNull) {
165
178
  .refine((value) => isValidIsoDate(value), { message: 'Expected date(ISO)' });
166
179
  return withEmptyPreprocessing(base, allowNull);
167
180
  }
181
+ /** Max nesting depth accepted when walking a `json` branch value. */
182
+ const JSON_MAX_DEPTH = 50;
183
+ /** Max number of items accepted in a `tags` branch array. */
184
+ const MAX_TAGS_COUNT = 100;
168
185
  /**
169
- * Compiles a Zod validation schema for JSON or tags branches.
186
+ * Recursively strips control characters from string leaves while enforcing a
187
+ * depth cap, mirroring the richtext sanitizer's DoS guards for arbitrary JSON.
170
188
  *
189
+ * @param value - The value (or sub-value) being walked.
190
+ * @param depth - Current recursion depth.
191
+ * @returns The sanitized value, or `undefined` with `tooDeep: true` if the cap was exceeded.
192
+ */
193
+ function sanitizeJsonValue(value, depth) {
194
+ if (depth > JSON_MAX_DEPTH)
195
+ return { value: undefined, tooDeep: true };
196
+ if (typeof value === 'string')
197
+ return { value: stripControlChars(value), tooDeep: false };
198
+ if (Array.isArray(value)) {
199
+ const out = [];
200
+ for (const item of value) {
201
+ const res = sanitizeJsonValue(item, depth + 1);
202
+ if (res.tooDeep)
203
+ return res;
204
+ out.push(res.value);
205
+ }
206
+ return { value: out, tooDeep: false };
207
+ }
208
+ if (isPlainObject(value)) {
209
+ const out = {};
210
+ for (const [k, v] of Object.entries(value)) {
211
+ const res = sanitizeJsonValue(v, depth + 1);
212
+ if (res.tooDeep)
213
+ return res;
214
+ out[k] = res.value;
215
+ }
216
+ return { value: out, tooDeep: false };
217
+ }
218
+ return { value, tooDeep: false };
219
+ }
220
+ /**
221
+ * Compiles a Zod validation schema for a `json` branch, bounding size and nesting
222
+ * depth like richtext, and stripping control characters from string leaves.
223
+ *
224
+ * @param options - The resolved validation options.
171
225
  * @param allowNull - Whether null values are allowed.
172
- * @returns The compiled JSON/tags schema.
226
+ * @returns The compiled JSON schema.
173
227
  */
174
- function jsonOrTagsSchema(allowNull) {
175
- const base = z.union([z.record(z.string(), z.unknown()), z.array(z.unknown())]);
228
+ function jsonSchema(options, allowNull) {
229
+ const base = z
230
+ .union([z.record(z.string(), z.unknown()), z.array(z.unknown())])
231
+ .transform((val, ctx) => {
232
+ // Fail-fast size check before the sanitizing walk, same order as richtext.
233
+ const rawSize = byteLength(JSON.stringify(val));
234
+ if (rawSize > options.maxTextLength) {
235
+ ctx.addIssue({ code: 'custom', message: `Expected json(max:${options.maxTextLength})` });
236
+ return z.NEVER;
237
+ }
238
+ const { value, tooDeep } = sanitizeJsonValue(val, 0);
239
+ if (tooDeep) {
240
+ ctx.addIssue({ code: 'custom', message: `Expected json(maxDepth:${JSON_MAX_DEPTH})` });
241
+ return z.NEVER;
242
+ }
243
+ return value;
244
+ });
245
+ return withEmptyPreprocessing(base, allowNull);
246
+ }
247
+ /**
248
+ * Compiles a Zod validation schema for a `tags` branch, constraining it to a
249
+ * bounded array of cleaned strings (fixes #183: previously any array/object
250
+ * shape passed, breaking callers like the kanban swap that cast to `string[]`).
251
+ *
252
+ * @param options - The resolved validation options.
253
+ * @param allowNull - Whether null values are allowed.
254
+ * @returns The compiled tags schema.
255
+ */
256
+ function tagsSchema(options, allowNull) {
257
+ const tagSchema = z
258
+ .string()
259
+ .transform((value) => cleanString(value))
260
+ .refine((value) => byteLength(value) <= options.maxTextLength, {
261
+ message: `Expected string(max:${options.maxTextLength})`,
262
+ });
263
+ const base = z.array(tagSchema).max(MAX_TAGS_COUNT, {
264
+ message: `Expected tags(max:${MAX_TAGS_COUNT})`,
265
+ });
176
266
  return withEmptyPreprocessing(base, allowNull);
177
267
  }
178
268
  /**
@@ -275,7 +365,8 @@ function repeaterSchema(branch, options) {
275
365
  const shape = {};
276
366
  for (const sub of subBranches) {
277
367
  const subSchema = schemaForBranch(sub, options);
278
- shape[sub.alias] = sub[requiredFlag] ? subSchema : subSchema.optional();
368
+ const isRequired = options.enforceRequiredFields && sub[requiredFlag];
369
+ shape[sub.alias] = isRequired ? subSchema : subSchema.optional();
279
370
  }
280
371
  // z.object() strips unknown keys by default — old item shapes from a renamed/
281
372
  // removed sub-field are dropped rather than rejected (sprint 10 §5.1).
@@ -300,8 +391,8 @@ const BRANCH_SCHEMA_BUILDERS = {
300
391
  number: (branch, options) => numberSchema(branch, options.allowNull),
301
392
  boolean: (_branch, options) => booleanSchema(options.allowNull),
302
393
  date: (_branch, options) => dateSchema(options.allowNull),
303
- json: (_branch, options) => jsonOrTagsSchema(options.allowNull),
304
- tags: (_branch, options) => jsonOrTagsSchema(options.allowNull),
394
+ json: (_branch, options) => jsonSchema(options, options.allowNull),
395
+ tags: (_branch, options) => tagsSchema(options, options.allowNull),
305
396
  file: (branch, options) => fileSchema(branch, options.allowNull),
306
397
  relation: (branch, options) => relationSchema(branch, options),
307
398
  repeater: (branch, options) => repeaterSchema(branch, options),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beechcms/core",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",