@metaobjectsdev/metadata 0.5.0-rc.1

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 (405) hide show
  1. package/LICENSE +189 -0
  2. package/README.md +29 -0
  3. package/dist/attr-class-map.d.ts +26 -0
  4. package/dist/attr-class-map.d.ts.map +1 -0
  5. package/dist/attr-class-map.js +44 -0
  6. package/dist/attr-class-map.js.map +1 -0
  7. package/dist/attr-schema-validate.d.ts +9 -0
  8. package/dist/attr-schema-validate.d.ts.map +1 -0
  9. package/dist/attr-schema-validate.js +100 -0
  10. package/dist/attr-schema-validate.js.map +1 -0
  11. package/dist/constants.d.ts +208 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +419 -0
  14. package/dist/constants.js.map +1 -0
  15. package/dist/core/attr/attr-constants.d.ts +12 -0
  16. package/dist/core/attr/attr-constants.d.ts.map +1 -0
  17. package/dist/core/attr/attr-constants.js +27 -0
  18. package/dist/core/attr/attr-constants.js.map +1 -0
  19. package/dist/core/attr/meta-attr-filter.d.ts +10 -0
  20. package/dist/core/attr/meta-attr-filter.d.ts.map +1 -0
  21. package/dist/core/attr/meta-attr-filter.js +56 -0
  22. package/dist/core/attr/meta-attr-filter.js.map +1 -0
  23. package/dist/core/attr/meta-attr-properties.d.ts +9 -0
  24. package/dist/core/attr/meta-attr-properties.d.ts.map +1 -0
  25. package/dist/core/attr/meta-attr-properties.js +22 -0
  26. package/dist/core/attr/meta-attr-properties.js.map +1 -0
  27. package/dist/core/attr/meta-attr-stringarray.d.ts +9 -0
  28. package/dist/core/attr/meta-attr-stringarray.d.ts.map +1 -0
  29. package/dist/core/attr/meta-attr-stringarray.js +29 -0
  30. package/dist/core/attr/meta-attr-stringarray.js.map +1 -0
  31. package/dist/core/attr/meta-attr.d.ts +37 -0
  32. package/dist/core/attr/meta-attr.d.ts.map +1 -0
  33. package/dist/core/attr/meta-attr.js +97 -0
  34. package/dist/core/attr/meta-attr.js.map +1 -0
  35. package/dist/core/export-json.d.ts +29 -0
  36. package/dist/core/export-json.d.ts.map +1 -0
  37. package/dist/core/export-json.js +45 -0
  38. package/dist/core/export-json.js.map +1 -0
  39. package/dist/core/field/field-constants.d.ts +40 -0
  40. package/dist/core/field/field-constants.d.ts.map +1 -0
  41. package/dist/core/field/field-constants.js +66 -0
  42. package/dist/core/field/field-constants.js.map +1 -0
  43. package/dist/core/field/field-schema.d.ts +6 -0
  44. package/dist/core/field/field-schema.d.ts.map +1 -0
  45. package/dist/core/field/field-schema.js +92 -0
  46. package/dist/core/field/field-schema.js.map +1 -0
  47. package/dist/core/field/meta-field.d.ts +50 -0
  48. package/dist/core/field/meta-field.d.ts.map +1 -0
  49. package/dist/core/field/meta-field.js +121 -0
  50. package/dist/core/field/meta-field.js.map +1 -0
  51. package/dist/core/file-meta-data-loader.d.ts +18 -0
  52. package/dist/core/file-meta-data-loader.d.ts.map +1 -0
  53. package/dist/core/file-meta-data-loader.js +81 -0
  54. package/dist/core/file-meta-data-loader.js.map +1 -0
  55. package/dist/core/file-source.d.ts +12 -0
  56. package/dist/core/file-source.d.ts.map +1 -0
  57. package/dist/core/file-source.js +46 -0
  58. package/dist/core/file-source.js.map +1 -0
  59. package/dist/core/identity/identity-constants.d.ts +19 -0
  60. package/dist/core/identity/identity-constants.d.ts.map +1 -0
  61. package/dist/core/identity/identity-constants.js +35 -0
  62. package/dist/core/identity/identity-constants.js.map +1 -0
  63. package/dist/core/identity/identity-schema.d.ts +6 -0
  64. package/dist/core/identity/identity-schema.d.ts.map +1 -0
  65. package/dist/core/identity/identity-schema.js +55 -0
  66. package/dist/core/identity/identity-schema.js.map +1 -0
  67. package/dist/core/identity/meta-identity.d.ts +71 -0
  68. package/dist/core/identity/meta-identity.d.ts.map +1 -0
  69. package/dist/core/identity/meta-identity.js +129 -0
  70. package/dist/core/identity/meta-identity.js.map +1 -0
  71. package/dist/core/index.d.ts +6 -0
  72. package/dist/core/index.d.ts.map +1 -0
  73. package/dist/core/index.js +11 -0
  74. package/dist/core/index.js.map +1 -0
  75. package/dist/core/object/meta-object.d.ts +39 -0
  76. package/dist/core/object/meta-object.d.ts.map +1 -0
  77. package/dist/core/object/meta-object.js +80 -0
  78. package/dist/core/object/meta-object.js.map +1 -0
  79. package/dist/core/object/object-constants.d.ts +5 -0
  80. package/dist/core/object/object-constants.d.ts.map +1 -0
  81. package/dist/core/object/object-constants.js +18 -0
  82. package/dist/core/object/object-constants.js.map +1 -0
  83. package/dist/core/object/object-schema.d.ts +4 -0
  84. package/dist/core/object/object-schema.d.ts.map +1 -0
  85. package/dist/core/object/object-schema.js +5 -0
  86. package/dist/core/object/object-schema.js.map +1 -0
  87. package/dist/core/parser-yaml.d.ts +3 -0
  88. package/dist/core/parser-yaml.d.ts.map +1 -0
  89. package/dist/core/parser-yaml.js +39 -0
  90. package/dist/core/parser-yaml.js.map +1 -0
  91. package/dist/core/query/query-constants.d.ts +20 -0
  92. package/dist/core/query/query-constants.d.ts.map +1 -0
  93. package/dist/core/query/query-constants.js +56 -0
  94. package/dist/core/query/query-constants.js.map +1 -0
  95. package/dist/core/relationship/find-reference.d.ts +22 -0
  96. package/dist/core/relationship/find-reference.d.ts.map +1 -0
  97. package/dist/core/relationship/find-reference.js +29 -0
  98. package/dist/core/relationship/find-reference.js.map +1 -0
  99. package/dist/core/relationship/meta-relationship.d.ts +11 -0
  100. package/dist/core/relationship/meta-relationship.d.ts.map +1 -0
  101. package/dist/core/relationship/meta-relationship.js +27 -0
  102. package/dist/core/relationship/meta-relationship.js.map +1 -0
  103. package/dist/core/relationship/relationship-constants.d.ts +14 -0
  104. package/dist/core/relationship/relationship-constants.d.ts.map +1 -0
  105. package/dist/core/relationship/relationship-constants.js +28 -0
  106. package/dist/core/relationship/relationship-constants.js.map +1 -0
  107. package/dist/core/relationship/relationship-schema.d.ts +4 -0
  108. package/dist/core/relationship/relationship-schema.d.ts.map +1 -0
  109. package/dist/core/relationship/relationship-schema.js +37 -0
  110. package/dist/core/relationship/relationship-schema.js.map +1 -0
  111. package/dist/core/validator/meta-validator.d.ts +29 -0
  112. package/dist/core/validator/meta-validator.d.ts.map +1 -0
  113. package/dist/core/validator/meta-validator.js +49 -0
  114. package/dist/core/validator/meta-validator.js.map +1 -0
  115. package/dist/core/validator/validator-constants.d.ts +11 -0
  116. package/dist/core/validator/validator-constants.d.ts.map +1 -0
  117. package/dist/core/validator/validator-constants.js +25 -0
  118. package/dist/core/validator/validator-constants.js.map +1 -0
  119. package/dist/core/validator/validator-schema.d.ts +4 -0
  120. package/dist/core/validator/validator-schema.d.ts.map +1 -0
  121. package/dist/core/validator/validator-schema.js +38 -0
  122. package/dist/core/validator/validator-schema.js.map +1 -0
  123. package/dist/core/yaml-desugar.d.ts +10 -0
  124. package/dist/core/yaml-desugar.d.ts.map +1 -0
  125. package/dist/core/yaml-desugar.js +99 -0
  126. package/dist/core/yaml-desugar.js.map +1 -0
  127. package/dist/core-attr-schemas.d.ts +22 -0
  128. package/dist/core-attr-schemas.d.ts.map +1 -0
  129. package/dist/core-attr-schemas.js +324 -0
  130. package/dist/core-attr-schemas.js.map +1 -0
  131. package/dist/core-types.d.ts +20 -0
  132. package/dist/core-types.d.ts.map +1 -0
  133. package/dist/core-types.js +225 -0
  134. package/dist/core-types.js.map +1 -0
  135. package/dist/data-converter.d.ts +17 -0
  136. package/dist/data-converter.d.ts.map +1 -0
  137. package/dist/data-converter.js +117 -0
  138. package/dist/data-converter.js.map +1 -0
  139. package/dist/data-type.d.ts +15 -0
  140. package/dist/data-type.d.ts.map +1 -0
  141. package/dist/data-type.js +25 -0
  142. package/dist/data-type.js.map +1 -0
  143. package/dist/db/db-attr-schemas.d.ts +8 -0
  144. package/dist/db/db-attr-schemas.d.ts.map +1 -0
  145. package/dist/db/db-attr-schemas.js +26 -0
  146. package/dist/db/db-attr-schemas.js.map +1 -0
  147. package/dist/db/db-provider.d.ts +3 -0
  148. package/dist/db/db-provider.d.ts.map +1 -0
  149. package/dist/db/db-provider.js +28 -0
  150. package/dist/db/db-provider.js.map +1 -0
  151. package/dist/errors.d.ts +26 -0
  152. package/dist/errors.d.ts.map +1 -0
  153. package/dist/errors.js +59 -0
  154. package/dist/errors.js.map +1 -0
  155. package/dist/index.d.ts +70 -0
  156. package/dist/index.d.ts.map +1 -0
  157. package/dist/index.js +76 -0
  158. package/dist/index.js.map +1 -0
  159. package/dist/loader/meta-data-loader.d.ts +87 -0
  160. package/dist/loader/meta-data-loader.d.ts.map +1 -0
  161. package/dist/loader/meta-data-loader.js +232 -0
  162. package/dist/loader/meta-data-loader.js.map +1 -0
  163. package/dist/loader/meta-data-source.d.ts +23 -0
  164. package/dist/loader/meta-data-source.d.ts.map +1 -0
  165. package/dist/loader/meta-data-source.js +20 -0
  166. package/dist/loader/meta-data-source.js.map +1 -0
  167. package/dist/loader/validation-passes.d.ts +7 -0
  168. package/dist/loader/validation-passes.d.ts.map +1 -0
  169. package/dist/loader/validation-passes.js +244 -0
  170. package/dist/loader/validation-passes.js.map +1 -0
  171. package/dist/meta/find-reference.d.ts +22 -0
  172. package/dist/meta/find-reference.d.ts.map +1 -0
  173. package/dist/meta/find-reference.js +29 -0
  174. package/dist/meta/find-reference.js.map +1 -0
  175. package/dist/meta/meta-attr.d.ts +8 -0
  176. package/dist/meta/meta-attr.d.ts.map +1 -0
  177. package/dist/meta/meta-attr.js +17 -0
  178. package/dist/meta/meta-attr.js.map +1 -0
  179. package/dist/meta/meta-data.d.ts +107 -0
  180. package/dist/meta/meta-data.d.ts.map +1 -0
  181. package/dist/meta/meta-data.js +302 -0
  182. package/dist/meta/meta-data.js.map +1 -0
  183. package/dist/meta/meta-field.d.ts +48 -0
  184. package/dist/meta/meta-field.d.ts.map +1 -0
  185. package/dist/meta/meta-field.js +94 -0
  186. package/dist/meta/meta-field.js.map +1 -0
  187. package/dist/meta/meta-identity.d.ts +71 -0
  188. package/dist/meta/meta-identity.d.ts.map +1 -0
  189. package/dist/meta/meta-identity.js +129 -0
  190. package/dist/meta/meta-identity.js.map +1 -0
  191. package/dist/meta/meta-layout.d.ts +23 -0
  192. package/dist/meta/meta-layout.d.ts.map +1 -0
  193. package/dist/meta/meta-layout.js +45 -0
  194. package/dist/meta/meta-layout.js.map +1 -0
  195. package/dist/meta/meta-object.d.ts +40 -0
  196. package/dist/meta/meta-object.d.ts.map +1 -0
  197. package/dist/meta/meta-object.js +81 -0
  198. package/dist/meta/meta-object.js.map +1 -0
  199. package/dist/meta/meta-origin.d.ts +32 -0
  200. package/dist/meta/meta-origin.d.ts.map +1 -0
  201. package/dist/meta/meta-origin.js +55 -0
  202. package/dist/meta/meta-origin.js.map +1 -0
  203. package/dist/meta/meta-relationship.d.ts +11 -0
  204. package/dist/meta/meta-relationship.d.ts.map +1 -0
  205. package/dist/meta/meta-relationship.js +27 -0
  206. package/dist/meta/meta-relationship.js.map +1 -0
  207. package/dist/meta/meta-root.d.ts +12 -0
  208. package/dist/meta/meta-root.d.ts.map +1 -0
  209. package/dist/meta/meta-root.js +24 -0
  210. package/dist/meta/meta-root.js.map +1 -0
  211. package/dist/meta/meta-source.d.ts +18 -0
  212. package/dist/meta/meta-source.d.ts.map +1 -0
  213. package/dist/meta/meta-source.js +31 -0
  214. package/dist/meta/meta-source.js.map +1 -0
  215. package/dist/meta/meta-validator.d.ts +29 -0
  216. package/dist/meta/meta-validator.d.ts.map +1 -0
  217. package/dist/meta/meta-validator.js +49 -0
  218. package/dist/meta/meta-validator.js.map +1 -0
  219. package/dist/meta/meta-view.d.ts +4 -0
  220. package/dist/meta/meta-view.d.ts.map +1 -0
  221. package/dist/meta/meta-view.js +8 -0
  222. package/dist/meta/meta-view.js.map +1 -0
  223. package/dist/naming.d.ts +27 -0
  224. package/dist/naming.d.ts.map +1 -0
  225. package/dist/naming.js +72 -0
  226. package/dist/naming.js.map +1 -0
  227. package/dist/object-serializer.d.ts +10 -0
  228. package/dist/object-serializer.d.ts.map +1 -0
  229. package/dist/object-serializer.js +128 -0
  230. package/dist/object-serializer.js.map +1 -0
  231. package/dist/overlay.d.ts +2 -0
  232. package/dist/overlay.d.ts.map +1 -0
  233. package/dist/overlay.js +6 -0
  234. package/dist/overlay.js.map +1 -0
  235. package/dist/parser-core.d.ts +47 -0
  236. package/dist/parser-core.d.ts.map +1 -0
  237. package/dist/parser-core.js +516 -0
  238. package/dist/parser-core.js.map +1 -0
  239. package/dist/parser-json.d.ts +4 -0
  240. package/dist/parser-json.d.ts.map +1 -0
  241. package/dist/parser-json.js +19 -0
  242. package/dist/parser-json.js.map +1 -0
  243. package/dist/persistence/db/db-attr-schemas.d.ts +8 -0
  244. package/dist/persistence/db/db-attr-schemas.d.ts.map +1 -0
  245. package/dist/persistence/db/db-attr-schemas.js +28 -0
  246. package/dist/persistence/db/db-attr-schemas.js.map +1 -0
  247. package/dist/persistence/db/db-constants.d.ts +5 -0
  248. package/dist/persistence/db/db-constants.d.ts.map +1 -0
  249. package/dist/persistence/db/db-constants.js +6 -0
  250. package/dist/persistence/db/db-constants.js.map +1 -0
  251. package/dist/persistence/db/db-provider.d.ts +3 -0
  252. package/dist/persistence/db/db-provider.d.ts.map +1 -0
  253. package/dist/persistence/db/db-provider.js +29 -0
  254. package/dist/persistence/db/db-provider.js.map +1 -0
  255. package/dist/persistence/db/db-schema.d.ts +8 -0
  256. package/dist/persistence/db/db-schema.d.ts.map +1 -0
  257. package/dist/persistence/db/db-schema.js +27 -0
  258. package/dist/persistence/db/db-schema.js.map +1 -0
  259. package/dist/persistence/origin/meta-origin.d.ts +32 -0
  260. package/dist/persistence/origin/meta-origin.d.ts.map +1 -0
  261. package/dist/persistence/origin/meta-origin.js +55 -0
  262. package/dist/persistence/origin/meta-origin.js.map +1 -0
  263. package/dist/persistence/origin/origin-constants.d.ts +12 -0
  264. package/dist/persistence/origin/origin-constants.d.ts.map +1 -0
  265. package/dist/persistence/origin/origin-constants.js +27 -0
  266. package/dist/persistence/origin/origin-constants.js.map +1 -0
  267. package/dist/persistence/origin/origin-schema.d.ts +4 -0
  268. package/dist/persistence/origin/origin-schema.d.ts.map +1 -0
  269. package/dist/persistence/origin/origin-schema.js +49 -0
  270. package/dist/persistence/origin/origin-schema.js.map +1 -0
  271. package/dist/persistence/source/meta-source.d.ts +18 -0
  272. package/dist/persistence/source/meta-source.d.ts.map +1 -0
  273. package/dist/persistence/source/meta-source.js +31 -0
  274. package/dist/persistence/source/meta-source.js.map +1 -0
  275. package/dist/persistence/source/source-constants.d.ts +16 -0
  276. package/dist/persistence/source/source-constants.d.ts.map +1 -0
  277. package/dist/persistence/source/source-constants.js +28 -0
  278. package/dist/persistence/source/source-constants.js.map +1 -0
  279. package/dist/presentation/layout/layout-constants.d.ts +10 -0
  280. package/dist/presentation/layout/layout-constants.d.ts.map +1 -0
  281. package/dist/presentation/layout/layout-constants.js +21 -0
  282. package/dist/presentation/layout/layout-constants.js.map +1 -0
  283. package/dist/presentation/layout/layout-schema.d.ts +4 -0
  284. package/dist/presentation/layout/layout-schema.d.ts.map +1 -0
  285. package/dist/presentation/layout/layout-schema.js +46 -0
  286. package/dist/presentation/layout/layout-schema.js.map +1 -0
  287. package/dist/presentation/layout/meta-layout.d.ts +23 -0
  288. package/dist/presentation/layout/meta-layout.d.ts.map +1 -0
  289. package/dist/presentation/layout/meta-layout.js +47 -0
  290. package/dist/presentation/layout/meta-layout.js.map +1 -0
  291. package/dist/presentation/view/meta-view.d.ts +4 -0
  292. package/dist/presentation/view/meta-view.d.ts.map +1 -0
  293. package/dist/presentation/view/meta-view.js +8 -0
  294. package/dist/presentation/view/meta-view.js.map +1 -0
  295. package/dist/presentation/view/view-constants.d.ts +20 -0
  296. package/dist/presentation/view/view-constants.d.ts.map +1 -0
  297. package/dist/presentation/view/view-constants.js +47 -0
  298. package/dist/presentation/view/view-constants.js.map +1 -0
  299. package/dist/presentation/view/view-schema.d.ts +4 -0
  300. package/dist/presentation/view/view-schema.d.ts.map +1 -0
  301. package/dist/presentation/view/view-schema.js +15 -0
  302. package/dist/presentation/view/view-schema.js.map +1 -0
  303. package/dist/provider.d.ts +20 -0
  304. package/dist/provider.d.ts.map +1 -0
  305. package/dist/provider.js +58 -0
  306. package/dist/provider.js.map +1 -0
  307. package/dist/registry.d.ts +89 -0
  308. package/dist/registry.d.ts.map +1 -0
  309. package/dist/registry.js +107 -0
  310. package/dist/registry.js.map +1 -0
  311. package/dist/serializer-json.d.ts +16 -0
  312. package/dist/serializer-json.d.ts.map +1 -0
  313. package/dist/serializer-json.js +154 -0
  314. package/dist/serializer-json.js.map +1 -0
  315. package/dist/shared/base-types.d.ts +23 -0
  316. package/dist/shared/base-types.d.ts.map +1 -0
  317. package/dist/shared/base-types.js +43 -0
  318. package/dist/shared/base-types.js.map +1 -0
  319. package/dist/shared/meta-data.d.ts +123 -0
  320. package/dist/shared/meta-data.d.ts.map +1 -0
  321. package/dist/shared/meta-data.js +365 -0
  322. package/dist/shared/meta-data.js.map +1 -0
  323. package/dist/shared/meta-root.d.ts +12 -0
  324. package/dist/shared/meta-root.d.ts.map +1 -0
  325. package/dist/shared/meta-root.js +24 -0
  326. package/dist/shared/meta-root.js.map +1 -0
  327. package/dist/shared/structural.d.ts +20 -0
  328. package/dist/shared/structural.d.ts.map +1 -0
  329. package/dist/shared/structural.js +49 -0
  330. package/dist/shared/structural.js.map +1 -0
  331. package/dist/subtype-rules.d.ts +8 -0
  332. package/dist/subtype-rules.d.ts.map +1 -0
  333. package/dist/subtype-rules.js +34 -0
  334. package/dist/subtype-rules.js.map +1 -0
  335. package/dist/super-resolve.d.ts +34 -0
  336. package/dist/super-resolve.d.ts.map +1 -0
  337. package/dist/super-resolve.js +124 -0
  338. package/dist/super-resolve.js.map +1 -0
  339. package/package.json +50 -0
  340. package/src/attr-class-map.ts +64 -0
  341. package/src/attr-schema-validate.ts +134 -0
  342. package/src/core/attr/attr-constants.ts +31 -0
  343. package/src/core/attr/meta-attr-filter.ts +67 -0
  344. package/src/core/attr/meta-attr-properties.ts +26 -0
  345. package/src/core/attr/meta-attr-stringarray.ts +31 -0
  346. package/src/core/attr/meta-attr.ts +125 -0
  347. package/src/core/export-json.ts +66 -0
  348. package/src/core/field/field-constants.ts +79 -0
  349. package/src/core/field/field-schema.ts +121 -0
  350. package/src/core/field/meta-field.ts +179 -0
  351. package/src/core/file-meta-data-loader.ts +89 -0
  352. package/src/core/file-source.ts +52 -0
  353. package/src/core/identity/identity-constants.ts +44 -0
  354. package/src/core/identity/identity-schema.ts +80 -0
  355. package/src/core/identity/meta-identity.ts +148 -0
  356. package/src/core/index.ts +12 -0
  357. package/src/core/object/meta-object.ts +151 -0
  358. package/src/core/object/object-constants.ts +21 -0
  359. package/src/core/object/object-schema.ts +7 -0
  360. package/src/core/parser-yaml.ts +54 -0
  361. package/src/core/query/query-constants.ts +66 -0
  362. package/src/core/relationship/find-reference.ts +44 -0
  363. package/src/core/relationship/meta-relationship.ts +36 -0
  364. package/src/core/relationship/relationship-constants.ts +38 -0
  365. package/src/core/relationship/relationship-schema.ts +49 -0
  366. package/src/core/validator/meta-validator.ts +62 -0
  367. package/src/core/validator/validator-constants.ts +31 -0
  368. package/src/core/validator/validator-schema.ts +50 -0
  369. package/src/core/yaml-desugar.ts +145 -0
  370. package/src/core-types.ts +329 -0
  371. package/src/data-converter.ts +125 -0
  372. package/src/data-type.ts +33 -0
  373. package/src/errors.ts +68 -0
  374. package/src/index.ts +165 -0
  375. package/src/loader/meta-data-loader.ts +307 -0
  376. package/src/loader/meta-data-source.ts +35 -0
  377. package/src/loader/validation-passes.ts +370 -0
  378. package/src/naming.ts +86 -0
  379. package/src/object-serializer.ts +153 -0
  380. package/src/overlay.ts +5 -0
  381. package/src/parser-core.ts +815 -0
  382. package/src/parser-json.ts +28 -0
  383. package/src/persistence/db/db-constants.ts +6 -0
  384. package/src/persistence/db/db-provider.ts +36 -0
  385. package/src/persistence/db/db-schema.ts +40 -0
  386. package/src/persistence/origin/meta-origin.ts +67 -0
  387. package/src/persistence/origin/origin-constants.ts +35 -0
  388. package/src/persistence/origin/origin-schema.ts +66 -0
  389. package/src/persistence/source/meta-source.ts +38 -0
  390. package/src/persistence/source/source-constants.ts +35 -0
  391. package/src/presentation/layout/layout-constants.ts +27 -0
  392. package/src/presentation/layout/layout-schema.ts +62 -0
  393. package/src/presentation/layout/meta-layout.ts +61 -0
  394. package/src/presentation/view/meta-view.ts +8 -0
  395. package/src/presentation/view/view-constants.ts +53 -0
  396. package/src/presentation/view/view-schema.ts +21 -0
  397. package/src/provider.ts +85 -0
  398. package/src/registry.ts +190 -0
  399. package/src/serializer-json.ts +210 -0
  400. package/src/shared/base-types.ts +52 -0
  401. package/src/shared/meta-data.ts +443 -0
  402. package/src/shared/meta-root.ts +33 -0
  403. package/src/shared/structural.ts +62 -0
  404. package/src/subtype-rules.ts +56 -0
  405. package/src/super-resolve.ts +147 -0
@@ -0,0 +1,370 @@
1
+ // Stateless validation passes for the MetaDataLoader pipeline.
2
+ //
3
+ // Each function takes a fully-merged MetaData root and returns errors or
4
+ // warnings. No loader state is read or written — these are pure functions.
5
+ //
6
+ // Exported: validateDataGridSortFields, validateFilterableHasIndex,
7
+ // validateOriginPaths (called by MetaDataLoader.load() in order).
8
+ // Private: _findObject, _findField, _findRelationship,
9
+ // _validateFromPath, _validateViaPath (helpers, not exported).
10
+
11
+ import type { MetaData } from "../shared/meta-data.js";
12
+ import { ParseError } from "../errors.js";
13
+ import {
14
+ TYPE_OBJECT,
15
+ TYPE_FIELD,
16
+ TYPE_LAYOUT,
17
+ TYPE_IDENTITY,
18
+ TYPE_ORIGIN,
19
+ TYPE_RELATIONSHIP,
20
+ } from "../shared/base-types.js";
21
+ import {
22
+ LAYOUT_SUBTYPE_DATA_GRID,
23
+ LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_FIELD,
24
+ LAYOUT_DATA_GRID_ATTR_FILTER,
25
+ } from "../presentation/layout/layout-constants.js";
26
+ import {
27
+ FIELD_ATTR_FILTERABLE,
28
+ } from "../core/field/field-constants.js";
29
+ import { FIELD_ATTR_DB_INDEXED } from "../persistence/db/db-constants.js";
30
+ import { IDENTITY_ATTR_FIELDS } from "../core/identity/identity-constants.js";
31
+ import {
32
+ ORIGIN_SUBTYPE_PASSTHROUGH,
33
+ ORIGIN_SUBTYPE_AGGREGATE,
34
+ ORIGIN_PASSTHROUGH_ATTR_FROM,
35
+ ORIGIN_PASSTHROUGH_ATTR_VIA,
36
+ ORIGIN_AGGREGATE_ATTR_OF,
37
+ ORIGIN_AGGREGATE_ATTR_VIA,
38
+ } from "../persistence/origin/origin-constants.js";
39
+ import { RELATIONSHIP_ATTR_OBJECT_REF } from "../core/relationship/relationship-constants.js";
40
+ import {
41
+ FILTER_COMPOSE_OR,
42
+ FILTER_COMPOSE_AND,
43
+ opsForSubType,
44
+ } from "../core/query/query-constants.js";
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // Layout dataGrid @defaultSortField validation
48
+ // ---------------------------------------------------------------------------
49
+
50
+ export function validateDataGridSortFields(root: MetaData): ParseError[] {
51
+ const errors: ParseError[] = [];
52
+ for (const obj of root.ownChildren().filter((c) => c.type === TYPE_OBJECT)) {
53
+ // Use children() so inherited fields (via extends:/super:) are
54
+ // visible when validating @defaultSortField references.
55
+ const effective = obj.children();
56
+ const fieldNames = new Set(
57
+ effective.filter((c) => c.type === TYPE_FIELD).map((f) => f.name),
58
+ );
59
+ for (const layout of effective.filter((c) => c.type === TYPE_LAYOUT && c.subType === LAYOUT_SUBTYPE_DATA_GRID)) {
60
+ const sortField = layout.ownAttr(LAYOUT_DATA_GRID_ATTR_DEFAULT_SORT_FIELD);
61
+ if (typeof sortField === "string" && !fieldNames.has(sortField)) {
62
+ errors.push(
63
+ new ParseError(
64
+ `dataGrid layout "${layout.name}" on entity "${obj.name}" has @defaultSortField "${sortField}" ` +
65
+ `but no such field exists on "${obj.name}". Available fields: ${[...fieldNames].join(", ")}`,
66
+ { code: "ERR_BAD_DEFAULT_SORT_FIELD" },
67
+ ),
68
+ );
69
+ }
70
+ }
71
+ }
72
+ return errors;
73
+ }
74
+
75
+ // ---------------------------------------------------------------------------
76
+ // @filterable without index validation
77
+ // ---------------------------------------------------------------------------
78
+
79
+ export function validateFilterableHasIndex(root: MetaData): string[] {
80
+ const warnings: string[] = [];
81
+ for (const obj of root.ownChildren().filter((c) => c.type === TYPE_OBJECT)) {
82
+ // Use children() so inherited fields and identities (via extends:/super:)
83
+ // are included when checking filterable-without-index.
84
+ const effective = obj.children();
85
+ // Build the set of field names that are part of any identity on this object.
86
+ const indexedFieldNames = new Set<string>();
87
+ for (const identity of effective.filter((c) => c.type === TYPE_IDENTITY)) {
88
+ const fields = identity.ownAttr(IDENTITY_ATTR_FIELDS);
89
+ if (typeof fields === "string") {
90
+ for (const name of fields.split(",")) indexedFieldNames.add(name.trim());
91
+ } else if (Array.isArray(fields)) {
92
+ for (const name of fields) if (typeof name === "string") indexedFieldNames.add(name);
93
+ }
94
+ }
95
+
96
+ for (const field of effective.filter((c) => c.type === TYPE_FIELD)) {
97
+ const filterable = field.ownAttr(FIELD_ATTR_FILTERABLE);
98
+ if (filterable !== true) continue;
99
+ if (field.ownAttr(FIELD_ATTR_DB_INDEXED) === true) continue;
100
+ if (indexedFieldNames.has(field.name)) continue;
101
+ warnings.push(
102
+ `[filterable-without-index] field "${obj.name}.${field.name}" has @filterable: true but is not ` +
103
+ `part of any identity. Filtering on this field will sequential-scan. Add @db.indexed: true ` +
104
+ `to the field (when supported), or remove @filterable: true.`,
105
+ );
106
+ }
107
+ }
108
+ return warnings;
109
+ }
110
+
111
+ // ---------------------------------------------------------------------------
112
+ // Origin path validation
113
+ //
114
+ // Walks every projection's fields, finds `origin` (TYPE_ORIGIN) children,
115
+ // and validates:
116
+ // - passthrough.@from resolves to an existing entity + field
117
+ // - aggregate.@of resolves to an existing entity + field
118
+ // - .@via paths resolve through real relationships, hopping entity-by-entity
119
+ // using each relationship's @objectRef
120
+ //
121
+ // Note: @agg vocabulary is validated by validateAttrSchema (A3 pass) via
122
+ // allowedValues on the origin.aggregate @agg attr schema — not here.
123
+ // ---------------------------------------------------------------------------
124
+
125
+ function _findObject(root: MetaData, name: string): MetaData | undefined {
126
+ return root.ownChildren().find((c) => c.type === TYPE_OBJECT && c.name === name);
127
+ }
128
+
129
+ function _findField(obj: MetaData, name: string): MetaData | undefined {
130
+ // Use children() so inherited fields (via extends:/super:) are included.
131
+ return obj.children().find((c) => c.type === TYPE_FIELD && c.name === name);
132
+ }
133
+
134
+ function _findRelationship(obj: MetaData, name: string): MetaData | undefined {
135
+ // Use children() so inherited relationships (via extends:/super:) are included.
136
+ return obj.children().find((c) => c.type === TYPE_RELATIONSHIP && c.name === name);
137
+ }
138
+
139
+ function _validateFromPath(
140
+ fromAttr: string,
141
+ root: MetaData,
142
+ projectionName: string,
143
+ fieldName: string,
144
+ errors: ParseError[],
145
+ label: string = "origin.passthrough.@from",
146
+ ): void {
147
+ const dotIdx = fromAttr.indexOf(".");
148
+ if (dotIdx < 1 || dotIdx === fromAttr.length - 1) {
149
+ errors.push(
150
+ new ParseError(
151
+ `${label} "${fromAttr}" on ${projectionName}.${fieldName}: must be of form "Entity.field".`,
152
+ { code: "ERR_INVALID_ORIGIN" },
153
+ ),
154
+ );
155
+ return;
156
+ }
157
+ const entityName = fromAttr.slice(0, dotIdx);
158
+ const targetFieldName = fromAttr.slice(dotIdx + 1);
159
+ const sourceObj = _findObject(root, entityName);
160
+ if (!sourceObj) {
161
+ errors.push(
162
+ new ParseError(
163
+ `${label} "${fromAttr}" on ${projectionName}.${fieldName}: no such entity "${entityName}".`,
164
+ { code: "ERR_INVALID_ORIGIN" },
165
+ ),
166
+ );
167
+ return;
168
+ }
169
+ const sourceField = _findField(sourceObj, targetFieldName);
170
+ if (!sourceField) {
171
+ errors.push(
172
+ new ParseError(
173
+ `${label} "${fromAttr}" on ${projectionName}.${fieldName}: no such field "${targetFieldName}" on ${entityName}.`,
174
+ { code: "ERR_INVALID_ORIGIN" },
175
+ ),
176
+ );
177
+ }
178
+ }
179
+
180
+ function _validateViaPath(
181
+ viaAttr: string,
182
+ root: MetaData,
183
+ projectionName: string,
184
+ fieldName: string,
185
+ errors: ParseError[],
186
+ ): void {
187
+ const segments = viaAttr.split(".");
188
+ if (segments.length < 2) {
189
+ errors.push(
190
+ new ParseError(
191
+ `origin.@via "${viaAttr}" on ${projectionName}.${fieldName}: must be of form "Entity.relationship[.relationship...]".`,
192
+ { code: "ERR_INVALID_ORIGIN" },
193
+ ),
194
+ );
195
+ return;
196
+ }
197
+ const [entityName, ...relSegments] = segments as [string, ...string[]];
198
+ let currentObj = _findObject(root, entityName);
199
+ if (!currentObj) {
200
+ errors.push(
201
+ new ParseError(
202
+ `origin.@via "${viaAttr}" on ${projectionName}.${fieldName}: no such entity "${entityName}".`,
203
+ { code: "ERR_INVALID_ORIGIN" },
204
+ ),
205
+ );
206
+ return;
207
+ }
208
+ for (const relName of relSegments) {
209
+ const rel = _findRelationship(currentObj, relName);
210
+ if (!rel) {
211
+ errors.push(
212
+ new ParseError(
213
+ `origin.@via "${viaAttr}" on ${projectionName}.${fieldName}: no such relationship "${relName}" on ${currentObj.name}.`,
214
+ { code: "ERR_INVALID_ORIGIN" },
215
+ ),
216
+ );
217
+ return;
218
+ }
219
+ const refTarget = rel.ownAttr(RELATIONSHIP_ATTR_OBJECT_REF);
220
+ if (typeof refTarget !== "string" || refTarget === "") {
221
+ errors.push(
222
+ new ParseError(
223
+ `origin.@via "${viaAttr}" on ${projectionName}.${fieldName}: relationship "${relName}" on ${currentObj.name} is missing @objectRef.`,
224
+ { code: "ERR_INVALID_ORIGIN" },
225
+ ),
226
+ );
227
+ return;
228
+ }
229
+ const nextObj = _findObject(root, refTarget);
230
+ if (!nextObj) {
231
+ errors.push(
232
+ new ParseError(
233
+ `origin.@via "${viaAttr}" on ${projectionName}.${fieldName}: relationship "${relName}" points to non-existent entity "${refTarget}".`,
234
+ { code: "ERR_INVALID_ORIGIN" },
235
+ ),
236
+ );
237
+ return;
238
+ }
239
+ currentObj = nextObj;
240
+ }
241
+ }
242
+
243
+ export function validateOriginPaths(root: MetaData): ParseError[] {
244
+ const errors: ParseError[] = [];
245
+ for (const obj of root.ownChildren().filter((c) => c.type === TYPE_OBJECT)) {
246
+ for (const field of obj.ownChildren().filter((c) => c.type === TYPE_FIELD)) {
247
+ for (const origin of field.ownChildren().filter((c) => c.type === TYPE_ORIGIN)) {
248
+ if (origin.subType === ORIGIN_SUBTYPE_PASSTHROUGH) {
249
+ const from = origin.ownAttr(ORIGIN_PASSTHROUGH_ATTR_FROM);
250
+ if (typeof from !== "string" || from === "") {
251
+ errors.push(
252
+ new ParseError(
253
+ `origin.passthrough on ${obj.name}.${field.name}: missing @from.`,
254
+ { code: "ERR_INVALID_ORIGIN" },
255
+ ),
256
+ );
257
+ continue;
258
+ }
259
+ _validateFromPath(from, root, obj.name, field.name, errors);
260
+ const via = origin.ownAttr(ORIGIN_PASSTHROUGH_ATTR_VIA);
261
+ if (typeof via === "string" && via !== "") {
262
+ _validateViaPath(via, root, obj.name, field.name, errors);
263
+ }
264
+ } else if (origin.subType === ORIGIN_SUBTYPE_AGGREGATE) {
265
+ const of_ = origin.ownAttr(ORIGIN_AGGREGATE_ATTR_OF);
266
+ if (typeof of_ !== "string" || of_ === "") {
267
+ errors.push(
268
+ new ParseError(
269
+ `origin.aggregate on ${obj.name}.${field.name}: missing @of.`,
270
+ { code: "ERR_INVALID_ORIGIN" },
271
+ ),
272
+ );
273
+ continue;
274
+ }
275
+ _validateFromPath(of_, root, obj.name, field.name, errors, "origin.aggregate.@of");
276
+ const via = origin.ownAttr(ORIGIN_AGGREGATE_ATTR_VIA);
277
+ if (typeof via !== "string" || via === "") {
278
+ errors.push(
279
+ new ParseError(
280
+ `origin.aggregate on ${obj.name}.${field.name}: missing @via (aggregates require a relationship path).`,
281
+ { code: "ERR_INVALID_ORIGIN" },
282
+ ),
283
+ );
284
+ continue;
285
+ }
286
+ _validateViaPath(via, root, obj.name, field.name, errors);
287
+ }
288
+ }
289
+ }
290
+ }
291
+ return errors;
292
+ }
293
+
294
+ // ---------------------------------------------------------------------------
295
+ // Layout dataGrid @filter value validation
296
+ //
297
+ // Runs after extends: resolution (so inherited @filterable fields are visible)
298
+ // and after parse-time desugaring (so every clause is canonical { op: value }).
299
+ // Builds the allowlist from @filterable fields using OPS_BY_SUBTYPE, then checks
300
+ // every filtered field is filterable and every op is allowed for its subtype.
301
+ // ---------------------------------------------------------------------------
302
+
303
+ export function validateDataGridFilterValues(root: MetaData): ParseError[] {
304
+ const errors: ParseError[] = [];
305
+ for (const obj of root.ownChildren().filter((c) => c.type === TYPE_OBJECT)) {
306
+ const effective = obj.children();
307
+ const allow = new Map<string, readonly string[]>();
308
+ for (const f of effective.filter((c) => c.type === TYPE_FIELD)) {
309
+ if (f.ownAttr(FIELD_ATTR_FILTERABLE) === true) {
310
+ allow.set(f.name, opsForSubType(f.subType));
311
+ }
312
+ }
313
+ for (const layout of effective.filter(
314
+ (c) => c.type === TYPE_LAYOUT && c.subType === LAYOUT_SUBTYPE_DATA_GRID,
315
+ )) {
316
+ const filter = layout.ownAttr(LAYOUT_DATA_GRID_ATTR_FILTER);
317
+ // Type errors (e.g. legacy string form) are reported by validateAttrSchema.
318
+ if (typeof filter !== "object" || filter === null || Array.isArray(filter)) continue;
319
+ checkFilterClauses(filter as Record<string, unknown>, allow, obj.name, layout.name, errors);
320
+ }
321
+ }
322
+ return errors;
323
+ }
324
+
325
+ function checkFilterClauses(
326
+ filter: Record<string, unknown>,
327
+ allow: Map<string, readonly string[]>,
328
+ entityName: string,
329
+ layoutName: string,
330
+ errors: ParseError[],
331
+ ): void {
332
+ for (const [key, clause] of Object.entries(filter)) {
333
+ if (key === FILTER_COMPOSE_OR || key === FILTER_COMPOSE_AND) {
334
+ if (Array.isArray(clause)) {
335
+ for (const sub of clause) {
336
+ if (typeof sub === "object" && sub !== null && !Array.isArray(sub)) {
337
+ checkFilterClauses(sub as Record<string, unknown>, allow, entityName, layoutName, errors);
338
+ }
339
+ }
340
+ }
341
+ continue;
342
+ }
343
+ const allowedOps = allow.get(key);
344
+ if (allowedOps === undefined) {
345
+ errors.push(
346
+ new ParseError(
347
+ `dataGrid layout "${layoutName}" on entity "${entityName}" has @filter over ` +
348
+ `non-filterable field "${key}". Filterable fields: ${[...allow.keys()].join(", ") || "(none)"}`,
349
+ { code: "ERR_BAD_ATTR_FILTER" },
350
+ ),
351
+ );
352
+ continue;
353
+ }
354
+ // After parse-time desugaring (FilterAttr.desugar), every non-composition field clause
355
+ // is canonical { op: value } — a bare scalar should not reach here; the object guard is defensive.
356
+ if (typeof clause === "object" && clause !== null && !Array.isArray(clause)) {
357
+ for (const op of Object.keys(clause)) {
358
+ if (!allowedOps.includes(op)) {
359
+ errors.push(
360
+ new ParseError(
361
+ `dataGrid layout "${layoutName}" on entity "${entityName}" @filter uses disallowed ` +
362
+ `op "${key}.${op}". Allowed ops for "${key}": ${allowedOps.join(", ")}`,
363
+ { code: "ERR_BAD_ATTR_FILTER" },
364
+ ),
365
+ );
366
+ }
367
+ }
368
+ }
369
+ }
370
+ }
package/src/naming.ts ADDED
@@ -0,0 +1,86 @@
1
+ import type { MetaData } from "./shared/meta-data.js";
2
+ import { TYPE_FIELD, TYPE_SOURCE } from "./shared/base-types.js";
3
+ import { PACKAGE_SEPARATOR } from "./shared/structural.js";
4
+ import { FIELD_ATTR_DB_COLUMN } from "./persistence/db/db-constants.js";
5
+ import {
6
+ SOURCE_SUBTYPE_DB_TABLE,
7
+ SOURCE_SUBTYPE_DB_VIEW,
8
+ SOURCE_DB_TABLE_ATTR_NAME,
9
+ SOURCE_ATTR_SCHEMA,
10
+ } from "./persistence/source/source-constants.js";
11
+
12
+ /**
13
+ * Strip the package prefix from a metadata-qualified name
14
+ * (e.g. "pkg::Name" → "Name"). Returns the input unchanged if no
15
+ * package separator is present. Single canonical helper consumed by
16
+ * both find-reference (cross-entity lookup) and codegen-ts (FQN
17
+ * normalization in generated code).
18
+ */
19
+ export function stripPackage(name: string | undefined): string {
20
+ if (!name) return "";
21
+ const idx = name.lastIndexOf(PACKAGE_SEPARATOR);
22
+ return idx === -1 ? name : name.slice(idx + PACKAGE_SEPARATOR.length);
23
+ }
24
+
25
+ export function toSnakeCase(s: string): string {
26
+ return s
27
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
28
+ .replace(/([a-z0-9])([A-Z])/g, "$1_$2")
29
+ .toLowerCase();
30
+ }
31
+
32
+ export function pluralize(s: string): string {
33
+ if (/(s|x|z|ch|sh)$/i.test(s)) return s + "es";
34
+ if (/[^aeiou]y$/i.test(s)) return s.slice(0, -1) + "ies";
35
+ return s + "s";
36
+ }
37
+
38
+ export function resolveTableName(entity: MetaData): string {
39
+ const source = entity.ownChildren().find(
40
+ (c) => c.type === TYPE_SOURCE && c.subType === SOURCE_SUBTYPE_DB_TABLE,
41
+ );
42
+ const name = source?.ownAttr(SOURCE_DB_TABLE_ATTR_NAME);
43
+ if (typeof name === "string" && name !== "") return name;
44
+ return pluralize(toSnakeCase(entity.name));
45
+ }
46
+
47
+ export function resolveColumnName(field: MetaData): string {
48
+ const attr = field.ownAttr(FIELD_ATTR_DB_COLUMN);
49
+ if (typeof attr === "string") return attr;
50
+ return toSnakeCase(field.name);
51
+ }
52
+
53
+ /**
54
+ * Returns the DB schema declared on an entity's source[dbTable] or source[dbView] child,
55
+ * or undefined if no @schema attr is set or no source child exists. Callers decide what
56
+ * "undefined" means for their dialect — Postgres treats it as the default public schema,
57
+ * SQLite treats it as the only allowed value (no schema concept).
58
+ */
59
+ export function resolveTableSchema(entity: MetaData): string | undefined {
60
+ const source = entity.ownChildren().find(
61
+ (c) => c.type === TYPE_SOURCE
62
+ && (c.subType === SOURCE_SUBTYPE_DB_TABLE || c.subType === SOURCE_SUBTYPE_DB_VIEW),
63
+ );
64
+ if (!source) return undefined;
65
+ const schema = source.ownAttr(SOURCE_ATTR_SCHEMA);
66
+ if (typeof schema === "string" && schema !== "") return schema;
67
+ return undefined;
68
+ }
69
+
70
+ /** Per-entity {jsName ↔ dbColumn} map. Built once per entity to avoid re-walking children on every row. */
71
+ export interface EntityNameMap {
72
+ jsToDb: Map<string, string>;
73
+ dbToJs: Map<string, string>;
74
+ }
75
+
76
+ export function buildNameMap(entity: MetaData): EntityNameMap {
77
+ const jsToDb = new Map<string, string>();
78
+ const dbToJs = new Map<string, string>();
79
+ for (const child of entity.ownChildren()) {
80
+ if (child.type !== TYPE_FIELD) continue;
81
+ const dbCol = resolveColumnName(child);
82
+ jsToDb.set(child.name, dbCol);
83
+ dbToJs.set(dbCol, child.name);
84
+ }
85
+ return { jsToDb, dbToJs };
86
+ }
@@ -0,0 +1,153 @@
1
+ // Metadata-driven object serializer.
2
+ //
3
+ // objectToJson / jsonToObject convert application-object instances <-> JSON
4
+ // driven by a MetaObject's field metadata — no per-entity code. Dispatch is on
5
+ // each field's DataType. Plain objects in, plain objects out (the caller does
6
+ // JSON.parse / JSON.stringify). Best-effort and total: neither function throws
7
+ // for malformed instance data, and there is no validation (settled in the
8
+ // spec — Java's object reader does not validate either).
9
+
10
+ import type { MetaData } from "./shared/meta-data.js";
11
+ import type { MetaObject } from "./core/object/meta-object.js";
12
+ import type { MetaField } from "./core/field/meta-field.js";
13
+ import {
14
+ DATA_TYPE_BOOLEAN,
15
+ DATA_TYPE_INT,
16
+ DATA_TYPE_LONG,
17
+ DATA_TYPE_DOUBLE,
18
+ DATA_TYPE_STRING,
19
+ DATA_TYPE_DATE,
20
+ DATA_TYPE_OBJECT,
21
+ } from "./data-type.js";
22
+ import { TYPE_OBJECT } from "./shared/base-types.js";
23
+
24
+ const TYPE_DISCRIMINATOR = "@type";
25
+
26
+ export interface ObjectSerializeOptions {
27
+ /** Emit the `@type` discriminator property. Default true. */
28
+ emitType?: boolean;
29
+ }
30
+
31
+ /** Serialize an application-object instance to wire JSON, driven by `mo`. */
32
+ export function objectToJson(
33
+ mo: MetaObject,
34
+ instance: Record<string, unknown>,
35
+ opts?: ObjectSerializeOptions,
36
+ ): Record<string, unknown> {
37
+ const out: Record<string, unknown> = {};
38
+ if (opts?.emitType ?? true) {
39
+ out[TYPE_DISCRIMINATOR] = mo.name;
40
+ }
41
+ for (const field of mo.fields()) {
42
+ const raw = instance[field.name];
43
+ if (raw === undefined) continue; // absent field → omit
44
+ out[field.name] = field.isArray
45
+ ? mapArray(raw, (el) => toJsonValue(field, el, mo))
46
+ : toJsonValue(field, raw, mo);
47
+ }
48
+ return out;
49
+ }
50
+
51
+ /** Parse wire JSON into an application-object instance, driven by `mo`. */
52
+ export function jsonToObject(
53
+ mo: MetaObject,
54
+ json: Record<string, unknown>,
55
+ ): Record<string, unknown> {
56
+ const out: Record<string, unknown> = {};
57
+ for (const field of mo.fields()) {
58
+ const raw = json[field.name];
59
+ if (raw === undefined) continue;
60
+ out[field.name] = field.isArray
61
+ ? mapArray(raw, (el) => fromJsonValue(field, el, mo))
62
+ : fromJsonValue(field, raw, mo);
63
+ }
64
+ return out;
65
+ }
66
+
67
+ // --- write-side conversion -------------------------------------------------
68
+
69
+ function toJsonValue(field: MetaField, raw: unknown, mo: MetaObject): unknown {
70
+ switch (field.dataType) {
71
+ case DATA_TYPE_DATE:
72
+ return toIsoString(raw);
73
+ case DATA_TYPE_OBJECT: {
74
+ const target = resolveObjectRef(field, mo);
75
+ if (target === undefined || !isPlainObject(raw)) return raw;
76
+ // Nested objects always carry their own @type (a generic reader needs
77
+ // it); `emitType: false` suppresses only the top-level discriminator.
78
+ return objectToJson(target, raw);
79
+ }
80
+ case DATA_TYPE_BOOLEAN:
81
+ case DATA_TYPE_INT:
82
+ case DATA_TYPE_LONG:
83
+ case DATA_TYPE_DOUBLE:
84
+ case DATA_TYPE_STRING:
85
+ default:
86
+ return raw; // scalars: already JSON-native, pass through
87
+ }
88
+ }
89
+
90
+ // --- read-side conversion --------------------------------------------------
91
+
92
+ function fromJsonValue(field: MetaField, raw: unknown, mo: MetaObject): unknown {
93
+ switch (field.dataType) {
94
+ case DATA_TYPE_BOOLEAN:
95
+ return coerceBoolean(raw);
96
+ case DATA_TYPE_INT:
97
+ case DATA_TYPE_LONG:
98
+ case DATA_TYPE_DOUBLE:
99
+ return coerceNumeric(raw);
100
+ case DATA_TYPE_OBJECT: {
101
+ const target = resolveObjectRef(field, mo);
102
+ if (target === undefined || !isPlainObject(raw)) return raw;
103
+ return jsonToObject(target, raw);
104
+ }
105
+ case DATA_TYPE_STRING:
106
+ case DATA_TYPE_DATE: // kept as the ISO string; the UI builds its own Date
107
+ default:
108
+ return raw;
109
+ }
110
+ }
111
+
112
+ // --- helpers ---------------------------------------------------------------
113
+
114
+ function mapArray(raw: unknown, convert: (el: unknown) => unknown): unknown {
115
+ return Array.isArray(raw) ? raw.map(convert) : raw;
116
+ }
117
+
118
+ function isPlainObject(v: unknown): v is Record<string, unknown> {
119
+ return typeof v === "object" && v !== null && !Array.isArray(v);
120
+ }
121
+
122
+ function toIsoString(raw: unknown): unknown {
123
+ if (raw instanceof Date) return raw.toISOString();
124
+ if (typeof raw === "number") return new Date(raw).toISOString();
125
+ return raw; // a string passes through; anything else best-effort
126
+ }
127
+
128
+ function coerceBoolean(raw: unknown): unknown {
129
+ if (typeof raw === "boolean") return raw;
130
+ if (raw === "true") return true;
131
+ if (raw === "false") return false;
132
+ return raw;
133
+ }
134
+
135
+ function coerceNumeric(raw: unknown): unknown {
136
+ if (typeof raw === "number") return raw;
137
+ if (typeof raw === "string" && raw.trim() !== "" && Number.isFinite(Number(raw))) {
138
+ return Number(raw);
139
+ }
140
+ return raw;
141
+ }
142
+
143
+ /** Resolve an object-typed field's `@objectRef` to its target MetaObject by
144
+ * walking to the tree root and looking up the named object child. Returns
145
+ * undefined when there is no ref or it does not resolve (caller passes the
146
+ * raw value through — best-effort). */
147
+ function resolveObjectRef(field: MetaField, mo: MetaObject): MetaObject | undefined {
148
+ const ref = field.objectRef;
149
+ if (ref === undefined) return undefined;
150
+ const found: MetaData | undefined = mo.root().ownChildByTypeAndName(TYPE_OBJECT, ref);
151
+ if (found === undefined) return undefined;
152
+ return found as MetaObject;
153
+ }
package/src/overlay.ts ADDED
@@ -0,0 +1,5 @@
1
+ // overlay.ts — empty module.
2
+ //
3
+ // Merging happens during parse via the parser's accumRoot + createOrFindMetaData
4
+ // logic. See parser-json.ts and the per-node isMerge flag on MetaData.
5
+ export {};