@flextudio/scenario 0.1.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 (856) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +260 -0
  3. package/bin/flex-scenario.mjs +895 -0
  4. package/commands/flex-spec.md +28 -0
  5. package/contract-data/README.md +267 -0
  6. package/contract-data/examples/README.md +147 -0
  7. package/contract-data/examples/basic/basic-list-detail.json +2521 -0
  8. package/contract-data/examples/basic/delivery-address-popup.json +2175 -0
  9. package/contract-data/examples/basic/fixedtop-floating-form.json +1524 -0
  10. package/contract-data/examples/basic/search-period-popup.json +1524 -0
  11. package/contract-data/examples/design/booking-wizard-3step.json +1335 -0
  12. package/contract-data/examples/design/list-detail-form-3step.json +1516 -0
  13. package/contract-data/examples/design/list-filter-2step.json +1365 -0
  14. package/contract-data/examples/design/list-filter-detail-3step.json +1570 -0
  15. package/contract-data/examples/design/result-entry-wizard-4step.json +1861 -0
  16. package/contract-data/examples/intent/mock-employee-list.json +54 -0
  17. package/contract-data/examples/intent/script-cart-flow.json +96 -0
  18. package/contract-data/examples/intent/script-dialog-confirm.json +61 -0
  19. package/contract-data/runtime/v1/collection/README.md +119 -0
  20. package/contract-data/runtime/v1/collection/_c.md +205 -0
  21. package/contract-data/runtime/v1/collection/category.md +165 -0
  22. package/contract-data/runtime/v1/collection/collection.md +135 -0
  23. package/contract-data/runtime/v1/collection/lifecycle.md +140 -0
  24. package/contract-data/runtime/v1/collection/naming.md +174 -0
  25. package/contract-data/runtime/v1/collection/sector.md +176 -0
  26. package/contract-data/runtime/v1/collection/status.md +114 -0
  27. package/contract-data/runtime/v1/intent-system/INTENT.md +552 -0
  28. package/contract-data/runtime/v1/intent-system/README.md +118 -0
  29. package/contract-data/runtime/v1/intent-system/intent.schema.json +164 -0
  30. package/contract-data/runtime/v1/intent-system/kinds/_base.mjs +137 -0
  31. package/contract-data/runtime/v1/intent-system/kinds/clearCategory.mjs +35 -0
  32. package/contract-data/runtime/v1/intent-system/kinds/copyStepValues.mjs +100 -0
  33. package/contract-data/runtime/v1/intent-system/kinds/deleteActive.mjs +45 -0
  34. package/contract-data/runtime/v1/intent-system/kinds/dialog.mjs +127 -0
  35. package/contract-data/runtime/v1/intent-system/kinds/reloadGroup.mjs +28 -0
  36. package/contract-data/runtime/v1/intent-system/kinds/updateActive.mjs +74 -0
  37. package/contract-data/runtime/v1/intent-system/materialize.mjs +495 -0
  38. package/contract-data/runtime/v1/script/README.md +37 -0
  39. package/contract-data/runtime/v1/script/current_step.md +112 -0
  40. package/contract-data/runtime/v1/script/f_collection.md +142 -0
  41. package/contract-data/runtime/v1/script/f_content.md +133 -0
  42. package/contract-data/runtime/v1/script/f_messagebox.md +132 -0
  43. package/contract-data/runtime/v1/script/scenario-gen-rules.md +264 -0
  44. package/contract-data/schema/v1/SKELETON-SHELL.md +120 -0
  45. package/contract-data/schema/v1/bottom-buttons.md +155 -0
  46. package/contract-data/schema/v1/bottom-buttons.schema.json +134 -0
  47. package/contract-data/schema/v1/control/_base.schema.json +1296 -0
  48. package/contract-data/schema/v1/control/button.md +147 -0
  49. package/contract-data/schema/v1/control/button.schema.json +55 -0
  50. package/contract-data/schema/v1/control/calendar-navigator.md +143 -0
  51. package/contract-data/schema/v1/control/calendar-navigator.schema.json +164 -0
  52. package/contract-data/schema/v1/control/calendar.md +128 -0
  53. package/contract-data/schema/v1/control/calendar.schema.json +18 -0
  54. package/contract-data/schema/v1/control/check-box.md +117 -0
  55. package/contract-data/schema/v1/control/check-box.schema.json +41 -0
  56. package/contract-data/schema/v1/control/combo.md +293 -0
  57. package/contract-data/schema/v1/control/combo.schema.json +23 -0
  58. package/contract-data/schema/v1/control/embed.md +211 -0
  59. package/contract-data/schema/v1/control/embed.schema.json +30 -0
  60. package/contract-data/schema/v1/control/image-box.md +237 -0
  61. package/contract-data/schema/v1/control/image-box.schema.json +49 -0
  62. package/contract-data/schema/v1/control/input-date.md +175 -0
  63. package/contract-data/schema/v1/control/input-date.schema.json +27 -0
  64. package/contract-data/schema/v1/control/input-file.md +192 -0
  65. package/contract-data/schema/v1/control/input-file.schema.json +139 -0
  66. package/contract-data/schema/v1/control/input-mask.md +89 -0
  67. package/contract-data/schema/v1/control/input-mask.schema.json +45 -0
  68. package/contract-data/schema/v1/control/input-number.md +55 -0
  69. package/contract-data/schema/v1/control/input-number.schema.json +24 -0
  70. package/contract-data/schema/v1/control/input-text.md +73 -0
  71. package/contract-data/schema/v1/control/input-text.schema.json +24 -0
  72. package/contract-data/schema/v1/control/label.md +127 -0
  73. package/contract-data/schema/v1/control/label.schema.json +113 -0
  74. package/contract-data/schema/v1/control/multi-input-box.md +51 -0
  75. package/contract-data/schema/v1/control/multi-input-box.schema.json +19 -0
  76. package/contract-data/schema/v1/control/other.schema.json +24 -0
  77. package/contract-data/schema/v1/control/radio-box.md +150 -0
  78. package/contract-data/schema/v1/control/radio-box.schema.json +87 -0
  79. package/contract-data/schema/v1/control/search.md +163 -0
  80. package/contract-data/schema/v1/control/search.schema.json +23 -0
  81. package/contract-data/schema/v1/control/tab.md +240 -0
  82. package/contract-data/schema/v1/control/tab.schema.json +112 -0
  83. package/contract-data/schema/v1/control/tree.md +278 -0
  84. package/contract-data/schema/v1/control/tree.schema.json +83 -0
  85. package/contract-data/schema/v1/control.md +264 -0
  86. package/contract-data/schema/v1/control.schema.json +30 -0
  87. package/contract-data/schema/v1/data-objects.md +278 -0
  88. package/contract-data/schema/v1/data-objects.schema.json +161 -0
  89. package/contract-data/schema/v1/data-sources.md +215 -0
  90. package/contract-data/schema/v1/data-sources.schema.json +184 -0
  91. package/contract-data/schema/v1/design-system/DESIGN.md +282 -0
  92. package/contract-data/schema/v1/design-system/README.md +235 -0
  93. package/contract-data/schema/v1/design-system/design.schema.json +496 -0
  94. package/contract-data/schema/v1/design-system/error-mapping.mjs +132 -0
  95. package/contract-data/schema/v1/design-system/materialize.mjs +1435 -0
  96. package/contract-data/schema/v1/design-system/tests/_base.additional-meta.test.mjs +98 -0
  97. package/contract-data/schema/v1/design-system/tests/_base.materialize.test.mjs +596 -0
  98. package/contract-data/schema/v1/design-system/tests/checklist.test.mjs +135 -0
  99. package/contract-data/schema/v1/design-system/tests/design.schema.test.mjs +487 -0
  100. package/contract-data/schema/v1/design-system/tests/error-mapping.test.mjs +244 -0
  101. package/contract-data/schema/v1/design-system/tests/materialize.test.mjs +1093 -0
  102. package/contract-data/schema/v1/design-system/tests/move-step.test.mjs +119 -0
  103. package/contract-data/schema/v1/design-system/tests/override.integration.test.mjs +116 -0
  104. package/contract-data/schema/v1/design-system/tokens.json +76 -0
  105. package/contract-data/schema/v1/events.md +467 -0
  106. package/contract-data/schema/v1/events.schema.json +272 -0
  107. package/contract-data/schema/v1/group.md +146 -0
  108. package/contract-data/schema/v1/group.schema.json +133 -0
  109. package/contract-data/schema/v1/mockup-data.md +186 -0
  110. package/contract-data/schema/v1/naming-objects.schema.json +133 -0
  111. package/contract-data/schema/v1/node.md +32 -0
  112. package/contract-data/schema/v1/node.schema.json +24 -0
  113. package/contract-data/schema/v1/patterns/_base.additional-meta.mjs +135 -0
  114. package/contract-data/schema/v1/patterns/_base.controls.mjs +759 -0
  115. package/contract-data/schema/v1/patterns/_base.icon.mjs +61 -0
  116. package/contract-data/schema/v1/patterns/_base.id.mjs +15 -0
  117. package/contract-data/schema/v1/patterns/_base.materialize.mjs +1181 -0
  118. package/contract-data/schema/v1/patterns/_base.style.mjs +312 -0
  119. package/contract-data/schema/v1/patterns/atom/badge.materialize.mjs +68 -0
  120. package/contract-data/schema/v1/patterns/atom/badge.schema.json +44 -0
  121. package/contract-data/schema/v1/patterns/atom/button.materialize.mjs +91 -0
  122. package/contract-data/schema/v1/patterns/atom/button.schema.json +70 -0
  123. package/contract-data/schema/v1/patterns/atom/checkbox.materialize.mjs +40 -0
  124. package/contract-data/schema/v1/patterns/atom/checkbox.schema.json +39 -0
  125. package/contract-data/schema/v1/patterns/atom/segmented-radio.materialize.mjs +67 -0
  126. package/contract-data/schema/v1/patterns/atom/segmented-radio.schema.json +49 -0
  127. package/contract-data/schema/v1/patterns/atom/switch.materialize.mjs +58 -0
  128. package/contract-data/schema/v1/patterns/atom/switch.schema.json +27 -0
  129. package/contract-data/schema/v1/patterns/molecule/checklist.materialize.mjs +130 -0
  130. package/contract-data/schema/v1/patterns/molecule/checklist.schema.json +63 -0
  131. package/contract-data/schema/v1/patterns/molecule/input-action.materialize.mjs +356 -0
  132. package/contract-data/schema/v1/patterns/molecule/input-action.schema.json +251 -0
  133. package/contract-data/schema/v1/patterns/molecule/input-button.materialize.mjs +183 -0
  134. package/contract-data/schema/v1/patterns/molecule/input-button.schema.json +141 -0
  135. package/contract-data/schema/v1/patterns/molecule/input-pair.materialize.mjs +254 -0
  136. package/contract-data/schema/v1/patterns/molecule/input-pair.schema.json +210 -0
  137. package/contract-data/schema/v1/scenario.md +112 -0
  138. package/contract-data/schema/v1/scenario.schema.json +161 -0
  139. package/contract-data/schema/v1/service/CustomSystem.md +139 -0
  140. package/contract-data/schema/v1/service/CustomSystem.schema.json +41 -0
  141. package/contract-data/schema/v1/service/Firestore.md +125 -0
  142. package/contract-data/schema/v1/service/Firestore.schema.json +28 -0
  143. package/contract-data/schema/v1/service/FlexAutoQuery.md +128 -0
  144. package/contract-data/schema/v1/service/FlexAutoQuery.schema.json +35 -0
  145. package/contract-data/schema/v1/service/FlexSQL.md +96 -0
  146. package/contract-data/schema/v1/service/FlexSQL.schema.json +33 -0
  147. package/contract-data/schema/v1/service/Flextudio API.md +161 -0
  148. package/contract-data/schema/v1/service/Flextudio API.schema.json +115 -0
  149. package/contract-data/schema/v1/service/Flextudio.md +87 -0
  150. package/contract-data/schema/v1/service/Flextudio.schema.json +26 -0
  151. package/contract-data/schema/v1/service/GoogleSheet.md +71 -0
  152. package/contract-data/schema/v1/service/GoogleSheet.schema.json +31 -0
  153. package/contract-data/schema/v1/service/README.md +127 -0
  154. package/contract-data/schema/v1/service/_base.schema.json +31 -0
  155. package/contract-data/schema/v1/service/ksystem.md +76 -0
  156. package/contract-data/schema/v1/service/ksystem.schema.json +36 -0
  157. package/contract-data/schema/v1/service-binding.md +228 -0
  158. package/contract-data/schema/v1/service-binding.schema.json +51 -0
  159. package/contract-data/schema/v1/step.md +546 -0
  160. package/contract-data/schema/v1/step.schema.json +258 -0
  161. package/contract-data/schema/v1/style-objects.md +183 -0
  162. package/contract-data/schema/v1/style-objects.schema.json +155 -0
  163. package/contract-data/spec/catalog.json +406 -0
  164. package/contract-data/spec/rules.md +400 -0
  165. package/node_modules/@flextudio/contract-core/contract.mjs +367 -0
  166. package/node_modules/@flextudio/contract-core/index.mjs +16 -0
  167. package/node_modules/@flextudio/contract-core/package.json +21 -0
  168. package/node_modules/@flextudio/contract-core/paths.mjs +72 -0
  169. package/node_modules/@flextudio/contract-core/schemas.mjs +474 -0
  170. package/node_modules/@flextudio/contract-core/validators.mjs +2471 -0
  171. package/node_modules/ajv/.runkit_example.js +23 -0
  172. package/node_modules/ajv/LICENSE +22 -0
  173. package/node_modules/ajv/README.md +207 -0
  174. package/node_modules/ajv/dist/2019.d.ts +19 -0
  175. package/node_modules/ajv/dist/2019.js +61 -0
  176. package/node_modules/ajv/dist/2019.js.map +1 -0
  177. package/node_modules/ajv/dist/2020.d.ts +19 -0
  178. package/node_modules/ajv/dist/2020.js +55 -0
  179. package/node_modules/ajv/dist/2020.js.map +1 -0
  180. package/node_modules/ajv/dist/ajv.d.ts +18 -0
  181. package/node_modules/ajv/dist/ajv.js +50 -0
  182. package/node_modules/ajv/dist/ajv.js.map +1 -0
  183. package/node_modules/ajv/dist/compile/codegen/code.d.ts +40 -0
  184. package/node_modules/ajv/dist/compile/codegen/code.js +156 -0
  185. package/node_modules/ajv/dist/compile/codegen/code.js.map +1 -0
  186. package/node_modules/ajv/dist/compile/codegen/index.d.ts +79 -0
  187. package/node_modules/ajv/dist/compile/codegen/index.js +697 -0
  188. package/node_modules/ajv/dist/compile/codegen/index.js.map +1 -0
  189. package/node_modules/ajv/dist/compile/codegen/scope.d.ts +79 -0
  190. package/node_modules/ajv/dist/compile/codegen/scope.js +143 -0
  191. package/node_modules/ajv/dist/compile/codegen/scope.js.map +1 -0
  192. package/node_modules/ajv/dist/compile/errors.d.ts +13 -0
  193. package/node_modules/ajv/dist/compile/errors.js +123 -0
  194. package/node_modules/ajv/dist/compile/errors.js.map +1 -0
  195. package/node_modules/ajv/dist/compile/index.d.ts +80 -0
  196. package/node_modules/ajv/dist/compile/index.js +242 -0
  197. package/node_modules/ajv/dist/compile/index.js.map +1 -0
  198. package/node_modules/ajv/dist/compile/jtd/parse.d.ts +4 -0
  199. package/node_modules/ajv/dist/compile/jtd/parse.js +350 -0
  200. package/node_modules/ajv/dist/compile/jtd/parse.js.map +1 -0
  201. package/node_modules/ajv/dist/compile/jtd/serialize.d.ts +4 -0
  202. package/node_modules/ajv/dist/compile/jtd/serialize.js +236 -0
  203. package/node_modules/ajv/dist/compile/jtd/serialize.js.map +1 -0
  204. package/node_modules/ajv/dist/compile/jtd/types.d.ts +6 -0
  205. package/node_modules/ajv/dist/compile/jtd/types.js +14 -0
  206. package/node_modules/ajv/dist/compile/jtd/types.js.map +1 -0
  207. package/node_modules/ajv/dist/compile/names.d.ts +20 -0
  208. package/node_modules/ajv/dist/compile/names.js +28 -0
  209. package/node_modules/ajv/dist/compile/names.js.map +1 -0
  210. package/node_modules/ajv/dist/compile/ref_error.d.ts +6 -0
  211. package/node_modules/ajv/dist/compile/ref_error.js +12 -0
  212. package/node_modules/ajv/dist/compile/ref_error.js.map +1 -0
  213. package/node_modules/ajv/dist/compile/resolve.d.ts +12 -0
  214. package/node_modules/ajv/dist/compile/resolve.js +155 -0
  215. package/node_modules/ajv/dist/compile/resolve.js.map +1 -0
  216. package/node_modules/ajv/dist/compile/rules.d.ts +28 -0
  217. package/node_modules/ajv/dist/compile/rules.js +26 -0
  218. package/node_modules/ajv/dist/compile/rules.js.map +1 -0
  219. package/node_modules/ajv/dist/compile/util.d.ts +40 -0
  220. package/node_modules/ajv/dist/compile/util.js +178 -0
  221. package/node_modules/ajv/dist/compile/util.js.map +1 -0
  222. package/node_modules/ajv/dist/compile/validate/applicability.d.ts +6 -0
  223. package/node_modules/ajv/dist/compile/validate/applicability.js +19 -0
  224. package/node_modules/ajv/dist/compile/validate/applicability.js.map +1 -0
  225. package/node_modules/ajv/dist/compile/validate/boolSchema.d.ts +4 -0
  226. package/node_modules/ajv/dist/compile/validate/boolSchema.js +50 -0
  227. package/node_modules/ajv/dist/compile/validate/boolSchema.js.map +1 -0
  228. package/node_modules/ajv/dist/compile/validate/dataType.d.ts +17 -0
  229. package/node_modules/ajv/dist/compile/validate/dataType.js +203 -0
  230. package/node_modules/ajv/dist/compile/validate/dataType.js.map +1 -0
  231. package/node_modules/ajv/dist/compile/validate/defaults.d.ts +2 -0
  232. package/node_modules/ajv/dist/compile/validate/defaults.js +35 -0
  233. package/node_modules/ajv/dist/compile/validate/defaults.js.map +1 -0
  234. package/node_modules/ajv/dist/compile/validate/index.d.ts +42 -0
  235. package/node_modules/ajv/dist/compile/validate/index.js +520 -0
  236. package/node_modules/ajv/dist/compile/validate/index.js.map +1 -0
  237. package/node_modules/ajv/dist/compile/validate/keyword.d.ts +8 -0
  238. package/node_modules/ajv/dist/compile/validate/keyword.js +124 -0
  239. package/node_modules/ajv/dist/compile/validate/keyword.js.map +1 -0
  240. package/node_modules/ajv/dist/compile/validate/subschema.d.ts +47 -0
  241. package/node_modules/ajv/dist/compile/validate/subschema.js +81 -0
  242. package/node_modules/ajv/dist/compile/validate/subschema.js.map +1 -0
  243. package/node_modules/ajv/dist/core.d.ts +174 -0
  244. package/node_modules/ajv/dist/core.js +618 -0
  245. package/node_modules/ajv/dist/core.js.map +1 -0
  246. package/node_modules/ajv/dist/jtd.d.ts +47 -0
  247. package/node_modules/ajv/dist/jtd.js +72 -0
  248. package/node_modules/ajv/dist/jtd.js.map +1 -0
  249. package/node_modules/ajv/dist/refs/data.json +13 -0
  250. package/node_modules/ajv/dist/refs/json-schema-2019-09/index.d.ts +2 -0
  251. package/node_modules/ajv/dist/refs/json-schema-2019-09/index.js +28 -0
  252. package/node_modules/ajv/dist/refs/json-schema-2019-09/index.js.map +1 -0
  253. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/applicator.json +53 -0
  254. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/content.json +17 -0
  255. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/core.json +57 -0
  256. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/format.json +14 -0
  257. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/meta-data.json +37 -0
  258. package/node_modules/ajv/dist/refs/json-schema-2019-09/meta/validation.json +90 -0
  259. package/node_modules/ajv/dist/refs/json-schema-2019-09/schema.json +39 -0
  260. package/node_modules/ajv/dist/refs/json-schema-2020-12/index.d.ts +2 -0
  261. package/node_modules/ajv/dist/refs/json-schema-2020-12/index.js +30 -0
  262. package/node_modules/ajv/dist/refs/json-schema-2020-12/index.js.map +1 -0
  263. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/applicator.json +48 -0
  264. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/content.json +17 -0
  265. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/core.json +51 -0
  266. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/format-annotation.json +14 -0
  267. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/meta-data.json +37 -0
  268. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/unevaluated.json +15 -0
  269. package/node_modules/ajv/dist/refs/json-schema-2020-12/meta/validation.json +90 -0
  270. package/node_modules/ajv/dist/refs/json-schema-2020-12/schema.json +55 -0
  271. package/node_modules/ajv/dist/refs/json-schema-draft-06.json +137 -0
  272. package/node_modules/ajv/dist/refs/json-schema-draft-07.json +151 -0
  273. package/node_modules/ajv/dist/refs/json-schema-secure.json +88 -0
  274. package/node_modules/ajv/dist/refs/jtd-schema.d.ts +3 -0
  275. package/node_modules/ajv/dist/refs/jtd-schema.js +118 -0
  276. package/node_modules/ajv/dist/refs/jtd-schema.js.map +1 -0
  277. package/node_modules/ajv/dist/runtime/equal.d.ts +6 -0
  278. package/node_modules/ajv/dist/runtime/equal.js +7 -0
  279. package/node_modules/ajv/dist/runtime/equal.js.map +1 -0
  280. package/node_modules/ajv/dist/runtime/parseJson.d.ts +18 -0
  281. package/node_modules/ajv/dist/runtime/parseJson.js +185 -0
  282. package/node_modules/ajv/dist/runtime/parseJson.js.map +1 -0
  283. package/node_modules/ajv/dist/runtime/quote.d.ts +5 -0
  284. package/node_modules/ajv/dist/runtime/quote.js +30 -0
  285. package/node_modules/ajv/dist/runtime/quote.js.map +1 -0
  286. package/node_modules/ajv/dist/runtime/re2.d.ts +6 -0
  287. package/node_modules/ajv/dist/runtime/re2.js +6 -0
  288. package/node_modules/ajv/dist/runtime/re2.js.map +1 -0
  289. package/node_modules/ajv/dist/runtime/timestamp.d.ts +5 -0
  290. package/node_modules/ajv/dist/runtime/timestamp.js +42 -0
  291. package/node_modules/ajv/dist/runtime/timestamp.js.map +1 -0
  292. package/node_modules/ajv/dist/runtime/ucs2length.d.ts +5 -0
  293. package/node_modules/ajv/dist/runtime/ucs2length.js +24 -0
  294. package/node_modules/ajv/dist/runtime/ucs2length.js.map +1 -0
  295. package/node_modules/ajv/dist/runtime/uri.d.ts +6 -0
  296. package/node_modules/ajv/dist/runtime/uri.js +6 -0
  297. package/node_modules/ajv/dist/runtime/uri.js.map +1 -0
  298. package/node_modules/ajv/dist/runtime/validation_error.d.ts +7 -0
  299. package/node_modules/ajv/dist/runtime/validation_error.js +11 -0
  300. package/node_modules/ajv/dist/runtime/validation_error.js.map +1 -0
  301. package/node_modules/ajv/dist/standalone/index.d.ts +6 -0
  302. package/node_modules/ajv/dist/standalone/index.js +90 -0
  303. package/node_modules/ajv/dist/standalone/index.js.map +1 -0
  304. package/node_modules/ajv/dist/standalone/instance.d.ts +12 -0
  305. package/node_modules/ajv/dist/standalone/instance.js +35 -0
  306. package/node_modules/ajv/dist/standalone/instance.js.map +1 -0
  307. package/node_modules/ajv/dist/types/index.d.ts +183 -0
  308. package/node_modules/ajv/dist/types/index.js +3 -0
  309. package/node_modules/ajv/dist/types/index.js.map +1 -0
  310. package/node_modules/ajv/dist/types/json-schema.d.ts +125 -0
  311. package/node_modules/ajv/dist/types/json-schema.js +3 -0
  312. package/node_modules/ajv/dist/types/json-schema.js.map +1 -0
  313. package/node_modules/ajv/dist/types/jtd-schema.d.ts +174 -0
  314. package/node_modules/ajv/dist/types/jtd-schema.js +3 -0
  315. package/node_modules/ajv/dist/types/jtd-schema.js.map +1 -0
  316. package/node_modules/ajv/dist/vocabularies/applicator/additionalItems.d.ts +8 -0
  317. package/node_modules/ajv/dist/vocabularies/applicator/additionalItems.js +49 -0
  318. package/node_modules/ajv/dist/vocabularies/applicator/additionalItems.js.map +1 -0
  319. package/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.d.ts +6 -0
  320. package/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js +106 -0
  321. package/node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js.map +1 -0
  322. package/node_modules/ajv/dist/vocabularies/applicator/allOf.d.ts +3 -0
  323. package/node_modules/ajv/dist/vocabularies/applicator/allOf.js +23 -0
  324. package/node_modules/ajv/dist/vocabularies/applicator/allOf.js.map +1 -0
  325. package/node_modules/ajv/dist/vocabularies/applicator/anyOf.d.ts +4 -0
  326. package/node_modules/ajv/dist/vocabularies/applicator/anyOf.js +12 -0
  327. package/node_modules/ajv/dist/vocabularies/applicator/anyOf.js.map +1 -0
  328. package/node_modules/ajv/dist/vocabularies/applicator/contains.d.ts +7 -0
  329. package/node_modules/ajv/dist/vocabularies/applicator/contains.js +95 -0
  330. package/node_modules/ajv/dist/vocabularies/applicator/contains.js.map +1 -0
  331. package/node_modules/ajv/dist/vocabularies/applicator/dependencies.d.ts +21 -0
  332. package/node_modules/ajv/dist/vocabularies/applicator/dependencies.js +85 -0
  333. package/node_modules/ajv/dist/vocabularies/applicator/dependencies.js.map +1 -0
  334. package/node_modules/ajv/dist/vocabularies/applicator/dependentSchemas.d.ts +3 -0
  335. package/node_modules/ajv/dist/vocabularies/applicator/dependentSchemas.js +11 -0
  336. package/node_modules/ajv/dist/vocabularies/applicator/dependentSchemas.js.map +1 -0
  337. package/node_modules/ajv/dist/vocabularies/applicator/if.d.ts +6 -0
  338. package/node_modules/ajv/dist/vocabularies/applicator/if.js +66 -0
  339. package/node_modules/ajv/dist/vocabularies/applicator/if.js.map +1 -0
  340. package/node_modules/ajv/dist/vocabularies/applicator/index.d.ts +13 -0
  341. package/node_modules/ajv/dist/vocabularies/applicator/index.js +44 -0
  342. package/node_modules/ajv/dist/vocabularies/applicator/index.js.map +1 -0
  343. package/node_modules/ajv/dist/vocabularies/applicator/items.d.ts +5 -0
  344. package/node_modules/ajv/dist/vocabularies/applicator/items.js +52 -0
  345. package/node_modules/ajv/dist/vocabularies/applicator/items.js.map +1 -0
  346. package/node_modules/ajv/dist/vocabularies/applicator/items2020.d.ts +6 -0
  347. package/node_modules/ajv/dist/vocabularies/applicator/items2020.js +30 -0
  348. package/node_modules/ajv/dist/vocabularies/applicator/items2020.js.map +1 -0
  349. package/node_modules/ajv/dist/vocabularies/applicator/not.d.ts +4 -0
  350. package/node_modules/ajv/dist/vocabularies/applicator/not.js +26 -0
  351. package/node_modules/ajv/dist/vocabularies/applicator/not.js.map +1 -0
  352. package/node_modules/ajv/dist/vocabularies/applicator/oneOf.d.ts +6 -0
  353. package/node_modules/ajv/dist/vocabularies/applicator/oneOf.js +60 -0
  354. package/node_modules/ajv/dist/vocabularies/applicator/oneOf.js.map +1 -0
  355. package/node_modules/ajv/dist/vocabularies/applicator/patternProperties.d.ts +3 -0
  356. package/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js +75 -0
  357. package/node_modules/ajv/dist/vocabularies/applicator/patternProperties.js.map +1 -0
  358. package/node_modules/ajv/dist/vocabularies/applicator/prefixItems.d.ts +3 -0
  359. package/node_modules/ajv/dist/vocabularies/applicator/prefixItems.js +12 -0
  360. package/node_modules/ajv/dist/vocabularies/applicator/prefixItems.js.map +1 -0
  361. package/node_modules/ajv/dist/vocabularies/applicator/properties.d.ts +3 -0
  362. package/node_modules/ajv/dist/vocabularies/applicator/properties.js +54 -0
  363. package/node_modules/ajv/dist/vocabularies/applicator/properties.js.map +1 -0
  364. package/node_modules/ajv/dist/vocabularies/applicator/propertyNames.d.ts +6 -0
  365. package/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js +38 -0
  366. package/node_modules/ajv/dist/vocabularies/applicator/propertyNames.js.map +1 -0
  367. package/node_modules/ajv/dist/vocabularies/applicator/thenElse.d.ts +3 -0
  368. package/node_modules/ajv/dist/vocabularies/applicator/thenElse.js +13 -0
  369. package/node_modules/ajv/dist/vocabularies/applicator/thenElse.js.map +1 -0
  370. package/node_modules/ajv/dist/vocabularies/code.d.ts +17 -0
  371. package/node_modules/ajv/dist/vocabularies/code.js +131 -0
  372. package/node_modules/ajv/dist/vocabularies/code.js.map +1 -0
  373. package/node_modules/ajv/dist/vocabularies/core/id.d.ts +3 -0
  374. package/node_modules/ajv/dist/vocabularies/core/id.js +10 -0
  375. package/node_modules/ajv/dist/vocabularies/core/id.js.map +1 -0
  376. package/node_modules/ajv/dist/vocabularies/core/index.d.ts +3 -0
  377. package/node_modules/ajv/dist/vocabularies/core/index.js +16 -0
  378. package/node_modules/ajv/dist/vocabularies/core/index.js.map +1 -0
  379. package/node_modules/ajv/dist/vocabularies/core/ref.d.ts +8 -0
  380. package/node_modules/ajv/dist/vocabularies/core/ref.js +122 -0
  381. package/node_modules/ajv/dist/vocabularies/core/ref.js.map +1 -0
  382. package/node_modules/ajv/dist/vocabularies/discriminator/index.d.ts +5 -0
  383. package/node_modules/ajv/dist/vocabularies/discriminator/index.js +104 -0
  384. package/node_modules/ajv/dist/vocabularies/discriminator/index.js.map +1 -0
  385. package/node_modules/ajv/dist/vocabularies/discriminator/types.d.ts +10 -0
  386. package/node_modules/ajv/dist/vocabularies/discriminator/types.js +9 -0
  387. package/node_modules/ajv/dist/vocabularies/discriminator/types.js.map +1 -0
  388. package/node_modules/ajv/dist/vocabularies/draft2020.d.ts +3 -0
  389. package/node_modules/ajv/dist/vocabularies/draft2020.js +23 -0
  390. package/node_modules/ajv/dist/vocabularies/draft2020.js.map +1 -0
  391. package/node_modules/ajv/dist/vocabularies/draft7.d.ts +3 -0
  392. package/node_modules/ajv/dist/vocabularies/draft7.js +17 -0
  393. package/node_modules/ajv/dist/vocabularies/draft7.js.map +1 -0
  394. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicAnchor.d.ts +5 -0
  395. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicAnchor.js +30 -0
  396. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicAnchor.js.map +1 -0
  397. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicRef.d.ts +5 -0
  398. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicRef.js +51 -0
  399. package/node_modules/ajv/dist/vocabularies/dynamic/dynamicRef.js.map +1 -0
  400. package/node_modules/ajv/dist/vocabularies/dynamic/index.d.ts +3 -0
  401. package/node_modules/ajv/dist/vocabularies/dynamic/index.js +9 -0
  402. package/node_modules/ajv/dist/vocabularies/dynamic/index.js.map +1 -0
  403. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveAnchor.d.ts +3 -0
  404. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveAnchor.js +16 -0
  405. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveAnchor.js.map +1 -0
  406. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveRef.d.ts +3 -0
  407. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveRef.js +10 -0
  408. package/node_modules/ajv/dist/vocabularies/dynamic/recursiveRef.js.map +1 -0
  409. package/node_modules/ajv/dist/vocabularies/errors.d.ts +9 -0
  410. package/node_modules/ajv/dist/vocabularies/errors.js +3 -0
  411. package/node_modules/ajv/dist/vocabularies/errors.js.map +1 -0
  412. package/node_modules/ajv/dist/vocabularies/format/format.d.ts +8 -0
  413. package/node_modules/ajv/dist/vocabularies/format/format.js +92 -0
  414. package/node_modules/ajv/dist/vocabularies/format/format.js.map +1 -0
  415. package/node_modules/ajv/dist/vocabularies/format/index.d.ts +3 -0
  416. package/node_modules/ajv/dist/vocabularies/format/index.js +6 -0
  417. package/node_modules/ajv/dist/vocabularies/format/index.js.map +1 -0
  418. package/node_modules/ajv/dist/vocabularies/jtd/discriminator.d.ts +6 -0
  419. package/node_modules/ajv/dist/vocabularies/jtd/discriminator.js +71 -0
  420. package/node_modules/ajv/dist/vocabularies/jtd/discriminator.js.map +1 -0
  421. package/node_modules/ajv/dist/vocabularies/jtd/elements.d.ts +5 -0
  422. package/node_modules/ajv/dist/vocabularies/jtd/elements.js +24 -0
  423. package/node_modules/ajv/dist/vocabularies/jtd/elements.js.map +1 -0
  424. package/node_modules/ajv/dist/vocabularies/jtd/enum.d.ts +6 -0
  425. package/node_modules/ajv/dist/vocabularies/jtd/enum.js +43 -0
  426. package/node_modules/ajv/dist/vocabularies/jtd/enum.js.map +1 -0
  427. package/node_modules/ajv/dist/vocabularies/jtd/error.d.ts +9 -0
  428. package/node_modules/ajv/dist/vocabularies/jtd/error.js +20 -0
  429. package/node_modules/ajv/dist/vocabularies/jtd/error.js.map +1 -0
  430. package/node_modules/ajv/dist/vocabularies/jtd/index.d.ts +10 -0
  431. package/node_modules/ajv/dist/vocabularies/jtd/index.js +29 -0
  432. package/node_modules/ajv/dist/vocabularies/jtd/index.js.map +1 -0
  433. package/node_modules/ajv/dist/vocabularies/jtd/metadata.d.ts +5 -0
  434. package/node_modules/ajv/dist/vocabularies/jtd/metadata.js +25 -0
  435. package/node_modules/ajv/dist/vocabularies/jtd/metadata.js.map +1 -0
  436. package/node_modules/ajv/dist/vocabularies/jtd/nullable.d.ts +4 -0
  437. package/node_modules/ajv/dist/vocabularies/jtd/nullable.js +22 -0
  438. package/node_modules/ajv/dist/vocabularies/jtd/nullable.js.map +1 -0
  439. package/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.d.ts +3 -0
  440. package/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.js +15 -0
  441. package/node_modules/ajv/dist/vocabularies/jtd/optionalProperties.js.map +1 -0
  442. package/node_modules/ajv/dist/vocabularies/jtd/properties.d.ts +22 -0
  443. package/node_modules/ajv/dist/vocabularies/jtd/properties.js +149 -0
  444. package/node_modules/ajv/dist/vocabularies/jtd/properties.js.map +1 -0
  445. package/node_modules/ajv/dist/vocabularies/jtd/ref.d.ts +4 -0
  446. package/node_modules/ajv/dist/vocabularies/jtd/ref.js +67 -0
  447. package/node_modules/ajv/dist/vocabularies/jtd/ref.js.map +1 -0
  448. package/node_modules/ajv/dist/vocabularies/jtd/type.d.ts +10 -0
  449. package/node_modules/ajv/dist/vocabularies/jtd/type.js +69 -0
  450. package/node_modules/ajv/dist/vocabularies/jtd/type.js.map +1 -0
  451. package/node_modules/ajv/dist/vocabularies/jtd/union.d.ts +3 -0
  452. package/node_modules/ajv/dist/vocabularies/jtd/union.js +12 -0
  453. package/node_modules/ajv/dist/vocabularies/jtd/union.js.map +1 -0
  454. package/node_modules/ajv/dist/vocabularies/jtd/values.d.ts +5 -0
  455. package/node_modules/ajv/dist/vocabularies/jtd/values.js +51 -0
  456. package/node_modules/ajv/dist/vocabularies/jtd/values.js.map +1 -0
  457. package/node_modules/ajv/dist/vocabularies/metadata.d.ts +3 -0
  458. package/node_modules/ajv/dist/vocabularies/metadata.js +18 -0
  459. package/node_modules/ajv/dist/vocabularies/metadata.js.map +1 -0
  460. package/node_modules/ajv/dist/vocabularies/next.d.ts +3 -0
  461. package/node_modules/ajv/dist/vocabularies/next.js +8 -0
  462. package/node_modules/ajv/dist/vocabularies/next.js.map +1 -0
  463. package/node_modules/ajv/dist/vocabularies/unevaluated/index.d.ts +3 -0
  464. package/node_modules/ajv/dist/vocabularies/unevaluated/index.js +7 -0
  465. package/node_modules/ajv/dist/vocabularies/unevaluated/index.js.map +1 -0
  466. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedItems.d.ts +6 -0
  467. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedItems.js +40 -0
  468. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedItems.js.map +1 -0
  469. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.d.ts +6 -0
  470. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js +65 -0
  471. package/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedProperties.js.map +1 -0
  472. package/node_modules/ajv/dist/vocabularies/validation/const.d.ts +6 -0
  473. package/node_modules/ajv/dist/vocabularies/validation/const.js +25 -0
  474. package/node_modules/ajv/dist/vocabularies/validation/const.js.map +1 -0
  475. package/node_modules/ajv/dist/vocabularies/validation/dependentRequired.d.ts +5 -0
  476. package/node_modules/ajv/dist/vocabularies/validation/dependentRequired.js +12 -0
  477. package/node_modules/ajv/dist/vocabularies/validation/dependentRequired.js.map +1 -0
  478. package/node_modules/ajv/dist/vocabularies/validation/enum.d.ts +8 -0
  479. package/node_modules/ajv/dist/vocabularies/validation/enum.js +48 -0
  480. package/node_modules/ajv/dist/vocabularies/validation/enum.js.map +1 -0
  481. package/node_modules/ajv/dist/vocabularies/validation/index.d.ts +16 -0
  482. package/node_modules/ajv/dist/vocabularies/validation/index.js +33 -0
  483. package/node_modules/ajv/dist/vocabularies/validation/index.js.map +1 -0
  484. package/node_modules/ajv/dist/vocabularies/validation/limitContains.d.ts +3 -0
  485. package/node_modules/ajv/dist/vocabularies/validation/limitContains.js +15 -0
  486. package/node_modules/ajv/dist/vocabularies/validation/limitContains.js.map +1 -0
  487. package/node_modules/ajv/dist/vocabularies/validation/limitItems.d.ts +3 -0
  488. package/node_modules/ajv/dist/vocabularies/validation/limitItems.js +24 -0
  489. package/node_modules/ajv/dist/vocabularies/validation/limitItems.js.map +1 -0
  490. package/node_modules/ajv/dist/vocabularies/validation/limitLength.d.ts +3 -0
  491. package/node_modules/ajv/dist/vocabularies/validation/limitLength.js +27 -0
  492. package/node_modules/ajv/dist/vocabularies/validation/limitLength.js.map +1 -0
  493. package/node_modules/ajv/dist/vocabularies/validation/limitNumber.d.ts +11 -0
  494. package/node_modules/ajv/dist/vocabularies/validation/limitNumber.js +27 -0
  495. package/node_modules/ajv/dist/vocabularies/validation/limitNumber.js.map +1 -0
  496. package/node_modules/ajv/dist/vocabularies/validation/limitProperties.d.ts +3 -0
  497. package/node_modules/ajv/dist/vocabularies/validation/limitProperties.js +24 -0
  498. package/node_modules/ajv/dist/vocabularies/validation/limitProperties.js.map +1 -0
  499. package/node_modules/ajv/dist/vocabularies/validation/multipleOf.d.ts +8 -0
  500. package/node_modules/ajv/dist/vocabularies/validation/multipleOf.js +26 -0
  501. package/node_modules/ajv/dist/vocabularies/validation/multipleOf.js.map +1 -0
  502. package/node_modules/ajv/dist/vocabularies/validation/pattern.d.ts +8 -0
  503. package/node_modules/ajv/dist/vocabularies/validation/pattern.js +33 -0
  504. package/node_modules/ajv/dist/vocabularies/validation/pattern.js.map +1 -0
  505. package/node_modules/ajv/dist/vocabularies/validation/required.d.ts +8 -0
  506. package/node_modules/ajv/dist/vocabularies/validation/required.js +79 -0
  507. package/node_modules/ajv/dist/vocabularies/validation/required.js.map +1 -0
  508. package/node_modules/ajv/dist/vocabularies/validation/uniqueItems.d.ts +9 -0
  509. package/node_modules/ajv/dist/vocabularies/validation/uniqueItems.js +64 -0
  510. package/node_modules/ajv/dist/vocabularies/validation/uniqueItems.js.map +1 -0
  511. package/node_modules/ajv/lib/2019.ts +81 -0
  512. package/node_modules/ajv/lib/2020.ts +75 -0
  513. package/node_modules/ajv/lib/ajv.ts +70 -0
  514. package/node_modules/ajv/lib/compile/codegen/code.ts +169 -0
  515. package/node_modules/ajv/lib/compile/codegen/index.ts +852 -0
  516. package/node_modules/ajv/lib/compile/codegen/scope.ts +215 -0
  517. package/node_modules/ajv/lib/compile/errors.ts +184 -0
  518. package/node_modules/ajv/lib/compile/index.ts +324 -0
  519. package/node_modules/ajv/lib/compile/jtd/parse.ts +411 -0
  520. package/node_modules/ajv/lib/compile/jtd/serialize.ts +277 -0
  521. package/node_modules/ajv/lib/compile/jtd/types.ts +16 -0
  522. package/node_modules/ajv/lib/compile/names.ts +27 -0
  523. package/node_modules/ajv/lib/compile/ref_error.ts +13 -0
  524. package/node_modules/ajv/lib/compile/resolve.ts +149 -0
  525. package/node_modules/ajv/lib/compile/rules.ts +50 -0
  526. package/node_modules/ajv/lib/compile/util.ts +213 -0
  527. package/node_modules/ajv/lib/compile/validate/applicability.ts +22 -0
  528. package/node_modules/ajv/lib/compile/validate/boolSchema.ts +47 -0
  529. package/node_modules/ajv/lib/compile/validate/dataType.ts +230 -0
  530. package/node_modules/ajv/lib/compile/validate/defaults.ts +32 -0
  531. package/node_modules/ajv/lib/compile/validate/index.ts +582 -0
  532. package/node_modules/ajv/lib/compile/validate/keyword.ts +171 -0
  533. package/node_modules/ajv/lib/compile/validate/subschema.ts +135 -0
  534. package/node_modules/ajv/lib/core.ts +892 -0
  535. package/node_modules/ajv/lib/jtd.ts +132 -0
  536. package/node_modules/ajv/lib/refs/data.json +13 -0
  537. package/node_modules/ajv/lib/refs/json-schema-2019-09/index.ts +28 -0
  538. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/applicator.json +53 -0
  539. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/content.json +17 -0
  540. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/core.json +57 -0
  541. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/format.json +14 -0
  542. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/meta-data.json +37 -0
  543. package/node_modules/ajv/lib/refs/json-schema-2019-09/meta/validation.json +90 -0
  544. package/node_modules/ajv/lib/refs/json-schema-2019-09/schema.json +39 -0
  545. package/node_modules/ajv/lib/refs/json-schema-2020-12/index.ts +30 -0
  546. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/applicator.json +48 -0
  547. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/content.json +17 -0
  548. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/core.json +51 -0
  549. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/format-annotation.json +14 -0
  550. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/meta-data.json +37 -0
  551. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/unevaluated.json +15 -0
  552. package/node_modules/ajv/lib/refs/json-schema-2020-12/meta/validation.json +90 -0
  553. package/node_modules/ajv/lib/refs/json-schema-2020-12/schema.json +55 -0
  554. package/node_modules/ajv/lib/refs/json-schema-draft-06.json +137 -0
  555. package/node_modules/ajv/lib/refs/json-schema-draft-07.json +151 -0
  556. package/node_modules/ajv/lib/refs/json-schema-secure.json +88 -0
  557. package/node_modules/ajv/lib/refs/jtd-schema.ts +130 -0
  558. package/node_modules/ajv/lib/runtime/equal.ts +7 -0
  559. package/node_modules/ajv/lib/runtime/parseJson.ts +177 -0
  560. package/node_modules/ajv/lib/runtime/quote.ts +31 -0
  561. package/node_modules/ajv/lib/runtime/re2.ts +6 -0
  562. package/node_modules/ajv/lib/runtime/timestamp.ts +46 -0
  563. package/node_modules/ajv/lib/runtime/ucs2length.ts +20 -0
  564. package/node_modules/ajv/lib/runtime/uri.ts +6 -0
  565. package/node_modules/ajv/lib/runtime/validation_error.ts +13 -0
  566. package/node_modules/ajv/lib/standalone/index.ts +100 -0
  567. package/node_modules/ajv/lib/standalone/instance.ts +36 -0
  568. package/node_modules/ajv/lib/types/index.ts +244 -0
  569. package/node_modules/ajv/lib/types/json-schema.ts +187 -0
  570. package/node_modules/ajv/lib/types/jtd-schema.ts +273 -0
  571. package/node_modules/ajv/lib/vocabularies/applicator/additionalItems.ts +56 -0
  572. package/node_modules/ajv/lib/vocabularies/applicator/additionalProperties.ts +118 -0
  573. package/node_modules/ajv/lib/vocabularies/applicator/allOf.ts +22 -0
  574. package/node_modules/ajv/lib/vocabularies/applicator/anyOf.ts +14 -0
  575. package/node_modules/ajv/lib/vocabularies/applicator/contains.ts +109 -0
  576. package/node_modules/ajv/lib/vocabularies/applicator/dependencies.ts +112 -0
  577. package/node_modules/ajv/lib/vocabularies/applicator/dependentSchemas.ts +11 -0
  578. package/node_modules/ajv/lib/vocabularies/applicator/if.ts +80 -0
  579. package/node_modules/ajv/lib/vocabularies/applicator/index.ts +53 -0
  580. package/node_modules/ajv/lib/vocabularies/applicator/items.ts +59 -0
  581. package/node_modules/ajv/lib/vocabularies/applicator/items2020.ts +36 -0
  582. package/node_modules/ajv/lib/vocabularies/applicator/not.ts +38 -0
  583. package/node_modules/ajv/lib/vocabularies/applicator/oneOf.ts +82 -0
  584. package/node_modules/ajv/lib/vocabularies/applicator/patternProperties.ts +91 -0
  585. package/node_modules/ajv/lib/vocabularies/applicator/prefixItems.ts +12 -0
  586. package/node_modules/ajv/lib/vocabularies/applicator/properties.ts +57 -0
  587. package/node_modules/ajv/lib/vocabularies/applicator/propertyNames.ts +50 -0
  588. package/node_modules/ajv/lib/vocabularies/applicator/thenElse.ts +13 -0
  589. package/node_modules/ajv/lib/vocabularies/code.ts +168 -0
  590. package/node_modules/ajv/lib/vocabularies/core/id.ts +10 -0
  591. package/node_modules/ajv/lib/vocabularies/core/index.ts +16 -0
  592. package/node_modules/ajv/lib/vocabularies/core/ref.ts +129 -0
  593. package/node_modules/ajv/lib/vocabularies/discriminator/index.ts +113 -0
  594. package/node_modules/ajv/lib/vocabularies/discriminator/types.ts +12 -0
  595. package/node_modules/ajv/lib/vocabularies/draft2020.ts +23 -0
  596. package/node_modules/ajv/lib/vocabularies/draft7.ts +17 -0
  597. package/node_modules/ajv/lib/vocabularies/dynamic/dynamicAnchor.ts +31 -0
  598. package/node_modules/ajv/lib/vocabularies/dynamic/dynamicRef.ts +51 -0
  599. package/node_modules/ajv/lib/vocabularies/dynamic/index.ts +9 -0
  600. package/node_modules/ajv/lib/vocabularies/dynamic/recursiveAnchor.ts +14 -0
  601. package/node_modules/ajv/lib/vocabularies/dynamic/recursiveRef.ts +10 -0
  602. package/node_modules/ajv/lib/vocabularies/errors.ts +18 -0
  603. package/node_modules/ajv/lib/vocabularies/format/format.ts +120 -0
  604. package/node_modules/ajv/lib/vocabularies/format/index.ts +6 -0
  605. package/node_modules/ajv/lib/vocabularies/jtd/discriminator.ts +89 -0
  606. package/node_modules/ajv/lib/vocabularies/jtd/elements.ts +32 -0
  607. package/node_modules/ajv/lib/vocabularies/jtd/enum.ts +45 -0
  608. package/node_modules/ajv/lib/vocabularies/jtd/error.ts +23 -0
  609. package/node_modules/ajv/lib/vocabularies/jtd/index.ts +37 -0
  610. package/node_modules/ajv/lib/vocabularies/jtd/metadata.ts +24 -0
  611. package/node_modules/ajv/lib/vocabularies/jtd/nullable.ts +21 -0
  612. package/node_modules/ajv/lib/vocabularies/jtd/optionalProperties.ts +15 -0
  613. package/node_modules/ajv/lib/vocabularies/jtd/properties.ts +184 -0
  614. package/node_modules/ajv/lib/vocabularies/jtd/ref.ts +76 -0
  615. package/node_modules/ajv/lib/vocabularies/jtd/type.ts +75 -0
  616. package/node_modules/ajv/lib/vocabularies/jtd/union.ts +12 -0
  617. package/node_modules/ajv/lib/vocabularies/jtd/values.ts +58 -0
  618. package/node_modules/ajv/lib/vocabularies/metadata.ts +17 -0
  619. package/node_modules/ajv/lib/vocabularies/next.ts +8 -0
  620. package/node_modules/ajv/lib/vocabularies/unevaluated/index.ts +7 -0
  621. package/node_modules/ajv/lib/vocabularies/unevaluated/unevaluatedItems.ts +47 -0
  622. package/node_modules/ajv/lib/vocabularies/unevaluated/unevaluatedProperties.ts +85 -0
  623. package/node_modules/ajv/lib/vocabularies/validation/const.ts +28 -0
  624. package/node_modules/ajv/lib/vocabularies/validation/dependentRequired.ts +23 -0
  625. package/node_modules/ajv/lib/vocabularies/validation/enum.ts +54 -0
  626. package/node_modules/ajv/lib/vocabularies/validation/index.ts +49 -0
  627. package/node_modules/ajv/lib/vocabularies/validation/limitContains.ts +16 -0
  628. package/node_modules/ajv/lib/vocabularies/validation/limitItems.ts +26 -0
  629. package/node_modules/ajv/lib/vocabularies/validation/limitLength.ts +30 -0
  630. package/node_modules/ajv/lib/vocabularies/validation/limitNumber.ts +42 -0
  631. package/node_modules/ajv/lib/vocabularies/validation/limitProperties.ts +26 -0
  632. package/node_modules/ajv/lib/vocabularies/validation/multipleOf.ts +34 -0
  633. package/node_modules/ajv/lib/vocabularies/validation/pattern.ts +39 -0
  634. package/node_modules/ajv/lib/vocabularies/validation/required.ts +98 -0
  635. package/node_modules/ajv/lib/vocabularies/validation/uniqueItems.ts +79 -0
  636. package/node_modules/ajv/package.json +126 -0
  637. package/node_modules/fast-deep-equal/LICENSE +21 -0
  638. package/node_modules/fast-deep-equal/README.md +96 -0
  639. package/node_modules/fast-deep-equal/es6/index.d.ts +2 -0
  640. package/node_modules/fast-deep-equal/es6/index.js +72 -0
  641. package/node_modules/fast-deep-equal/es6/react.d.ts +2 -0
  642. package/node_modules/fast-deep-equal/es6/react.js +79 -0
  643. package/node_modules/fast-deep-equal/index.d.ts +4 -0
  644. package/node_modules/fast-deep-equal/index.js +46 -0
  645. package/node_modules/fast-deep-equal/package.json +61 -0
  646. package/node_modules/fast-deep-equal/react.d.ts +2 -0
  647. package/node_modules/fast-deep-equal/react.js +53 -0
  648. package/node_modules/fast-uri/.gitattributes +2 -0
  649. package/node_modules/fast-uri/.github/dependabot.yml +13 -0
  650. package/node_modules/fast-uri/.github/workflows/ci.yml +106 -0
  651. package/node_modules/fast-uri/.github/workflows/lock-threads.yml +19 -0
  652. package/node_modules/fast-uri/.github/workflows/package-manager-ci.yml +24 -0
  653. package/node_modules/fast-uri/LICENSE +30 -0
  654. package/node_modules/fast-uri/README.md +152 -0
  655. package/node_modules/fast-uri/benchmark/benchmark.mjs +159 -0
  656. package/node_modules/fast-uri/benchmark/equal.mjs +51 -0
  657. package/node_modules/fast-uri/benchmark/non-simple-domain.mjs +22 -0
  658. package/node_modules/fast-uri/benchmark/package.json +17 -0
  659. package/node_modules/fast-uri/benchmark/string-array-to-hex-stripped.mjs +24 -0
  660. package/node_modules/fast-uri/benchmark/ws-is-secure.mjs +65 -0
  661. package/node_modules/fast-uri/eslint.config.js +6 -0
  662. package/node_modules/fast-uri/index.js +406 -0
  663. package/node_modules/fast-uri/lib/schemes.js +267 -0
  664. package/node_modules/fast-uri/lib/utils.js +443 -0
  665. package/node_modules/fast-uri/package.json +68 -0
  666. package/node_modules/fast-uri/test/ajv.test.js +43 -0
  667. package/node_modules/fast-uri/test/equal.test.js +117 -0
  668. package/node_modules/fast-uri/test/fixtures/uri-js-parse.json +501 -0
  669. package/node_modules/fast-uri/test/fixtures/uri-js-serialize.json +120 -0
  670. package/node_modules/fast-uri/test/parse.test.js +323 -0
  671. package/node_modules/fast-uri/test/resolve.test.js +87 -0
  672. package/node_modules/fast-uri/test/rfc-3986.test.js +90 -0
  673. package/node_modules/fast-uri/test/security-normalization.test.js +39 -0
  674. package/node_modules/fast-uri/test/security.test.js +133 -0
  675. package/node_modules/fast-uri/test/serialize.test.js +151 -0
  676. package/node_modules/fast-uri/test/uri-js-compatibility.test.js +33 -0
  677. package/node_modules/fast-uri/test/uri-js.test.js +912 -0
  678. package/node_modules/fast-uri/test/util.test.js +38 -0
  679. package/node_modules/fast-uri/tsconfig.json +9 -0
  680. package/node_modules/fast-uri/types/index.d.ts +60 -0
  681. package/node_modules/fast-uri/types/index.test-d.ts +17 -0
  682. package/node_modules/json-schema-traverse/.eslintrc.yml +27 -0
  683. package/node_modules/json-schema-traverse/.github/FUNDING.yml +2 -0
  684. package/node_modules/json-schema-traverse/.github/workflows/build.yml +28 -0
  685. package/node_modules/json-schema-traverse/.github/workflows/publish.yml +27 -0
  686. package/node_modules/json-schema-traverse/LICENSE +21 -0
  687. package/node_modules/json-schema-traverse/README.md +95 -0
  688. package/node_modules/json-schema-traverse/index.d.ts +40 -0
  689. package/node_modules/json-schema-traverse/index.js +93 -0
  690. package/node_modules/json-schema-traverse/package.json +43 -0
  691. package/node_modules/json-schema-traverse/spec/.eslintrc.yml +6 -0
  692. package/node_modules/json-schema-traverse/spec/fixtures/schema.js +125 -0
  693. package/node_modules/json-schema-traverse/spec/index.spec.js +171 -0
  694. package/node_modules/require-from-string/index.js +34 -0
  695. package/node_modules/require-from-string/license +21 -0
  696. package/node_modules/require-from-string/package.json +28 -0
  697. package/node_modules/require-from-string/readme.md +56 -0
  698. package/package.json +51 -0
  699. package/scripts/api-call.mjs +59 -0
  700. package/scripts/auth.mjs +262 -0
  701. package/scripts/build-skill-payload.mjs +338 -0
  702. package/scripts/cleanup.mjs +166 -0
  703. package/scripts/install-paths.mjs +146 -0
  704. package/scripts/postinstall.mjs +218 -0
  705. package/scripts/postpack.mjs +43 -0
  706. package/scripts/prepack.mjs +222 -0
  707. package/scripts/tty-menu.mjs +100 -0
  708. package/skill/README.md +55 -0
  709. package/skill/SKILL.md +138 -0
  710. package/skill/catalog.json +406 -0
  711. package/skill/design-rules.md +282 -0
  712. package/skill/design-system.md +235 -0
  713. package/skill/docs/SKELETON-SHELL.md +120 -0
  714. package/skill/docs/bottom-buttons.md +155 -0
  715. package/skill/docs/control/button.md +147 -0
  716. package/skill/docs/control/calendar-navigator.md +143 -0
  717. package/skill/docs/control/calendar.md +128 -0
  718. package/skill/docs/control/check-box.md +117 -0
  719. package/skill/docs/control/combo.md +293 -0
  720. package/skill/docs/control/embed.md +211 -0
  721. package/skill/docs/control/image-box.md +237 -0
  722. package/skill/docs/control/input-date.md +175 -0
  723. package/skill/docs/control/input-file.md +192 -0
  724. package/skill/docs/control/input-mask.md +89 -0
  725. package/skill/docs/control/input-number.md +55 -0
  726. package/skill/docs/control/input-text.md +73 -0
  727. package/skill/docs/control/label.md +127 -0
  728. package/skill/docs/control/multi-input-box.md +51 -0
  729. package/skill/docs/control/radio-box.md +150 -0
  730. package/skill/docs/control/search.md +163 -0
  731. package/skill/docs/control/tab.md +240 -0
  732. package/skill/docs/control/tree.md +278 -0
  733. package/skill/docs/control.md +264 -0
  734. package/skill/docs/data-objects.md +278 -0
  735. package/skill/docs/data-sources.md +215 -0
  736. package/skill/docs/events.md +467 -0
  737. package/skill/docs/group.md +146 -0
  738. package/skill/docs/index.json +125 -0
  739. package/skill/docs/mockup-data.md +186 -0
  740. package/skill/docs/node.md +32 -0
  741. package/skill/docs/scenario.md +112 -0
  742. package/skill/docs/service/CustomSystem.md +139 -0
  743. package/skill/docs/service/Firestore.md +125 -0
  744. package/skill/docs/service/FlexAutoQuery.md +128 -0
  745. package/skill/docs/service/FlexSQL.md +96 -0
  746. package/skill/docs/service/Flextudio API.md +161 -0
  747. package/skill/docs/service/Flextudio.md +87 -0
  748. package/skill/docs/service/GoogleSheet.md +71 -0
  749. package/skill/docs/service/README.md +127 -0
  750. package/skill/docs/service/ksystem.md +76 -0
  751. package/skill/docs/service-binding.md +228 -0
  752. package/skill/docs/step.md +546 -0
  753. package/skill/docs/style-objects.md +183 -0
  754. package/skill/examples/README.md +147 -0
  755. package/skill/examples/basic/basic-list-detail.json +2521 -0
  756. package/skill/examples/basic/delivery-address-popup.json +2175 -0
  757. package/skill/examples/basic/fixedtop-floating-form.json +1524 -0
  758. package/skill/examples/basic/search-period-popup.json +1524 -0
  759. package/skill/examples/design/booking-wizard-3step.json +1335 -0
  760. package/skill/examples/design/list-detail-form-3step.json +1516 -0
  761. package/skill/examples/design/list-filter-2step.json +1365 -0
  762. package/skill/examples/design/list-filter-detail-3step.json +1570 -0
  763. package/skill/examples/design/result-entry-wizard-4step.json +1861 -0
  764. package/skill/examples/index.json +150 -0
  765. package/skill/examples/intent/mock-employee-list.json +54 -0
  766. package/skill/examples/intent/script-cart-flow.json +96 -0
  767. package/skill/examples/intent/script-dialog-confirm.json +61 -0
  768. package/skill/intent-rules.md +552 -0
  769. package/skill/intent-system.md +118 -0
  770. package/skill/patterns/atom/badge.json +103 -0
  771. package/skill/patterns/atom/button.json +111 -0
  772. package/skill/patterns/atom/checkbox.json +70 -0
  773. package/skill/patterns/atom/segmented-radio.json +92 -0
  774. package/skill/patterns/atom/switch.json +57 -0
  775. package/skill/patterns/index.json +471 -0
  776. package/skill/patterns/molecule/checklist.json +107 -0
  777. package/skill/patterns/molecule/input-action.json +355 -0
  778. package/skill/patterns/molecule/input-button.json +212 -0
  779. package/skill/patterns/molecule/input-pair.json +284 -0
  780. package/skill/references/build-sequence.md +55 -0
  781. package/skill/references/patterns-cheatsheet.md +87 -0
  782. package/skill/references/spec-evolve/README.md +43 -0
  783. package/skill/references/spec-evolve/conventions.md +92 -0
  784. package/skill/references/spec-evolve/data-connection.md +102 -0
  785. package/skill/references/spec-evolve/intake.md +41 -0
  786. package/skill/references/spec-evolve/key-roles.md +44 -0
  787. package/skill/references/spec-evolve/lint.md +27 -0
  788. package/skill/references/spec-evolve/mockup.md +50 -0
  789. package/skill/references/spec-evolve/query-screens.md +66 -0
  790. package/skill/references/spec-evolve/routing.md +43 -0
  791. package/skill/references/spec-evolve/spec-format.md +76 -0
  792. package/skill/references/spec-evolve/templates/master-detail.spec.md +97 -0
  793. package/skill/references/spec-evolve/templates/query-screen.spec.md +96 -0
  794. package/skill/references/spec-evolve/templates/static-prototype.spec.md +54 -0
  795. package/skill/references/spec-evolve/templates-index.json +26 -0
  796. package/skill/rules.md +400 -0
  797. package/skill/schemas/bottom-buttons.schema.json +134 -0
  798. package/skill/schemas/control/_base.schema.json +1296 -0
  799. package/skill/schemas/control/button.schema.json +55 -0
  800. package/skill/schemas/control/calendar-navigator.schema.json +164 -0
  801. package/skill/schemas/control/calendar.schema.json +18 -0
  802. package/skill/schemas/control/check-box.schema.json +41 -0
  803. package/skill/schemas/control/combo.schema.json +23 -0
  804. package/skill/schemas/control/embed.schema.json +30 -0
  805. package/skill/schemas/control/image-box.schema.json +49 -0
  806. package/skill/schemas/control/input-date.schema.json +27 -0
  807. package/skill/schemas/control/input-file.schema.json +139 -0
  808. package/skill/schemas/control/input-mask.schema.json +45 -0
  809. package/skill/schemas/control/input-number.schema.json +24 -0
  810. package/skill/schemas/control/input-text.schema.json +24 -0
  811. package/skill/schemas/control/label.schema.json +113 -0
  812. package/skill/schemas/control/multi-input-box.schema.json +19 -0
  813. package/skill/schemas/control/other.schema.json +24 -0
  814. package/skill/schemas/control/radio-box.schema.json +87 -0
  815. package/skill/schemas/control/search.schema.json +23 -0
  816. package/skill/schemas/control/tab.schema.json +112 -0
  817. package/skill/schemas/control/tree.schema.json +83 -0
  818. package/skill/schemas/control.schema.json +30 -0
  819. package/skill/schemas/data-objects.schema.json +161 -0
  820. package/skill/schemas/data-sources.schema.json +184 -0
  821. package/skill/schemas/design-system/design.schema.json +496 -0
  822. package/skill/schemas/events.schema.json +272 -0
  823. package/skill/schemas/group.schema.json +133 -0
  824. package/skill/schemas/index.json +362 -0
  825. package/skill/schemas/naming-objects.schema.json +133 -0
  826. package/skill/schemas/node.schema.json +24 -0
  827. package/skill/schemas/patterns/atom/badge.schema.json +44 -0
  828. package/skill/schemas/patterns/atom/button.schema.json +70 -0
  829. package/skill/schemas/patterns/atom/checkbox.schema.json +39 -0
  830. package/skill/schemas/patterns/atom/segmented-radio.schema.json +49 -0
  831. package/skill/schemas/patterns/atom/switch.schema.json +27 -0
  832. package/skill/schemas/patterns/molecule/checklist.schema.json +63 -0
  833. package/skill/schemas/patterns/molecule/input-action.schema.json +251 -0
  834. package/skill/schemas/patterns/molecule/input-button.schema.json +141 -0
  835. package/skill/schemas/patterns/molecule/input-pair.schema.json +210 -0
  836. package/skill/schemas/scenario.schema.json +161 -0
  837. package/skill/schemas/service/CustomSystem.schema.json +41 -0
  838. package/skill/schemas/service/Firestore.schema.json +28 -0
  839. package/skill/schemas/service/FlexAutoQuery.schema.json +35 -0
  840. package/skill/schemas/service/FlexSQL.schema.json +33 -0
  841. package/skill/schemas/service/Flextudio API.schema.json +115 -0
  842. package/skill/schemas/service/Flextudio.schema.json +26 -0
  843. package/skill/schemas/service/GoogleSheet.schema.json +31 -0
  844. package/skill/schemas/service/_base.schema.json +31 -0
  845. package/skill/schemas/service/ksystem.schema.json +36 -0
  846. package/skill/schemas/service-binding.schema.json +51 -0
  847. package/skill/schemas/step.schema.json +258 -0
  848. package/skill/schemas/style-objects.schema.json +155 -0
  849. package/skill/skill-guides/README.md +50 -0
  850. package/skill/skill-guides/control-options.md +126 -0
  851. package/skill/skill-guides/events.md +61 -0
  852. package/skill/skill-guides/failure-discipline.md +95 -0
  853. package/skill/skill-guides/index.json +40 -0
  854. package/skill/skill-guides/prompt-interview.md +92 -0
  855. package/skill/skill-guides/scripts.md +169 -0
  856. package/skill/skill-guides/step-navigation.md +98 -0
@@ -0,0 +1,1181 @@
1
+ // _base.materialize.mjs
2
+ // ─────────────────────────────────────────────────────────────────────────────
3
+ // 패턴 dispatcher + 트리 walker.
4
+ //
5
+ // LLM 이 emit 한 시나리오 (raw control + pattern invocation 의 혼합) 를 받아
6
+ // 모든 pattern invocation 을 그 패턴의 materializer 로 치환한 풀 메타데이터로
7
+ // 변환한다. 결과는 engine schema 검증 통과 가능한 상태가 된다.
8
+ //
9
+ // 입력 shape (development.md §2):
10
+ // - 패턴 호출: { "<patternName>": { ...props } } ← 키 1개, 값 객체.
11
+ // - 원시 컨트롤: { "ControlType": "InputText", ... }
12
+ // - 원시 그룹: { "ContentsType": "Group", Contents: [...] }
13
+ // - 그 외: Step 메타데이터(StepName/BottomButtons/Next/...) 또는 ScenarioMeta
14
+ // — 항상 raw passthrough.
15
+ //
16
+ // 처리 규칙:
17
+ // 1. 트리 walk 는 `Contents` (Group children) 와 `Dialog.Layouts[*].Controls`
18
+ // 배열에만 들어간다. FontStyle/BorderStyle 등 raw 스타일 객체에는 descend 하지
19
+ // 않음 (단일 키가 우연히 패턴 이름과 충돌하는 false positive 방지).
20
+ // 2. ID 카운터는 입력의 max `f_N` Id 에서 시작 → raw 가 미리 박은 ID 와 겹치지 않음.
21
+ // 3. 패턴 materializer 가 throw 하면 path + 메시지를 errors 에 모아 반환. 트리는
22
+ // 계속 walk (다른 노드 에러도 한 번에 보고).
23
+ // 4. 동일 이름이 여러 tier 에 있으면 registry 로드 시 throw (전역 유일).
24
+ // 5. 단일 key 객체인데 알려진 패턴 이름이 아니면 raw 로 간주하고 그 안의 컨테이너
25
+ // 필드를 계속 walk — 시나리오 구조상 ScenarioMeta / 비-Contents 객체일 수도 있어서
26
+ // permissive.
27
+ // ─────────────────────────────────────────────────────────────────────────────
28
+
29
+ import { readdirSync } from "node:fs";
30
+ import { dirname, join } from "node:path";
31
+ import { fileURLToPath, pathToFileURL } from "node:url";
32
+
33
+ import { applyDesign } from "../design-system/materialize.mjs";
34
+ import { makeGroup } from "./_base.controls.mjs";
35
+ import { generateId } from "./_base.id.mjs";
36
+
37
+ const __dirname = dirname(fileURLToPath(import.meta.url));
38
+ const PATTERN_TIERS = Object.freeze(["atom", "molecule", "organism"]);
39
+
40
+ // Step 의 세 가지 children 컨테이너 — schema 가 모두 Group[] 만 받음.
41
+ const STEP_CONTAINER_KEYS = Object.freeze([
42
+ "Contents",
43
+ "FixedContentsTop",
44
+ "FixedContentsBottom",
45
+ ]);
46
+
47
+ // ─────────────────────────────────────────────────────────────────────────────
48
+ // Registry (lazy load + cache)
49
+ // ─────────────────────────────────────────────────────────────────────────────
50
+
51
+ let _registry = null;
52
+
53
+ async function loadRegistry() {
54
+ if (_registry) return _registry;
55
+ const reg = new Map();
56
+ for (const tier of PATTERN_TIERS) {
57
+ const dir = join(__dirname, tier);
58
+ let entries;
59
+ try {
60
+ entries = readdirSync(dir);
61
+ } catch {
62
+ continue;
63
+ }
64
+ for (const entry of entries) {
65
+ if (!entry.endsWith(".materialize.mjs")) continue;
66
+ if (entry.startsWith("_")) continue; // _base.materialize.mjs etc.
67
+ const name = entry.slice(0, -".materialize.mjs".length);
68
+ if (reg.has(name)) {
69
+ const existing = reg.get(name);
70
+ throw new Error(
71
+ `_base.materialize: pattern name conflict — '${name}' 가 ${existing.tier} 와 ${tier} 양쪽에 존재. 패턴 이름은 전역 유일.`,
72
+ );
73
+ }
74
+ const mod = await import(pathToFileURL(join(dir, entry)).href);
75
+ if (typeof mod.default !== "function") {
76
+ throw new Error(
77
+ `_base.materialize: ${tier}/${entry} 에 default export (materialize fn) 없음.`,
78
+ );
79
+ }
80
+ reg.set(name, { tier, materialize: mod.default });
81
+ }
82
+ }
83
+ _registry = reg;
84
+ return reg;
85
+ }
86
+
87
+ /** 테스트 / 외부 introspection 용. */
88
+ export async function getPatternRegistry() {
89
+ return await loadRegistry();
90
+ }
91
+
92
+ /** 테스트 hot-reload 용 — 다음 호출에서 다시 스캔. */
93
+ export function _resetRegistryForTest() {
94
+ _registry = null;
95
+ }
96
+
97
+ // ─────────────────────────────────────────────────────────────────────────────
98
+ // ID counter helpers
99
+ // ─────────────────────────────────────────────────────────────────────────────
100
+
101
+ const ID_RE = /^f_([1-9][0-9]*)$/;
102
+
103
+ function findMaxId(obj, max = 0) {
104
+ if (!obj || typeof obj !== "object") return max;
105
+ if (Array.isArray(obj)) {
106
+ for (const v of obj) max = findMaxId(v, max);
107
+ return max;
108
+ }
109
+ for (const [k, v] of Object.entries(obj)) {
110
+ if (k === "Id" && typeof v === "string") {
111
+ const m = ID_RE.exec(v);
112
+ if (m) {
113
+ const n = parseInt(m[1], 10);
114
+ if (n > max) max = n;
115
+ }
116
+ } else if (v && typeof v === "object") {
117
+ max = findMaxId(v, max);
118
+ }
119
+ }
120
+ return max;
121
+ }
122
+
123
+ // ─────────────────────────────────────────────────────────────────────────────
124
+ // Tree walker / dispatcher
125
+ // ─────────────────────────────────────────────────────────────────────────────
126
+
127
+ /**
128
+ * 단일 노드 처리:
129
+ * - 패턴 호출이면 materializer 호출 후 결과 반환.
130
+ * - 그렇지 않으면 raw 로 보고 컨테이너 필드만 재귀.
131
+ */
132
+ // LLM 디버깅에 유용한 props 스냅샷 — 너무 길면 잘라낸다.
133
+ function propsSnapshot(props, maxChars = 240) {
134
+ if (props == null) return null;
135
+ let s;
136
+ try {
137
+ s = JSON.stringify(props);
138
+ } catch {
139
+ return "<unserializable>";
140
+ }
141
+ if (s.length <= maxChars) return s;
142
+ return s.slice(0, maxChars - 1) + "…";
143
+ }
144
+
145
+ // 컨트롤 enum 의 흔한 변형(대소문자·확실한 동의어)을 정본으로 정규화.
146
+ // 모델이 개념은 맞고 토큰만 틀리게 쓰는 케이스('money'→'Money', 'ckey'→'LabelCKey')를
147
+ // 결정적으로 교정 — validate write-back 으로 스튜디오엔 정본이 기록된다.
148
+ // 엄격 allowlist: (1) 대소문자만 다른 정본, (2) 명시 동의어 만 교정. 미매칭은 원본 유지
149
+ // (스키마가 정상적으로 잡음). 모호한 값(LabelType:'labelvalue' = labeltext? LabelCKey?
150
+ // / InputType:'money' = MaskType? InputNumber?)은 의도 추정 불가라 교정 대상 제외.
151
+ const ENUM_CANONICAL = {
152
+ LabelType: { canon: ["labeltext", "LabelCKey"], synonyms: { ckey: "LabelCKey" } },
153
+ MaskType: { canon: ["Time", "Money", "Date", "Phone"], synonyms: {} },
154
+ // Calendar SelectType — 모델이 일반/CSS 어휘(one/single, range/period)를 쓰는 케이스.
155
+ // canon: SingleDate(단일) / FromTo(기간). enum=["SingleDate","FromTo"].
156
+ SelectType: {
157
+ canon: ["SingleDate", "FromTo"],
158
+ synonyms: { one: "SingleDate", single: "SingleDate", date: "SingleDate", range: "FromTo", period: "FromTo", fromto: "FromTo" },
159
+ },
160
+ };
161
+
162
+ function canonicalizeControlEnums(node) {
163
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
164
+ if (!("ControlType" in node)) return node;
165
+ let out = node;
166
+ for (const [field, spec] of Object.entries(ENUM_CANONICAL)) {
167
+ const v = node[field];
168
+ if (typeof v !== "string" || v === "") continue;
169
+ if (spec.canon.includes(v)) continue; // 이미 정본
170
+ const lc = v.toLowerCase();
171
+ const caseMatch = spec.canon.find((c) => c.toLowerCase() === lc); // 대소문자만 다름
172
+ const fixed = caseMatch ?? spec.synonyms[lc]; // 또는 명시 동의어
173
+ if (fixed && fixed !== v) {
174
+ if (out === node) out = { ...node };
175
+ out[field] = fixed;
176
+ }
177
+ }
178
+ return out;
179
+ }
180
+
181
+ // Label LabelType ↔ 채운 필드 정합 — LabelType 과 실제 채운 필드(labeltext/LabelCKey)가
182
+ // 불일치하면 채워진 필드 기준으로 LabelType 을 교정. Label 의 allOf if/then
183
+ // (LabelType='labeltext'→labeltext required / 'LabelCKey'→LabelCKey required) 위반은
184
+ // 상위 Control union 의 oneOf 를 통째로 탈락시켜 형제마다 'must match exactly one
185
+ // schema in oneOf' cascade 를 일으킨다 (관측: LabelType='labeltext' 인데 labeltext 없이
186
+ // LabelCKey 만 채움). 결정적 정합 — 채워진 필드가 단일하게 가리킬 때만.
187
+ // - LabelCKey 채워짐 + labeltext 비어있음 → LabelType:"LabelCKey"
188
+ // - labeltext 채워짐 + LabelCKey 비어있음 → LabelType:"labeltext"
189
+ // - 둘 다 채워짐 / 둘 다 비어있음 → 모호 → 손대지 않음 (schema 가 잡게).
190
+ function canonicalizeLabelType(node) {
191
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
192
+ if (node.ControlType !== "Label") return node;
193
+ const filled = (v) => typeof v === "string" && v.length > 0;
194
+ const hasText = filled(node.labeltext);
195
+ const hasCkey = filled(node.LabelCKey);
196
+ let want = null;
197
+ if (hasCkey && !hasText) want = "LabelCKey";
198
+ else if (hasText && !hasCkey) want = "labeltext";
199
+ if (want && node.LabelType !== want) return { ...node, LabelType: want };
200
+ return node;
201
+ }
202
+
203
+ // Items 원소 표준키 외 strip — Combo/RadioBox/CheckBox 의 인라인 `Items[]` 원소는
204
+ // 스키마상 ItemName/ItemValue(+CheckBox ItemValueDel) 만 정의. additionalProperties:true
205
+ // 라 기본 검증은 통과하나 strict 변종(unevaluatedProperties:false)에서 막힌다
206
+ // (strict-fields). 모델이 스펙의 실데이터 필드(예: bizUnitName/bizUnitCode)를 Items 에
207
+ // 직접 박는 케이스 — 관측상 ItemName/ItemValue 와 값이 중복이라 손실 없이 제거.
208
+ // - 표준키(ItemName/ItemValue/ItemValueDel) 만 남김. 실데이터 다중 컬럼은 DataSource(Grid)로.
209
+ const ITEM_STD_KEYS = new Set(["ItemName", "ItemValue", "ItemValueDel"]);
210
+ // ★ Combo/Search 의 인라인 데이터는 본체가 아니라 자식(ComboList/List)의 Items 에
211
+ // 온다 — 실제 strict-fields frontier 가 ComboList.Items 였으므로 자식 호스트 포함.
212
+ const ITEM_STD_HOSTS = new Set(["Combo", "ComboList", "RadioBox", "CheckBox", "List"]);
213
+ function canonicalizeItemFields(node) {
214
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
215
+ if (!("ControlType" in node) || !Array.isArray(node.Items)) return node;
216
+ if (!ITEM_STD_HOSTS.has(node.ControlType)) return node;
217
+ let changed = false;
218
+ const items = node.Items.map((it) => {
219
+ if (!it || typeof it !== "object" || Array.isArray(it)) return it;
220
+ if (Object.keys(it).every((k) => ITEM_STD_KEYS.has(k))) return it;
221
+ changed = true;
222
+ const clean = {};
223
+ for (const k of Object.keys(it)) if (ITEM_STD_KEYS.has(k)) clean[k] = it[k];
224
+ return clean;
225
+ });
226
+ return changed ? { ...node, Items: items } : node;
227
+ }
228
+
229
+ // 입력(편집) 컨트롤 후손 탐지 — detail(읽기전용) vs update(수정) 판정용.
230
+ // Contents 서브트리(자식 Group 포함)에 편집 컨트롤이 하나라도 있으면 true.
231
+ const EDIT_CONTROLS = new Set([
232
+ "InputText", "InputNumber", "InputDate", "InputMask", "MultiInputBox",
233
+ "Combo", "Search", "CheckBox", "RadioBox", "InputFile",
234
+ ]);
235
+ function hasEditableDescendant(node) {
236
+ let found = false;
237
+ const walk = (n) => {
238
+ if (found || !n || typeof n !== "object") return;
239
+ if (Array.isArray(n)) { for (const c of n) walk(c); return; }
240
+ if (typeof n.ControlType === "string" && EDIT_CONTROLS.has(n.ControlType)) { found = true; return; }
241
+ if (Array.isArray(n.Contents)) for (const c of n.Contents) walk(c);
242
+ };
243
+ if (Array.isArray(node.Contents)) for (const c of node.Contents) walk(c);
244
+ return found;
245
+ }
246
+
247
+ // DataConnection 정본화 — 스튜디오 canonical 은 단일 객체
248
+ // `{TargetType:'category', DataUsage, CategoryName, ...}`. 모델이 intent 예제를
249
+ // 따라 단일원소 배열 `[{...}]` 로 쓰거나 TargetType 을 누락하는 케이스를 결정적으로
250
+ // 교정 (validate write-back 으로 스튜디오엔 정본 기록).
251
+ // - 단일원소 배열 → 그 객체로 unwrap. (0개/다중 원소는 비정상 → 스키마가 잡게 둠.)
252
+ // - TargetType 누락/빈값 → const 'category' 주입 (유일 허용값이라 항상 안전).
253
+ // - DataUsage 조건부 필수 주입 (schema allOf if/then = 스튜디오 property-data.js):
254
+ // default→UseNewSector:true+OnlyIfNoSector:true / new→UseNewSector:true /
255
+ // detail|update→UseTargetSector:true+TargetSector:{} / query→추가 없음.
256
+ // 모델이 DataUsage 만 적고 짝 필드를 빠뜨리는 케이스를 정본으로(누락 시만 주입).
257
+ // - ★ DataUsage 무관 공통: TargetSector.Filters 가 채워져 있으면 UseTargetSector:true 보장.
258
+ // UseTargetSector 가 켜져있지 않으면 런타임이 Filters 를 무시하고 카테고리 전체 섹터를
259
+ // 전송한다 (data-objects.md §1, events.schema.json UseFilter 와 동치). 특히 query 에서
260
+ // 부분 필터링(Parent/Custom/Condition) 시 모델이 Filters 만 넣고 UseTargetSector 를
261
+ // 빠뜨리는 케이스 — 필터가 무시되어 조회가 전체로 새는 문제를 결정적으로 교정.
262
+ function canonicalizeDataConnection(node) {
263
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
264
+ const orig = node.DataConnection;
265
+ if (orig == null) return node;
266
+ let dc = orig;
267
+ let changed = false;
268
+ if (Array.isArray(dc)) {
269
+ if (dc.length === 1 && dc[0] && typeof dc[0] === "object" && !Array.isArray(dc[0])) {
270
+ dc = dc[0];
271
+ changed = true;
272
+ } else {
273
+ return node; // 0개/다중 원소 배열 → 스키마가 정상적으로 거부
274
+ }
275
+ }
276
+ if (typeof dc !== "object" || Array.isArray(dc)) return node;
277
+ // 이후 필드 보강은 복사본 work 에 (orig 불변 보장).
278
+ const work = { ...dc };
279
+ if (typeof work.TargetType !== "string" || work.TargetType === "") {
280
+ work.TargetType = "category";
281
+ changed = true;
282
+ }
283
+ // DataUsage 조건부 필수 (누락 시에만 주입; 기존 값 보존).
284
+ const du = typeof work.DataUsage === "string" ? work.DataUsage : "";
285
+ const ensure = (k, v) => { if (!(k in work)) { work[k] = v; changed = true; } };
286
+ if (du === "default") { ensure("UseNewSector", true); ensure("OnlyIfNoSector", true); }
287
+ else if (du === "new") { ensure("UseNewSector", true); }
288
+ else if (du === "detail" || du === "update") {
289
+ ensure("UseTargetSector", true);
290
+ // detail/update 는 선택된 1건(activeSector)을 가져와야 한다 — TargetSector.Filters 에
291
+ // Status:["active"] 가 있어야 데이터가 흐른다. 빈 객체({})만 주입하면 상세/수정 화면이 비어버린다.
292
+ // 기존에 Filters 가 채워져 있으면(Status/Parent 등) 보존, 없거나 비어있을 때만 Status:active 주입.
293
+ const ts = work.TargetSector;
294
+ const hasFilters = ts && typeof ts === "object" && Array.isArray(ts.Filters) && ts.Filters.length > 0;
295
+ if (!hasFilters) {
296
+ work.TargetSector = {
297
+ ...(ts && typeof ts === "object" ? ts : {}),
298
+ Filters: [{ FilterType: "Status", Status: ["active"] }],
299
+ };
300
+ changed = true;
301
+ }
302
+ // detail(읽기전용) vs update(수정) 교정: 둘 다 activeSector 를 받고 구조가 같다 — 차이는 편집 가능 여부뿐.
303
+ // 그룹 후손에 편집 컨트롤이 있으면 update, 없으면(Label 등 표시만) detail 로 결정적 교정.
304
+ const want = hasEditableDescendant(node) ? "update" : "detail";
305
+ if (work.DataUsage !== want) { work.DataUsage = want; changed = true; }
306
+ }
307
+ // flat DCParentKey/DCChildKey 교정 — 이 키들은 DataConnection 최상위가 아니라
308
+ // TargetSector.Filters 의 Parent 필터 안에 들어가야 한다 (운영 메타 4/4·schema sectorFilter
309
+ // Parent 분기가 정본). 모델이 new 용 `DCLinkCkey.DCLinkItems[{DCParentKey,DCChildKey}]` 와
310
+ // query 용 `Parent` 필터를 혼동해 DC 최상위에 flat 으로 두는 케이스를 결정적으로 이전:
311
+ // - Parent 필터가 있으면 그 안의 빈 키만 flat 값으로 채우고(필터 우선), DC 의 flat 키 제거.
312
+ // - Parent 필터가 없고 DataUsage:query 면 Parent 필터를 생성해 채운다.
313
+ // - new+UseDCLink 는 DCLinkCkey.DCLinkItems 영역이므로 대상 아님 (건드리지 않음).
314
+ {
315
+ const flatP = typeof work.DCParentKey === "string" ? work.DCParentKey : undefined;
316
+ const flatC = typeof work.DCChildKey === "string" ? work.DCChildKey : undefined;
317
+ const isDcLinkNew = du === "new" && work.UseDCLink === true;
318
+ if ((flatP !== undefined || flatC !== undefined) && !isDcLinkNew) {
319
+ const ts = (work.TargetSector && typeof work.TargetSector === "object" && !Array.isArray(work.TargetSector))
320
+ ? { ...work.TargetSector } : {};
321
+ const filters = Array.isArray(ts.Filters) ? ts.Filters.slice() : [];
322
+ let pIdx = filters.findIndex((f) => f && typeof f === "object" && f.FilterType === "Parent");
323
+ if (pIdx >= 0 || du === "query") {
324
+ if (pIdx < 0) { filters.push({ FilterType: "Parent" }); pIdx = filters.length - 1; }
325
+ const pf = { ...filters[pIdx] };
326
+ if ((pf.DCParentKey === undefined || pf.DCParentKey === "") && flatP !== undefined) pf.DCParentKey = flatP;
327
+ if ((pf.DCChildKey === undefined || pf.DCChildKey === "") && flatC !== undefined) pf.DCChildKey = flatC;
328
+ filters[pIdx] = pf;
329
+ ts.Filters = filters;
330
+ work.TargetSector = ts;
331
+ delete work.DCParentKey;
332
+ delete work.DCChildKey;
333
+ changed = true;
334
+ }
335
+ }
336
+ }
337
+ // 공통: TargetSector.Filters 사용 시 UseTargetSector:true 필수 (DataUsage 무관 — query 의 부분
338
+ // 필터링 포함). 미설정/false 모두 교정 — Filters 가 실재하면 스위치가 켜져 있어야 필터가 적용된다.
339
+ // detail/update 는 위에서 이미 ensure 했으므로 idempotent.
340
+ {
341
+ const ts = work.TargetSector;
342
+ const hasFilters = ts && typeof ts === "object" && Array.isArray(ts.Filters) && ts.Filters.length > 0;
343
+ if (hasFilters && work.UseTargetSector !== true) { work.UseTargetSector = true; changed = true; }
344
+ }
345
+ return changed ? { ...node, DataConnection: work } : node;
346
+ }
347
+
348
+ // AllowExtensions 정본화 — 스키마는 소문자 확장자 배열(`^[a-z0-9]+$`)을 요구하나
349
+ // 모델이 콤마 문자열("jpg,jpeg,png,pdf")로 쓰는 케이스를 결정적으로 교정.
350
+ // - 문자열 → 콤마 분리 + trim + 소문자 → 배열 (확장자는 대소문자 무관, 스키마는 소문자).
351
+ // - 이미 배열이거나 분리 결과가 비면 원본 유지(스키마가 잡게).
352
+ function canonicalizeAllowExtensions(node) {
353
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
354
+ const v = node.AllowExtensions;
355
+ if (typeof v !== "string") return node;
356
+ const arr = v.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
357
+ if (arr.length === 0) return node;
358
+ return { ...node, AllowExtensions: arr };
359
+ }
360
+
361
+ // InputFile InnerCKey 정본화 — Attributes.InnerCKey 는 [no-inner-block] 정책으로
362
+ // 스키마가 무조건 차단(input-file.schema.json: "InnerCKey": false → 'boolean schema
363
+ // is false'). 모델이 본체 FlexKey.ckey(또는 Ckeys)를 이미 채우고도 InnerCKey 를
364
+ // 중복으로 다는 케이스가 잦다(관측: FlexFile + FlexKey.ckey==InnerCKey). 결정적 strip.
365
+ // - 손실 방지: 모듈별 1차 저장 필드가 비어 있을 때만 InnerCKey 값을 이관(필드 복사,
366
+ // 발명 아님 — canonicalizeComboKeys 의 Ckeys 복사와 동류). 이미 채워져 있으면 제거만.
367
+ // - InputFile 한정 (InnerCKey:false 가 input-file.schema.json 에만 정의 — 타 컨트롤은
368
+ // additionalProperties:true 라 에러 없음).
369
+ function canonicalizeInputFileInnerCKey(node) {
370
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
371
+ if (node.ControlType !== "InputFile") return node;
372
+ const attrs = node.Attributes;
373
+ if (!attrs || typeof attrs !== "object" || Array.isArray(attrs)) return node;
374
+ if (!("InnerCKey" in attrs)) return node;
375
+ const { InnerCKey, ...rest } = attrs;
376
+ const val = typeof InnerCKey === "string" ? InnerCKey.trim() : "";
377
+ if (val) {
378
+ const mod = node.Module || "FlexFile";
379
+ if (mod === "KsystemFile" || mod === "KsystemPayPDF") {
380
+ // 1차 저장 = Ckeys 배열
381
+ if (!Array.isArray(rest.Ckeys) || rest.Ckeys.length === 0) rest.Ckeys = [val];
382
+ } else {
383
+ // FlexFile / HostingFolder / ServerkitFile → FlexKey.ckey
384
+ const fk = (rest.FlexKey && typeof rest.FlexKey === "object" && !Array.isArray(rest.FlexKey))
385
+ ? rest.FlexKey : {};
386
+ if (typeof fk.ckey !== "string" || fk.ckey === "") rest.FlexKey = { ...fk, ckey: val };
387
+ }
388
+ }
389
+ return { ...node, Attributes: rest };
390
+ }
391
+
392
+ // Combo/Search 본체 Ckeys ↔ 자식 ComboList/List Ckeys 동기화 ([ds-key] 1차 원인).
393
+ // 모델이 본체 Ckeys 만 채우고 자식 Ckeys 를 비우는 케이스 — 자식이 비어있고 본체가
394
+ // 채워져 있으면 본체 Ckeys 를 자식에 복사 (combo.md: 자식 Ckeys = 본체 Ckeys 동일).
395
+ // 둘 다 채워졌는데 다르면 모호 → 손대지 않음(스키마 [ds-key] 가 잡음).
396
+ const DIALOG_INNER_TYPE = { Combo: "ComboList", Search: "List" };
397
+ function canonicalizeComboKeys(node) {
398
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
399
+ const innerType = DIALOG_INNER_TYPE[node.ControlType];
400
+ if (!innerType) return node;
401
+ const body = node.Ckeys;
402
+ if (!Array.isArray(body) || body.length === 0) return node; // 본체 기준 없으면 동기화 안 함
403
+ const layouts = node?.Dialog?.Layouts;
404
+ if (!Array.isArray(layouts)) return node;
405
+ let changed = false;
406
+ const newLayouts = layouts.map((layout) => {
407
+ if (!layout || !Array.isArray(layout.Controls)) return layout;
408
+ let lc = false;
409
+ const controls = layout.Controls.map((c) => {
410
+ if (c && c.ControlType === innerType && (!Array.isArray(c.Ckeys) || c.Ckeys.length === 0)) {
411
+ lc = true; changed = true;
412
+ return { ...c, Ckeys: [...body] };
413
+ }
414
+ return c;
415
+ });
416
+ return lc ? { ...layout, Controls: controls } : layout;
417
+ });
418
+ return changed ? { ...node, Dialog: { ...node.Dialog, Layouts: newLayouts } } : node;
419
+ }
420
+
421
+ // Combo/Search 데이터바인딩 보정 2종 (기존 필드 복사 — 발명 아님):
422
+ // 1. display-key 보정 ([display-key] cross-check) — 본체가 표시값을 못 정하는 케이스.
423
+ // needsDisplay 컨텍스트(Search 본체 항상 / Combo 는 자식 ComboList UseDataSource!==false)
424
+ // 에서 DisplayType!=='DisplayValue'(표현식은 발명 불가) + CtrlDisplayCkey 비어있으면
425
+ // 본체 Ckeys 의 표시키(마지막 원소 = [값키,표시키])를 CtrlDisplayCkey 로 등록.
426
+ // 2. DataSourceName 본체→자식 (Combo 한정 — Search 본체엔 DataSourceName 없음, 자식 List 가 원천).
427
+ // 본체에 DataSourceName 있고 자식 ComboList 에 없으면 복사 (자식 required 누락 방지).
428
+ function canonicalizeDialogDataBinding(node) {
429
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
430
+ const innerType = DIALOG_INNER_TYPE[node.ControlType];
431
+ if (!innerType) return node;
432
+ let out = node;
433
+ const mut = () => { if (out === node) out = { ...node }; };
434
+ const layouts = node?.Dialog?.Layouts;
435
+ const filled = (v) => typeof v === "string" && v.length > 0;
436
+
437
+ // needsDisplay (checkDisplayCkey 와 동일 기준)
438
+ let needsDisplay = node.ControlType === "Search";
439
+ if (node.ControlType === "Combo" && Array.isArray(layouts)) {
440
+ for (const layout of layouts) for (const inner of (layout?.Controls ?? [])) {
441
+ if (inner && inner.ControlType === "ComboList" && inner.UseDataSource !== false) needsDisplay = true;
442
+ }
443
+ }
444
+
445
+ // 1. display-key 보정
446
+ if (needsDisplay) {
447
+ const dt = node.DisplayType;
448
+ if (dt !== "DisplayValue" && !filled(node.CtrlDisplayCkey) &&
449
+ (dt === "CtrlDisplayCkey" || !filled(node.DisplayValue)) &&
450
+ Array.isArray(node.Ckeys) && node.Ckeys.length > 0) {
451
+ const disp = node.Ckeys[node.Ckeys.length - 1]; // [값키, 표시키]
452
+ if (typeof disp === "string" && disp !== "") { mut(); out.CtrlDisplayCkey = disp; }
453
+ }
454
+ }
455
+
456
+ // 1b. 고정모드(ComboList UseDataSource:false) — 본체 CtrlDisplayCkey 를 자식 SaveNameKey/SaveValueKey 와 정합.
457
+ // "보여지는 콜렉션키(CtrlDisplayCkey) ↔ 저장 name 키(SaveNameKey)" 연결을 결정적으로 보장.
458
+ // 누락이면 SaveNameKey(없으면 SaveValueKey)로 채우고, 불일치면 교정 (기존 필드 복사 — 발명 아님).
459
+ // 고정모드는 needsDisplay 제외라 보정 1 이 안 건드림 → 여기서 별도 처리.
460
+ // ★ DisplayValue:"" fallback 컨벤션 폐기(combo.md §고정데이터) — 런타임의 SaveNameKey 자동표시
461
+ // 의존을 제거하고 CtrlDisplayCkey 를 명시 채워, 비워두면 선택 후 본체가 빈 칸이 되는 문제 차단.
462
+ if (node.ControlType === "Combo" && Array.isArray(layouts) && node.DisplayType !== "DisplayValue") {
463
+ // 비어있을 때 채우는 건 DisplayValue 표현식이 없을 때만 (보정 1 과 동일 가드 — 표현식 표시 의도 보존).
464
+ const dt = node.DisplayType;
465
+ const canFill = dt === "CtrlDisplayCkey" || !filled(out.DisplayValue);
466
+ for (const layout of layouts) for (const inner of (layout?.Controls ?? [])) {
467
+ if (inner && inner.ControlType === "ComboList" && inner.UseDataSource === false) {
468
+ const snk = filled(inner.SaveNameKey) ? inner.SaveNameKey : null;
469
+ const svk = filled(inner.SaveValueKey) ? inner.SaveValueKey : null;
470
+ const fallback = snk || svk;
471
+ if (!fallback) continue; // SaveKey 둘 다 비면 채울 원본이 없음 ([combo-fixed] 가 별도로 잡음)
472
+ const cur = out.CtrlDisplayCkey;
473
+ const matched = cur === snk || cur === svk;
474
+ if (filled(cur)) {
475
+ // 채워져 있는데 SaveKey 와 불일치 → 교정 (표시 정합).
476
+ if (!matched) { mut(); out.CtrlDisplayCkey = fallback; }
477
+ } else if (canFill) {
478
+ // 비어있고 DisplayValue 표현식도 없음 → SaveNameKey 로 채워 표시키↔저장키 연결 확정.
479
+ mut(); out.CtrlDisplayCkey = fallback;
480
+ }
481
+ }
482
+ }
483
+ }
484
+
485
+ // 2. DataSourceName 본체→자식 (Combo)
486
+ const bodyDsn = node.DataSourceName;
487
+ if (filled(bodyDsn) && Array.isArray(layouts)) {
488
+ let changedL = false;
489
+ const newLayouts = layouts.map((layout) => {
490
+ if (!layout || !Array.isArray(layout.Controls)) return layout;
491
+ let lc = false;
492
+ const controls = layout.Controls.map((c) => {
493
+ if (c && c.ControlType === innerType && !filled(c.DataSourceName)) {
494
+ lc = true; changedL = true;
495
+ return { ...c, DataSourceName: bodyDsn };
496
+ }
497
+ return c;
498
+ });
499
+ return lc ? { ...layout, Controls: controls } : layout;
500
+ });
501
+ if (changedL) { mut(); out.Dialog = { ...node.Dialog, Layouts: newLayouts }; }
502
+ }
503
+ return out;
504
+ }
505
+
506
+ // Dialog host 자식(ComboList/List) 의 결정적·안전한 정본화. 기존 canonicalizer
507
+ // 와 동일한 기준 — 데이터 의존적 값을 "발명" 하지 않고, 구조 신호 또는 모델이
508
+ // 이미 명세한 필드만 사용한다. (CollectionMapper 처럼 원본 필드명을 알아야 하는
509
+ // 매핑은 손대지 않고 schema 가 에러로 남긴다.)
510
+ // 1. Fixed ComboList: Items 보유 + DataSourceName 없음 + UseDataSource!==false
511
+ // → UseDataSource:false. combo.md — 누락 시 런타임이 DataSource 모드로 오인해
512
+ // Items 를 무시하고 CollectionMapper 를 요구한다. Items 존재가 Fixed 의 확정
513
+ // 신호라 발명이 아닌 구조 판정.
514
+ // 2. KeywordSearchCkey (List, UseKeywordSearch:true, 누락): 모델이 이미 명세한
515
+ // 표시 필드(Title) — 통상 검색 대상도 표시 필드 — 또는 자식/본체 Ckeys[0] 로
516
+ // 채움. 기존 필드 복사라 발명 아님 (canonicalizeComboKeys 의 Ckeys 복사와 동류).
517
+ function canonicalizeDialogInner(node) {
518
+ const innerType = DIALOG_INNER_TYPE[node?.ControlType];
519
+ if (!innerType) return node;
520
+ const layouts = node?.Dialog?.Layouts;
521
+ if (!Array.isArray(layouts)) return node;
522
+ const hostCkeys = Array.isArray(node.Ckeys) ? node.Ckeys : [];
523
+ let changed = false;
524
+ const newLayouts = layouts.map((layout) => {
525
+ if (!layout || !Array.isArray(layout.Controls)) return layout;
526
+ let lc = false;
527
+ const controls = layout.Controls.map((c) => {
528
+ if (!c || typeof c !== "object" || c.ControlType !== innerType) return c;
529
+ let out = c;
530
+ const set = (k, v) => { if (out === c) out = { ...c }; out[k] = v; lc = true; changed = true; };
531
+
532
+ // 1. Fixed ComboList → UseDataSource:false
533
+ const isFixed = Array.isArray(c.Items) && c.Items.length > 0 && !c.DataSourceName;
534
+ if (isFixed && c.UseDataSource !== false) set("UseDataSource", false);
535
+
536
+ // 2. KeywordSearchCkey (List)
537
+ if (innerType === "List" && c.UseKeywordSearch === true &&
538
+ (typeof c.KeywordSearchCkey !== "string" || c.KeywordSearchCkey === "")) {
539
+ const ckeys = (Array.isArray(c.Ckeys) && c.Ckeys.length) ? c.Ckeys : hostCkeys;
540
+ const kw = (typeof c.Title === "string" && c.Title) ? c.Title : (ckeys[0] || "");
541
+ if (kw) set("KeywordSearchCkey", kw);
542
+ }
543
+ return out;
544
+ });
545
+ return lc ? { ...layout, Controls: controls } : layout;
546
+ });
547
+ return changed ? { ...node, Dialog: { ...node.Dialog, Layouts: newLayouts } } : node;
548
+ }
549
+
550
+ // Dialog.Layouts 원소 ContentsType strip — Combo 의 Dialog(ComboList 호스트) Layout
551
+ // 원소는 `Controls` 만 두는 게 정본 형태. 모델이 `"ContentsType":"Layout"` 을 붙이는
552
+ // 케이스를 제거(스키마상 optional 이라 검증은 통과하나 정본 형태가 아님). Controls 등
553
+ // 나머지 키는 그대로 보존.
554
+ // - ★ Combo 한정 — InputDate(calendarDialog) / Search(searchDialog) 의 Layout 원소는
555
+ // ContentsType:"Layout" 이 정본이므로 건드리지 않는다.
556
+ function canonicalizeDialogLayout(node) {
557
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
558
+ if (node.ControlType !== "Combo") return node;
559
+ const layouts = node?.Dialog?.Layouts;
560
+ if (!Array.isArray(layouts)) return node;
561
+ let changed = false;
562
+ const newLayouts = layouts.map((L) => {
563
+ if (L && typeof L === "object" && !Array.isArray(L) && "ContentsType" in L) {
564
+ changed = true;
565
+ const { ContentsType, ...rest } = L;
566
+ return rest;
567
+ }
568
+ return L;
569
+ });
570
+ return changed ? { ...node, Dialog: { ...node.Dialog, Layouts: newLayouts } } : node;
571
+ }
572
+
573
+ // boolean 문자열 정본화 — 스튜디오 boolean 토글을 모델이 문자열 "true"/"false"
574
+ // 로 쓰는 케이스를 결정적으로 교정 (schema 는 boolean 요구 → "false" 는
575
+ // 'must be boolean' 에러). boolean 으로 쓰이는 필드명은 Use*/Is*/is* 접두 +
576
+ // 소수 예외(아래) 로 수렴(property-data.js createXxx EditControl 진실원본).
577
+ // - 이름이 매칭되고 값이 정확히 "true"/"false"(공백/대소문자 무시) 일 때만 coerce.
578
+ // (Caption 등 자유 텍스트 오염 방지 — 이름 가드 + 값 가드 이중 안전장치.)
579
+ // - 전체 트리 deep-walk (style 하위객체·Contents·Dialog 등 모든 깊이 포함).
580
+ const BOOL_FIELD_EXTRA = new Set([
581
+ "ExternalDB", "FlexWrap", "MatchText", "NotSeperateInnerBlock",
582
+ "OnlyIfNoSector", "SetCategory",
583
+ ]);
584
+ function isBooleanFieldName(k) {
585
+ return /^(Use|Is|is)/.test(k) || BOOL_FIELD_EXTRA.has(k);
586
+ }
587
+ function coerceBooleansDeep(value) {
588
+ if (Array.isArray(value)) {
589
+ let changed = false;
590
+ const next = value.map((v) => {
591
+ const r = coerceBooleansDeep(v);
592
+ if (r !== v) changed = true;
593
+ return r;
594
+ });
595
+ return changed ? next : value;
596
+ }
597
+ if (value && typeof value === "object") {
598
+ let changed = false;
599
+ const out = {};
600
+ for (const [k, v] of Object.entries(value)) {
601
+ if (typeof v === "string" && isBooleanFieldName(k)) {
602
+ const t = v.trim().toLowerCase();
603
+ if (t === "true") { out[k] = true; changed = true; continue; }
604
+ if (t === "false") { out[k] = false; changed = true; continue; }
605
+ }
606
+ const r = coerceBooleansDeep(v);
607
+ if (r !== v) changed = true;
608
+ out[k] = r;
609
+ }
610
+ return changed ? out : value;
611
+ }
612
+ return value;
613
+ }
614
+
615
+ // display 토큰 정본화 — `{=Field}` 는 단일 중괄호 display 토큰(Caption/labeltext 등에서
616
+ // 컬렉션 키 바인딩). 모델이 i18n 토큰 `{{...}}` 과 혼동해 `{{=Field}}` 처럼 이중 중괄호로
617
+ // 쓰는 케이스를 결정적으로 `{=Field}` 로 교정. = 로 시작하는 이중 중괄호만 대상이라
618
+ // 순수 i18n 토큰(`{{KEY}}`, = 없음)은 건드리지 않는다. 전체 트리 deep-walk.
619
+ function normalizeDisplayTokensDeep(value) {
620
+ if (typeof value === "string") {
621
+ if (!value.includes("{{=")) return value;
622
+ const fixed = value.replace(/\{\{=([^{}]*)\}\}/g, "{=$1}");
623
+ return fixed !== value ? fixed : value;
624
+ }
625
+ if (Array.isArray(value)) {
626
+ let changed = false;
627
+ const next = value.map((v) => { const r = normalizeDisplayTokensDeep(v); if (r !== v) changed = true; return r; });
628
+ return changed ? next : value;
629
+ }
630
+ if (value && typeof value === "object") {
631
+ let changed = false;
632
+ const out = {};
633
+ for (const [k, v] of Object.entries(value)) { const r = normalizeDisplayTokensDeep(v); if (r !== v) changed = true; out[k] = r; }
634
+ return changed ? out : value;
635
+ }
636
+ return value;
637
+ }
638
+
639
+ // GridHeader 정본화 — Grid DataSource 의 GridHeader 는 컬럼 키 문자열 배열
640
+ // ["fCode", ...] 가 정본. 모델이 [{Key,Title}] 객체 배열로 쓰는 케이스를 키
641
+ // 배열로 교정 (Title 은 컨트롤 라벨에서 표현 — 헤더는 키 매핑 전용).
642
+ // - 객체 원소가 하나라도 있을 때만 변환. 이미 문자열 배열이면 그대로.
643
+ // - Key 누락/빈 문자열 원소는 드롭(스키마가 빈 배열을 잡게).
644
+ function normalizeGridHeaders(scenario) {
645
+ const ds = scenario?.DataSources;
646
+ if (!ds || typeof ds !== "object" || Array.isArray(ds)) return scenario;
647
+ let changed = false;
648
+ const out = {};
649
+ for (const [name, src] of Object.entries(ds)) {
650
+ if (
651
+ src && typeof src === "object" && !Array.isArray(src) &&
652
+ src.DataSourceType === "Grid" && Array.isArray(src.GridHeader) &&
653
+ src.GridHeader.some((h) => h && typeof h === "object" && !Array.isArray(h))
654
+ ) {
655
+ const keys = src.GridHeader
656
+ .map((h) => (h && typeof h === "object" && !Array.isArray(h)) ? h.Key : h)
657
+ .filter((k) => typeof k === "string" && k.length > 0);
658
+ out[name] = { ...src, GridHeader: keys };
659
+ changed = true;
660
+ } else {
661
+ out[name] = src;
662
+ }
663
+ }
664
+ return changed ? { ...scenario, DataSources: out } : scenario;
665
+ }
666
+
667
+ // DataSource 객체 구조 정본화 — 모델이 컨트롤 습관을 scenario.DataSources 에 전이하는
668
+ // 케이스를 결정적으로 교정 (관측: DataSourceType:"Fixed" 인데 FixedItems 대신 Items +
669
+ // DataSource 객체 안에 잉여 DataSourceName → dataSourceFixed required 위반으로 oneOf
670
+ // 전 분기 탈락 'must match exactly one schema').
671
+ // 1. 잉여 DataSourceName strip — DataSources 맵의 키가 이미 이름이라 객체 안 키는
672
+ // 어느 DataSourceType 에도 미정의(잉여). 모든 타입에서 제거.
673
+ // 2. Fixed: Items(배열) → FixedItems (FixedItems 없고 Items 만 있을 때 리네임).
674
+ // 3. Grid: Items(배열) → GridItems (GridItems 없고 Items 만 있을 때 리네임).
675
+ function canonicalizeDataSources(scenario) {
676
+ const ds = scenario?.DataSources;
677
+ if (!ds || typeof ds !== "object" || Array.isArray(ds)) return scenario;
678
+ let changed = false;
679
+ const out = {};
680
+ for (const [name, src] of Object.entries(ds)) {
681
+ if (!src || typeof src !== "object" || Array.isArray(src)) { out[name] = src; continue; }
682
+ let s = src;
683
+ const mut = () => { if (s === src) s = { ...src }; };
684
+ // 1. 잉여 DataSourceName
685
+ if ("DataSourceName" in s) { mut(); delete s.DataSourceName; changed = true; }
686
+ // 2. Fixed: Items → FixedItems
687
+ if (s.DataSourceType === "Fixed" && !Array.isArray(s.FixedItems) && Array.isArray(s.Items)) {
688
+ mut(); s.FixedItems = s.Items; delete s.Items; changed = true;
689
+ }
690
+ // 3. Grid: Items → GridItems
691
+ if (s.DataSourceType === "Grid" && !Array.isArray(s.GridItems) && Array.isArray(s.Items)) {
692
+ mut(); s.GridItems = s.Items; delete s.Items; changed = true;
693
+ }
694
+ out[name] = s;
695
+ }
696
+ return changed ? { ...scenario, DataSources: out } : scenario;
697
+ }
698
+
699
+ // ScenarioTitle 정본화 — scenario.schema.json 이 const "" (가비지 슬롯, 실제 표시명은
700
+ // fScenarioName). 모델이 화면 제목을 ScenarioTitle 에 채우는 케이스를 결정적으로 "" 로.
701
+ function normalizeScenarioConstants(scenario) {
702
+ if (!scenario || typeof scenario !== "object" || Array.isArray(scenario)) return scenario;
703
+ if ("ScenarioTitle" in scenario && scenario.ScenarioTitle !== "") {
704
+ return { ...scenario, ScenarioTitle: "" };
705
+ }
706
+ return scenario;
707
+ }
708
+
709
+ // BottomButton 정본화 (bottom-buttons.schema.json) — 모델이 일반 컨트롤/Step 습관을
710
+ // BottomButton 에 과적용하는 결정적 케이스 3종을 BottomButton 노드 한정으로 교정:
711
+ // (a) 잉여 토글 strip — `UseEvents`/`UseClickEvent` 는 BottomButton 에 미정의
712
+ // (Events:{Click:...} 단독이 canonical, 73-76행). 컨트롤/Step 에선 유효 → 전역 금지.
713
+ // (b) Prev 주입 — `MoveTo`∈{Prev,Prev_ReStart} 면 top-level `Prev` 필수
714
+ // (if/then). 누락 시 canonical 빈 객체 `{MoveStepOrder:[]}` 주입.
715
+ // (c) Next 슬롯 정본화 — `Next.Step{N}` 슬롯 값은 canonical 빈 문자열 `""`.
716
+ // 모델이 객체(`{Condition,MoveTo,Direction}`)를 넣는 케이스를 `""` 로 (MoveStepOrder 배열 유지).
717
+ function normalizeBottomButtons(scenario) {
718
+ const steps = scenario?.Steps;
719
+ if (!steps || typeof steps !== "object" || Array.isArray(steps)) return scenario;
720
+ let changed = false;
721
+ const newSteps = {};
722
+ for (const [stepId, step] of Object.entries(steps)) {
723
+ const bb = step?.BottomButtons;
724
+ if (!Array.isArray(bb)) { newSteps[stepId] = step; continue; }
725
+ let stepChanged = false;
726
+ const cleaned = bb.map((b) => {
727
+ if (!b || typeof b !== "object" || Array.isArray(b)) return b;
728
+ let out = b;
729
+ const mut = () => { if (out === b) out = { ...b }; };
730
+ // (a) 잉여 토글
731
+ for (const tog of ["UseEvents", "UseClickEvent"]) {
732
+ if (tog in out) { mut(); delete out[tog]; }
733
+ }
734
+ // (b) Prev 주입
735
+ if ((out.MoveTo === "Prev" || out.MoveTo === "Prev_ReStart") &&
736
+ !(out.Prev && typeof out.Prev === "object" && !Array.isArray(out.Prev))) {
737
+ mut(); out.Prev = { MoveStepOrder: [] };
738
+ }
739
+ // (c) Next 슬롯 객체 → ""
740
+ if (out.Next && typeof out.Next === "object" && !Array.isArray(out.Next)) {
741
+ let nx = out.Next;
742
+ for (const [k, v] of Object.entries(out.Next)) {
743
+ if (/^Step[1-9][0-9]*$/.test(k) && typeof v !== "string") {
744
+ if (nx === out.Next) nx = { ...out.Next };
745
+ nx[k] = "";
746
+ }
747
+ }
748
+ if (nx !== out.Next) { mut(); out.Next = nx; }
749
+ }
750
+ if (out !== b) stepChanged = true;
751
+ return out;
752
+ });
753
+ if (stepChanged) { newSteps[stepId] = { ...step, BottomButtons: cleaned }; changed = true; }
754
+ else newSteps[stepId] = step;
755
+ }
756
+ return changed ? { ...scenario, Steps: newSteps } : scenario;
757
+ }
758
+
759
+ function materializeNode(node, ctx, registry, path, errors, counters) {
760
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
761
+
762
+ // raw control / raw group 우선 — 패턴 이름 검사 전에 단정.
763
+ if ("ControlType" in node || node.ContentsType === "Group") {
764
+ counters.rawPassed += 1;
765
+ // design 키 expand — 자식 컨테이너 재귀 전에 처리해 raw style fields 가
766
+ // 머지된 노드를 가지고 walk 한다. (design 키 자체는 결과에서 제거.)
767
+ const {
768
+ control: expanded,
769
+ sourceMap: designSm,
770
+ errors: designErrors,
771
+ } = applyDesign(node, path);
772
+ if (designErrors.length > 0) {
773
+ errors.push(...designErrors);
774
+ }
775
+ if (Object.keys(designSm).length > 0) {
776
+ counters.designsApplied += 1;
777
+ ctx.designSourceMaps[path] = designSm;
778
+ }
779
+ // 컨트롤 enum + DataConnection + AllowExtensions + InputFile InnerCKey + Combo Ckeys + Dialog 자식
780
+ // 정본화 — 자식 재귀 전에. (canonicalizeComboKeys 가 host→자식 Ckeys 동기화를
781
+ // 먼저 한 뒤 canonicalizeDialogInner 가 그 Ckeys 를 활용.)
782
+ const normalized = canonicalizeDialogLayout(
783
+ canonicalizeDialogInner(
784
+ canonicalizeDialogDataBinding(
785
+ canonicalizeComboKeys(
786
+ canonicalizeItemFields(
787
+ canonicalizeInputFileInnerCKey(
788
+ canonicalizeAllowExtensions(
789
+ canonicalizeDataConnection(canonicalizeLabelType(canonicalizeControlEnums(expanded))),
790
+ ),
791
+ ),
792
+ ),
793
+ ),
794
+ ),
795
+ ),
796
+ );
797
+ return recurseContainer(normalized, ctx, registry, path, errors, counters);
798
+ }
799
+
800
+ // 단일 key 객체 → 패턴 후보.
801
+ const keys = Object.keys(node);
802
+ if (keys.length === 1) {
803
+ const patternName = keys[0];
804
+ const entry = registry.get(patternName);
805
+ if (entry) {
806
+ const props = node[patternName];
807
+ if (!props || typeof props !== "object" || Array.isArray(props)) {
808
+ errors.push({
809
+ kind: "materialize",
810
+ phase: "props-shape",
811
+ path,
812
+ patternName,
813
+ tier: entry.tier,
814
+ propsSnapshot: propsSnapshot(props),
815
+ message: `pattern '${patternName}' 의 props 가 객체가 아님 (받은 타입: ${Array.isArray(props) ? "array" : typeof props}).`,
816
+ hint: `호출 shape: { "${patternName}": { ...props } }. props 는 반드시 plain object — array / string / null 불가.`,
817
+ nextStep: `get_pattern({ name: "${patternName}" }) 로 정확한 props 스키마 확인.`,
818
+ });
819
+ return null;
820
+ }
821
+ let result;
822
+ try {
823
+ result = entry.materialize(props, ctx);
824
+ } catch (e) {
825
+ errors.push({
826
+ kind: "materialize",
827
+ phase: "factory-throw",
828
+ path,
829
+ patternName,
830
+ tier: entry.tier,
831
+ propsSnapshot: propsSnapshot(props),
832
+ message: `pattern '${patternName}' (${entry.tier}) materialize 실패: ${e.message}`,
833
+ hint: e.message?.includes("unknown")
834
+ ? `enum / 미등록 값일 가능성 — 에러 메시지의 값 vs 스키마 enum 비교.`
835
+ : e.message?.includes("필수") || e.message?.includes("required")
836
+ ? `필수 prop 누락 — 에러 메시지의 prop 이름 확인.`
837
+ : `pattern 의 materializer 가 props 를 거부함 — 에러 메시지 참고.`,
838
+ nextStep: `get_pattern({ name: "${patternName}", tier: "${entry.tier}" }) 로 properties/required/allOf 확인 후 props 재구성.`,
839
+ });
840
+ return null;
841
+ }
842
+ counters.patternsApplied += 1;
843
+ // 패턴 결과는 fully-materialized 라 추가 walk 불필요 (development.md §6).
844
+ return result;
845
+ }
846
+ // 단일 key 인데 알려진 패턴이 아님 → raw 객체로 간주 (false-positive 방지).
847
+ // 예: ScenarioMeta, dataConnection 의 단일 카테고리 키 등.
848
+ // 단, "패턴처럼 보이는" 단일 key 가 actually raw 일 때 LLM 이 헷갈리지 않도록
849
+ // 후보 제안은 응답에 직접 푸시하지 않고 (raw 처리 우선) recurse 만 함.
850
+ return recurseContainer(node, ctx, registry, path, errors, counters);
851
+ }
852
+
853
+ // 다중 key 객체 → raw passthrough, 컨테이너 필드만 재귀.
854
+ return recurseContainer(node, ctx, registry, path, errors, counters);
855
+ }
856
+
857
+ /**
858
+ * Raw 객체의 컨테이너 필드(Contents / Dialog.Layouts[*].Controls)만 좁게 재귀.
859
+ * 일반 속성 객체(FontStyle 등)에는 들어가지 않는다.
860
+ */
861
+ function recurseContainer(node, ctx, registry, path, errors, counters) {
862
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
863
+ const out = { ...node };
864
+
865
+ if (Array.isArray(out.Contents)) {
866
+ out.Contents = out.Contents.map((c, i) =>
867
+ materializeNode(c, ctx, registry, `${path}.Contents[${i}]`, errors, counters),
868
+ );
869
+ }
870
+
871
+ // Step 의 FixedContentsTop/Bottom 도 walking — 그 안에 박힌 pattern invocation
872
+ // 도 materialize. (Group 노드는 이 키들을 갖지 않으므로 if 가드로 안전.)
873
+ for (const key of ["FixedContentsTop", "FixedContentsBottom"]) {
874
+ if (Array.isArray(out[key])) {
875
+ out[key] = out[key].map((c, i) =>
876
+ materializeNode(c, ctx, registry, `${path}.${key}[${i}]`, errors, counters),
877
+ );
878
+ }
879
+ }
880
+
881
+ if (out.Dialog && typeof out.Dialog === "object" && Array.isArray(out.Dialog.Layouts)) {
882
+ out.Dialog = {
883
+ ...out.Dialog,
884
+ Layouts: out.Dialog.Layouts.map((layout, li) => {
885
+ if (!layout || typeof layout !== "object" || !Array.isArray(layout.Controls)) {
886
+ return layout;
887
+ }
888
+ return {
889
+ ...layout,
890
+ Controls: layout.Controls.map((c, ci) =>
891
+ materializeNode(
892
+ c,
893
+ ctx,
894
+ registry,
895
+ `${path}.Dialog.Layouts[${li}].Controls[${ci}]`,
896
+ errors,
897
+ counters,
898
+ ),
899
+ ),
900
+ };
901
+ }),
902
+ };
903
+ }
904
+
905
+ return out;
906
+ }
907
+
908
+ // ─────────────────────────────────────────────────────────────────────────────
909
+ // Auto-wrap — Step 컨테이너 children 의 Control 결과를 Group 으로 감싼다.
910
+ // ─────────────────────────────────────────────────────────────────────────────
911
+
912
+ /**
913
+ * Step.{Contents, FixedContentsTop, FixedContentsBottom} 은 schema 가
914
+ * Group[] 만 받음 (scenario.schema.json / step.schema.json 의
915
+ * `items: { $ref: "group.schema.json" }`).
916
+ *
917
+ * 그런데 atom 패턴 (button, badge, checkbox, switch, segmented-radio) 은
918
+ * Control (Label / CheckBox / RadioBox) 을 emit 한다. molecule 패턴은 Group 을
919
+ * emit 해서 OK. LLM 이 raw Control 을 Step.Contents 에 직접 박는 경우도 동일 문제.
920
+ *
921
+ * 해결: Step 컨테이너 entry 위치에서 결과가 Control 이면 단일-자식 Group 으로
922
+ * 자동 wrap. molecule 결과 (이미 Group) 와 raw Group 은 통과.
923
+ *
924
+ * Wrap Group 의 ContentsName: `Wrap${ControlName||"Auto"}` 로 의미 부여.
925
+ */
926
+ function autoWrapStepChild(node, ctx) {
927
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
928
+ // 이미 Group → wrap 불필요.
929
+ if (node.ContentsType === "Group") return node;
930
+ // Control 이 아니면 (예: null, 잘못된 노드) → 통과 — schema 가 알아서 거부.
931
+ if (!node.ControlType) return node;
932
+
933
+ const baseName = String(node.ControlName || node.ControlName2 || "Auto");
934
+ return {
935
+ ...makeGroup({ name: `Wrap${baseName}`, children: [node] }),
936
+ Id: generateId(ctx),
937
+ };
938
+ }
939
+
940
+ // ─────────────────────────────────────────────────────────────────────────────
941
+ // Public: 시나리오 전체 materialize
942
+ // ─────────────────────────────────────────────────────────────────────────────
943
+
944
+ /**
945
+ * 시나리오 JSON 을 받아 mixed input 을 풀 메타데이터로 변환.
946
+ *
947
+ * 동작:
948
+ * - 시나리오 루트 객체는 그대로 보존 (Steps, ScenarioMeta, ServiceBinding 등 키 유지).
949
+ * - Steps[*].Contents 와 Steps[*].Contents[*] 의 하위 컨테이너 (Group.Contents,
950
+ * Dialog.Layouts[*].Controls) 를 walk 하면서 pattern invocation 을 치환.
951
+ * - Step-level 메타데이터 (StepName, BottomButtons, Next 등) 와 ScenarioMeta 는
952
+ * touch 안 함 (development.md §2: 항상 raw).
953
+ *
954
+ * 응답:
955
+ * {
956
+ * scenario: <materialized>,
957
+ * report: { patternsRegistered, patternsApplied, startMaxId, endMaxId, generatedIds },
958
+ * errors: [ { kind:"materialize", path, patternName?, tier?, message }, ... ]
959
+ * }
960
+ *
961
+ * errors 가 비어있지 않더라도 부분 결과 (scenario) 는 반환 — 호출자가 fail-fast
962
+ * 정책으로 검증 단계 진입 여부 결정.
963
+ */
964
+ export async function materializeScenario(scenario) {
965
+ let registry;
966
+ try {
967
+ registry = await loadRegistry();
968
+ } catch (e) {
969
+ return {
970
+ scenario,
971
+ report: { patternsRegistered: 0, patternsApplied: 0, startMaxId: 0, endMaxId: 0, generatedIds: 0 },
972
+ errors: [
973
+ {
974
+ kind: "materialize",
975
+ path: "$",
976
+ message: `registry load failed: ${e.message}`,
977
+ },
978
+ ],
979
+ };
980
+ }
981
+
982
+ if (!scenario || typeof scenario !== "object" || Array.isArray(scenario)) {
983
+ return {
984
+ scenario,
985
+ report: { patternsRegistered: registry.size, patternsApplied: 0, startMaxId: 0, endMaxId: 0, generatedIds: 0 },
986
+ errors: [
987
+ {
988
+ kind: "materialize",
989
+ path: "$",
990
+ message: "scenario 는 object 여야 함.",
991
+ },
992
+ ],
993
+ };
994
+ }
995
+
996
+ const errors = [];
997
+ const counters = {
998
+ patternsApplied: 0,
999
+ rawPassed: 0,
1000
+ autoWrapped: 0,
1001
+ designsApplied: 0,
1002
+ };
1003
+ const startMaxId = findMaxId(scenario);
1004
+ const ctx = {
1005
+ idCounter: { current: startMaxId },
1006
+ designSourceMaps: {},
1007
+ };
1008
+
1009
+ const out = { ...scenario };
1010
+ if (out.Steps && typeof out.Steps === "object" && !Array.isArray(out.Steps)) {
1011
+ const newSteps = {};
1012
+ for (const [stepId, step] of Object.entries(out.Steps)) {
1013
+ if (!step || typeof step !== "object" || Array.isArray(step)) {
1014
+ newSteps[stepId] = step;
1015
+ continue;
1016
+ }
1017
+ // 1) 각 Step 의 children (Contents / FixedContentsTop / FixedContentsBottom)
1018
+ // + Dialog 의 pattern invocation 을 materialize.
1019
+ const materialized = recurseContainer(
1020
+ step,
1021
+ ctx,
1022
+ registry,
1023
+ `Steps.${stepId}`,
1024
+ errors,
1025
+ counters,
1026
+ );
1027
+ // 2) Step 의 세 가지 children 컨테이너는 schema 가 Group[] 만 받으므로
1028
+ // Control 결과 (atom 패턴 출력 또는 raw Control) 를 Group 으로 자동 wrap.
1029
+ for (const key of STEP_CONTAINER_KEYS) {
1030
+ if (!Array.isArray(materialized[key])) continue;
1031
+ materialized[key] = materialized[key].map((item) => {
1032
+ const wrapped = autoWrapStepChild(item, ctx);
1033
+ if (wrapped !== item) counters.autoWrapped += 1;
1034
+ return wrapped;
1035
+ });
1036
+ }
1037
+ // 3) BottomButtons 는 ControlType/Group 이 아니라 recurseContainer 의 design
1038
+ // expand 를 안 탄다. design 키가 residual 로 남으므로 (strict 'design' 미정의)
1039
+ // 여기서 applyDesign 으로 raw 스타일 키(Width/BgStyle/...)로 expand.
1040
+ if (Array.isArray(materialized.BottomButtons)) {
1041
+ materialized.BottomButtons = materialized.BottomButtons.map((b, i) => {
1042
+ if (!b || typeof b !== "object" || Array.isArray(b) || !("design" in b)) return b;
1043
+ const p = `Steps.${stepId}.BottomButtons.${i}`;
1044
+ const { control, sourceMap, errors: dErrs } = applyDesign(b, p);
1045
+ if (dErrs.length > 0) errors.push(...dErrs);
1046
+ if (Object.keys(sourceMap).length > 0) {
1047
+ counters.designsApplied += 1;
1048
+ ctx.designSourceMaps[p] = sourceMap;
1049
+ }
1050
+ return control;
1051
+ });
1052
+ }
1053
+ newSteps[stepId] = materialized;
1054
+ }
1055
+ out.Steps = newSteps;
1056
+ }
1057
+
1058
+ // 전체 트리 후처리 — boolean 문자열 coerce + display 토큰({{=}}→{=}) + Grid
1059
+ // GridHeader 키배열 + ScenarioTitle const + BottomButton(토글/Prev/Next 슬롯) 정본화.
1060
+ const finalized = normalizeScenarioConstants(
1061
+ normalizeBottomButtons(
1062
+ canonicalizeDataSources(normalizeGridHeaders(normalizeDisplayTokensDeep(coerceBooleansDeep(out)))),
1063
+ ),
1064
+ );
1065
+
1066
+ const endMaxId = ctx.idCounter.current;
1067
+ return {
1068
+ scenario: finalized,
1069
+ report: {
1070
+ patternsRegistered: registry.size,
1071
+ patternsApplied: counters.patternsApplied,
1072
+ rawNodesPassed: counters.rawPassed,
1073
+ autoWrapped: counters.autoWrapped,
1074
+ designsApplied: counters.designsApplied,
1075
+ designSourceMaps: ctx.designSourceMaps,
1076
+ startMaxId,
1077
+ endMaxId,
1078
+ generatedIds: endMaxId - startMaxId,
1079
+ },
1080
+ errors,
1081
+ };
1082
+ }
1083
+
1084
+ // ─────────────────────────────────────────────────────────────────────────────
1085
+ // Public: 단편 (Group / Control / Step / Scenario / pattern invocation) materialize
1086
+ // ─────────────────────────────────────────────────────────────────────────────
1087
+
1088
+ /**
1089
+ * validate_fragment 가 호출하는 경량 materialize. shape 자동 판별:
1090
+ *
1091
+ * - Scenario (Steps 키 보유) → materializeScenario 위임.
1092
+ * - Step (Contents / FixedContentsTop / FixedContentsBottom 중 하나 이상 보유,
1093
+ * ContentsType:'Group' 도 아니고 ControlType 도 없음) → 세 컨테이너 walking +
1094
+ * Control 결과 autoWrap.
1095
+ * - Group / Control / 단일-key pattern invocation → materializeNode 한 번.
1096
+ *
1097
+ * materializeScenario 와 동일한 errors / report shape 으로 응답.
1098
+ */
1099
+ export async function materializeFragment(node) {
1100
+ let registry;
1101
+ try {
1102
+ registry = await loadRegistry();
1103
+ } catch (e) {
1104
+ return {
1105
+ fragment: node,
1106
+ report: { patternsRegistered: 0, patternsApplied: 0, rawNodesPassed: 0, autoWrapped: 0, designsApplied: 0, designSourceMaps: {}, startMaxId: 0, endMaxId: 0, generatedIds: 0 },
1107
+ errors: [
1108
+ { kind: "materialize", path: "$", message: `registry load failed: ${e.message}` },
1109
+ ],
1110
+ };
1111
+ }
1112
+
1113
+ if (!node || typeof node !== "object" || Array.isArray(node)) {
1114
+ return {
1115
+ fragment: node,
1116
+ report: { patternsRegistered: registry.size, patternsApplied: 0, rawNodesPassed: 0, autoWrapped: 0, designsApplied: 0, designSourceMaps: {}, startMaxId: 0, endMaxId: 0, generatedIds: 0 },
1117
+ errors: [
1118
+ { kind: "materialize", path: "$", message: "fragment 는 object 여야 함." },
1119
+ ],
1120
+ };
1121
+ }
1122
+
1123
+ // Scenario 전체가 들어온 경우 — materializeScenario 위임 (Steps 워킹 + autoWrap).
1124
+ if (node.Steps && typeof node.Steps === "object" && !Array.isArray(node.Steps)) {
1125
+ const r = await materializeScenario(node);
1126
+ return { fragment: r.scenario, report: r.report, errors: r.errors };
1127
+ }
1128
+
1129
+ const errors = [];
1130
+ const counters = {
1131
+ patternsApplied: 0,
1132
+ rawPassed: 0,
1133
+ autoWrapped: 0,
1134
+ designsApplied: 0,
1135
+ };
1136
+ const startMaxId = findMaxId(node);
1137
+ const ctx = {
1138
+ idCounter: { current: startMaxId },
1139
+ designSourceMaps: {},
1140
+ };
1141
+
1142
+ // Step 모양 판별 — 컨테이너 키가 있는데 Group/Control 식별자는 없음.
1143
+ const isStepShape =
1144
+ !("ControlType" in node) &&
1145
+ node.ContentsType !== "Group" &&
1146
+ (Array.isArray(node.Contents) ||
1147
+ Array.isArray(node.FixedContentsTop) ||
1148
+ Array.isArray(node.FixedContentsBottom));
1149
+
1150
+ let out;
1151
+ if (isStepShape) {
1152
+ out = recurseContainer(node, ctx, registry, "$", errors, counters);
1153
+ for (const key of STEP_CONTAINER_KEYS) {
1154
+ if (!Array.isArray(out[key])) continue;
1155
+ out[key] = out[key].map((item) => {
1156
+ const wrapped = autoWrapStepChild(item, ctx);
1157
+ if (wrapped !== item) counters.autoWrapped += 1;
1158
+ return wrapped;
1159
+ });
1160
+ }
1161
+ } else {
1162
+ out = materializeNode(node, ctx, registry, "$", errors, counters);
1163
+ }
1164
+
1165
+ const endMaxId = ctx.idCounter.current;
1166
+ return {
1167
+ fragment: normalizeDisplayTokensDeep(coerceBooleansDeep(out)),
1168
+ report: {
1169
+ patternsRegistered: registry.size,
1170
+ patternsApplied: counters.patternsApplied,
1171
+ rawNodesPassed: counters.rawPassed,
1172
+ autoWrapped: counters.autoWrapped,
1173
+ designsApplied: counters.designsApplied,
1174
+ designSourceMaps: ctx.designSourceMaps,
1175
+ startMaxId,
1176
+ endMaxId,
1177
+ generatedIds: endMaxId - startMaxId,
1178
+ },
1179
+ errors,
1180
+ };
1181
+ }