@elastic/isomer-sdk 0.1.0 → 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.
Files changed (288) hide show
  1. package/NOTICE.txt +0 -286
  2. package/README.md +13 -2
  3. package/THIRD_PARTY_LICENSES.md +1 -885
  4. package/dist/author/authored_fields.d.ts +93 -18
  5. package/dist/author/authored_fields.d.ts.map +1 -1
  6. package/dist/author/authored_fields.js +63 -43
  7. package/dist/author/authored_fields.js.map +1 -1
  8. package/dist/author/authoring_input.d.ts +7 -0
  9. package/dist/author/authoring_input.d.ts.map +1 -0
  10. package/dist/author/authoring_input.js +66 -0
  11. package/dist/author/authoring_input.js.map +1 -0
  12. package/dist/author/authoring_model.d.ts +33 -0
  13. package/dist/author/authoring_model.d.ts.map +1 -0
  14. package/dist/author/authoring_model.js +142 -0
  15. package/dist/author/authoring_model.js.map +1 -0
  16. package/dist/author/declarations.d.ts +13 -0
  17. package/dist/author/declarations.d.ts.map +1 -0
  18. package/dist/author/declarations.js +288 -0
  19. package/dist/author/declarations.js.map +1 -0
  20. package/dist/author/index.d.ts +4 -1
  21. package/dist/author/index.d.ts.map +1 -1
  22. package/dist/author/index.js +4 -1
  23. package/dist/author/index.js.map +1 -1
  24. package/dist/author/jsx_shim.d.ts +50 -30
  25. package/dist/author/jsx_shim.d.ts.map +1 -1
  26. package/dist/author/jsx_shim.js +146 -138
  27. package/dist/author/jsx_shim.js.map +1 -1
  28. package/dist/author/print_jsx.d.ts +19 -0
  29. package/dist/author/print_jsx.d.ts.map +1 -0
  30. package/dist/author/print_jsx.js +372 -0
  31. package/dist/author/print_jsx.js.map +1 -0
  32. package/dist/author/prompt.d.ts +2 -2
  33. package/dist/author/prompt.d.ts.map +1 -1
  34. package/dist/author/prompt.js +7 -2
  35. package/dist/author/prompt.js.map +1 -1
  36. package/dist/author/schema_to_typescript.d.ts +37 -0
  37. package/dist/author/schema_to_typescript.d.ts.map +1 -0
  38. package/dist/author/schema_to_typescript.js +289 -0
  39. package/dist/author/schema_to_typescript.js.map +1 -0
  40. package/dist/cjs/author/authored_fields.js +68 -47
  41. package/dist/cjs/author/authored_fields.js.map +1 -1
  42. package/dist/cjs/author/authoring_input.js +70 -0
  43. package/dist/cjs/author/authoring_input.js.map +1 -0
  44. package/dist/cjs/author/authoring_model.js +149 -0
  45. package/dist/cjs/author/authoring_model.js.map +1 -0
  46. package/dist/cjs/author/declarations.js +292 -0
  47. package/dist/cjs/author/declarations.js.map +1 -0
  48. package/dist/cjs/author/index.js +10 -1
  49. package/dist/cjs/author/index.js.map +1 -1
  50. package/dist/cjs/author/jsx_shim.js +148 -140
  51. package/dist/cjs/author/jsx_shim.js.map +1 -1
  52. package/dist/cjs/author/print_jsx.js +378 -0
  53. package/dist/cjs/author/print_jsx.js.map +1 -0
  54. package/dist/cjs/author/prompt.js +7 -2
  55. package/dist/cjs/author/prompt.js.map +1 -1
  56. package/dist/cjs/author/schema_to_typescript.js +298 -0
  57. package/dist/cjs/author/schema_to_typescript.js.map +1 -0
  58. package/dist/cjs/composition/body_node_base.js +11 -4
  59. package/dist/cjs/composition/body_node_base.js.map +1 -1
  60. package/dist/cjs/composition/error.js +2 -0
  61. package/dist/cjs/composition/error.js.map +1 -1
  62. package/dist/cjs/composition/index.js +2 -1
  63. package/dist/cjs/composition/index.js.map +1 -1
  64. package/dist/cjs/composition/structured_value.js.map +1 -1
  65. package/dist/cjs/define/frame.js +2 -3
  66. package/dist/cjs/define/frame.js.map +1 -1
  67. package/dist/cjs/define/index.js +7 -1
  68. package/dist/cjs/define/index.js.map +1 -1
  69. package/dist/cjs/define/primitive_example.js +26 -0
  70. package/dist/cjs/define/primitive_example.js.map +1 -0
  71. package/dist/cjs/define/primitive_icon.js +17 -0
  72. package/dist/cjs/define/primitive_icon.js.map +1 -0
  73. package/dist/cjs/define/primitive_module.js +24 -7
  74. package/dist/cjs/define/primitive_module.js.map +1 -1
  75. package/dist/cjs/define/slack_assets.js.map +1 -1
  76. package/dist/cjs/entries/index.js +8 -2
  77. package/dist/cjs/entries/index.js.map +1 -1
  78. package/dist/cjs/entries/markdown.js +2 -1
  79. package/dist/cjs/entries/markdown.js.map +1 -1
  80. package/dist/cjs/entries/slack.js +1 -2
  81. package/dist/cjs/entries/slack.js.map +1 -1
  82. package/dist/cjs/pack/capabilities.js +17 -11
  83. package/dist/cjs/pack/capabilities.js.map +1 -1
  84. package/dist/cjs/pack/compose.js +4 -1
  85. package/dist/cjs/pack/compose.js.map +1 -1
  86. package/dist/cjs/pack/index.js +2 -1
  87. package/dist/cjs/pack/index.js.map +1 -1
  88. package/dist/cjs/pack/primitive_pack.js +27 -5
  89. package/dist/cjs/pack/primitive_pack.js.map +1 -1
  90. package/dist/cjs/render/anchors.js +1 -1
  91. package/dist/cjs/render/anchors.js.map +1 -1
  92. package/dist/cjs/render/format_number.js +2 -1
  93. package/dist/cjs/render/format_number.js.map +1 -1
  94. package/dist/cjs/render/html/envelope.js +12 -6
  95. package/dist/cjs/render/html/envelope.js.map +1 -1
  96. package/dist/cjs/render/layout_check.js.map +1 -1
  97. package/dist/cjs/render/markdown/builder.js +18 -8
  98. package/dist/cjs/render/markdown/builder.js.map +1 -1
  99. package/dist/cjs/render/markdown/format.js +70 -30
  100. package/dist/cjs/render/markdown/format.js.map +1 -1
  101. package/dist/cjs/render/markdown/host_tags.js +67 -0
  102. package/dist/cjs/render/markdown/host_tags.js.map +1 -0
  103. package/dist/cjs/render/markdown/index.js +3 -1
  104. package/dist/cjs/render/markdown/index.js.map +1 -1
  105. package/dist/cjs/render/markdown/split.js +325 -0
  106. package/dist/cjs/render/markdown/split.js.map +1 -0
  107. package/dist/cjs/render/primitive_dispatch.js +11 -25
  108. package/dist/cjs/render/primitive_dispatch.js.map +1 -1
  109. package/dist/cjs/render/react/content.js +3 -1
  110. package/dist/cjs/render/react/content.js.map +1 -1
  111. package/dist/cjs/render/slack/format.js +1 -601
  112. package/dist/cjs/render/slack/format.js.map +1 -1
  113. package/dist/cjs/render/slack/index.js +1 -2
  114. package/dist/cjs/render/slack/index.js.map +1 -1
  115. package/dist/cjs/render/slack/markdown_content.js +172 -115
  116. package/dist/cjs/render/slack/markdown_content.js.map +1 -1
  117. package/dist/cjs/testing/conformance.js +40 -24
  118. package/dist/cjs/testing/conformance.js.map +1 -1
  119. package/dist/cjs/testing/icon.js +248 -0
  120. package/dist/cjs/testing/icon.js.map +1 -0
  121. package/dist/cjs/testing/index.js +3 -1
  122. package/dist/cjs/testing/index.js.map +1 -1
  123. package/dist/cjs/testing/registration.js +5 -3
  124. package/dist/cjs/testing/registration.js.map +1 -1
  125. package/dist/cjs/validate/authoring_schema.js +17 -1
  126. package/dist/cjs/validate/authoring_schema.js.map +1 -1
  127. package/dist/cjs/validate/index.js +2 -1
  128. package/dist/cjs/validate/index.js.map +1 -1
  129. package/dist/cjs/validate/json_schema.js +10 -3
  130. package/dist/cjs/validate/json_schema.js.map +1 -1
  131. package/dist/cjs/validate/url.js +2 -1
  132. package/dist/cjs/validate/url.js.map +1 -1
  133. package/dist/cjs/validate/validation.js +2 -45
  134. package/dist/cjs/validate/validation.js.map +1 -1
  135. package/dist/composition/body_node_base.d.ts +7 -6
  136. package/dist/composition/body_node_base.d.ts.map +1 -1
  137. package/dist/composition/body_node_base.js +10 -3
  138. package/dist/composition/body_node_base.js.map +1 -1
  139. package/dist/composition/error.d.ts +2 -0
  140. package/dist/composition/error.d.ts.map +1 -1
  141. package/dist/composition/error.js +2 -0
  142. package/dist/composition/error.js.map +1 -1
  143. package/dist/composition/index.d.ts +1 -1
  144. package/dist/composition/index.d.ts.map +1 -1
  145. package/dist/composition/index.js +1 -1
  146. package/dist/composition/index.js.map +1 -1
  147. package/dist/composition/structured_value.d.ts +3 -3
  148. package/dist/composition/structured_value.d.ts.map +1 -1
  149. package/dist/composition/structured_value.js.map +1 -1
  150. package/dist/define/frame.d.ts +9 -20
  151. package/dist/define/frame.d.ts.map +1 -1
  152. package/dist/define/frame.js +2 -3
  153. package/dist/define/frame.js.map +1 -1
  154. package/dist/define/index.d.ts +3 -1
  155. package/dist/define/index.d.ts.map +1 -1
  156. package/dist/define/index.js +3 -1
  157. package/dist/define/index.js.map +1 -1
  158. package/dist/define/primitive_example.d.ts +30 -0
  159. package/dist/define/primitive_example.d.ts.map +1 -0
  160. package/dist/define/primitive_example.js +21 -0
  161. package/dist/define/primitive_example.js.map +1 -0
  162. package/dist/define/primitive_icon.d.ts +11 -0
  163. package/dist/define/primitive_icon.d.ts.map +1 -0
  164. package/dist/define/primitive_icon.js +14 -0
  165. package/dist/define/primitive_icon.js.map +1 -0
  166. package/dist/define/primitive_module.d.ts +45 -24
  167. package/dist/define/primitive_module.d.ts.map +1 -1
  168. package/dist/define/primitive_module.js +24 -7
  169. package/dist/define/primitive_module.js.map +1 -1
  170. package/dist/define/slack_assets.d.ts +1 -1
  171. package/dist/define/slack_assets.d.ts.map +1 -1
  172. package/dist/define/slack_assets.js.map +1 -1
  173. package/dist/entries/index.d.ts +3 -3
  174. package/dist/entries/index.d.ts.map +1 -1
  175. package/dist/entries/index.js +3 -3
  176. package/dist/entries/index.js.map +1 -1
  177. package/dist/entries/markdown.d.ts +1 -1
  178. package/dist/entries/markdown.d.ts.map +1 -1
  179. package/dist/entries/markdown.js +1 -1
  180. package/dist/entries/markdown.js.map +1 -1
  181. package/dist/entries/slack.d.ts +1 -1
  182. package/dist/entries/slack.d.ts.map +1 -1
  183. package/dist/entries/slack.js +1 -1
  184. package/dist/entries/slack.js.map +1 -1
  185. package/dist/pack/capabilities.d.ts +24 -10
  186. package/dist/pack/capabilities.d.ts.map +1 -1
  187. package/dist/pack/capabilities.js +17 -11
  188. package/dist/pack/capabilities.js.map +1 -1
  189. package/dist/pack/compose.d.ts +4 -1
  190. package/dist/pack/compose.d.ts.map +1 -1
  191. package/dist/pack/compose.js +4 -1
  192. package/dist/pack/compose.js.map +1 -1
  193. package/dist/pack/index.d.ts +2 -2
  194. package/dist/pack/index.d.ts.map +1 -1
  195. package/dist/pack/index.js +2 -2
  196. package/dist/pack/index.js.map +1 -1
  197. package/dist/pack/primitive_pack.d.ts +14 -3
  198. package/dist/pack/primitive_pack.d.ts.map +1 -1
  199. package/dist/pack/primitive_pack.js +25 -4
  200. package/dist/pack/primitive_pack.js.map +1 -1
  201. package/dist/render/anchors.d.ts +2 -2
  202. package/dist/render/anchors.d.ts.map +1 -1
  203. package/dist/render/anchors.js +1 -1
  204. package/dist/render/anchors.js.map +1 -1
  205. package/dist/render/format_number.d.ts.map +1 -1
  206. package/dist/render/format_number.js +2 -1
  207. package/dist/render/format_number.js.map +1 -1
  208. package/dist/render/html/envelope.d.ts +3 -3
  209. package/dist/render/html/envelope.js +12 -6
  210. package/dist/render/html/envelope.js.map +1 -1
  211. package/dist/render/layout_check.d.ts +1 -1
  212. package/dist/render/layout_check.d.ts.map +1 -1
  213. package/dist/render/layout_check.js.map +1 -1
  214. package/dist/render/markdown/builder.d.ts +5 -4
  215. package/dist/render/markdown/builder.d.ts.map +1 -1
  216. package/dist/render/markdown/builder.js +16 -7
  217. package/dist/render/markdown/builder.js.map +1 -1
  218. package/dist/render/markdown/format.d.ts +9 -0
  219. package/dist/render/markdown/format.d.ts.map +1 -1
  220. package/dist/render/markdown/format.js +67 -31
  221. package/dist/render/markdown/format.js.map +1 -1
  222. package/dist/render/markdown/host_tags.d.ts +14 -0
  223. package/dist/render/markdown/host_tags.d.ts.map +1 -0
  224. package/dist/render/markdown/host_tags.js +63 -0
  225. package/dist/render/markdown/host_tags.js.map +1 -0
  226. package/dist/render/markdown/index.d.ts +1 -0
  227. package/dist/render/markdown/index.d.ts.map +1 -1
  228. package/dist/render/markdown/index.js +1 -0
  229. package/dist/render/markdown/index.js.map +1 -1
  230. package/dist/render/markdown/split.d.ts +32 -0
  231. package/dist/render/markdown/split.d.ts.map +1 -0
  232. package/dist/render/markdown/split.js +321 -0
  233. package/dist/render/markdown/split.js.map +1 -0
  234. package/dist/render/primitive_dispatch.d.ts +6 -6
  235. package/dist/render/primitive_dispatch.d.ts.map +1 -1
  236. package/dist/render/primitive_dispatch.js +12 -26
  237. package/dist/render/primitive_dispatch.js.map +1 -1
  238. package/dist/render/react/content.d.ts +1 -1
  239. package/dist/render/react/content.d.ts.map +1 -1
  240. package/dist/render/react/content.js +3 -1
  241. package/dist/render/react/content.js.map +1 -1
  242. package/dist/render/slack/format.d.ts +0 -25
  243. package/dist/render/slack/format.d.ts.map +1 -1
  244. package/dist/render/slack/format.js +1 -599
  245. package/dist/render/slack/format.js.map +1 -1
  246. package/dist/render/slack/index.d.ts +1 -1
  247. package/dist/render/slack/index.d.ts.map +1 -1
  248. package/dist/render/slack/index.js +1 -1
  249. package/dist/render/slack/index.js.map +1 -1
  250. package/dist/render/slack/markdown_content.d.ts +10 -4
  251. package/dist/render/slack/markdown_content.d.ts.map +1 -1
  252. package/dist/render/slack/markdown_content.js +169 -113
  253. package/dist/render/slack/markdown_content.js.map +1 -1
  254. package/dist/testing/conformance.d.ts +19 -14
  255. package/dist/testing/conformance.d.ts.map +1 -1
  256. package/dist/testing/conformance.js +40 -24
  257. package/dist/testing/conformance.js.map +1 -1
  258. package/dist/testing/icon.d.ts +11 -0
  259. package/dist/testing/icon.d.ts.map +1 -0
  260. package/dist/testing/icon.js +244 -0
  261. package/dist/testing/icon.js.map +1 -0
  262. package/dist/testing/index.d.ts +2 -1
  263. package/dist/testing/index.d.ts.map +1 -1
  264. package/dist/testing/index.js +1 -0
  265. package/dist/testing/index.js.map +1 -1
  266. package/dist/testing/registration.d.ts +1 -1
  267. package/dist/testing/registration.d.ts.map +1 -1
  268. package/dist/testing/registration.js +6 -4
  269. package/dist/testing/registration.js.map +1 -1
  270. package/dist/validate/authoring_schema.d.ts +6 -0
  271. package/dist/validate/authoring_schema.d.ts.map +1 -1
  272. package/dist/validate/authoring_schema.js +15 -0
  273. package/dist/validate/authoring_schema.js.map +1 -1
  274. package/dist/validate/index.d.ts +1 -1
  275. package/dist/validate/index.d.ts.map +1 -1
  276. package/dist/validate/index.js +1 -1
  277. package/dist/validate/index.js.map +1 -1
  278. package/dist/validate/json_schema.d.ts.map +1 -1
  279. package/dist/validate/json_schema.js +10 -3
  280. package/dist/validate/json_schema.js.map +1 -1
  281. package/dist/validate/url.d.ts.map +1 -1
  282. package/dist/validate/url.js +2 -1
  283. package/dist/validate/url.js.map +1 -1
  284. package/dist/validate/validation.d.ts +1 -11
  285. package/dist/validate/validation.d.ts.map +1 -1
  286. package/dist/validate/validation.js +3 -46
  287. package/dist/validate/validation.js.map +1 -1
  288. package/package.json +3 -2
@@ -6,11 +6,11 @@
6
6
  * 2.0.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.readAuthoredSpec = exports.fromTextChildren = exports.authoredText = exports.authoredProps = exports.authoredChild = void 0;
9
+ exports.readAuthoredSpec = exports.fromNodeChildren = exports.fromTextChildren = exports.authoredToItem = exports.authoredNodes = exports.authoredText = exports.authoredProps = exports.authoredChild = void 0;
10
10
  exports.fromChildren = fromChildren;
11
11
  const error_1 = require("../composition/error");
12
12
  /**
13
- * Child-element type a schema field is filled from.
13
+ * Member name of the child component a schema field is filled from.
14
14
  *
15
15
  * `Symbol.for`: ESM and CJS builds must agree, same as `authorType`.
16
16
  */
@@ -19,23 +19,32 @@ exports.authoredChild = Symbol.for('elastic.isomer.authored_child');
19
19
  exports.authoredProps = Symbol.for('elastic.isomer.authored_props');
20
20
  /** Set when a field is filled from text children. */
21
21
  exports.authoredText = Symbol.for('elastic.isomer.authored_text');
22
- const authoredToItem = Symbol.for('elastic.isomer.authored_to_item');
22
+ /** Set when a field is filled from primitive elements no other field claims. */
23
+ exports.authoredNodes = Symbol.for('elastic.isomer.authored_nodes');
24
+ /** Holds a {@link fromChildren} brand's `toItem`. */
25
+ exports.authoredToItem = Symbol.for('elastic.isomer.authored_to_item');
23
26
  const authoredTextField = Symbol.for('elastic.isomer.authored_text_field');
24
27
  const authoredCollapse = Symbol.for('elastic.isomer.authored_collapse');
28
+ const authoredDedent = Symbol.for('elastic.isomer.authored_dedent');
29
+ const authoredPropsSchema = Symbol.for('elastic.isomer.authored_props_schema');
25
30
  const BRANDS = [
26
31
  exports.authoredChild,
27
32
  authoredTextField,
28
- authoredToItem,
33
+ exports.authoredToItem,
29
34
  exports.authoredText,
35
+ exports.authoredNodes,
30
36
  authoredCollapse,
37
+ authoredDedent,
38
+ authoredPropsSchema,
31
39
  ];
32
40
  // Applies a complete branding. Branding an instance again is allowed only with
33
41
  // the same configuration, absent options included, since both fields share it.
34
42
  const brand = (caller, schema, config) => {
35
43
  const record = schema;
36
44
  if (BRANDS.some((key) => Object.hasOwn(schema, key))) {
37
- if (BRANDS.every((key) => record[key] === config[key]))
45
+ if (BRANDS.every((key) => record[key] === config[key])) {
38
46
  return;
47
+ }
39
48
  throw new error_1.IsomerError(error_1.ISOMER_ERROR_CODES.AUTHORED_SCHEMA_REUSED, `${caller}: this schema instance is already branded another way; pass each field its own schema.`);
40
49
  }
41
50
  for (const key of BRANDS) {
@@ -47,27 +56,42 @@ const brand = (caller, schema, config) => {
47
56
  }
48
57
  }
49
58
  };
50
- function fromChildren(childType, schema, options) {
59
+ function fromChildren(name, schema, options) {
51
60
  brand('fromChildren', schema, {
52
- [exports.authoredChild]: childType,
61
+ [exports.authoredChild]: name,
53
62
  [authoredTextField]: options?.text,
54
- [authoredToItem]: options?.toItem,
63
+ [exports.authoredToItem]: options?.toItem,
64
+ [authoredPropsSchema]: options?.propsSchema,
55
65
  });
56
66
  return schema;
57
67
  }
58
68
  /**
59
69
  * Brands `schema` as text children.
60
70
  *
61
- * Whitespace collapses unless `collapseWhitespace` is `false`.
71
+ * Whitespace collapses unless `collapseWhitespace` is `false`. `dedent` keeps
72
+ * it and reads the text as source, as {@link textFromChildren} does.
62
73
  */
63
74
  const fromTextChildren = (schema, options) => {
64
75
  brand('fromTextChildren', schema, {
65
76
  [exports.authoredText]: true,
66
- [authoredCollapse]: options?.collapseWhitespace === false ? false : undefined,
77
+ [authoredCollapse]: options?.collapseWhitespace === false || options?.dedent
78
+ ? false
79
+ : undefined,
80
+ [authoredDedent]: options?.dedent ? true : undefined,
67
81
  });
68
82
  return schema;
69
83
  };
70
84
  exports.fromTextChildren = fromTextChildren;
85
+ /**
86
+ * Brands `schema`, a node or an array of nodes, as the primitive elements among
87
+ * the children that no other field claims. Use it for nodes the tree walk does
88
+ * not visit; a walked child slot fills from children already.
89
+ */
90
+ const fromNodeChildren = (schema) => {
91
+ brand('fromNodeChildren', schema, { [exports.authoredNodes]: true });
92
+ return schema;
93
+ };
94
+ exports.fromNodeChildren = fromNodeChildren;
71
95
  const zodDefType = (schema) => schema._zod?.def?.type;
72
96
  const WRAPPER_TYPES = new Set(['optional', 'nullable', 'default', 'readonly']);
73
97
  const innerSchema = (schema) => {
@@ -85,8 +109,9 @@ const brandHolder = (schema, key) => {
85
109
  // Whether any wrapper layer of `schema` accepts `undefined`.
86
110
  const optionalThrough = (schema) => {
87
111
  for (let current = schema; current; current = innerSchema(current)) {
88
- if (isOptionalSchema(current))
112
+ if (isOptionalSchema(current)) {
89
113
  return true;
114
+ }
90
115
  }
91
116
  return false;
92
117
  };
@@ -102,50 +127,33 @@ const isOptionalSchema = (schema) => {
102
127
  const type = zodDefType(schema);
103
128
  return type === 'optional' || type === 'default';
104
129
  };
105
- const schemaSignature = (schema, seen = new Set()) => {
106
- if (seen.has(schema)) {
107
- return 'cycle';
108
- }
109
- seen.add(schema);
110
- const type = zodDefType(schema) ?? '?';
111
- if (type === 'object' && 'shape' in schema) {
112
- const shape = schema.shape;
113
- const fields = Object.keys(shape)
114
- .sort()
115
- .map((key) => `${key}:${schemaSignature(shape[key], seen)}`);
116
- return `{${fields.join(',')}}`;
117
- }
118
- if (type === 'array' && 'element' in schema) {
119
- return `[${schemaSignature(schema.element, seen)}]`;
120
- }
121
- const inner = innerSchema(schema);
122
- if (inner) {
123
- return `${type}(${schemaSignature(inner, seen)})`;
124
- }
125
- return type;
126
- };
127
130
  const arrayElement = (schema) => {
128
131
  const inner = unwrapAll(schema);
129
- if (zodDefType(inner) === 'array' && 'element' in inner) {
130
- return inner.element;
131
- }
132
- return inner;
132
+ return zodDefType(inner) === 'array' && 'element' in inner
133
+ ? inner.element
134
+ : undefined;
133
135
  };
134
136
  const readChild = (field, schema) => {
135
137
  const holder = brandHolder(schema, exports.authoredChild);
136
- const childType = holder?.[exports.authoredChild];
137
- if (!holder || typeof childType !== 'string') {
138
+ const name = holder?.[exports.authoredChild];
139
+ if (!holder || typeof name !== 'string') {
138
140
  return undefined;
139
141
  }
140
142
  const textField = holder[authoredTextField];
141
- const toItem = holder[authoredToItem];
143
+ const toItem = holder[exports.authoredToItem];
144
+ const propsSchema = holder[authoredPropsSchema];
145
+ const element = arrayElement(holder);
146
+ const itemSchema = element ?? unwrapAll(holder);
142
147
  const child = {
143
148
  field,
144
- childType,
145
- itemSchema: arrayElement(holder),
149
+ name,
150
+ itemSchema,
151
+ array: element !== undefined,
146
152
  optional: optionalThrough(schema),
147
- signature: schemaSignature(arrayElement(holder)),
148
153
  };
154
+ if (propsSchema) {
155
+ child.propsSchema = propsSchema;
156
+ }
149
157
  if (typeof textField === 'string') {
150
158
  child.textField = textField;
151
159
  }
@@ -159,19 +167,27 @@ const readText = (field, schema) => {
159
167
  if (!holder) {
160
168
  return undefined;
161
169
  }
162
- return {
170
+ const text = {
163
171
  field,
164
172
  collapseWhitespace: holder[authoredCollapse] !== false,
165
173
  optional: optionalThrough(schema),
166
174
  };
175
+ if (holder[authoredDedent] === true) {
176
+ text.dedent = true;
177
+ }
178
+ return text;
167
179
  };
168
- /** Top-level branded fields on an object schema. Nested brands stay on the item schema. */
180
+ /**
181
+ * The branded fields on an object schema, top level only: read a child's own
182
+ * brands from its {@link AuthoredChildField.itemSchema}.
183
+ */
169
184
  const readAuthoredSpec = (schema) => {
170
185
  if (zodDefType(schema) !== 'object' || !('shape' in schema)) {
171
- return { children: [], text: [] };
186
+ return { children: [], text: [], nodes: [] };
172
187
  }
173
188
  const children = [];
174
189
  const text = [];
190
+ const nodes = [];
175
191
  for (const [field, fieldSchema] of Object.entries(schema.shape)) {
176
192
  const child = readChild(field, fieldSchema);
177
193
  if (child) {
@@ -181,9 +197,14 @@ const readAuthoredSpec = (schema) => {
181
197
  const textField = readText(field, fieldSchema);
182
198
  if (textField) {
183
199
  text.push(textField);
200
+ continue;
201
+ }
202
+ const holder = brandHolder(fieldSchema, exports.authoredNodes);
203
+ if (holder) {
204
+ nodes.push({ field, array: arrayElement(holder) !== undefined });
184
205
  }
185
206
  }
186
- return { children, text };
207
+ return { children, text, nodes };
187
208
  };
188
209
  exports.readAuthoredSpec = readAuthoredSpec;
189
210
  //# sourceMappingURL=authored_fields.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"authored_fields.js","sourceRoot":"","sources":["../../../src/author/authored_fields.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport type { ReactNode } from 'react';\nimport type { ZodType } from 'zod';\n\nimport { ISOMER_ERROR_CODES, IsomerError } from '../composition/error';\nimport type { PrimitiveNode } from '../define/primitive_module';\n\n/**\n * Child-element type a schema field is filled from.\n *\n * `Symbol.for`: ESM and CJS builds must agree, same as `authorType`.\n */\nexport const authoredChild = Symbol.for('elastic.isomer.authored_child');\n\n/** Phantom props type for the child component. Not set at runtime. */\nexport const authoredProps = Symbol.for('elastic.isomer.authored_props');\n\n/** Set when a field is filled from text children. */\nexport const authoredText = Symbol.for('elastic.isomer.authored_text');\n\nconst authoredToItem = Symbol.for('elastic.isomer.authored_to_item');\nconst authoredTextField = Symbol.for('elastic.isomer.authored_text_field');\nconst authoredCollapse = Symbol.for('elastic.isomer.authored_collapse');\n\n/**\n * A field filled from child elements of `TName`.\n *\n * Phantom: `z.infer` still reads the underlying schema. The shim reads `TName`\n * and `TProps` off the field type, and the symbols off the schema value.\n */\nexport interface AuthoredChildBrand<TName extends string, TProps> {\n readonly [authoredChild]: TName;\n readonly [authoredProps]: TProps;\n}\n\n/** A field filled from text children. */\nexport interface AuthoredTextBrand {\n readonly [authoredText]: true;\n}\n\n/** What {@link fromChildren}'s `toItem` receives. */\nexport interface AuthorChildContext {\n /** Nested elements, parsed as body nodes. */\n parseChildren: (children: ReactNode) => PrimitiveNode[];\n}\n\ntype ArrayItem<TSchema extends ZodType> =\n NonNullable<zOutput<TSchema>> extends readonly (infer Item)[]\n ? Item\n : NonNullable<zOutput<TSchema>>;\n\ntype zOutput<TSchema> = TSchema extends { _zod: { output: infer Output } }\n ? Output\n : never;\n\n/** `TText` is optional on the child props because leftover text fills it. */\ntype ChildProps<TItem, TText extends string | undefined> = [TText] extends [\n string,\n]\n ? Omit<TItem, TText> &\n Partial<Pick<TItem, Extract<TText, keyof TItem>>> & {\n children?: ReactNode;\n }\n : TItem & { children?: ReactNode };\n\nconst BRANDS = [\n authoredChild,\n authoredTextField,\n authoredToItem,\n authoredText,\n authoredCollapse,\n] as const;\n\n// Applies a complete branding. Branding an instance again is allowed only with\n// the same configuration, absent options included, since both fields share it.\nconst brand = (\n caller: 'fromChildren' | 'fromTextChildren',\n schema: object,\n config: Partial<Record<(typeof BRANDS)[number], unknown>>\n): void => {\n const record = schema as Record<symbol, unknown>;\n if (BRANDS.some((key) => Object.hasOwn(schema, key))) {\n if (BRANDS.every((key) => record[key] === config[key])) return;\n throw new IsomerError(\n ISOMER_ERROR_CODES.AUTHORED_SCHEMA_REUSED,\n `${caller}: this schema instance is already branded another way; pass each field its own schema.`\n );\n }\n for (const key of BRANDS) {\n if (config[key] !== undefined) {\n Object.defineProperty(schema, key, {\n value: config[key],\n enumerable: false,\n });\n }\n }\n};\n\n/**\n * Brands `schema` as JSX children of `childType`.\n *\n * `options.text` copies leftover text onto that field. `options.toItem` replaces\n * the default prop copy; its props annotation is the child component's props.\n * The brand is read through `.optional()`, `.nullable()`, `.default()`, and\n * `.readonly()`; any other method clones without it, so call it on `schema`\n * before passing it in.\n */\nexport function fromChildren<\n const TName extends string,\n TSchema extends ZodType,\n>(\n childType: TName,\n schema: TSchema\n): TSchema &\n AuthoredChildBrand<TName, ChildProps<ArrayItem<TSchema>, undefined>>;\nexport function fromChildren<\n const TName extends string,\n TSchema extends ZodType,\n const TText extends string,\n>(\n childType: TName,\n schema: TSchema,\n options: { text: TText }\n): TSchema & AuthoredChildBrand<TName, ChildProps<ArrayItem<TSchema>, TText>>;\nexport function fromChildren<\n const TName extends string,\n TSchema extends ZodType,\n TProps,\n>(\n childType: TName,\n schema: TSchema,\n options: {\n text?: string;\n toItem(props: TProps, context: AuthorChildContext): unknown;\n }\n): TSchema & AuthoredChildBrand<TName, TProps>;\nexport function fromChildren(\n childType: string,\n schema: ZodType,\n options?: {\n text?: string;\n toItem?: (this: void, props: never, context: AuthorChildContext) => unknown;\n }\n): ZodType {\n brand('fromChildren', schema, {\n [authoredChild]: childType,\n [authoredTextField]: options?.text,\n [authoredToItem]: options?.toItem,\n });\n return schema;\n}\n\n/**\n * Brands `schema` as text children.\n *\n * Whitespace collapses unless `collapseWhitespace` is `false`.\n */\nexport const fromTextChildren = <TSchema extends ZodType>(\n schema: TSchema,\n options?: { collapseWhitespace?: boolean }\n): TSchema & AuthoredTextBrand => {\n brand('fromTextChildren', schema, {\n [authoredText]: true,\n [authoredCollapse]:\n options?.collapseWhitespace === false ? false : undefined,\n });\n return schema as TSchema & AuthoredTextBrand;\n};\n\n/** One {@link fromChildren} field as the shim reads it. */\nexport interface AuthoredChildField {\n field: string;\n childType: string;\n /** Field leftover text children fill. */\n textField?: string;\n /** Replaces the default prop copy. */\n toItem?: (props: object, context: AuthorChildContext) => unknown;\n /** The array element schema, or the field schema itself when it is not an array. */\n itemSchema: ZodType;\n /** Whether the field accepts `undefined`, so children may be omitted. */\n optional: boolean;\n /** Structural fingerprint of `itemSchema`; every field branding one child type must share it. */\n signature: string;\n}\n\n/** One {@link fromTextChildren} field as the shim reads it. */\nexport interface AuthoredTextField {\n field: string;\n /** `true` unless the brand was given `collapseWhitespace: false`. */\n collapseWhitespace: boolean;\n /** Whether the field accepts `undefined`, so text children may be omitted. */\n optional: boolean;\n}\n\n/** The branded fields found on one object schema. */\nexport interface AuthoredSpec {\n children: AuthoredChildField[];\n text: AuthoredTextField[];\n}\n\nconst zodDefType = (schema: object): string | undefined =>\n (schema as { _zod?: { def?: { type?: string } } })._zod?.def?.type;\n\nconst WRAPPER_TYPES = new Set(['optional', 'nullable', 'default', 'readonly']);\n\ninterface WrapperDef {\n type?: string;\n innerType?: ZodType;\n}\n\nconst innerSchema = (schema: ZodType): ZodType | undefined => {\n const def: WrapperDef | undefined = (\n schema as { _zod?: { def?: WrapperDef } }\n )._zod?.def;\n return def?.type && WRAPPER_TYPES.has(def.type) ? def.innerType : undefined;\n};\n\n// The schema holding `brand`: `schema` or one it wraps.\nconst brandHolder = (schema: ZodType, key: symbol): ZodType | undefined => {\n let current: ZodType | undefined = schema;\n while (current && !Object.hasOwn(current, key)) {\n current = innerSchema(current);\n }\n return current;\n};\n\n// Whether any wrapper layer of `schema` accepts `undefined`.\nconst optionalThrough = (schema: ZodType): boolean => {\n for (\n let current: ZodType | undefined = schema;\n current;\n current = innerSchema(current)\n ) {\n if (isOptionalSchema(current)) return true;\n }\n return false;\n};\n\nconst unwrapAll = (schema: ZodType): ZodType => {\n let current = schema;\n for (let inner = innerSchema(current); inner; inner = innerSchema(current)) {\n current = inner;\n }\n return current;\n};\n\n/** `undefined` is a valid value, so children may be omitted. */\nconst isOptionalSchema = (schema: ZodType): boolean => {\n const type = zodDefType(schema);\n return type === 'optional' || type === 'default';\n};\n\nconst schemaSignature = (\n schema: ZodType,\n seen: Set<object> = new Set()\n): string => {\n if (seen.has(schema)) {\n return 'cycle';\n }\n seen.add(schema);\n const type = zodDefType(schema) ?? '?';\n if (type === 'object' && 'shape' in schema) {\n const shape = schema.shape as Record<string, ZodType>;\n const fields = Object.keys(shape)\n .sort()\n .map((key) => `${key}:${schemaSignature(shape[key] as ZodType, seen)}`);\n return `{${fields.join(',')}}`;\n }\n if (type === 'array' && 'element' in schema) {\n return `[${schemaSignature((schema as { element: ZodType }).element, seen)}]`;\n }\n const inner = innerSchema(schema);\n if (inner) {\n return `${type}(${schemaSignature(inner, seen)})`;\n }\n return type;\n};\n\nconst arrayElement = (schema: ZodType): ZodType => {\n const inner = unwrapAll(schema);\n if (zodDefType(inner) === 'array' && 'element' in inner) {\n return (inner as { element: ZodType }).element;\n }\n return inner;\n};\n\nconst readChild = (\n field: string,\n schema: ZodType\n): AuthoredChildField | undefined => {\n const holder = brandHolder(schema, authoredChild);\n const childType = (holder as { [authoredChild]?: unknown } | undefined)?.[\n authoredChild\n ];\n if (!holder || typeof childType !== 'string') {\n return undefined;\n }\n const textField = (holder as { [authoredTextField]?: unknown })[\n authoredTextField\n ];\n const toItem = (holder as { [authoredToItem]?: unknown })[authoredToItem];\n const child: AuthoredChildField = {\n field,\n childType,\n itemSchema: arrayElement(holder),\n optional: optionalThrough(schema),\n signature: schemaSignature(arrayElement(holder)),\n };\n if (typeof textField === 'string') {\n child.textField = textField;\n }\n if (typeof toItem === 'function') {\n child.toItem = toItem as (\n props: object,\n context: AuthorChildContext\n ) => unknown;\n }\n return child;\n};\n\nconst readText = (\n field: string,\n schema: ZodType\n): AuthoredTextField | undefined => {\n const holder = brandHolder(schema, authoredText);\n if (!holder) {\n return undefined;\n }\n return {\n field,\n collapseWhitespace:\n (holder as { [authoredCollapse]?: unknown })[authoredCollapse] !== false,\n optional: optionalThrough(schema),\n };\n};\n\n/** Top-level branded fields on an object schema. Nested brands stay on the item schema. */\nexport const readAuthoredSpec = (schema: ZodType): AuthoredSpec => {\n if (zodDefType(schema) !== 'object' || !('shape' in schema)) {\n return { children: [], text: [] };\n }\n const children: AuthoredChildField[] = [];\n const text: AuthoredTextField[] = [];\n for (const [field, fieldSchema] of Object.entries(\n schema.shape as Record<string, ZodType>\n )) {\n const child = readChild(field, fieldSchema);\n if (child) {\n children.push(child);\n continue;\n }\n const textField = readText(field, fieldSchema);\n if (textField) {\n text.push(textField);\n }\n }\n return { children, text };\n};\n"]}
1
+ {"version":3,"file":"authored_fields.js","sourceRoot":"","sources":["../../../src/author/authored_fields.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport type { ReactNode } from 'react';\nimport type { ZodType } from 'zod';\n\nimport { ISOMER_ERROR_CODES, IsomerError } from '../composition/error';\nimport type { PrimitiveNode } from '../define/primitive_module';\n\n/**\n * Member name of the child component a schema field is filled from.\n *\n * `Symbol.for`: ESM and CJS builds must agree, same as `authorType`.\n */\nexport const authoredChild = Symbol.for('elastic.isomer.authored_child');\n\n/** Phantom props type for the child component. Not set at runtime. */\nexport const authoredProps = Symbol.for('elastic.isomer.authored_props');\n\n/** Set when a field is filled from text children. */\nexport const authoredText = Symbol.for('elastic.isomer.authored_text');\n\n/** Set when a field is filled from primitive elements no other field claims. */\nexport const authoredNodes = Symbol.for('elastic.isomer.authored_nodes');\n\n/** Holds a {@link fromChildren} brand's `toItem`. */\nexport const authoredToItem = Symbol.for('elastic.isomer.authored_to_item');\nconst authoredTextField = Symbol.for('elastic.isomer.authored_text_field');\nconst authoredCollapse = Symbol.for('elastic.isomer.authored_collapse');\nconst authoredDedent = Symbol.for('elastic.isomer.authored_dedent');\nconst authoredPropsSchema = Symbol.for('elastic.isomer.authored_props_schema');\n\n/**\n * A field filled from child elements of `TName`.\n *\n * Phantom: `z.infer` still reads the underlying schema. The shim reads `TName`\n * and `TProps` off the field type, and the symbols off the schema value.\n */\nexport interface AuthoredChildBrand<TName extends string, TProps> {\n readonly [authoredChild]: TName;\n readonly [authoredProps]: TProps;\n}\n\n/** A child field whose `toItem` builds each item, so the shim fills none of the item's own brands. */\nexport interface AuthoredToItemBrand {\n readonly [authoredToItem]: (\n props: never,\n context: AuthorChildContext\n ) => unknown;\n}\n\n/** A field filled from text children. */\nexport interface AuthoredTextBrand {\n readonly [authoredText]: true;\n}\n\n/** A field filled from primitive elements, like a child slot the tree walk does not visit. */\nexport interface AuthoredNodesBrand {\n readonly [authoredNodes]: true;\n}\n\n/** What {@link fromChildren}'s `toItem` receives. */\nexport interface AuthorChildContext {\n /** Nested elements, parsed as body nodes. */\n parseChildren: (children: ReactNode) => PrimitiveNode[];\n}\n\ntype ArrayItem<TSchema extends ZodType> =\n NonNullable<zOutput<TSchema>> extends readonly (infer Item)[]\n ? Item\n : NonNullable<zOutput<TSchema>>;\n\ntype zInput<TSchema> = TSchema extends { _zod: { input: infer Input } }\n ? Input\n : never;\n\ntype zOutput<TSchema> = TSchema extends { _zod: { output: infer Output } }\n ? Output\n : never;\n\ntype WrapperOf<TInner> = {\n _zod: {\n def: {\n type: 'optional' | 'nullable' | 'default' | 'readonly';\n innerType: TInner;\n };\n };\n};\n\ntype Unwrapped<TSchema> =\n TSchema extends WrapperOf<infer Inner> ? Unwrapped<Inner> : TSchema;\n\n/** Whether `F`, or a wrapper layer of it, carries a {@link fromChildren} brand. */\ntype IsChildBranded<F> =\n F extends AuthoredChildBrand<string, unknown>\n ? true\n : F extends WrapperOf<infer Inner>\n ? IsChildBranded<Inner>\n : false;\n\n/** A branded field's item schema: the array element through any wrapper, or the unwrapped schema. */\nexport type ItemSchema<TSchema> =\n Unwrapped<TSchema> extends { element: infer Element }\n ? Element\n : Unwrapped<TSchema>;\n\n/** Item fields a nested {@link fromChildren} brand fills from child elements. */\ntype ChildBrandedKeys<TItemSchema> = TItemSchema extends {\n shape: infer Shape;\n}\n ? string extends keyof Shape\n ? never\n : {\n [K in keyof Shape]: IsChildBranded<Shape[K]> extends true ? K : never;\n }[keyof Shape]\n : never;\n\n/** `TOptional` is optional on the child props because text or child elements fill it. */\ntype ChildProps<TItem, TOptional extends PropertyKey> = [TOptional] extends [\n never,\n]\n ? TItem & { children?: ReactNode }\n : Omit<TItem, TOptional> &\n Partial<Pick<TItem, Extract<TOptional, keyof TItem>>> & {\n children?: ReactNode;\n };\n\nconst BRANDS = [\n authoredChild,\n authoredTextField,\n authoredToItem,\n authoredText,\n authoredNodes,\n authoredCollapse,\n authoredDedent,\n authoredPropsSchema,\n] as const;\n\n// Applies a complete branding. Branding an instance again is allowed only with\n// the same configuration, absent options included, since both fields share it.\nconst brand = (\n caller: 'fromChildren' | 'fromNodeChildren' | 'fromTextChildren',\n schema: object,\n config: Partial<Record<(typeof BRANDS)[number], unknown>>\n): void => {\n const record = schema as Record<symbol, unknown>;\n if (BRANDS.some((key) => Object.hasOwn(schema, key))) {\n if (BRANDS.every((key) => record[key] === config[key])) {\n return;\n }\n throw new IsomerError(\n ISOMER_ERROR_CODES.AUTHORED_SCHEMA_REUSED,\n `${caller}: this schema instance is already branded another way; pass each field its own schema.`\n );\n }\n for (const key of BRANDS) {\n if (config[key] !== undefined) {\n Object.defineProperty(schema, key, {\n value: config[key],\n enumerable: false,\n });\n }\n }\n};\n\n/**\n * Brands `schema` as JSX children of the member `name`, capitalized on the\n * primitive's component: `fromChildren('item', …)` on `slideList` is\n * `<SlideList.Item>`. Names are unique across a primitive's child tree.\n *\n * `options.text` copies leftover text onto that field. `options.toItem` replaces\n * the default prop copy; its props annotation is the child component's props.\n * The brand is read through `.optional()`, `.nullable()`, `.default()`, and\n * `.readonly()`; any other method clones without it, so call it on `schema`\n * before passing it in.\n */\nexport function fromChildren<\n const TName extends string,\n TSchema extends ZodType,\n>(\n name: TName,\n schema: TSchema\n): TSchema &\n AuthoredChildBrand<\n TName,\n ChildProps<ArrayItem<TSchema>, ChildBrandedKeys<ItemSchema<TSchema>>>\n >;\nexport function fromChildren<\n const TName extends string,\n TSchema extends ZodType,\n const TText extends string,\n>(\n name: TName,\n schema: TSchema,\n options: { text: TText; toItem?: never }\n): TSchema &\n AuthoredChildBrand<\n TName,\n ChildProps<\n ArrayItem<TSchema>,\n TText | ChildBrandedKeys<ItemSchema<TSchema>>\n >\n >;\nexport function fromChildren<\n const TName extends string,\n TSchema extends ZodType,\n TPropsSchema extends ZodType,\n>(\n name: TName,\n schema: TSchema,\n options: {\n text?: string;\n propsSchema: TPropsSchema;\n toItem(\n props: zInput<TPropsSchema> & { children?: ReactNode },\n context: AuthorChildContext\n ): unknown;\n }\n): TSchema &\n AuthoredChildBrand<TName, zInput<TPropsSchema> & { children?: ReactNode }> &\n AuthoredToItemBrand;\nexport function fromChildren<\n const TName extends string,\n TSchema extends ZodType,\n TProps,\n>(\n name: TName,\n schema: TSchema,\n options: {\n text?: string;\n toItem(props: TProps, context: AuthorChildContext): unknown;\n propsSchema?: never;\n }\n): TSchema & AuthoredChildBrand<TName, TProps> & AuthoredToItemBrand;\nexport function fromChildren(\n name: string,\n schema: ZodType,\n options?: {\n text?: string;\n toItem?: (this: void, props: never, context: AuthorChildContext) => unknown;\n propsSchema?: ZodType;\n }\n): ZodType {\n brand('fromChildren', schema, {\n [authoredChild]: name,\n [authoredTextField]: options?.text,\n [authoredToItem]: options?.toItem,\n [authoredPropsSchema]: options?.propsSchema,\n });\n return schema;\n}\n\n/**\n * Brands `schema` as text children.\n *\n * Whitespace collapses unless `collapseWhitespace` is `false`. `dedent` keeps\n * it and reads the text as source, as {@link textFromChildren} does.\n */\nexport const fromTextChildren = <TSchema extends ZodType>(\n schema: TSchema,\n options?: { collapseWhitespace?: boolean; dedent?: boolean }\n): TSchema & AuthoredTextBrand => {\n brand('fromTextChildren', schema, {\n [authoredText]: true,\n [authoredCollapse]:\n options?.collapseWhitespace === false || options?.dedent\n ? false\n : undefined,\n [authoredDedent]: options?.dedent ? true : undefined,\n });\n return schema as TSchema & AuthoredTextBrand;\n};\n\n/**\n * Brands `schema`, a node or an array of nodes, as the primitive elements among\n * the children that no other field claims. Use it for nodes the tree walk does\n * not visit; a walked child slot fills from children already.\n */\nexport const fromNodeChildren = <TSchema extends ZodType>(\n schema: TSchema\n): TSchema & AuthoredNodesBrand => {\n brand('fromNodeChildren', schema, { [authoredNodes]: true });\n return schema as TSchema & AuthoredNodesBrand;\n};\n\n/** One {@link fromChildren} field as the shim reads it. */\nexport interface AuthoredChildField {\n field: string;\n /** The member name `fromChildren` was given, before capitalizing. */\n name: string;\n /** Field leftover text children fill. */\n textField?: string;\n /** Replaces the default prop copy. */\n toItem?: (props: object, context: AuthorChildContext) => unknown;\n /** The array element schema, or the field schema itself when it is not an array. */\n itemSchema: ZodType;\n /** Input props for a custom `toItem`, excluding JSX children. */\n propsSchema?: ZodType;\n /** Whether the field holds an array of items rather than one item. */\n array: boolean;\n /** Whether the field accepts `undefined`, so children may be omitted. */\n optional: boolean;\n}\n\n/** One {@link fromTextChildren} field as the shim reads it. */\nexport interface AuthoredTextField {\n field: string;\n /** `true` unless the brand was given `collapseWhitespace: false` or `dedent`. */\n collapseWhitespace: boolean;\n /** Set when the brand was given `dedent`. */\n dedent?: true;\n /** Whether the field accepts `undefined`, so text children may be omitted. */\n optional: boolean;\n}\n\n/** One {@link fromNodeChildren} field as the shim reads it. */\nexport interface AuthoredNodesField {\n field: string;\n /** Whether the field holds an array of nodes rather than one. */\n array: boolean;\n}\n\n/** The branded fields found on one object schema. */\nexport interface AuthoredSpec {\n children: AuthoredChildField[];\n text: AuthoredTextField[];\n /** Absent on a spec built by hand; read as none. */\n nodes?: AuthoredNodesField[];\n}\n\nconst zodDefType = (schema: object): string | undefined =>\n (schema as { _zod?: { def?: { type?: string } } })._zod?.def?.type;\n\nconst WRAPPER_TYPES = new Set(['optional', 'nullable', 'default', 'readonly']);\n\ninterface WrapperDef {\n type?: string;\n innerType?: ZodType;\n}\n\nconst innerSchema = (schema: ZodType): ZodType | undefined => {\n const def: WrapperDef | undefined = (\n schema as { _zod?: { def?: WrapperDef } }\n )._zod?.def;\n return def?.type && WRAPPER_TYPES.has(def.type) ? def.innerType : undefined;\n};\n\n// The schema holding `brand`: `schema` or one it wraps.\nconst brandHolder = (schema: ZodType, key: symbol): ZodType | undefined => {\n let current: ZodType | undefined = schema;\n while (current && !Object.hasOwn(current, key)) {\n current = innerSchema(current);\n }\n return current;\n};\n\n// Whether any wrapper layer of `schema` accepts `undefined`.\nconst optionalThrough = (schema: ZodType): boolean => {\n for (\n let current: ZodType | undefined = schema;\n current;\n current = innerSchema(current)\n ) {\n if (isOptionalSchema(current)) {\n return true;\n }\n }\n return false;\n};\n\nconst unwrapAll = (schema: ZodType): ZodType => {\n let current = schema;\n for (let inner = innerSchema(current); inner; inner = innerSchema(current)) {\n current = inner;\n }\n return current;\n};\n\n/** `undefined` is a valid value, so children may be omitted. */\nconst isOptionalSchema = (schema: ZodType): boolean => {\n const type = zodDefType(schema);\n return type === 'optional' || type === 'default';\n};\n\nconst arrayElement = (schema: ZodType): ZodType | undefined => {\n const inner = unwrapAll(schema);\n return zodDefType(inner) === 'array' && 'element' in inner\n ? (inner as { element: ZodType }).element\n : undefined;\n};\n\nconst readChild = (\n field: string,\n schema: ZodType\n): AuthoredChildField | undefined => {\n const holder = brandHolder(schema, authoredChild);\n const name = (holder as { [authoredChild]?: unknown } | undefined)?.[\n authoredChild\n ];\n if (!holder || typeof name !== 'string') {\n return undefined;\n }\n const textField = (holder as { [authoredTextField]?: unknown })[\n authoredTextField\n ];\n const toItem = (holder as { [authoredToItem]?: unknown })[authoredToItem];\n const propsSchema = (holder as { [authoredPropsSchema]?: ZodType })[\n authoredPropsSchema\n ];\n const element = arrayElement(holder);\n const itemSchema = element ?? unwrapAll(holder);\n const child: AuthoredChildField = {\n field,\n name,\n itemSchema,\n array: element !== undefined,\n optional: optionalThrough(schema),\n };\n if (propsSchema) {\n child.propsSchema = propsSchema;\n }\n if (typeof textField === 'string') {\n child.textField = textField;\n }\n if (typeof toItem === 'function') {\n child.toItem = toItem as (\n props: object,\n context: AuthorChildContext\n ) => unknown;\n }\n return child;\n};\n\nconst readText = (\n field: string,\n schema: ZodType\n): AuthoredTextField | undefined => {\n const holder = brandHolder(schema, authoredText);\n if (!holder) {\n return undefined;\n }\n const text: AuthoredTextField = {\n field,\n collapseWhitespace:\n (holder as { [authoredCollapse]?: unknown })[authoredCollapse] !== false,\n optional: optionalThrough(schema),\n };\n if ((holder as { [authoredDedent]?: unknown })[authoredDedent] === true) {\n text.dedent = true;\n }\n return text;\n};\n\n/**\n * The branded fields on an object schema, top level only: read a child's own\n * brands from its {@link AuthoredChildField.itemSchema}.\n */\nexport const readAuthoredSpec = (schema: ZodType): AuthoredSpec => {\n if (zodDefType(schema) !== 'object' || !('shape' in schema)) {\n return { children: [], text: [], nodes: [] };\n }\n const children: AuthoredChildField[] = [];\n const text: AuthoredTextField[] = [];\n const nodes: AuthoredNodesField[] = [];\n for (const [field, fieldSchema] of Object.entries(\n schema.shape as Record<string, ZodType>\n )) {\n const child = readChild(field, fieldSchema);\n if (child) {\n children.push(child);\n continue;\n }\n const textField = readText(field, fieldSchema);\n if (textField) {\n text.push(textField);\n continue;\n }\n const holder = brandHolder(fieldSchema, authoredNodes);\n if (holder) {\n nodes.push({ field, array: arrayElement(holder) !== undefined });\n }\n }\n return { children, text, nodes };\n};\n"]}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
4
+ * or more contributor license agreements. Licensed under the Elastic License
5
+ * 2.0; you may not use this file except in compliance with the Elastic License
6
+ * 2.0.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.prepareAuthoringInput = void 0;
10
+ const zod_1 = require("zod");
11
+ const isSchema = (value) => typeof value === 'object' &&
12
+ value !== null &&
13
+ '_zod' in value &&
14
+ typeof value._zod?.def?.type === 'string';
15
+ /** Input-schema copy without executable defaults or catch values. */
16
+ const prepareAuthoringInput = (schema) => {
17
+ const copies = new Map();
18
+ const metadata = zod_1.z.registry();
19
+ const copyValue = (value) => {
20
+ if (isSchema(value)) {
21
+ return copySchema(value);
22
+ }
23
+ if (Array.isArray(value)) {
24
+ return value.map(copyValue);
25
+ }
26
+ if (typeof value !== 'object' || value === null) {
27
+ return value;
28
+ }
29
+ const prototype = Object.getPrototypeOf(value);
30
+ if (prototype !== Object.prototype && prototype !== null) {
31
+ return value;
32
+ }
33
+ return Object.fromEntries(Object.entries(value).map(([key, member]) => [key, copyValue(member)]));
34
+ };
35
+ const copySchema = (source) => {
36
+ const cached = copies.get(source);
37
+ if (cached) {
38
+ return cached;
39
+ }
40
+ let result;
41
+ copies.set(source, zod_1.z.lazy(() => result));
42
+ const { def } = source._zod;
43
+ if (def.type === 'default' ||
44
+ def.type === 'prefault' ||
45
+ def.type === 'catch') {
46
+ const { innerType } = def;
47
+ const inner = copySchema(innerType);
48
+ result =
49
+ def.type === 'catch'
50
+ ? zod_1.z.clone(inner, inner._zod.def)
51
+ : zod_1.z.optional(inner);
52
+ }
53
+ else if (def.type === 'lazy') {
54
+ const { getter } = def;
55
+ result = zod_1.z.lazy(() => copySchema(getter()));
56
+ }
57
+ else {
58
+ result = zod_1.z.clone(source, copyValue(def));
59
+ }
60
+ copies.set(source, result);
61
+ const meta = zod_1.z.globalRegistry.get(source);
62
+ if (meta) {
63
+ metadata.add(result, meta);
64
+ }
65
+ return result;
66
+ };
67
+ return { schema: copySchema(schema), metadata };
68
+ };
69
+ exports.prepareAuthoringInput = prepareAuthoringInput;
70
+ //# sourceMappingURL=authoring_input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring_input.js","sourceRoot":"","sources":["../../../src/author/authoring_input.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport { z, type ZodType } from 'zod';\n\nconst isSchema = (value: unknown): value is ZodType =>\n typeof value === 'object' &&\n value !== null &&\n '_zod' in value &&\n typeof (value as ZodType)._zod?.def?.type === 'string';\n\n/** Input-schema copy without executable defaults or catch values. */\nexport const prepareAuthoringInput = (schema: ZodType) => {\n const copies = new Map<ZodType, ZodType>();\n const metadata = z.registry<z.GlobalMeta>();\n const copyValue = (value: unknown): unknown => {\n if (isSchema(value)) {\n return copySchema(value);\n }\n if (Array.isArray(value)) {\n return value.map(copyValue);\n }\n if (typeof value !== 'object' || value === null) {\n return value;\n }\n const prototype: unknown = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n return value;\n }\n return Object.fromEntries(\n Object.entries(value).map(([key, member]) => [key, copyValue(member)])\n );\n };\n const copySchema = (source: ZodType): ZodType => {\n const cached = copies.get(source);\n if (cached) {\n return cached;\n }\n let result: ZodType;\n copies.set(\n source,\n z.lazy(() => result)\n );\n const { def } = source._zod;\n if (\n def.type === 'default' ||\n def.type === 'prefault' ||\n def.type === 'catch'\n ) {\n const { innerType } = def as { type: string; innerType: ZodType };\n const inner = copySchema(innerType);\n result =\n def.type === 'catch'\n ? z.clone(inner, inner._zod.def)\n : z.optional(inner);\n } else if (def.type === 'lazy') {\n const { getter } = def as { type: string; getter: () => ZodType };\n result = z.lazy(() => copySchema(getter()));\n } else {\n result = z.clone(source, copyValue(def) as typeof def);\n }\n copies.set(source, result);\n const meta = z.globalRegistry.get(source);\n if (meta) {\n metadata.add(result, meta);\n }\n return result;\n };\n return { schema: copySchema(schema), metadata };\n};\n"]}
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
4
+ * or more contributor license agreements. Licensed under the Elastic License
5
+ * 2.0; you may not use this file except in compliance with the Elastic License
6
+ * 2.0.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.capitalize = exports.inferChildSlots = exports.createAuthoringModel = exports.memberType = void 0;
10
+ const error_1 = require("../composition/error");
11
+ const authored_fields_1 = require("./authored_fields");
12
+ /** The {@link AuthoringChild.authorType} of `field`'s elements under the primitive `owner`. */
13
+ const memberType = (owner, { name }) => `${owner}.${(0, exports.capitalize)(name)}`;
14
+ exports.memberType = memberType;
15
+ const createAuthoringModel = (primitives) => {
16
+ const authoredByType = new Map();
17
+ const membersByType = new Map();
18
+ const collectMembers = (type, spec) => {
19
+ const members = new Map();
20
+ const visited = new Set();
21
+ const collect = (fields, path) => {
22
+ const siblings = new Set();
23
+ for (const field of fields) {
24
+ const member = (0, exports.capitalize)(field.name);
25
+ const prior = members.get(member);
26
+ if (prior &&
27
+ (!isSameChild(prior.field, field) || siblings.has(member))) {
28
+ throw new error_1.IsomerError('DUPLICATE_AUTHORED_CHILD', `buildJsxShim: "${prior.field.field}" and "${field.field}" both become <${(0, exports.capitalize)(type)}.${member}>`);
29
+ }
30
+ siblings.add(member);
31
+ const nextPath = [...path, field];
32
+ if (!prior) {
33
+ members.set(member, {
34
+ field,
35
+ primitiveType: type,
36
+ member,
37
+ authorType: (0, exports.memberType)(type, field),
38
+ path: nextPath,
39
+ });
40
+ }
41
+ if (field.toItem || visited.has(field.itemSchema)) {
42
+ continue;
43
+ }
44
+ visited.add(field.itemSchema);
45
+ collect((0, authored_fields_1.readAuthoredSpec)(field.itemSchema).children, nextPath);
46
+ }
47
+ };
48
+ collect(spec.children, []);
49
+ if (members.size > 0) {
50
+ membersByType.set(type, [...members.values()]);
51
+ }
52
+ };
53
+ for (const { type, schema } of primitives) {
54
+ if (!isZodType(schema)) {
55
+ continue;
56
+ }
57
+ const spec = (0, authored_fields_1.readAuthoredSpec)(schema);
58
+ if (spec.children.length === 0 &&
59
+ spec.text.length === 0 &&
60
+ !spec.nodes?.length) {
61
+ continue;
62
+ }
63
+ authoredByType.set(type, spec);
64
+ collectMembers(type, spec);
65
+ }
66
+ const typeByName = new Map([['Composition', 'view']]);
67
+ for (const { type } of primitives) {
68
+ const name = (0, exports.capitalize)(type);
69
+ const earlier = typeByName.get(name);
70
+ if (earlier !== undefined && earlier !== type) {
71
+ throw new error_1.IsomerError('DUPLICATE_PRIMITIVE_TYPE', `buildJsxShim: "${earlier}" and "${type}" both become the component ${name}`);
72
+ }
73
+ typeByName.set(name, type);
74
+ }
75
+ const holderByType = new Map(primitives.map(({ type }) => [type, `the primitive "${type}"`]));
76
+ for (const { authorType, primitiveType, member } of [
77
+ ...membersByType.values(),
78
+ ].flat()) {
79
+ const holder = `the member ${member} of "${primitiveType}"`;
80
+ const earlier = holderByType.get(authorType);
81
+ if (earlier !== undefined) {
82
+ throw new error_1.IsomerError('DUPLICATE_PRIMITIVE_TYPE', `buildJsxShim: ${earlier} and ${holder} share the type "${authorType}"`);
83
+ }
84
+ holderByType.set(authorType, holder);
85
+ }
86
+ const childSlotsByType = new Map(primitives.map(({ type, children }) => {
87
+ const walked = (0, exports.inferChildSlots)(children);
88
+ const nodes = (authoredByType.get(type)?.nodes ?? []).filter(({ field }) => !walked.some((slot) => slot.field === field));
89
+ return [
90
+ type,
91
+ [...walked, ...nodes.map(({ array, field }) => ({ array, field }))],
92
+ ];
93
+ }));
94
+ return { authoredByType, membersByType, childSlotsByType };
95
+ };
96
+ exports.createAuthoringModel = createAuthoringModel;
97
+ const isSameChild = (a, b) => a.itemSchema === b.itemSchema &&
98
+ a.propsSchema === b.propsSchema &&
99
+ a.toItem === b.toItem &&
100
+ a.textField === b.textField;
101
+ const isZodType = (schema) => typeof schema === 'object' && schema !== null && '_zod' in schema;
102
+ /**
103
+ * Reads {@link PrimitiveDefinition.children} against a probe node so JSX can
104
+ * fill the same fields a tree walk would visit. Paths like `body[0]` are array
105
+ * slots; a bare `header` is a single nested node.
106
+ */
107
+ const inferChildSlots = (children) => {
108
+ if (typeof children !== 'function') {
109
+ return [];
110
+ }
111
+ const probeNode = { type: '__probe__' };
112
+ const node = new Proxy({}, {
113
+ get(_target, prop) {
114
+ if (prop === 'type') {
115
+ return probeNode.type;
116
+ }
117
+ return [probeNode];
118
+ },
119
+ });
120
+ try {
121
+ const refs = children(node);
122
+ if (!Array.isArray(refs)) {
123
+ return [];
124
+ }
125
+ const byField = new Map();
126
+ for (const ref of refs) {
127
+ if (!isChildRef(ref)) {
128
+ continue;
129
+ }
130
+ const field = /^[A-Za-z_]\w*/.exec(ref.path)?.[0];
131
+ if (!field) {
132
+ continue;
133
+ }
134
+ byField.set(field, byField.get(field) === true || /\[\d+\]/.test(ref.path));
135
+ }
136
+ return [...byField.entries()].map(([field, array]) => ({ array, field }));
137
+ }
138
+ catch {
139
+ return [];
140
+ }
141
+ };
142
+ exports.inferChildSlots = inferChildSlots;
143
+ const isChildRef = (value) => typeof value === 'object' &&
144
+ value !== null &&
145
+ 'path' in value &&
146
+ typeof value.path === 'string';
147
+ const capitalize = (value) => `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`;
148
+ exports.capitalize = capitalize;
149
+ //# sourceMappingURL=authoring_model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring_model.js","sourceRoot":"","sources":["../../../src/author/authoring_model.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport type { ZodType } from 'zod';\n\nimport { IsomerError } from '../composition/error';\nimport type { PrimitiveNode } from '../define/primitive_module';\n\nimport {\n type AuthoredChildField,\n type AuthoredSpec,\n readAuthoredSpec,\n} from './authored_fields';\n\nexport interface ChildSlot {\n array: boolean;\n field: string;\n}\n\nexport interface AuthoringChild {\n field: AuthoredChildField;\n primitiveType: string;\n /** Property name on the primitive's component, e.g. `Item`. */\n member: string;\n /** What the member's elements carry as {@link authorType}, e.g. `slideList.Item`. */\n authorType: string;\n path: readonly AuthoredChildField[];\n}\n\n/** The {@link AuthoringChild.authorType} of `field`'s elements under the primitive `owner`. */\nexport const memberType = (\n owner: string,\n { name }: Pick<AuthoredChildField, 'name'>\n): string => `${owner}.${capitalize(name)}`;\n\nexport const createAuthoringModel = (\n primitives: readonly { type: string; schema?: unknown; children?: unknown }[]\n) => {\n const authoredByType = new Map<string, AuthoredSpec>();\n const membersByType = new Map<string, AuthoringChild[]>();\n const collectMembers = (type: string, spec: AuthoredSpec): void => {\n const members = new Map<string, AuthoringChild>();\n const visited = new Set<ZodType>();\n const collect = (\n fields: readonly AuthoredChildField[],\n path: readonly AuthoredChildField[]\n ): void => {\n const siblings = new Set<string>();\n for (const field of fields) {\n const member = capitalize(field.name);\n const prior = members.get(member);\n if (\n prior &&\n (!isSameChild(prior.field, field) || siblings.has(member))\n ) {\n throw new IsomerError(\n 'DUPLICATE_AUTHORED_CHILD',\n `buildJsxShim: \"${prior.field.field}\" and \"${field.field}\" both become <${capitalize(type)}.${member}>`\n );\n }\n siblings.add(member);\n const nextPath = [...path, field];\n if (!prior) {\n members.set(member, {\n field,\n primitiveType: type,\n member,\n authorType: memberType(type, field),\n path: nextPath,\n });\n }\n if (field.toItem || visited.has(field.itemSchema)) {\n continue;\n }\n visited.add(field.itemSchema);\n collect(readAuthoredSpec(field.itemSchema).children, nextPath);\n }\n };\n collect(spec.children, []);\n if (members.size > 0) {\n membersByType.set(type, [...members.values()]);\n }\n };\n for (const { type, schema } of primitives) {\n if (!isZodType(schema)) {\n continue;\n }\n const spec = readAuthoredSpec(schema);\n if (\n spec.children.length === 0 &&\n spec.text.length === 0 &&\n !spec.nodes?.length\n ) {\n continue;\n }\n authoredByType.set(type, spec);\n collectMembers(type, spec);\n }\n const typeByName = new Map([['Composition', 'view']]);\n for (const { type } of primitives) {\n const name = capitalize(type);\n const earlier = typeByName.get(name);\n if (earlier !== undefined && earlier !== type) {\n throw new IsomerError(\n 'DUPLICATE_PRIMITIVE_TYPE',\n `buildJsxShim: \"${earlier}\" and \"${type}\" both become the component ${name}`\n );\n }\n typeByName.set(name, type);\n }\n const holderByType = new Map(\n primitives.map(({ type }) => [type, `the primitive \"${type}\"`])\n );\n for (const { authorType, primitiveType, member } of [\n ...membersByType.values(),\n ].flat()) {\n const holder = `the member ${member} of \"${primitiveType}\"`;\n const earlier = holderByType.get(authorType);\n if (earlier !== undefined) {\n throw new IsomerError(\n 'DUPLICATE_PRIMITIVE_TYPE',\n `buildJsxShim: ${earlier} and ${holder} share the type \"${authorType}\"`\n );\n }\n holderByType.set(authorType, holder);\n }\n const childSlotsByType = new Map(\n primitives.map(({ type, children }) => {\n const walked = inferChildSlots(children);\n const nodes = (authoredByType.get(type)?.nodes ?? []).filter(\n ({ field }) => !walked.some((slot) => slot.field === field)\n );\n return [\n type,\n [...walked, ...nodes.map(({ array, field }) => ({ array, field }))],\n ];\n })\n );\n return { authoredByType, membersByType, childSlotsByType };\n};\n\nconst isSameChild = (a: AuthoredChildField, b: AuthoredChildField): boolean =>\n a.itemSchema === b.itemSchema &&\n a.propsSchema === b.propsSchema &&\n a.toItem === b.toItem &&\n a.textField === b.textField;\n\nconst isZodType = (schema: unknown): schema is ZodType =>\n typeof schema === 'object' && schema !== null && '_zod' in schema;\n\n/**\n * Reads {@link PrimitiveDefinition.children} against a probe node so JSX can\n * fill the same fields a tree walk would visit. Paths like `body[0]` are array\n * slots; a bare `header` is a single nested node.\n */\nexport const inferChildSlots = (children: unknown): readonly ChildSlot[] => {\n if (typeof children !== 'function') {\n return [];\n }\n const probeNode: PrimitiveNode = { type: '__probe__' };\n const node = new Proxy(\n {},\n {\n get(_target, prop) {\n if (prop === 'type') {\n return probeNode.type;\n }\n return [probeNode];\n },\n }\n );\n try {\n const refs = (children as (value: unknown) => unknown)(node);\n if (!Array.isArray(refs)) {\n return [];\n }\n const byField = new Map<string, boolean>();\n for (const ref of refs) {\n if (!isChildRef(ref)) {\n continue;\n }\n const field = /^[A-Za-z_]\\w*/.exec(ref.path)?.[0];\n if (!field) {\n continue;\n }\n byField.set(\n field,\n byField.get(field) === true || /\\[\\d+\\]/.test(ref.path)\n );\n }\n return [...byField.entries()].map(([field, array]) => ({ array, field }));\n } catch {\n return [];\n }\n};\n\nconst isChildRef = (value: unknown): value is { path: string } =>\n typeof value === 'object' &&\n value !== null &&\n 'path' in value &&\n typeof value.path === 'string';\n\nexport const capitalize = (value: string): string =>\n `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`;\n"]}