canopycms 0.0.54 → 0.0.56

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.
Files changed (225) hide show
  1. package/dist/api/assets.d.ts +14 -2
  2. package/dist/api/assets.d.ts.map +1 -1
  3. package/dist/api/assets.js +14 -3
  4. package/dist/api/assets.js.map +1 -1
  5. package/dist/api/branch-status.d.ts.map +1 -1
  6. package/dist/api/branch-status.js +8 -2
  7. package/dist/api/branch-status.js.map +1 -1
  8. package/dist/api/client.d.ts +2 -2
  9. package/dist/api/client.d.ts.map +1 -1
  10. package/dist/api/client.js +29 -14
  11. package/dist/api/client.js.map +1 -1
  12. package/dist/api/content.d.ts +2 -2
  13. package/dist/api/content.d.ts.map +1 -1
  14. package/dist/api/content.js +160 -26
  15. package/dist/api/content.js.map +1 -1
  16. package/dist/api/entries.d.ts.map +1 -1
  17. package/dist/api/entries.js +8 -4
  18. package/dist/api/entries.js.map +1 -1
  19. package/dist/api/github-sync.d.ts.map +1 -1
  20. package/dist/api/github-sync.js +45 -7
  21. package/dist/api/github-sync.js.map +1 -1
  22. package/dist/api/groups.d.ts.map +1 -1
  23. package/dist/api/groups.js +15 -5
  24. package/dist/api/groups.js.map +1 -1
  25. package/dist/api/permissions.d.ts +6 -6
  26. package/dist/api/permissions.d.ts.map +1 -1
  27. package/dist/api/permissions.js +24 -9
  28. package/dist/api/permissions.js.map +1 -1
  29. package/dist/api/request-body-hash.d.ts +33 -0
  30. package/dist/api/request-body-hash.d.ts.map +1 -0
  31. package/dist/api/request-body-hash.js +43 -0
  32. package/dist/api/request-body-hash.js.map +1 -0
  33. package/dist/api/resolve-references.d.ts.map +1 -1
  34. package/dist/api/resolve-references.js +8 -1
  35. package/dist/api/resolve-references.js.map +1 -1
  36. package/dist/api/schema.js +9 -9
  37. package/dist/api/schema.js.map +1 -1
  38. package/dist/api/settings-helpers.d.ts +14 -1
  39. package/dist/api/settings-helpers.d.ts.map +1 -1
  40. package/dist/api/settings-helpers.js +11 -2
  41. package/dist/api/settings-helpers.js.map +1 -1
  42. package/dist/api/types.d.ts +10 -0
  43. package/dist/api/types.d.ts.map +1 -1
  44. package/dist/auth/caching-auth-plugin.d.ts +8 -1
  45. package/dist/auth/caching-auth-plugin.d.ts.map +1 -1
  46. package/dist/auth/caching-auth-plugin.js +6 -1
  47. package/dist/auth/caching-auth-plugin.js.map +1 -1
  48. package/dist/auth/index.d.ts +1 -0
  49. package/dist/auth/index.d.ts.map +1 -1
  50. package/dist/auth/index.js +1 -0
  51. package/dist/auth/index.js.map +1 -1
  52. package/dist/auth/plugin.d.ts +35 -0
  53. package/dist/auth/plugin.d.ts.map +1 -1
  54. package/dist/auth/plugin.js +27 -1
  55. package/dist/auth/plugin.js.map +1 -1
  56. package/dist/authorization/helpers.d.ts +16 -0
  57. package/dist/authorization/helpers.d.ts.map +1 -1
  58. package/dist/authorization/helpers.js +18 -0
  59. package/dist/authorization/helpers.js.map +1 -1
  60. package/dist/authorization/index.d.ts +1 -1
  61. package/dist/authorization/index.d.ts.map +1 -1
  62. package/dist/authorization/index.js +1 -1
  63. package/dist/authorization/index.js.map +1 -1
  64. package/dist/build/generate-ai-content.d.ts.map +1 -1
  65. package/dist/build/generate-ai-content.js +7 -0
  66. package/dist/build/generate-ai-content.js.map +1 -1
  67. package/dist/cli/cli.d.ts.map +1 -1
  68. package/dist/cli/cli.js +2 -1
  69. package/dist/cli/cli.js.map +1 -1
  70. package/dist/cli/generate-ai-content.js +1150 -355
  71. package/dist/cli/init.d.ts +1 -1
  72. package/dist/cli/init.d.ts.map +1 -1
  73. package/dist/cli/init.js +40 -13
  74. package/dist/cli/init.js.map +1 -1
  75. package/dist/cli/sync.d.ts.map +1 -1
  76. package/dist/cli/sync.js +88 -60
  77. package/dist/cli/sync.js.map +1 -1
  78. package/dist/cli/template-files/canopy.ts.template +2 -1
  79. package/dist/cli/template-files/edit-page.tsx.template +8 -1
  80. package/dist/cli/template-files/middleware.ts.template +18 -0
  81. package/dist/cli/templates.d.ts.map +1 -1
  82. package/dist/cli/templates.js +19 -4
  83. package/dist/cli/templates.js.map +1 -1
  84. package/dist/config/helpers.d.ts +9 -1
  85. package/dist/config/helpers.d.ts.map +1 -1
  86. package/dist/config/helpers.js +33 -75
  87. package/dist/config/helpers.js.map +1 -1
  88. package/dist/config/schemas/config.d.ts +8 -24
  89. package/dist/config/schemas/config.d.ts.map +1 -1
  90. package/dist/config/schemas/config.js +12 -5
  91. package/dist/config/schemas/config.js.map +1 -1
  92. package/dist/config/schemas/media.d.ts +1 -10
  93. package/dist/config/schemas/media.d.ts.map +1 -1
  94. package/dist/config/schemas/media.js +8 -6
  95. package/dist/config/schemas/media.js.map +1 -1
  96. package/dist/config/types.d.ts +6 -4
  97. package/dist/config/types.d.ts.map +1 -1
  98. package/dist/config-test.d.ts +5 -3
  99. package/dist/config-test.d.ts.map +1 -1
  100. package/dist/config-test.js +9 -1
  101. package/dist/config-test.js.map +1 -1
  102. package/dist/content-id-index.d.ts +12 -6
  103. package/dist/content-id-index.d.ts.map +1 -1
  104. package/dist/content-id-index.js +12 -6
  105. package/dist/content-id-index.js.map +1 -1
  106. package/dist/content-index-generation.d.ts +30 -0
  107. package/dist/content-index-generation.d.ts.map +1 -0
  108. package/dist/content-index-generation.js +131 -0
  109. package/dist/content-index-generation.js.map +1 -0
  110. package/dist/content-index-registry.d.ts +38 -0
  111. package/dist/content-index-registry.d.ts.map +1 -0
  112. package/dist/content-index-registry.js +53 -0
  113. package/dist/content-index-registry.js.map +1 -0
  114. package/dist/content-listing.d.ts +3 -1
  115. package/dist/content-listing.d.ts.map +1 -1
  116. package/dist/content-listing.js +1 -0
  117. package/dist/content-listing.js.map +1 -1
  118. package/dist/content-store.d.ts +130 -6
  119. package/dist/content-store.d.ts.map +1 -1
  120. package/dist/content-store.js +343 -31
  121. package/dist/content-store.js.map +1 -1
  122. package/dist/editor/Editor.d.ts.map +1 -1
  123. package/dist/editor/Editor.js +27 -19
  124. package/dist/editor/Editor.js.map +1 -1
  125. package/dist/editor/FormRenderer.d.ts +7 -0
  126. package/dist/editor/FormRenderer.d.ts.map +1 -1
  127. package/dist/editor/FormRenderer.js +12 -3
  128. package/dist/editor/FormRenderer.js.map +1 -1
  129. package/dist/editor/components/EditorHeader.d.ts.map +1 -1
  130. package/dist/editor/components/EditorHeader.js +3 -4
  131. package/dist/editor/components/EditorHeader.js.map +1 -1
  132. package/dist/editor/components/EditorSidebar.d.ts.map +1 -1
  133. package/dist/editor/components/EditorSidebar.js +2 -4
  134. package/dist/editor/components/EditorSidebar.js.map +1 -1
  135. package/dist/editor/fields/ReferenceField.d.ts.map +1 -1
  136. package/dist/editor/fields/ReferenceField.js +19 -2
  137. package/dist/editor/fields/ReferenceField.js.map +1 -1
  138. package/dist/editor/group-manager/hooks/useGroupState.d.ts.map +1 -1
  139. package/dist/editor/group-manager/hooks/useGroupState.js +5 -2
  140. package/dist/editor/group-manager/hooks/useGroupState.js.map +1 -1
  141. package/dist/editor/hooks/useDraftManager.d.ts +15 -0
  142. package/dist/editor/hooks/useDraftManager.d.ts.map +1 -1
  143. package/dist/editor/hooks/useDraftManager.js +140 -1
  144. package/dist/editor/hooks/useDraftManager.js.map +1 -1
  145. package/dist/editor/hooks/useEntryManager.d.ts +9 -2
  146. package/dist/editor/hooks/useEntryManager.d.ts.map +1 -1
  147. package/dist/editor/hooks/useEntryManager.js +9 -3
  148. package/dist/editor/hooks/useEntryManager.js.map +1 -1
  149. package/dist/editor/hooks/useSchemaManager.d.ts +34 -10
  150. package/dist/editor/hooks/useSchemaManager.d.ts.map +1 -1
  151. package/dist/editor/hooks/useSchemaManager.js +22 -25
  152. package/dist/editor/hooks/useSchemaManager.js.map +1 -1
  153. package/dist/editor/schema-editor/CollectionEditor.d.ts +6 -5
  154. package/dist/editor/schema-editor/CollectionEditor.d.ts.map +1 -1
  155. package/dist/editor/schema-editor/CollectionEditor.js +37 -12
  156. package/dist/editor/schema-editor/CollectionEditor.js.map +1 -1
  157. package/dist/entry-link-resolver.d.ts.map +1 -1
  158. package/dist/entry-link-resolver.js +5 -0
  159. package/dist/entry-link-resolver.js.map +1 -1
  160. package/dist/git-manager.d.ts +38 -3
  161. package/dist/git-manager.d.ts.map +1 -1
  162. package/dist/git-manager.js +141 -33
  163. package/dist/git-manager.js.map +1 -1
  164. package/dist/github-service.d.ts +69 -3
  165. package/dist/github-service.d.ts.map +1 -1
  166. package/dist/github-service.js +149 -25
  167. package/dist/github-service.js.map +1 -1
  168. package/dist/http/handler.d.ts +1 -1
  169. package/dist/http/handler.d.ts.map +1 -1
  170. package/dist/http/handler.js +36 -7
  171. package/dist/http/handler.js.map +1 -1
  172. package/dist/http/router.d.ts +11 -0
  173. package/dist/http/router.d.ts.map +1 -1
  174. package/dist/http/router.js +80 -16
  175. package/dist/http/router.js.map +1 -1
  176. package/dist/paths/validation.d.ts.map +1 -1
  177. package/dist/paths/validation.js +12 -0
  178. package/dist/paths/validation.js.map +1 -1
  179. package/dist/schema/schema-store.d.ts +9 -0
  180. package/dist/schema/schema-store.d.ts.map +1 -1
  181. package/dist/schema/schema-store.js +57 -8
  182. package/dist/schema/schema-store.js.map +1 -1
  183. package/dist/services.d.ts +1 -0
  184. package/dist/services.d.ts.map +1 -1
  185. package/dist/services.js +9 -2
  186. package/dist/services.js.map +1 -1
  187. package/dist/static/index.d.ts +32 -0
  188. package/dist/static/index.d.ts.map +1 -1
  189. package/dist/static/index.js +90 -0
  190. package/dist/static/index.js.map +1 -1
  191. package/dist/sync-core.d.ts.map +1 -1
  192. package/dist/sync-core.js +22 -9
  193. package/dist/sync-core.js.map +1 -1
  194. package/dist/user.d.ts +0 -18
  195. package/dist/user.d.ts.map +1 -1
  196. package/dist/user.js +7 -22
  197. package/dist/user.js.map +1 -1
  198. package/dist/utils/error.d.ts +8 -0
  199. package/dist/utils/error.d.ts.map +1 -1
  200. package/dist/utils/error.js +35 -7
  201. package/dist/utils/error.js.map +1 -1
  202. package/dist/validation/deletion-checker.d.ts.map +1 -1
  203. package/dist/validation/deletion-checker.js +6 -5
  204. package/dist/validation/deletion-checker.js.map +1 -1
  205. package/dist/validation/entry-validator.d.ts +67 -0
  206. package/dist/validation/entry-validator.d.ts.map +1 -0
  207. package/dist/validation/entry-validator.js +277 -0
  208. package/dist/validation/entry-validator.js.map +1 -0
  209. package/dist/validation/field-traversal.d.ts +23 -1
  210. package/dist/validation/field-traversal.d.ts.map +1 -1
  211. package/dist/validation/field-traversal.js +29 -9
  212. package/dist/validation/field-traversal.js.map +1 -1
  213. package/dist/worker/cms-worker.d.ts +70 -6
  214. package/dist/worker/cms-worker.d.ts.map +1 -1
  215. package/dist/worker/cms-worker.js +199 -93
  216. package/dist/worker/cms-worker.js.map +1 -1
  217. package/package.json +2 -2
  218. package/dist/editor/components/EditorContext.d.ts +0 -35
  219. package/dist/editor/components/EditorContext.d.ts.map +0 -1
  220. package/dist/editor/components/EditorContext.js +0 -19
  221. package/dist/editor/components/EditorContext.js.map +0 -1
  222. package/dist/editor/env.d.ts +0 -5
  223. package/dist/editor/env.d.ts.map +0 -1
  224. package/dist/editor/env.js +0 -5
  225. package/dist/editor/env.js.map +0 -1
package/dist/user.d.ts CHANGED
@@ -29,24 +29,6 @@ export type CanopyUser = AnonymousUser | AuthenticatedUser;
29
29
  * Callers must explicitly pass this to indicate anonymous access is intended.
30
30
  */
31
31
  export declare const ANONYMOUS_USER: AnonymousUser;
32
- /**
33
- * Type guard for anonymous user
34
- */
35
- export declare const isAnonymousUser: (user: CanopyUser) => user is AnonymousUser;
36
- /**
37
- * Type guard for authenticated user
38
- */
39
- export declare const isAuthenticatedUser: (user: CanopyUser) => user is AuthenticatedUser;
40
- /**
41
- * Create an authenticated user from auth provider data
42
- */
43
- export declare const createAuthenticatedUser: (data: {
44
- userId: CanopyUserId;
45
- groups?: CanopyGroupId[];
46
- email?: string;
47
- name?: string;
48
- avatarUrl?: string;
49
- }) => AuthenticatedUser;
50
32
  /**
51
33
  * Convert authentication result to CanopyUser.
52
34
  * Applies bootstrap admin groups, merges internal groups, and returns ANONYMOUS_USER if not authenticated.
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAGxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAElE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,SAAS,EAAE,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAA;IACrB,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,iBAAiB,CAAA;AAE1D;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,aAIV,CAAA;AAEnB;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,UAAU,KAAG,IAAI,IAAI,aAChC,CAAA;AAE3B;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,UAAU,KAAG,IAAI,IAAI,iBAChC,CAAA;AAE/B;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM;IAC5C,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,CAAC,EAAE,aAAa,EAAE,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,KAAG,iBAOF,CAAA;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,oBAAoB,EAChC,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC9B,cAAc,CAAC,EAAE,aAAa,EAAE,GAC/B,UAAU,CA8BZ"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAGxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAElE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,SAAS,EAAE,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAA;IACrB,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,iBAAiB,CAAA;AAE1D;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,aAIV,CAAA;AAEnB;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,oBAAoB,EAChC,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,EAC9B,cAAc,CAAC,EAAE,aAAa,EAAE,GAC/B,UAAU,CAkCZ"}
package/dist/user.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Import from client-safe subpaths to avoid pulling in server-only loader code
2
- import { RESERVED_GROUPS } from './authorization/helpers.js';
2
+ import { RESERVED_GROUPS, stripReservedGroups } from './authorization/helpers.js';
3
3
  /**
4
4
  * Branded ANONYMOUS_USER constant - use this for intentional anonymous access.
5
5
  * Callers must explicitly pass this to indicate anonymous access is intended.
@@ -9,25 +9,6 @@ export const ANONYMOUS_USER = Object.freeze({
9
9
  userId: 'anonymous',
10
10
  groups: [],
11
11
  });
12
- /**
13
- * Type guard for anonymous user
14
- */
15
- export const isAnonymousUser = (user) => user.type === 'anonymous';
16
- /**
17
- * Type guard for authenticated user
18
- */
19
- export const isAuthenticatedUser = (user) => user.type === 'authenticated';
20
- /**
21
- * Create an authenticated user from auth provider data
22
- */
23
- export const createAuthenticatedUser = (data) => ({
24
- type: 'authenticated',
25
- userId: data.userId,
26
- groups: data.groups ?? [],
27
- email: data.email,
28
- name: data.name,
29
- avatarUrl: data.avatarUrl,
30
- });
31
12
  /**
32
13
  * Convert authentication result to CanopyUser.
33
14
  * Applies bootstrap admin groups, merges internal groups, and returns ANONYMOUS_USER if not authenticated.
@@ -43,8 +24,12 @@ export function authResultToCanopyUser(authResult, bootstrapAdminIds, internalGr
43
24
  if (!authResult.success || !authResult.user) {
44
25
  return ANONYMOUS_USER;
45
26
  }
46
- // Step 1: Start with external groups from auth provider
47
- const groups = [...(authResult.user.externalGroups ?? [])];
27
+ // Step 1: Start with external groups from the auth provider.
28
+ // SECURITY (SEC-H1): reserved privileged group IDs (Admins/Reviewers) are
29
+ // stripped here so a provider-controlled group name can never grant
30
+ // CanopyCMS privilege. Reserved membership is only added below, from
31
+ // bootstrapAdminIds and Canopy-managed internal groups.
32
+ const groups = stripReservedGroups(authResult.user.externalGroups ?? []);
48
33
  // Step 2: Add Admins group if user is in bootstrap admin list
49
34
  if (bootstrapAdminIds.has(authResult.user.userId) && !groups.includes(RESERVED_GROUPS.ADMINS)) {
50
35
  groups.push(RESERVED_GROUPS.ADMINS);
package/dist/user.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"user.js","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAEA,+EAA+E;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AA6BzD;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAkB,MAAM,CAAC,MAAM,CAAC;IACzD,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,EAAW;CACpB,CAAkB,CAAA;AAEnB;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAgB,EAAyB,EAAE,CACzE,IAAI,CAAC,IAAI,KAAK,WAAW,CAAA;AAE3B;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAgB,EAA6B,EAAE,CACjF,IAAI,CAAC,IAAI,KAAK,eAAe,CAAA;AAE/B;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,IAMvC,EAAqB,EAAE,CAAC,CAAC;IACxB,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,IAAI,CAAC,MAAM;IACnB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;IACzB,KAAK,EAAE,IAAI,CAAC,KAAK;IACjB,IAAI,EAAE,IAAI,CAAC,IAAI;IACf,SAAS,EAAE,IAAI,CAAC,SAAS;CAC1B,CAAC,CAAA;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CACpC,UAAgC,EAChC,iBAA8B,EAC9B,cAAgC;IAEhC,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC5C,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,wDAAwD;IACxD,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,CAAA;IAE1D,8DAA8D;IAC9D,IAAI,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9F,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;IAED,4DAA4D;IAC5D,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBACjF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM;QAC9B,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK;QAC5B,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI;QAC1B,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS;QACpC,MAAM;KACP,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"user.js","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAEA,+EAA+E;AAC/E,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AA6B9E;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAkB,MAAM,CAAC,MAAM,CAAC;IACzD,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,EAAW;CACpB,CAAkB,CAAA;AAEnB;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CACpC,UAAgC,EAChC,iBAA8B,EAC9B,cAAgC;IAEhC,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC5C,OAAO,cAAc,CAAA;IACvB,CAAC;IAED,6DAA6D;IAC7D,0EAA0E;IAC1E,oEAAoE;IACpE,qEAAqE;IACrE,wDAAwD;IACxD,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,CAAA;IAExE,8DAA8D;IAC9D,IAAI,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9F,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;IAED,4DAA4D;IAC5D,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBACjF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM;QAC9B,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK;QAC5B,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI;QAC1B,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS;QACpC,MAAM;KACP,CAAA;AACH,CAAC"}
@@ -36,6 +36,14 @@ export declare function getErrorMessage(err: unknown): string;
36
36
  * and not sensitive); absolute paths outside it are replaced with `<path>`.
37
37
  */
38
38
  export declare function sanitizeErrorMessage(message: string): string;
39
+ /**
40
+ * Redact only credential material from a message, leaving filesystem paths
41
+ * intact. For server-side log lines that deliberately keep full path detail
42
+ * (server logs only, useful for debugging) but must never persist a live
43
+ * token — client-facing messages go through sanitizeErrorMessage instead,
44
+ * which calls this and then also redacts paths.
45
+ */
46
+ export declare function redactCredentials(message: string): string;
39
47
  /**
40
48
  * Type guard to check if an error is a Node.js system error with a code property.
41
49
  *
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAQpD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA8B5D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAAC,cAAc,CAEtE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEvD"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAQpD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAsC5D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAAC,cAAc,CAEtE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEvD"}
@@ -44,12 +44,7 @@ export function getErrorMessage(err) {
44
44
  * and not sensitive); absolute paths outside it are replaced with `<path>`.
45
45
  */
46
46
  export function sanitizeErrorMessage(message) {
47
- let result = message;
48
- // Credentials in URLs: scheme://user:token@host or scheme://token@host.
49
- // Anchored on the literal `://` (leaving the scheme untouched) — a `\w+`
50
- // scheme prefix would backtrack polynomially on long word-character runs
51
- // (CodeQL js/polynomial-redos).
52
- result = result.replace(/(:\/\/)[^/\s@]+@/g, '$1***@');
47
+ let result = redactCredentials(message);
53
48
  // Paths under the project root become relative (split/join avoids regex
54
49
  // escaping issues with arbitrary cwd values). The bare-cwd replacement is
55
50
  // anchored to a token boundary so sibling directories that merely share
@@ -59,6 +54,10 @@ export function sanitizeErrorMessage(message) {
59
54
  if (cwd !== '/') {
60
55
  result = result.split(`${cwd}/`).join('');
61
56
  const cwdPattern = cwd.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
57
+ // cwdPattern is process.cwd() (server-controlled, not attacker/entry-content
58
+ // data) with regex metacharacters escaped by the literal regex above, so
59
+ // this cannot be used to inject an attacker-chosen pattern.
60
+ // eslint-disable-next-line security/detect-non-literal-regexp
62
61
  result = result.replace(new RegExp(`${cwdPattern}(?=[\\s'"),:;]|$)`, 'g'), '.');
63
62
  }
64
63
  // Quoted absolute paths (git quotes most paths in its messages): redact
@@ -69,11 +68,40 @@ export function sanitizeErrorMessage(message) {
69
68
  // limitation: an UNQUOTED path containing spaces is only redacted up to
70
69
  // the first space — spaces are legal both inside paths and as message
71
70
  // separators, so this is not generally solvable here.
72
- result = result.replace(/(^|[\s'"(=])\/(?:[^/\s'")]+\/)+[^/\s'")]*/g, '$1<path>');
71
+ //
72
+ // The repeated group `(?:[^/\s'")]+\/)+` looks nested-quantifier-shaped, but
73
+ // the inner character class excludes `/`, so each repetition can only end at
74
+ // a literal `/` boundary in the input: there is exactly one way to decompose
75
+ // any matched string into repetitions (no same-substring ambiguity), so this
76
+ // does not backtrack catastrophically. Verified empirically with inputs up
77
+ // to 400k chars (adversarial runs of non-slash chars, with and without
78
+ // trailing slashes): scaling stayed linear, not quadratic/exponential.
79
+ // eslint-disable-next-line security/detect-unsafe-regex
80
+ result = result.replace(/(^|[\s'"(=:,[])\/(?:[^/\s'")]+\/)+[^/\s'")]*/g, '$1<path>');
73
81
  // Windows drive paths
74
82
  result = result.replace(/[A-Za-z]:\\[^\s'")]+/g, '<path>');
75
83
  return result;
76
84
  }
85
+ /**
86
+ * Redact only credential material from a message, leaving filesystem paths
87
+ * intact. For server-side log lines that deliberately keep full path detail
88
+ * (server logs only, useful for debugging) but must never persist a live
89
+ * token — client-facing messages go through sanitizeErrorMessage instead,
90
+ * which calls this and then also redacts paths.
91
+ */
92
+ export function redactCredentials(message) {
93
+ let result = message;
94
+ // Credentials in URLs: scheme://user:token@host or scheme://token@host.
95
+ // Anchored on the literal `://` (leaving the scheme untouched) — a `\w+`
96
+ // scheme prefix would backtrack polynomially on long word-character runs
97
+ // (CodeQL js/polynomial-redos).
98
+ result = result.replace(/(:\/\/)[^/\s@]+@/g, '$1***@');
99
+ // Bare token shapes (defense-in-depth for messages that embed a token
100
+ // outside URL userinfo): GitHub token prefixes and Bearer values.
101
+ result = result.replace(/\b(?:gh[pousr]|github_pat)_[A-Za-z0-9_]{8,}/g, '***');
102
+ result = result.replace(/\b(Bearer\s+)[A-Za-z0-9._~+/=-]{8,}/g, '$1***');
103
+ return result;
104
+ }
77
105
  /**
78
106
  * Type guard to check if an error is a Node.js system error with a code property.
79
107
  *
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,OAAO,CAAA;IACpB,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;AACpB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,IAAI,MAAM,GAAG,OAAO,CAAA;IACpB,wEAAwE;IACxE,yEAAyE;IACzE,yEAAyE;IACzE,gCAAgC;IAChC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAA;IACtD,wEAAwE;IACxE,0EAA0E;IAC1E,wEAAwE;IACxE,qEAAqE;IACrE,yDAAyD;IACzD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;QAChB,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACzC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;QAC7D,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,mBAAmB,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;IACjF,CAAC;IACD,wEAAwE;IACxE,0CAA0C;IAC1C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IACnF,qEAAqE;IACrE,yEAAyE;IACzE,wEAAwE;IACxE,sEAAsE;IACtE,sDAAsD;IACtD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,4CAA4C,EAAE,UAAU,CAAC,CAAA;IACjF,sBAAsB;IACtB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAA;IAC1D,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,OAAO,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,CAAA;AAC9C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAA;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAA;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAA;AAClD,CAAC"}
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"deletion-checker.d.ts","sourceRoot":"","sources":["../../src/validation/deletion-checker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,IAAI,EAAqB,MAAM,UAAU,CAAA;AAEzE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,WAAW,CAAA;IACvB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,aAAa,EAAE,CAAA;CAC9B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eAAe;IAExB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,WAAW;gBAFX,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE;QAAE,MAAM,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;IAGlE;;;;;OAKG;IACG,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQzD;;;;;OAKG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAYhE;;OAEG;YACW,cAAc;IAkC5B;;;OAGG;IACH,OAAO,CAAC,YAAY;IA4FpB;;OAEG;IACH,OAAO,CAAC,uBAAuB;CAgChC"}
1
+ {"version":3,"file":"deletion-checker.d.ts","sourceRoot":"","sources":["../../src/validation/deletion-checker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,IAAI,EAAqB,MAAM,UAAU,CAAA;AAGzE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,WAAW,CAAA;IACvB,IAAI,EAAE,IAAI,CAAA;IACV,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,aAAa,EAAE,CAAA;CAC9B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eAAe;IAExB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,WAAW;gBAFX,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE;QAAE,MAAM,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;IAGlE;;;;;OAKG;IACG,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQzD;;;;;OAKG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAYhE;;OAEG;YACW,cAAc;IAkC5B;;;OAGG;IACH,OAAO,CAAC,YAAY;IA4FpB;;OAEG;IACH,OAAO,CAAC,uBAAuB;CAgChC"}
@@ -1,3 +1,4 @@
1
+ import { resolveBlockItem } from './field-traversal.js';
1
2
  /**
2
3
  * DeletionChecker finds all references to an entry before deletion.
3
4
  *
@@ -121,15 +122,15 @@ export class DeletionChecker {
121
122
  }
122
123
  }
123
124
  else if (field.type === 'block') {
124
- // Handle block fields
125
+ // Handle block fields — real block items are { template, value }, with
126
+ // nested field values under `value` (resolved by resolveBlockItem)
125
127
  const blockField = field;
126
128
  if (Array.isArray(value)) {
127
129
  value.forEach((item, index) => {
128
130
  if (typeof item === 'object' && item !== null) {
129
- const blockType = item._type;
130
- const blockDef = blockField.templates?.find((b) => b.name === blockType);
131
- if (blockDef && blockDef.fields) {
132
- found.push(...this.findIdInData(item, targetId, blockDef.fields, `${fieldPath}[${index}]`));
131
+ const resolved = resolveBlockItem(blockField, item);
132
+ if (resolved) {
133
+ found.push(...this.findIdInData(resolved.data, targetId, resolved.fields, `${fieldPath}[${index}]`));
133
134
  }
134
135
  }
135
136
  });
@@ -1 +1 @@
1
- {"version":3,"file":"deletion-checker.js","sourceRoot":"","sources":["../../src/validation/deletion-checker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deletion-checker.js","sourceRoot":"","sources":["../../src/validation/deletion-checker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Pure, isomorphic schema validation for entry data.
3
+ *
4
+ * This module is the single source of the schema-driven validation rules that
5
+ * run BOTH client-side (pre-save UX in the editor) and server-side (the
6
+ * authoritative write boundary in api/content.ts). It therefore must stay free
7
+ * of server-only imports (node:fs, ContentStore, ContentIdIndex, ...) — it may
8
+ * only depend on config types and other pure modules.
9
+ *
10
+ * What it checks (pure rules — no filesystem access):
11
+ * - required fields are present and non-empty
12
+ * - values match their field type (string/number/boolean/datetime/select/...)
13
+ * - `list` fields hold arrays; non-list fields hold single values
14
+ * - select values are one of the configured options
15
+ * - reference values are well-formed (id string or resolved `{ id }` object)
16
+ * and non-empty when required
17
+ * - block items resolve to a known template (via the shared `resolveBlockItem`
18
+ * from field-traversal, so `{ template, value }`-nested fields are validated)
19
+ *
20
+ * Reference EXISTENCE is intentionally NOT checked here: it requires the
21
+ * content ID index (filesystem) and is enforced server-side only, by running
22
+ * `ReferenceValidator` at the write boundary.
23
+ */
24
+ import type { ContentFormat, EntrySchema } from '../config';
25
+ /**
26
+ * One per-field validation error. `fieldPath` uses the canonical CanopyCMS
27
+ * path format shared with field-traversal and the editor's canopy-path
28
+ * helpers: dot notation with bracketed indices (e.g. `blocks[0].title`).
29
+ */
30
+ export interface EntryFieldError {
31
+ fieldPath: string;
32
+ message: string;
33
+ }
34
+ /**
35
+ * Extract the id from a reference value. The editor holds references either
36
+ * as an id string or as a resolved object `{ id, slug, collection, ... }`
37
+ * (content reads resolve references by default). Returns undefined for any
38
+ * other shape.
39
+ */
40
+ export declare function referenceValueId(value: unknown): string | undefined;
41
+ /**
42
+ * Merge an md/mdx body string into the data record under the schema's body
43
+ * field name (`isBody: true`, defaulting to `'body'`), so required/type checks
44
+ * apply to the body like any other field.
45
+ */
46
+ export declare function mergeBodyIntoData(fields: EntrySchema, data: Record<string, unknown>, body: string | undefined): Record<string, unknown>;
47
+ /**
48
+ * Validate entry data against an entry schema. Pure — safe to run in the
49
+ * browser. Returns one error per offending field path; an empty array means
50
+ * the data is structurally valid.
51
+ */
52
+ export declare function validateEntryData(fields: EntrySchema, data: Record<string, unknown>, pathPrefix?: string): EntryFieldError[];
53
+ /**
54
+ * Validate an editor FormValue (client-side entry point). For md/mdx formats
55
+ * the editor keeps the body under the literal `body` key; remap it to the
56
+ * schema's body field before validating so required/type checks see it.
57
+ */
58
+ export declare function validateEntryFormValue(fields: EntrySchema, format: ContentFormat | undefined, value: Record<string, unknown>): EntryFieldError[];
59
+ /**
60
+ * Return a copy of `data` with resolved reference objects (`{ id, ... }`)
61
+ * collapsed back to their id strings, recursing through objects, lists, and
62
+ * block `{ template, value }` items. Used server-side so `ReferenceValidator`
63
+ * (which expects id strings) can check reference existence on editor payloads
64
+ * that may still carry resolved objects from a prior read.
65
+ */
66
+ export declare function normalizeReferenceValues(fields: EntrySchema, data: Record<string, unknown>): Record<string, unknown>;
67
+ //# sourceMappingURL=entry-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-validator.d.ts","sourceRoot":"","sources":["../../src/validation/entry-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAEV,aAAa,EACb,WAAW,EAMZ,MAAM,WAAW,CAAA;AAMlB;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAWD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAInE;AAKD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGzB;AAyDD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,UAAU,SAAK,GACd,eAAe,EAAE,CAiGnB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,aAAa,GAAG,SAAS,EACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,eAAe,EAAE,CASnB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqDzB"}
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Pure, isomorphic schema validation for entry data.
3
+ *
4
+ * This module is the single source of the schema-driven validation rules that
5
+ * run BOTH client-side (pre-save UX in the editor) and server-side (the
6
+ * authoritative write boundary in api/content.ts). It therefore must stay free
7
+ * of server-only imports (node:fs, ContentStore, ContentIdIndex, ...) — it may
8
+ * only depend on config types and other pure modules.
9
+ *
10
+ * What it checks (pure rules — no filesystem access):
11
+ * - required fields are present and non-empty
12
+ * - values match their field type (string/number/boolean/datetime/select/...)
13
+ * - `list` fields hold arrays; non-list fields hold single values
14
+ * - select values are one of the configured options
15
+ * - reference values are well-formed (id string or resolved `{ id }` object)
16
+ * and non-empty when required
17
+ * - block items resolve to a known template (via the shared `resolveBlockItem`
18
+ * from field-traversal, so `{ template, value }`-nested fields are validated)
19
+ *
20
+ * Reference EXISTENCE is intentionally NOT checked here: it requires the
21
+ * content ID index (filesystem) and is enforced server-side only, by running
22
+ * `ReferenceValidator` at the write boundary.
23
+ */
24
+ import { fieldTypes } from '../config/index.js';
25
+ import { resolveBlockItem } from './field-traversal.js';
26
+ import { findBodyFieldName } from '../utils/body-field.js';
27
+ import { isDataOnlyFormat } from '../utils/format.js';
28
+ const KNOWN_FIELD_TYPES = new Set(fieldTypes);
29
+ /** Field types whose value is a plain string. */
30
+ const STRING_FIELD_TYPES = new Set(['string', 'rich-text', 'markdown', 'mdx', 'image', 'code']);
31
+ function isPlainRecord(value) {
32
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
33
+ }
34
+ /**
35
+ * Extract the id from a reference value. The editor holds references either
36
+ * as an id string or as a resolved object `{ id, slug, collection, ... }`
37
+ * (content reads resolve references by default). Returns undefined for any
38
+ * other shape.
39
+ */
40
+ export function referenceValueId(value) {
41
+ if (typeof value === 'string')
42
+ return value;
43
+ if (isPlainRecord(value) && typeof value.id === 'string')
44
+ return value.id;
45
+ return undefined;
46
+ }
47
+ const selectOptionValues = (field) => (field.options ?? []).map((opt) => (typeof opt === 'string' ? opt : opt.value));
48
+ /**
49
+ * Merge an md/mdx body string into the data record under the schema's body
50
+ * field name (`isBody: true`, defaulting to `'body'`), so required/type checks
51
+ * apply to the body like any other field.
52
+ */
53
+ export function mergeBodyIntoData(fields, data, body) {
54
+ if (body === undefined)
55
+ return data;
56
+ return { ...data, [findBodyFieldName(fields)]: body };
57
+ }
58
+ /** Validate a single scalar (non-object, non-block) value against its field type. */
59
+ function validateScalar(field, value, path) {
60
+ switch (field.type) {
61
+ case 'number':
62
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
63
+ return [{ fieldPath: path, message: 'Expected a number' }];
64
+ }
65
+ return [];
66
+ case 'boolean':
67
+ if (typeof value !== 'boolean') {
68
+ return [{ fieldPath: path, message: 'Expected true or false' }];
69
+ }
70
+ return [];
71
+ case 'datetime':
72
+ if (typeof value !== 'string' || (value !== '' && Number.isNaN(Date.parse(value)))) {
73
+ return [{ fieldPath: path, message: 'Expected a valid date/time string' }];
74
+ }
75
+ return [];
76
+ case 'select': {
77
+ if (typeof value !== 'string') {
78
+ return [{ fieldPath: path, message: 'Expected a selection' }];
79
+ }
80
+ const options = selectOptionValues(field);
81
+ if (value !== '' && !options.includes(value)) {
82
+ return [{ fieldPath: path, message: `Must be one of: ${options.join(', ')}` }];
83
+ }
84
+ return [];
85
+ }
86
+ case 'reference':
87
+ if (referenceValueId(value) === undefined) {
88
+ return [{ fieldPath: path, message: 'Expected a reference id' }];
89
+ }
90
+ return [];
91
+ default:
92
+ if (STRING_FIELD_TYPES.has(field.type)) {
93
+ if (typeof value !== 'string') {
94
+ return [{ fieldPath: path, message: 'Expected text' }];
95
+ }
96
+ }
97
+ // Custom (adopter-defined) field types: semantics unknown, skip type checks.
98
+ return [];
99
+ }
100
+ }
101
+ /** True when a required field should be considered missing/empty. */
102
+ function isEmptyForRequired(field, value) {
103
+ if (value === undefined || value === null)
104
+ return true;
105
+ if (Array.isArray(value))
106
+ return value.length === 0;
107
+ if (typeof value === 'string') {
108
+ // Strings, selects, references, datetimes: empty string means "not filled in".
109
+ return value.trim() === '';
110
+ }
111
+ return false;
112
+ }
113
+ /**
114
+ * Validate entry data against an entry schema. Pure — safe to run in the
115
+ * browser. Returns one error per offending field path; an empty array means
116
+ * the data is structurally valid.
117
+ */
118
+ export function validateEntryData(fields, data, pathPrefix = '') {
119
+ const errors = [];
120
+ for (const field of fields) {
121
+ // Inline groups are transparent to the data — children live at this level.
122
+ if (field.type === 'group') {
123
+ errors.push(...validateEntryData(field.fields, data, pathPrefix));
124
+ continue;
125
+ }
126
+ const path = pathPrefix ? `${pathPrefix}.${field.name}` : field.name;
127
+ const value = data[field.name];
128
+ const isRequired = 'required' in field && field.required === true;
129
+ if (isRequired && isEmptyForRequired(field, value)) {
130
+ const message = Array.isArray(value)
131
+ ? 'At least one item is required'
132
+ : 'This field is required';
133
+ errors.push({ fieldPath: path, message });
134
+ continue;
135
+ }
136
+ // Optional and absent: nothing further to check.
137
+ if (value === undefined || value === null)
138
+ continue;
139
+ if (field.type === 'block') {
140
+ const blockField = field;
141
+ if (!Array.isArray(value)) {
142
+ errors.push({ fieldPath: path, message: 'Expected a list of blocks' });
143
+ continue;
144
+ }
145
+ value.forEach((item, index) => {
146
+ const itemPath = `${path}[${index}]`;
147
+ if (!isPlainRecord(item)) {
148
+ errors.push({ fieldPath: itemPath, message: 'Expected a block object' });
149
+ return;
150
+ }
151
+ const resolved = resolveBlockItem(blockField, item);
152
+ if (!resolved) {
153
+ const template = typeof item.template === 'string' ? item.template : undefined;
154
+ errors.push({
155
+ fieldPath: itemPath,
156
+ message: template ? `Unknown block template "${template}"` : 'Missing block template',
157
+ });
158
+ return;
159
+ }
160
+ errors.push(...validateEntryData(resolved.fields, resolved.data, itemPath));
161
+ });
162
+ continue;
163
+ }
164
+ if (field.type === 'object') {
165
+ const objectField = field;
166
+ if (objectField.list) {
167
+ if (!Array.isArray(value)) {
168
+ errors.push({ fieldPath: path, message: 'Expected a list of items' });
169
+ continue;
170
+ }
171
+ value.forEach((item, index) => {
172
+ const itemPath = `${path}[${index}]`;
173
+ if (!isPlainRecord(item)) {
174
+ errors.push({ fieldPath: itemPath, message: 'Expected an object' });
175
+ return;
176
+ }
177
+ if (objectField.fields) {
178
+ errors.push(...validateEntryData(objectField.fields, item, itemPath));
179
+ }
180
+ });
181
+ }
182
+ else if (!isPlainRecord(value)) {
183
+ errors.push({ fieldPath: path, message: 'Expected an object' });
184
+ }
185
+ else if (objectField.fields) {
186
+ errors.push(...validateEntryData(objectField.fields, value, path));
187
+ }
188
+ continue;
189
+ }
190
+ // Scalar (and list-of-scalar) fields.
191
+ if ('list' in field && field.list) {
192
+ if (!Array.isArray(value)) {
193
+ errors.push({ fieldPath: path, message: 'Expected a list of values' });
194
+ continue;
195
+ }
196
+ value.forEach((item, index) => {
197
+ errors.push(...validateScalar(field, item, `${path}[${index}]`));
198
+ });
199
+ continue;
200
+ }
201
+ if (Array.isArray(value) && KNOWN_FIELD_TYPES.has(field.type)) {
202
+ errors.push({ fieldPath: path, message: 'Expected a single value, not a list' });
203
+ continue;
204
+ }
205
+ errors.push(...validateScalar(field, value, path));
206
+ }
207
+ return errors;
208
+ }
209
+ /**
210
+ * Validate an editor FormValue (client-side entry point). For md/mdx formats
211
+ * the editor keeps the body under the literal `body` key; remap it to the
212
+ * schema's body field before validating so required/type checks see it.
213
+ */
214
+ export function validateEntryFormValue(fields, format, value) {
215
+ if (format && !isDataOnlyFormat(format)) {
216
+ const { body, ...rest } = value;
217
+ return validateEntryData(fields, mergeBodyIntoData(fields, rest, typeof body === 'string' ? body : ''));
218
+ }
219
+ return validateEntryData(fields, value);
220
+ }
221
+ /**
222
+ * Return a copy of `data` with resolved reference objects (`{ id, ... }`)
223
+ * collapsed back to their id strings, recursing through objects, lists, and
224
+ * block `{ template, value }` items. Used server-side so `ReferenceValidator`
225
+ * (which expects id strings) can check reference existence on editor payloads
226
+ * that may still carry resolved objects from a prior read.
227
+ */
228
+ export function normalizeReferenceValues(fields, data) {
229
+ const result = { ...data };
230
+ for (const field of fields) {
231
+ if (field.type === 'group') {
232
+ Object.assign(result, normalizeReferenceValues(field.fields, result));
233
+ continue;
234
+ }
235
+ const value = result[field.name];
236
+ if (value === undefined || value === null)
237
+ continue;
238
+ if (field.type === 'reference') {
239
+ const refField = field;
240
+ if (refField.list && Array.isArray(value)) {
241
+ result[field.name] = value.map((item) => referenceValueId(item) ?? item);
242
+ }
243
+ else {
244
+ result[field.name] = referenceValueId(value) ?? value;
245
+ }
246
+ continue;
247
+ }
248
+ if (field.type === 'object') {
249
+ const objectField = field;
250
+ if (!objectField.fields)
251
+ continue;
252
+ if (objectField.list && Array.isArray(value)) {
253
+ result[field.name] = value.map((item) => isPlainRecord(item) ? normalizeReferenceValues(objectField.fields, item) : item);
254
+ }
255
+ else if (isPlainRecord(value)) {
256
+ result[field.name] = normalizeReferenceValues(objectField.fields, value);
257
+ }
258
+ continue;
259
+ }
260
+ if (field.type === 'block' && Array.isArray(value)) {
261
+ const blockField = field;
262
+ result[field.name] = value.map((item) => {
263
+ if (!isPlainRecord(item))
264
+ return item;
265
+ const resolved = resolveBlockItem(blockField, item);
266
+ if (!resolved)
267
+ return item;
268
+ const normalized = normalizeReferenceValues(resolved.fields, resolved.data);
269
+ // Canonical `{ template, value }` shape keeps nested values under `value`;
270
+ // the inline `_type` shape keeps them on the item itself.
271
+ return isPlainRecord(item.value) ? { ...item, value: normalized } : normalized;
272
+ });
273
+ }
274
+ }
275
+ return result;
276
+ }
277
+ //# sourceMappingURL=entry-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-validator.js","sourceRoot":"","sources":["../../src/validation/entry-validator.ts"],"names":[],"mappings":"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"}