@carlonicora/nextjs-jsonapi 1.2.0 → 1.3.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 (272) hide show
  1. package/dist/{BlockNoteEditor-CNXQ3WL3.js → BlockNoteEditor-7WYPN34K.js} +17 -17
  2. package/dist/{BlockNoteEditor-CNXQ3WL3.js.map → BlockNoteEditor-7WYPN34K.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-DC33K4IF.mjs → BlockNoteEditor-V625C23O.mjs} +7 -7
  4. package/dist/{JsonApiRequest-O7BGUMFO.mjs → JsonApiRequest-6UR7DIAR.mjs} +4 -2
  5. package/dist/JsonApiRequest-UJ7FGIVI.js +25 -0
  6. package/dist/JsonApiRequest-UJ7FGIVI.js.map +1 -0
  7. package/dist/{chunk-EZK3H6EJ.js → chunk-5IET37O4.js} +206 -206
  8. package/dist/{chunk-EZK3H6EJ.js.map → chunk-5IET37O4.js.map} +1 -1
  9. package/dist/{chunk-Y4XI3AZR.mjs → chunk-5QC7A6BL.mjs} +32 -20
  10. package/dist/chunk-5QC7A6BL.mjs.map +1 -0
  11. package/dist/{chunk-LJRD4SRV.js → chunk-DEYKTLA3.js} +6 -6
  12. package/dist/{chunk-LJRD4SRV.js.map → chunk-DEYKTLA3.js.map} +1 -1
  13. package/dist/{chunk-NPPQNSXN.mjs → chunk-FMBQZAIP.mjs} +3 -3
  14. package/dist/{chunk-MHVXFWZY.mjs → chunk-HTLEKZND.mjs} +3 -3
  15. package/dist/{chunk-74F6BBHH.mjs → chunk-IKBA4AHN.mjs} +2 -1
  16. package/dist/chunk-IKBA4AHN.mjs.map +1 -0
  17. package/dist/{chunk-JLN6UWII.mjs → chunk-JGFWIT2E.mjs} +2 -2
  18. package/dist/{chunk-KDFDGXCX.js → chunk-K2ANOT66.js} +576 -564
  19. package/dist/chunk-K2ANOT66.js.map +1 -0
  20. package/dist/{chunk-X53MF5ZN.mjs → chunk-P2F54I7Q.mjs} +2 -2
  21. package/dist/{chunk-5ZEADNNP.js → chunk-PMXG5WBC.js} +3 -2
  22. package/dist/chunk-PMXG5WBC.js.map +1 -0
  23. package/dist/{chunk-L6LH7WA4.js → chunk-PO5Q3H5I.js} +190 -190
  24. package/dist/{chunk-L6LH7WA4.js.map → chunk-PO5Q3H5I.js.map} +1 -1
  25. package/dist/{chunk-WZJDLITG.js → chunk-Q4FXESVT.js} +3 -3
  26. package/dist/{chunk-WZJDLITG.js.map → chunk-Q4FXESVT.js.map} +1 -1
  27. package/dist/client/index.js +7 -7
  28. package/dist/client/index.mjs +6 -6
  29. package/dist/components/index.js +7 -7
  30. package/dist/components/index.mjs +6 -6
  31. package/dist/contexts/index.js +7 -7
  32. package/dist/contexts/index.mjs +6 -6
  33. package/dist/core/index.js +2 -2
  34. package/dist/core/index.mjs +1 -1
  35. package/dist/features/index.js +4 -4
  36. package/dist/features/index.mjs +3 -3
  37. package/dist/hooks/index.js +7 -7
  38. package/dist/hooks/index.mjs +6 -6
  39. package/dist/index.d.mts +2 -1
  40. package/dist/index.d.ts +2 -1
  41. package/dist/index.js +5 -3
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +4 -2
  44. package/dist/scripts/generate-web-module/generator.d.ts +15 -0
  45. package/dist/scripts/generate-web-module/generator.d.ts.map +1 -0
  46. package/dist/scripts/generate-web-module/generator.js +320 -0
  47. package/dist/scripts/generate-web-module/generator.js.map +1 -0
  48. package/dist/scripts/generate-web-module/index.d.ts +16 -0
  49. package/dist/scripts/generate-web-module/index.d.ts.map +1 -0
  50. package/dist/scripts/generate-web-module/index.js +80 -0
  51. package/dist/scripts/generate-web-module/index.js.map +1 -0
  52. package/dist/scripts/generate-web-module/templates/components/container.template.d.ts +14 -0
  53. package/dist/scripts/generate-web-module/templates/components/container.template.d.ts.map +1 -0
  54. package/dist/scripts/generate-web-module/templates/components/container.template.js +124 -0
  55. package/dist/scripts/generate-web-module/templates/components/container.template.js.map +1 -0
  56. package/dist/scripts/generate-web-module/templates/components/content.template.d.ts +15 -0
  57. package/dist/scripts/generate-web-module/templates/components/content.template.d.ts.map +1 -0
  58. package/dist/scripts/generate-web-module/templates/components/content.template.js +39 -0
  59. package/dist/scripts/generate-web-module/templates/components/content.template.js.map +1 -0
  60. package/dist/scripts/generate-web-module/templates/components/deleter.template.d.ts +14 -0
  61. package/dist/scripts/generate-web-module/templates/components/deleter.template.d.ts.map +1 -0
  62. package/dist/scripts/generate-web-module/templates/components/deleter.template.js +51 -0
  63. package/dist/scripts/generate-web-module/templates/components/deleter.template.js.map +1 -0
  64. package/dist/scripts/generate-web-module/templates/components/details.template.d.ts +14 -0
  65. package/dist/scripts/generate-web-module/templates/components/details.template.d.ts.map +1 -0
  66. package/dist/scripts/generate-web-module/templates/components/details.template.js +109 -0
  67. package/dist/scripts/generate-web-module/templates/components/details.template.js.map +1 -0
  68. package/dist/scripts/generate-web-module/templates/components/editor.template.d.ts +14 -0
  69. package/dist/scripts/generate-web-module/templates/components/editor.template.d.ts.map +1 -0
  70. package/dist/scripts/generate-web-module/templates/components/editor.template.js +459 -0
  71. package/dist/scripts/generate-web-module/templates/components/editor.template.js.map +1 -0
  72. package/dist/scripts/generate-web-module/templates/components/index.d.ts +15 -0
  73. package/dist/scripts/generate-web-module/templates/components/index.d.ts.map +1 -0
  74. package/dist/scripts/generate-web-module/templates/components/index.js +29 -0
  75. package/dist/scripts/generate-web-module/templates/components/index.js.map +1 -0
  76. package/dist/scripts/generate-web-module/templates/components/list-container.template.d.ts +14 -0
  77. package/dist/scripts/generate-web-module/templates/components/list-container.template.d.ts.map +1 -0
  78. package/dist/scripts/generate-web-module/templates/components/list-container.template.js +30 -0
  79. package/dist/scripts/generate-web-module/templates/components/list-container.template.js.map +1 -0
  80. package/dist/scripts/generate-web-module/templates/components/list.template.d.ts +14 -0
  81. package/dist/scripts/generate-web-module/templates/components/list.template.d.ts.map +1 -0
  82. package/dist/scripts/generate-web-module/templates/components/list.template.js +84 -0
  83. package/dist/scripts/generate-web-module/templates/components/list.template.js.map +1 -0
  84. package/dist/scripts/generate-web-module/templates/components/multi-selector.template.d.ts +14 -0
  85. package/dist/scripts/generate-web-module/templates/components/multi-selector.template.d.ts.map +1 -0
  86. package/dist/scripts/generate-web-module/templates/components/multi-selector.template.js +184 -0
  87. package/dist/scripts/generate-web-module/templates/components/multi-selector.template.js.map +1 -0
  88. package/dist/scripts/generate-web-module/templates/components/selector.template.d.ts +14 -0
  89. package/dist/scripts/generate-web-module/templates/components/selector.template.d.ts.map +1 -0
  90. package/dist/scripts/generate-web-module/templates/components/selector.template.js +199 -0
  91. package/dist/scripts/generate-web-module/templates/components/selector.template.js.map +1 -0
  92. package/dist/scripts/generate-web-module/templates/context.template.d.ts +14 -0
  93. package/dist/scripts/generate-web-module/templates/context.template.d.ts.map +1 -0
  94. package/dist/scripts/generate-web-module/templates/context.template.js +121 -0
  95. package/dist/scripts/generate-web-module/templates/context.template.js.map +1 -0
  96. package/dist/scripts/generate-web-module/templates/data/fields.template.d.ts +14 -0
  97. package/dist/scripts/generate-web-module/templates/data/fields.template.d.ts.map +1 -0
  98. package/dist/scripts/generate-web-module/templates/data/fields.template.js +55 -0
  99. package/dist/scripts/generate-web-module/templates/data/fields.template.js.map +1 -0
  100. package/dist/scripts/generate-web-module/templates/data/index.d.ts +10 -0
  101. package/dist/scripts/generate-web-module/templates/data/index.d.ts.map +1 -0
  102. package/dist/scripts/generate-web-module/templates/data/index.js +26 -0
  103. package/dist/scripts/generate-web-module/templates/data/index.js.map +1 -0
  104. package/dist/scripts/generate-web-module/templates/data/interface.template.d.ts +14 -0
  105. package/dist/scripts/generate-web-module/templates/data/interface.template.d.ts.map +1 -0
  106. package/dist/scripts/generate-web-module/templates/data/interface.template.js +116 -0
  107. package/dist/scripts/generate-web-module/templates/data/interface.template.js.map +1 -0
  108. package/dist/scripts/generate-web-module/templates/data/model.template.d.ts +14 -0
  109. package/dist/scripts/generate-web-module/templates/data/model.template.d.ts.map +1 -0
  110. package/dist/scripts/generate-web-module/templates/data/model.template.js +274 -0
  111. package/dist/scripts/generate-web-module/templates/data/model.template.js.map +1 -0
  112. package/dist/scripts/generate-web-module/templates/data/service.template.d.ts +14 -0
  113. package/dist/scripts/generate-web-module/templates/data/service.template.d.ts.map +1 -0
  114. package/dist/scripts/generate-web-module/templates/data/service.template.js +168 -0
  115. package/dist/scripts/generate-web-module/templates/data/service.template.js.map +1 -0
  116. package/dist/scripts/generate-web-module/templates/index.d.ts +12 -0
  117. package/dist/scripts/generate-web-module/templates/index.d.ts.map +1 -0
  118. package/dist/scripts/generate-web-module/templates/index.js +37 -0
  119. package/dist/scripts/generate-web-module/templates/index.js.map +1 -0
  120. package/dist/scripts/generate-web-module/templates/module.template.d.ts +14 -0
  121. package/dist/scripts/generate-web-module/templates/module.template.d.ts.map +1 -0
  122. package/dist/scripts/generate-web-module/templates/module.template.js +64 -0
  123. package/dist/scripts/generate-web-module/templates/module.template.js.map +1 -0
  124. package/dist/scripts/generate-web-module/templates/pages/detail-page.template.d.ts +14 -0
  125. package/dist/scripts/generate-web-module/templates/pages/detail-page.template.d.ts.map +1 -0
  126. package/dist/scripts/generate-web-module/templates/pages/detail-page.template.js +65 -0
  127. package/dist/scripts/generate-web-module/templates/pages/detail-page.template.js.map +1 -0
  128. package/dist/scripts/generate-web-module/templates/pages/index.d.ts +8 -0
  129. package/dist/scripts/generate-web-module/templates/pages/index.d.ts.map +1 -0
  130. package/dist/scripts/generate-web-module/templates/pages/index.js +13 -0
  131. package/dist/scripts/generate-web-module/templates/pages/index.js.map +1 -0
  132. package/dist/scripts/generate-web-module/templates/pages/list-page.template.d.ts +14 -0
  133. package/dist/scripts/generate-web-module/templates/pages/list-page.template.d.ts.map +1 -0
  134. package/dist/scripts/generate-web-module/templates/pages/list-page.template.js +37 -0
  135. package/dist/scripts/generate-web-module/templates/pages/list-page.template.js.map +1 -0
  136. package/dist/scripts/generate-web-module/templates/table-hook.template.d.ts +14 -0
  137. package/dist/scripts/generate-web-module/templates/table-hook.template.d.ts.map +1 -0
  138. package/dist/scripts/generate-web-module/templates/table-hook.template.js +174 -0
  139. package/dist/scripts/generate-web-module/templates/table-hook.template.js.map +1 -0
  140. package/dist/scripts/generate-web-module/transformers/field-mapper.d.ts +55 -0
  141. package/dist/scripts/generate-web-module/transformers/field-mapper.d.ts.map +1 -0
  142. package/dist/scripts/generate-web-module/transformers/field-mapper.js +179 -0
  143. package/dist/scripts/generate-web-module/transformers/field-mapper.js.map +1 -0
  144. package/dist/scripts/generate-web-module/transformers/i18n-generator.d.ts +78 -0
  145. package/dist/scripts/generate-web-module/transformers/i18n-generator.d.ts.map +1 -0
  146. package/dist/scripts/generate-web-module/transformers/i18n-generator.js +182 -0
  147. package/dist/scripts/generate-web-module/transformers/i18n-generator.js.map +1 -0
  148. package/dist/scripts/generate-web-module/transformers/import-resolver.d.ts +106 -0
  149. package/dist/scripts/generate-web-module/transformers/import-resolver.d.ts.map +1 -0
  150. package/dist/scripts/generate-web-module/transformers/import-resolver.js +193 -0
  151. package/dist/scripts/generate-web-module/transformers/import-resolver.js.map +1 -0
  152. package/dist/scripts/generate-web-module/transformers/index.d.ts +12 -0
  153. package/dist/scripts/generate-web-module/transformers/index.d.ts.map +1 -0
  154. package/dist/scripts/generate-web-module/transformers/index.js +28 -0
  155. package/dist/scripts/generate-web-module/transformers/index.js.map +1 -0
  156. package/dist/scripts/generate-web-module/transformers/name-transformer.d.ts +60 -0
  157. package/dist/scripts/generate-web-module/transformers/name-transformer.d.ts.map +1 -0
  158. package/dist/scripts/generate-web-module/transformers/name-transformer.js +115 -0
  159. package/dist/scripts/generate-web-module/transformers/name-transformer.js.map +1 -0
  160. package/dist/scripts/generate-web-module/transformers/parent-detector.d.ts +57 -0
  161. package/dist/scripts/generate-web-module/transformers/parent-detector.d.ts.map +1 -0
  162. package/dist/scripts/generate-web-module/transformers/parent-detector.js +88 -0
  163. package/dist/scripts/generate-web-module/transformers/parent-detector.js.map +1 -0
  164. package/dist/scripts/generate-web-module/transformers/relationship-resolver.d.ts +68 -0
  165. package/dist/scripts/generate-web-module/transformers/relationship-resolver.d.ts.map +1 -0
  166. package/dist/scripts/generate-web-module/transformers/relationship-resolver.js +219 -0
  167. package/dist/scripts/generate-web-module/transformers/relationship-resolver.js.map +1 -0
  168. package/dist/scripts/generate-web-module/types/field-mapping.types.d.ts +68 -0
  169. package/dist/scripts/generate-web-module/types/field-mapping.types.d.ts.map +1 -0
  170. package/dist/scripts/generate-web-module/types/field-mapping.types.js +129 -0
  171. package/dist/scripts/generate-web-module/types/field-mapping.types.js.map +1 -0
  172. package/dist/scripts/generate-web-module/types/index.d.ts +9 -0
  173. package/dist/scripts/generate-web-module/types/index.d.ts.map +1 -0
  174. package/dist/scripts/generate-web-module/types/index.js +25 -0
  175. package/dist/scripts/generate-web-module/types/index.js.map +1 -0
  176. package/dist/scripts/generate-web-module/types/json-schema.interface.d.ts +40 -0
  177. package/dist/scripts/generate-web-module/types/json-schema.interface.d.ts.map +1 -0
  178. package/dist/scripts/generate-web-module/types/json-schema.interface.js +10 -0
  179. package/dist/scripts/generate-web-module/types/json-schema.interface.js.map +1 -0
  180. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts +128 -0
  181. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts.map +1 -0
  182. package/dist/scripts/generate-web-module/types/template-data.interface.js +9 -0
  183. package/dist/scripts/generate-web-module/types/template-data.interface.js.map +1 -0
  184. package/dist/scripts/generate-web-module/utils/bootstrapper-updater.d.ts +29 -0
  185. package/dist/scripts/generate-web-module/utils/bootstrapper-updater.d.ts.map +1 -0
  186. package/dist/scripts/generate-web-module/utils/bootstrapper-updater.js +153 -0
  187. package/dist/scripts/generate-web-module/utils/bootstrapper-updater.js.map +1 -0
  188. package/dist/scripts/generate-web-module/utils/file-writer.d.ts +38 -0
  189. package/dist/scripts/generate-web-module/utils/file-writer.d.ts.map +1 -0
  190. package/dist/scripts/generate-web-module/utils/file-writer.js +126 -0
  191. package/dist/scripts/generate-web-module/utils/file-writer.js.map +1 -0
  192. package/dist/scripts/generate-web-module/utils/i18n-updater.d.ts +28 -0
  193. package/dist/scripts/generate-web-module/utils/i18n-updater.d.ts.map +1 -0
  194. package/dist/scripts/generate-web-module/utils/i18n-updater.js +122 -0
  195. package/dist/scripts/generate-web-module/utils/i18n-updater.js.map +1 -0
  196. package/dist/scripts/generate-web-module/utils/index.d.ts +9 -0
  197. package/dist/scripts/generate-web-module/utils/index.d.ts.map +1 -0
  198. package/dist/scripts/generate-web-module/utils/index.js +20 -0
  199. package/dist/scripts/generate-web-module/utils/index.js.map +1 -0
  200. package/dist/scripts/generate-web-module/validators/json-schema-validator.d.ts +46 -0
  201. package/dist/scripts/generate-web-module/validators/json-schema-validator.d.ts.map +1 -0
  202. package/dist/scripts/generate-web-module/validators/json-schema-validator.js +265 -0
  203. package/dist/scripts/generate-web-module/validators/json-schema-validator.js.map +1 -0
  204. package/dist/shadcnui/index.js +4 -4
  205. package/dist/shadcnui/index.mjs +3 -3
  206. package/dist/utils/index.js +3 -3
  207. package/dist/utils/index.mjs +2 -2
  208. package/package.json +27 -21
  209. package/scripts/generate-web-module/generator.ts +363 -0
  210. package/scripts/generate-web-module/index.ts +49 -0
  211. package/scripts/generate-web-module/templates/components/container.template.ts +129 -0
  212. package/scripts/generate-web-module/templates/components/content.template.ts +40 -0
  213. package/scripts/generate-web-module/templates/components/deleter.template.ts +51 -0
  214. package/scripts/generate-web-module/templates/components/details.template.ts +115 -0
  215. package/scripts/generate-web-module/templates/components/editor.template.ts +495 -0
  216. package/scripts/generate-web-module/templates/components/index.ts +18 -0
  217. package/scripts/generate-web-module/templates/components/list-container.template.ts +30 -0
  218. package/scripts/generate-web-module/templates/components/list.template.ts +91 -0
  219. package/scripts/generate-web-module/templates/components/multi-selector.template.ts +184 -0
  220. package/scripts/generate-web-module/templates/components/selector.template.ts +199 -0
  221. package/scripts/generate-web-module/templates/context.template.ts +121 -0
  222. package/scripts/generate-web-module/templates/data/fields.template.ts +64 -0
  223. package/scripts/generate-web-module/templates/data/index.ts +10 -0
  224. package/scripts/generate-web-module/templates/data/interface.template.ts +136 -0
  225. package/scripts/generate-web-module/templates/data/model.template.ts +327 -0
  226. package/scripts/generate-web-module/templates/data/service.template.ts +185 -0
  227. package/scripts/generate-web-module/templates/index.ts +34 -0
  228. package/scripts/generate-web-module/templates/module.template.ts +69 -0
  229. package/scripts/generate-web-module/templates/pages/detail-page.template.ts +65 -0
  230. package/scripts/generate-web-module/templates/pages/index.ts +8 -0
  231. package/scripts/generate-web-module/templates/pages/list-page.template.ts +37 -0
  232. package/scripts/generate-web-module/templates/table-hook.template.ts +182 -0
  233. package/scripts/generate-web-module/transformers/field-mapper.ts +201 -0
  234. package/scripts/generate-web-module/transformers/i18n-generator.ts +199 -0
  235. package/scripts/generate-web-module/transformers/import-resolver.ts +250 -0
  236. package/scripts/generate-web-module/transformers/index.ts +12 -0
  237. package/scripts/generate-web-module/transformers/name-transformer.ts +115 -0
  238. package/scripts/generate-web-module/transformers/parent-detector.ts +87 -0
  239. package/scripts/generate-web-module/transformers/relationship-resolver.ts +221 -0
  240. package/scripts/generate-web-module/tsconfig.json +24 -0
  241. package/scripts/generate-web-module/types/field-mapping.types.ts +141 -0
  242. package/scripts/generate-web-module/types/index.ts +9 -0
  243. package/scripts/generate-web-module/types/json-schema.interface.ts +42 -0
  244. package/scripts/generate-web-module/types/template-data.interface.ts +164 -0
  245. package/scripts/generate-web-module/utils/bootstrapper-updater.ts +145 -0
  246. package/scripts/generate-web-module/utils/file-writer.ts +115 -0
  247. package/scripts/generate-web-module/utils/i18n-updater.ts +108 -0
  248. package/scripts/generate-web-module/utils/index.ts +9 -0
  249. package/scripts/generate-web-module/validators/json-schema-validator.ts +306 -0
  250. package/src/components/errors/ErrorDetails.tsx +2 -2
  251. package/src/features/auth/components/containers/AuthContainer.tsx +1 -1
  252. package/src/features/auth/components/details/LandingComponent.tsx +20 -1
  253. package/src/features/auth/components/forms/AcceptInvitation.tsx +1 -1
  254. package/src/features/auth/components/forms/ActivateAccount.tsx +1 -1
  255. package/src/features/auth/components/forms/ForgotPassword.tsx +1 -1
  256. package/src/features/auth/components/forms/Login.tsx +1 -1
  257. package/src/features/auth/components/forms/Register.tsx +1 -1
  258. package/src/features/auth/components/forms/ResetPassword.tsx +1 -1
  259. package/src/features/company/components/forms/CompanyLicense.tsx +1 -8
  260. package/src/unified/JsonApiRequest.ts +2 -2
  261. package/dist/JsonApiRequest-VARLNKAF.js +0 -23
  262. package/dist/JsonApiRequest-VARLNKAF.js.map +0 -1
  263. package/dist/chunk-5ZEADNNP.js.map +0 -1
  264. package/dist/chunk-74F6BBHH.mjs.map +0 -1
  265. package/dist/chunk-KDFDGXCX.js.map +0 -1
  266. package/dist/chunk-Y4XI3AZR.mjs.map +0 -1
  267. /package/dist/{BlockNoteEditor-DC33K4IF.mjs.map → BlockNoteEditor-V625C23O.mjs.map} +0 -0
  268. /package/dist/{JsonApiRequest-O7BGUMFO.mjs.map → JsonApiRequest-6UR7DIAR.mjs.map} +0 -0
  269. /package/dist/{chunk-NPPQNSXN.mjs.map → chunk-FMBQZAIP.mjs.map} +0 -0
  270. /package/dist/{chunk-MHVXFWZY.mjs.map → chunk-HTLEKZND.mjs.map} +0 -0
  271. /package/dist/{chunk-JLN6UWII.mjs.map → chunk-JGFWIT2E.mjs.map} +0 -0
  272. /package/dist/{chunk-X53MF5ZN.mjs.map → chunk-P2F54I7Q.mjs.map} +0 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Relationship Resolver
3
+ *
4
+ * Resolves JSON relationship definitions to frontend representations
5
+ * including form fields, imports, and service methods.
6
+ */
7
+
8
+ import { JsonRelationshipDefinition } from "../types/json-schema.interface";
9
+ import { FrontendRelationship, RelationshipServiceMethod } from "../types/template-data.interface";
10
+ import { AUTHOR_VARIANT, AUTHOR_ZOD_SCHEMA, ENTITY_ZOD_SCHEMA } from "../types/field-mapping.types";
11
+ import { toCamelCase, toKebabCase, pluralize, toPascalCase } from "./name-transformer";
12
+
13
+ /**
14
+ * Resolve a JSON relationship to frontend representation
15
+ *
16
+ * @param rel - JSON relationship definition
17
+ * @returns Frontend relationship representation
18
+ */
19
+ export function resolveRelationship(rel: JsonRelationshipDefinition): FrontendRelationship {
20
+ const isAuthor = rel.variant === AUTHOR_VARIANT;
21
+ const effectiveName = rel.variant || rel.name;
22
+ const effectiveNameLower = toCamelCase(effectiveName);
23
+ const modelKebab = toKebabCase(rel.name);
24
+
25
+ // Form field ID
26
+ const formFieldId = effectiveNameLower;
27
+ const formFieldIdPlural = pluralize(effectiveNameLower);
28
+
29
+ // Payload field ID for API calls
30
+ let payloadFieldId: string;
31
+ if (rel.single) {
32
+ payloadFieldId = `${effectiveNameLower}Id`;
33
+ } else {
34
+ payloadFieldId = `${toCamelCase(rel.name)}Ids`;
35
+ }
36
+
37
+ // Selector component name
38
+ let selectorComponent: string;
39
+ if (rel.single) {
40
+ selectorComponent = `${rel.name}Selector`;
41
+ } else {
42
+ selectorComponent = `${rel.name}MultiSelector`;
43
+ }
44
+
45
+ // Zod schema
46
+ let zodSchema: string;
47
+ if (isAuthor) {
48
+ zodSchema = rel.nullable
49
+ ? `${AUTHOR_ZOD_SCHEMA}.optional()`
50
+ : `${AUTHOR_ZOD_SCHEMA}.refine((data) => data.id && data.id.length > 0, { message: t(\`generic.relationships.author.error\`) })`;
51
+ } else if (rel.single) {
52
+ zodSchema = rel.nullable
53
+ ? `${ENTITY_ZOD_SCHEMA}.optional()`
54
+ : `${ENTITY_ZOD_SCHEMA}.refine((data) => data.id && data.id.length > 0, { message: t(\`generic.relationships.${effectiveNameLower}.error\`) })`;
55
+ } else {
56
+ zodSchema = rel.nullable ? `z.array(${ENTITY_ZOD_SCHEMA}).optional()` : `z.array(${ENTITY_ZOD_SCHEMA})`;
57
+ }
58
+
59
+ // Import paths - map directory to web path
60
+ const webDirectory = mapDirectoryToWebPath(rel.directory);
61
+ const importPath = `@/features/${webDirectory}/${modelKebab}/components/forms/${selectorComponent}`;
62
+ const interfaceImportPath = `@/features/${webDirectory}/${modelKebab}/data/${rel.name}Interface`;
63
+ const serviceImportPath = `@/features/${webDirectory}/${modelKebab}/data/${rel.name}Service`;
64
+
65
+ return {
66
+ name: rel.name,
67
+ variant: rel.variant,
68
+ directory: rel.directory,
69
+ single: rel.single,
70
+ nullable: rel.nullable,
71
+ formFieldId,
72
+ formFieldIdPlural,
73
+ payloadFieldId,
74
+ selectorComponent,
75
+ zodSchema,
76
+ importPath,
77
+ interfaceImportPath,
78
+ serviceImportPath,
79
+ interfaceName: `${rel.name}Interface`,
80
+ modelKebab,
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Resolve all relationships from JSON schema
86
+ *
87
+ * @param relationships - Array of JSON relationship definitions
88
+ * @returns Array of frontend relationship representations
89
+ */
90
+ export function resolveRelationships(relationships: JsonRelationshipDefinition[]): FrontendRelationship[] {
91
+ return relationships.map(resolveRelationship);
92
+ }
93
+
94
+ /**
95
+ * Map directory value to web path
96
+ * e.g., "features" -> "features", "foundations" -> "foundations"
97
+ *
98
+ * @param directory - Directory value from JSON
99
+ * @returns Web path segment
100
+ */
101
+ export function mapDirectoryToWebPath(directory: string): string {
102
+ // The directory value maps directly to the web path
103
+ return directory;
104
+ }
105
+
106
+ /**
107
+ * Generate service method definitions for relationships
108
+ *
109
+ * @param relationships - Array of frontend relationships
110
+ * @returns Array of service method definitions
111
+ */
112
+ export function generateServiceMethods(relationships: FrontendRelationship[]): RelationshipServiceMethod[] {
113
+ return relationships.map((rel) => {
114
+ const effectiveName = rel.variant || rel.name;
115
+ return {
116
+ methodName: `findManyBy${toPascalCase(effectiveName)}`,
117
+ paramName: `${toCamelCase(effectiveName)}Id`,
118
+ relationshipName: rel.name,
119
+ relationshipEndpoint: pluralize(toKebabCase(rel.name)),
120
+ };
121
+ });
122
+ }
123
+
124
+ /**
125
+ * Get unique selector imports needed for the editor
126
+ *
127
+ * @param relationships - Array of frontend relationships
128
+ * @returns Deduplicated array of import statements
129
+ */
130
+ export function getSelectorImports(relationships: FrontendRelationship[]): string[] {
131
+ const imports = new Set<string>();
132
+
133
+ relationships.forEach((rel) => {
134
+ // Don't import User selector from same module - it's typically a library import
135
+ if (rel.name === "User" && rel.variant === AUTHOR_VARIANT) {
136
+ // User selector is imported from library or user feature
137
+ imports.add(`import { UserSelector } from "@/features/foundations/user/components/forms/UserSelector";`);
138
+ } else {
139
+ imports.add(`import ${rel.selectorComponent} from "${rel.importPath}";`);
140
+ }
141
+ });
142
+
143
+ return Array.from(imports);
144
+ }
145
+
146
+ /**
147
+ * Get form JSX for a relationship field
148
+ *
149
+ * @param rel - Frontend relationship
150
+ * @param moduleName - Module name for i18n keys
151
+ * @returns JSX code for the relationship selector
152
+ */
153
+ export function getRelationshipFormJsx(rel: FrontendRelationship, moduleName: string): string {
154
+ const isRequired = !rel.nullable;
155
+ const lowerModuleName = moduleName.toLowerCase();
156
+
157
+ if (rel.single) {
158
+ // Single selector
159
+ if (rel.variant === AUTHOR_VARIANT) {
160
+ // Author is auto-set, usually not shown in form or read-only
161
+ return "";
162
+ }
163
+ return `<${rel.name}Selector
164
+ id="${rel.formFieldId}"
165
+ form={form}
166
+ label={t(\`generic.relationships.${rel.formFieldId}.label\`)}
167
+ placeholder={t(\`generic.relationships.${rel.formFieldId}.placeholder\`)}
168
+ ${isRequired ? "isRequired" : ""}
169
+ />`;
170
+ } else {
171
+ // Multi selector
172
+ return `<${rel.name}MultiSelector
173
+ id="${rel.formFieldId}"
174
+ form={form}
175
+ label={t(\`types.${pluralize(toKebabCase(rel.name))}\`, { count: 2 })}
176
+ />`;
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Get default value expression for a relationship in form
182
+ *
183
+ * @param rel - Frontend relationship
184
+ * @param modelVarName - Variable name for the model (e.g., "article")
185
+ * @returns Expression for default value
186
+ */
187
+ export function getDefaultValueExpression(rel: FrontendRelationship, modelVarName: string): string {
188
+ const propertyName = rel.variant ? toCamelCase(rel.variant) : toCamelCase(rel.name);
189
+ const pluralPropertyName = pluralize(propertyName);
190
+
191
+ if (rel.single) {
192
+ if (rel.variant === AUTHOR_VARIANT) {
193
+ // Author has special shape with avatar
194
+ return `${modelVarName}?.${propertyName}
195
+ ? { id: ${modelVarName}.${propertyName}.id, name: ${modelVarName}.${propertyName}.name, avatar: ${modelVarName}.${propertyName}.avatar }
196
+ : undefined`;
197
+ }
198
+ return `${modelVarName}?.${propertyName}
199
+ ? { id: ${modelVarName}.${propertyName}.id, name: ${modelVarName}.${propertyName}.name }
200
+ : undefined`;
201
+ } else {
202
+ // Multi-select
203
+ return `${modelVarName}?.${pluralPropertyName}
204
+ ? ${modelVarName}.${pluralPropertyName}.map((item) => ({ id: item.id, name: item.name }))
205
+ : []`;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Get payload mapping for a relationship
211
+ *
212
+ * @param rel - Frontend relationship
213
+ * @returns Payload field assignment code
214
+ */
215
+ export function getPayloadMapping(rel: FrontendRelationship): string {
216
+ if (rel.single) {
217
+ return `${rel.payloadFieldId}: values.${rel.formFieldId}?.id`;
218
+ } else {
219
+ return `${rel.payloadFieldId}: values.${rel.formFieldId} ? values.${rel.formFieldId}.map((item) => item.id) : []`;
220
+ }
221
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "target": "es2020",
7
+ "outDir": "../../dist/scripts/generate-web-module",
8
+ "rootDir": ".",
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "sourceMap": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "strict": true,
15
+ "resolveJsonModule": true
16
+ },
17
+ "include": [
18
+ "./**/*.ts"
19
+ ],
20
+ "exclude": [
21
+ "node_modules",
22
+ "dist"
23
+ ]
24
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Field Mapping Types
3
+ *
4
+ * Defines the mapping rules between JSON schema field types
5
+ * and their TypeScript, Zod, and form component equivalents.
6
+ */
7
+
8
+ import { FormComponentType } from "./template-data.interface";
9
+
10
+ /**
11
+ * Mapping from JSON type to TypeScript type
12
+ */
13
+ export const JSON_TO_TS_TYPE: Record<string, string> = {
14
+ string: "string",
15
+ number: "number",
16
+ boolean: "boolean",
17
+ date: "Date",
18
+ any: "any",
19
+ };
20
+
21
+ /**
22
+ * Mapping from JSON type to Zod schema (base, without modifiers)
23
+ */
24
+ export const JSON_TO_ZOD_BASE: Record<string, string> = {
25
+ string: "z.string()",
26
+ number: "z.number()",
27
+ boolean: "z.boolean()",
28
+ date: "z.date()",
29
+ any: "z.any()",
30
+ };
31
+
32
+ /**
33
+ * Special field names that get specific form components
34
+ */
35
+ export const SPECIAL_FIELD_COMPONENTS: Record<string, FormComponentType> = {
36
+ content: "BlockNoteEditor",
37
+ description: "FormTextarea",
38
+ abstract: "FormTextarea",
39
+ body: "FormTextarea",
40
+ };
41
+
42
+ /**
43
+ * Default form component by type
44
+ */
45
+ export const TYPE_TO_FORM_COMPONENT: Record<string, FormComponentType> = {
46
+ string: "FormInput",
47
+ number: "FormInputNumber",
48
+ boolean: "Checkbox",
49
+ date: "DatePicker",
50
+ any: "FormInput",
51
+ };
52
+
53
+ /**
54
+ * Fields that indicate the module extends Content
55
+ */
56
+ export const CONTENT_INDICATOR_FIELDS = ["name", "tldr", "abstract"];
57
+
58
+ /**
59
+ * Standard fields added to all modules
60
+ */
61
+ export const STANDARD_FIELDS = ["createdAt", "updatedAt"];
62
+
63
+ /**
64
+ * Author variant special handling
65
+ */
66
+ export const AUTHOR_VARIANT = "Author";
67
+
68
+ /**
69
+ * Zod schema for author relationships
70
+ */
71
+ export const AUTHOR_ZOD_SCHEMA = "userObjectSchema";
72
+
73
+ /**
74
+ * Zod schema for entity relationships (non-author)
75
+ */
76
+ export const ENTITY_ZOD_SCHEMA = "entityObjectSchema";
77
+
78
+ /**
79
+ * Default icon for new modules
80
+ */
81
+ export const DEFAULT_MODULE_ICON = "FileTextIcon";
82
+
83
+ /**
84
+ * Get TypeScript type for a field
85
+ */
86
+ export function getTsType(jsonType: string): string {
87
+ return JSON_TO_TS_TYPE[jsonType] || "any";
88
+ }
89
+
90
+ /**
91
+ * Get base Zod schema for a field type
92
+ */
93
+ export function getZodBase(jsonType: string): string {
94
+ return JSON_TO_ZOD_BASE[jsonType] || "z.any()";
95
+ }
96
+
97
+ /**
98
+ * Get form component for a field
99
+ */
100
+ export function getFormComponent(fieldName: string, fieldType: string): FormComponentType {
101
+ // Check for special field names first
102
+ if (SPECIAL_FIELD_COMPONENTS[fieldName]) {
103
+ return SPECIAL_FIELD_COMPONENTS[fieldName];
104
+ }
105
+ // Fall back to type-based component
106
+ return TYPE_TO_FORM_COMPONENT[fieldType] || "FormInput";
107
+ }
108
+
109
+ /**
110
+ * Check if a field name indicates BlockNoteEditor should be used
111
+ */
112
+ export function isContentField(fieldName: string): boolean {
113
+ return fieldName === "content";
114
+ }
115
+
116
+ /**
117
+ * Build complete Zod schema for a field
118
+ */
119
+ export function buildZodSchema(fieldType: string, nullable: boolean, fieldName: string): string {
120
+ const base = getZodBase(fieldType);
121
+
122
+ // Content fields use z.any()
123
+ if (isContentField(fieldName)) {
124
+ return "z.any()";
125
+ }
126
+
127
+ // String fields with min(1) for required
128
+ if (fieldType === "string") {
129
+ if (nullable) {
130
+ return `${base}.optional()`;
131
+ }
132
+ return `${base}.min(1, { message: t(\`features.\${moduleName}.fields.${fieldName}.error\`) })`;
133
+ }
134
+
135
+ // Other fields with optional modifier
136
+ if (nullable) {
137
+ return `${base}.optional()`;
138
+ }
139
+
140
+ return base;
141
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Types Index
3
+ *
4
+ * Re-exports all type definitions for the web module generator.
5
+ */
6
+
7
+ export * from "./json-schema.interface";
8
+ export * from "./template-data.interface";
9
+ export * from "./field-mapping.types";
@@ -0,0 +1,42 @@
1
+ /**
2
+ * JSON Schema Interfaces
3
+ *
4
+ * Type definitions for the JSON module definition files
5
+ * located in the /structure folder.
6
+ * Copied from backend generator - shared schema format.
7
+ */
8
+
9
+ /**
10
+ * Field definition in JSON schema
11
+ */
12
+ export interface JsonFieldDefinition {
13
+ name: string;
14
+ type: string;
15
+ nullable: boolean;
16
+ }
17
+
18
+ /**
19
+ * Relationship definition in JSON schema
20
+ */
21
+ export interface JsonRelationshipDefinition {
22
+ name: string;
23
+ variant?: string;
24
+ directory: string;
25
+ single: boolean;
26
+ relationshipName: string; // Backend-specific, ignored in frontend
27
+ toNode: boolean; // Backend-specific, ignored in frontend
28
+ nullable: boolean;
29
+ }
30
+
31
+ /**
32
+ * Complete module definition from JSON
33
+ */
34
+ export interface JsonModuleDefinition {
35
+ moduleId: string;
36
+ moduleName: string;
37
+ endpointName: string;
38
+ targetDir: string;
39
+ languages: string[];
40
+ fields: JsonFieldDefinition[];
41
+ relationships: JsonRelationshipDefinition[];
42
+ }
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Frontend Template Data Interfaces
3
+ *
4
+ * Type definitions for the data passed to templates
5
+ * during frontend module generation.
6
+ */
7
+
8
+ /**
9
+ * Name transformations for different naming conventions
10
+ */
11
+ export interface NameTransforms {
12
+ pascalCase: string; // e.g., "Comment"
13
+ camelCase: string; // e.g., "comment"
14
+ kebabCase: string; // e.g., "comment"
15
+ pluralPascal: string; // e.g., "Comments"
16
+ pluralCamel: string; // e.g., "comments"
17
+ pluralKebab: string; // e.g., "comments"
18
+ titleCase: string; // e.g., "Comment" (for labels)
19
+ pluralTitleCase: string; // e.g., "Comments" (for labels)
20
+ }
21
+
22
+ /**
23
+ * Frontend field representation
24
+ */
25
+ export interface FrontendField {
26
+ name: string;
27
+ type: string;
28
+ tsType: string; // TypeScript type
29
+ zodSchema: string; // Zod schema code
30
+ formComponent: FormComponentType;
31
+ nullable: boolean;
32
+ isContentField: boolean; // Indicates BlockNoteEditor
33
+ }
34
+
35
+ /**
36
+ * Form component types
37
+ */
38
+ export type FormComponentType = "FormInput" | "FormTextarea" | "BlockNoteEditor" | "Checkbox" | "DatePicker" | "FormInputNumber";
39
+
40
+ /**
41
+ * Frontend relationship representation
42
+ */
43
+ export interface FrontendRelationship {
44
+ name: string; // e.g., "User"
45
+ variant?: string; // e.g., "Author"
46
+ directory: string; // e.g., "foundations"
47
+ single: boolean;
48
+ nullable: boolean;
49
+ // Derived properties
50
+ formFieldId: string; // e.g., "author" (lowercase variant) or "user"
51
+ formFieldIdPlural: string; // e.g., "topics" for multi-select
52
+ payloadFieldId: string; // e.g., "authorId" or "topicIds"
53
+ selectorComponent: string; // e.g., "UserSelector" or "TopicMultiSelector"
54
+ zodSchema: string; // e.g., "userObjectSchema" or "z.array(entityObjectSchema)"
55
+ importPath: string; // Full import path for selector
56
+ interfaceImportPath: string; // Full import path for interface
57
+ serviceImportPath: string; // Full import path for service
58
+ interfaceName: string; // e.g., "UserInterface"
59
+ modelKebab: string; // e.g., "user"
60
+ }
61
+
62
+ /**
63
+ * i18n key structure
64
+ */
65
+ export interface I18nKeySet {
66
+ moduleName: string; // e.g., "comment"
67
+ fields: Record<
68
+ string,
69
+ {
70
+ label: string;
71
+ placeholder: string;
72
+ error: string;
73
+ }
74
+ >;
75
+ relationships: Record<
76
+ string,
77
+ {
78
+ label: string;
79
+ placeholder: string;
80
+ error: string;
81
+ list: string;
82
+ }
83
+ >;
84
+ type: {
85
+ singular: string;
86
+ plural: string;
87
+ icuPlural: string; // ICU format plural
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Import statement groups
93
+ */
94
+ export interface ImportStatements {
95
+ // Related model/interface imports
96
+ models: string[];
97
+ // Selector component imports
98
+ selectors: string[];
99
+ // Library imports (from @carlonicora/nextjs-jsonapi)
100
+ library: string[];
101
+ }
102
+
103
+ /**
104
+ * Complete template data passed to all templates
105
+ */
106
+ export interface FrontendTemplateData {
107
+ // Name variations
108
+ names: NameTransforms;
109
+
110
+ // Module metadata
111
+ moduleId: string;
112
+ endpoint: string;
113
+ targetDir: "features" | "foundations";
114
+
115
+ // Parent class detection
116
+ extendsContent: boolean;
117
+
118
+ // Field mappings
119
+ fields: FrontendField[];
120
+
121
+ // Relationship mappings
122
+ relationships: FrontendRelationship[];
123
+
124
+ // i18n keys
125
+ i18nKeys: I18nKeySet;
126
+
127
+ // Import statements
128
+ imports: ImportStatements;
129
+
130
+ // For table structure
131
+ tableFieldNames: string[];
132
+
133
+ // For service generation
134
+ relationshipServiceMethods: RelationshipServiceMethod[];
135
+ }
136
+
137
+ /**
138
+ * Service method for relationship queries
139
+ */
140
+ export interface RelationshipServiceMethod {
141
+ methodName: string; // e.g., "findManyByAuthor"
142
+ paramName: string; // e.g., "authorId"
143
+ relationshipName: string; // e.g., "User"
144
+ relationshipEndpoint: string; // e.g., "users"
145
+ }
146
+
147
+ /**
148
+ * Options for the generator
149
+ */
150
+ export interface GenerateWebModuleOptions {
151
+ jsonPath: string;
152
+ dryRun?: boolean;
153
+ force?: boolean;
154
+ noRegister?: boolean;
155
+ }
156
+
157
+ /**
158
+ * Generated file info
159
+ */
160
+ export interface GeneratedFile {
161
+ path: string;
162
+ content: string;
163
+ type: "data" | "component" | "context" | "hook" | "module" | "page";
164
+ }