@nutin/cli 1.3.1 → 2.0.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 (287) hide show
  1. package/CHANGELOG.md +89 -9
  2. package/README.md +20 -35
  3. package/bin/add-feature.mjs +9 -0
  4. package/bin/cli.mjs +8 -0
  5. package/bin/create-app.mjs +5 -4
  6. package/bin/update-app.mjs +9 -0
  7. package/lib/index.mjs +76 -25
  8. package/lib/src/add-feature/feature-adder.mjs +83 -0
  9. package/lib/src/add-feature/feature-context-builder.mjs +25 -0
  10. package/lib/src/add-feature/nutin-config-updater.mjs +29 -0
  11. package/lib/src/add-feature/package-json-updater.mjs +49 -0
  12. package/lib/src/common/feature-registry.mjs +11 -0
  13. package/lib/src/common/file-generator.mjs +159 -0
  14. package/lib/src/common/meta-bootstrap-prompt.mjs +33 -0
  15. package/lib/src/common/package-data.mjs +10 -0
  16. package/lib/src/common/package-json-helper.mjs +103 -0
  17. package/lib/src/common/project-meta.mjs +54 -0
  18. package/lib/src/create-app/context-builder.mjs +21 -0
  19. package/lib/src/{git-manager.mjs → create-app/git-manager.mjs} +2 -2
  20. package/lib/src/create-app/json-manager.mjs +73 -0
  21. package/lib/src/{prompts.mjs → create-app/new-app-prompt.mjs} +6 -6
  22. package/lib/src/{project-generator.mjs → create-app/project-generator.mjs} +10 -8
  23. package/lib/src/create-app/success-message.mjs +14 -0
  24. package/lib/src/update-app/conflict-report-writer.mjs +31 -0
  25. package/lib/src/update-app/fetch-old-templates.mjs +61 -0
  26. package/lib/src/update-app/project-updater.mjs +136 -0
  27. package/lib/src/update-app/template-differ.mjs +124 -0
  28. package/lib/src/update-app/update-context-builder.mjs +25 -0
  29. package/lib/src/update-app/update-summary-printer.mjs +22 -0
  30. package/lib/src/update-app/version-compare.mjs +12 -0
  31. package/lib/src/utils/print.mjs +36 -0
  32. package/lib/src/utils/promise-exec-alias.mjs +4 -0
  33. package/package.json +17 -12
  34. package/templates/base/.gitignore.hbs +6 -1
  35. package/templates/base/AGENTS.md.hbs +169 -0
  36. package/templates/base/GETTING_STARTED.md.hbs +227 -0
  37. package/templates/base/README.md.hbs +8 -17
  38. package/templates/base/config/languages.json.hbs +6 -0
  39. package/templates/base/config/seo.json.hbs +12 -0
  40. package/templates/base/nutin.config.js.hbs +51 -0
  41. package/templates/base/src/app/components/index.ts.hbs +1 -2
  42. package/templates/base/src/app/globals.d.ts.hbs +3 -19
  43. package/templates/base/src/{libs/guards → app}/guards.ts.hbs +1 -5
  44. package/templates/base/src/app/main.ts.hbs +7 -26
  45. package/templates/base/src/app/services/index.ts.hbs +1 -1
  46. package/templates/base/src/app/views/home/home.view.html.hbs +7 -0
  47. package/templates/base/src/app/views/home/home.view.ts.hbs +1 -56
  48. package/templates/base/src/app/views/index.ts.hbs +1 -0
  49. package/templates/base/src/app/views/not-found/not-found.view.html.hbs +8 -0
  50. package/templates/base/src/app/views/not-found/not-found.view.ts.hbs +4 -37
  51. package/templates/base/src/core/base-classes/base-component/base-component.test.js.hbs +158 -0
  52. package/templates/base/src/core/base-classes/base-component/base-component.ts.hbs +68 -35
  53. package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.test.js.hbs +124 -0
  54. package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.ts.hbs +9 -8
  55. package/templates/base/src/core/base-classes/base-component/helpers/children.helper.test.js.hbs +74 -0
  56. package/templates/base/src/core/base-classes/base-component/helpers/children.helper.ts.hbs +1 -1
  57. package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.test.js.hbs +145 -0
  58. package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.ts.hbs +7 -1
  59. package/templates/base/src/core/base-classes/base-component/helpers/event.helper.test.js.hbs +88 -0
  60. package/templates/base/src/core/base-classes/base-component/helpers/event.helper.ts.hbs +2 -2
  61. package/templates/base/src/core/base-classes/base-component/helpers/i18n.helper.test.js.hbs +62 -0
  62. package/templates/base/src/core/base-classes/base-component/helpers/pipe.helper.test.js.hbs +82 -0
  63. package/templates/base/src/core/base-classes/base-component/helpers/security.helper.test.js.hbs +142 -0
  64. package/templates/base/src/core/base-classes/base-component/helpers/security.helper.ts.hbs +67 -22
  65. package/templates/base/src/core/base-classes/base-component/helpers/token.helper.test.js.hbs +183 -0
  66. package/templates/base/src/core/base-classes/component/component.test.js.hbs +85 -0
  67. package/templates/base/src/core/base-classes/component/component.ts.hbs +24 -33
  68. package/templates/base/src/core/base-classes/component/helpers/config.helper.test.js.hbs +58 -0
  69. package/templates/base/src/core/base-classes/component/helpers/data-binding.helper.test.js.hbs +75 -0
  70. package/templates/base/src/core/base-classes/service/service.test.js.hbs +150 -0
  71. package/templates/base/src/core/base-classes/service/service.ts.hbs +26 -20
  72. package/templates/base/src/core/base-classes/view/view.test.js.hbs +74 -0
  73. package/templates/base/src/core/base-classes/view/view.ts.hbs +17 -41
  74. package/templates/base/src/core/config.ts.hbs +7 -0
  75. package/templates/base/src/core/index.ts.hbs +0 -3
  76. package/templates/base/src/core/internals.d.ts.hbs +27 -0
  77. package/templates/base/src/core/nutin-config.d.ts.hbs +4 -0
  78. package/templates/base/src/core/services/event-bus/event-bus.test.js.hbs +67 -3
  79. package/templates/base/src/core/services/event-bus/event-bus.ts.hbs +9 -4
  80. package/templates/base/src/core/services/event-bus/index.ts.hbs +3 -0
  81. package/templates/base/src/core/services/event-bus/lifecycle.facade.test.js.hbs +123 -0
  82. package/templates/base/src/core/services/event-bus/lifecycle.facade.ts.hbs +61 -0
  83. package/templates/base/src/core/services/event-bus/navigation.facade.test.js.hbs +46 -0
  84. package/templates/base/src/core/services/event-bus/navigation.facade.ts.hbs +25 -0
  85. package/templates/base/src/core/services/globals/globals.test.js.hbs +149 -0
  86. package/templates/base/src/core/services/globals/globals.ts.hbs +95 -0
  87. package/templates/base/src/core/services/http-client/helpers/http-builder.helper.test.js.hbs +25 -0
  88. package/templates/base/src/core/services/http-client/helpers/http-manager.helper.test.js.hbs +20 -0
  89. package/templates/base/src/core/services/http-client/http-client.test.js.hbs +43 -0
  90. package/templates/base/src/core/services/i18n/i18n.test.js.hbs +270 -0
  91. package/templates/{features/i18n → base}/src/core/services/i18n/i18n.ts.hbs +22 -4
  92. package/templates/base/src/core/services/index.ts.hbs +5 -6
  93. package/templates/base/src/core/services/pipe-registry/pipe-registry.test.js.hbs +60 -1
  94. package/templates/base/src/core/services/pipe-registry/pipe-registry.ts.hbs +1 -1
  95. package/templates/base/src/core/services/pipe-registry/pipes.test.js.hbs +128 -0
  96. package/templates/base/src/{libs/pipes → core/services/pipe-registry}/pipes.ts.hbs +8 -5
  97. package/templates/base/src/core/services/router/helpers/navigation-manager.helper.test.js.hbs +149 -6
  98. package/templates/base/src/core/services/router/helpers/navigation-manager.helper.ts.hbs +40 -29
  99. package/templates/base/src/core/services/router/helpers/route-guard-manager.helper.test.js.hbs +27 -0
  100. package/templates/base/src/core/services/router/helpers/view-render-manager.helper.test.js.hbs +83 -17
  101. package/templates/base/src/core/services/router/helpers/view-render-manager.helper.ts.hbs +14 -38
  102. package/templates/base/src/core/services/router/router.test.js.hbs +226 -2
  103. package/templates/base/src/core/services/router/router.ts.hbs +40 -8
  104. package/templates/base/src/index.html.hbs +2 -6
  105. package/templates/base/src/styles/_styles.scss.hbs +102 -43
  106. package/templates/base/src/styles/base/_variables.scss.hbs +1 -86
  107. package/templates/base/src/styles/main.scss.hbs +1 -18
  108. package/templates/base/src/styles/tailwind.css.hbs +2 -0
  109. package/templates/base/tools/builder/builder.config.js.hbs +40 -0
  110. package/templates/base/tools/builder/builder.js.hbs +24 -26
  111. package/templates/base/tools/builder/core/app/binary-extensions.test.js.hbs +16 -0
  112. package/templates/base/tools/builder/core/app/compile-ts.js.hbs +16 -0
  113. package/templates/base/tools/builder/core/{copy-static.js.hbs → app/copy-static.js.hbs} +27 -34
  114. package/templates/base/tools/builder/core/app/validate-routes.js.hbs +77 -0
  115. package/templates/base/tools/builder/core/finalize-build.js.hbs +16 -7
  116. package/templates/base/tools/builder/core/{add-tags.js.hbs → html-index/add-tags.js.hbs} +2 -2
  117. package/templates/base/tools/builder/core/html-index/add-tags.test.js.hbs +56 -0
  118. package/templates/base/tools/builder/core/{validate-html.js.hbs → html-index/validate-html.js.hbs} +5 -11
  119. package/templates/base/tools/builder/core/html-templates/merge-templates.js.hbs +152 -0
  120. package/templates/base/tools/builder/core/html-templates/minify-html.js.hbs +15 -0
  121. package/templates/base/tools/builder/core/html-templates/process-html-templates.js.hbs +8 -0
  122. package/templates/{features/i18n/tools/builder/core → base/tools/builder/core/i18n}/build-i18n.js.hbs +6 -17
  123. package/templates/base/tools/builder/core/prod-bundle/compress-files.js.hbs +37 -0
  124. package/templates/base/tools/builder/core/prod-bundle/esbuild.js.hbs +30 -0
  125. package/templates/base/tools/builder/core/{hash-files.js.hbs → prod-bundle/hash-files.js.hbs} +14 -11
  126. package/templates/base/tools/builder/core/seo/generate-robots-txt.js.hbs +51 -0
  127. package/templates/base/tools/builder/core/seo/generate-seo-files.js.hbs +16 -0
  128. package/templates/base/tools/builder/core/seo/generate-seo-html.js.hbs +128 -0
  129. package/templates/base/tools/builder/core/seo/generate-sitemap-xml.js.hbs +43 -0
  130. package/templates/base/tools/builder/core/seo/html-substitutions.js.hbs +99 -0
  131. package/templates/base/tools/builder/core/seo/i18n-resolution.js.hbs +66 -0
  132. package/templates/base/tools/builder/core/seo/route-output.js.hbs +64 -0
  133. package/templates/base/tools/builder/core/seo/ssr/ssr-bundle.js.hbs +54 -0
  134. package/templates/base/tools/builder/core/seo/ssr/ssr-polyfills.js.hbs +132 -0
  135. package/templates/base/tools/builder/core/seo/ssr/ssr-render.js.hbs +95 -0
  136. package/templates/base/tools/builder/core/styles/sass.js.hbs +40 -0
  137. package/templates/base/tools/builder/core/styles/tailwind.js.hbs +84 -0
  138. package/templates/base/tools/dev/dev-serve.js.hbs +26 -18
  139. package/templates/base/tools/dev/serve.js.hbs +11 -1
  140. package/templates/base/tools/dev/watcher.js.hbs +14 -6
  141. package/templates/base/tools/generator/generator.js.hbs +64 -47
  142. package/templates/base/tools/generator/handle-file.js.hbs +17 -44
  143. package/templates/base/tools/generator/handle-file.test.js.hbs +72 -0
  144. package/templates/base/tools/generator/templates/{component.template.js.hbs → component/component.template.js.hbs} +3 -2
  145. package/templates/base/tools/generator/templates/component/component.template.test.js.hbs +23 -0
  146. package/templates/base/tools/generator/templates/html/html.template.js.hbs +2 -0
  147. package/templates/base/tools/generator/templates/html/html.template.test.js.hbs +7 -0
  148. package/templates/base/tools/generator/templates/index.js.hbs +7 -12
  149. package/templates/base/tools/generator/templates/locale/locale.template.js.hbs +4 -0
  150. package/templates/base/tools/generator/templates/locale/locale.template.test.js.hbs +7 -0
  151. package/templates/base/tools/generator/templates/scss/scss.template.js.hbs +1 -0
  152. package/templates/base/tools/generator/templates/scss/scss.template.test.js.hbs +7 -0
  153. package/templates/base/tools/generator/templates/service/service.template.js.hbs +17 -0
  154. package/templates/base/tools/generator/templates/service/service.template.test.js.hbs +22 -0
  155. package/templates/base/tools/generator/templates/test/test.template.js.hbs +10 -0
  156. package/templates/base/tools/generator/templates/test/test.template.test.js.hbs +27 -0
  157. package/templates/base/tools/generator/templates/{view.template.js.hbs → view/view.template.js.hbs} +3 -2
  158. package/templates/base/tools/generator/templates/view/view.template.test.js.hbs +24 -0
  159. package/templates/base/tools/testin-nutin/core/coverage/collect-coverage.js.hbs +39 -0
  160. package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.js.hbs +115 -0
  161. package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.test.js.hbs +74 -0
  162. package/templates/base/tools/testin-nutin/core/coverage/write-summary-report.js.hbs +54 -0
  163. package/templates/base/tools/testin-nutin/core/coverage/write-uncovered-report.js.hbs +44 -0
  164. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/assertion-lib.js.hbs +62 -24
  165. package/templates/base/tools/testin-nutin/core/globals/clock.js.hbs +206 -0
  166. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/jsdom-setup.js.hbs +19 -6
  167. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/register-test-globals.js.hbs +13 -4
  168. package/templates/base/tools/testin-nutin/core/globals/silence-console.js.hbs +23 -0
  169. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/spyon.js.hbs +2 -0
  170. package/templates/base/tools/testin-nutin/core/index.js.hbs +9 -0
  171. package/templates/base/tools/testin-nutin/core/printer.js.hbs +85 -0
  172. package/templates/base/tools/testin-nutin/core/queue/queue.test.js.hbs +46 -0
  173. package/templates/base/tools/testin-nutin/core/queue/test-discovery.test.js.hbs +46 -0
  174. package/templates/base/tools/testin-nutin/core/queue/test-queue.js.hbs +154 -0
  175. package/templates/{features/testinNutin → base/tools}/testin-nutin/core/tests/assertions.test.js.hbs +27 -0
  176. package/templates/base/tools/testin-nutin/core/tests/clock.test.js.hbs +118 -0
  177. package/templates/base/tools/testin-nutin/core/tests/globals-each-all.test.js.hbs +28 -0
  178. package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/create-mock-method.js.hbs +2 -1
  179. package/templates/base/tools/testin-nutin/mocks/create-mock-method.test.js.hbs +64 -0
  180. package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-event-bus.js.hbs +3 -2
  181. package/templates/base/tools/testin-nutin/mocks/mock-event-bus.test.js.hbs +66 -0
  182. package/templates/base/tools/testin-nutin/mocks/mock-http-client.test.js.hbs +26 -0
  183. package/templates/base/tools/testin-nutin/mocks/mock-i18n.test.js.hbs +61 -0
  184. package/templates/base/tools/testin-nutin/mocks/mock-router.test.js.hbs +29 -0
  185. package/templates/base/tools/testin-nutin/runner.js.hbs +100 -0
  186. package/templates/base/tools/testin-nutin/watch-tests.js.hbs +37 -0
  187. package/templates/base/tools/utils/error-exit.js.hbs +8 -0
  188. package/templates/base/tools/utils/format.js.hbs +10 -10
  189. package/templates/base/tools/utils/format.test.js.hbs +45 -0
  190. package/templates/base/tools/utils/get-files-recursive.js.hbs +6 -1
  191. package/templates/base/tools/utils/get-files-recursive.test.js.hbs +49 -0
  192. package/templates/base/tools/utils/get-rel-to-core.test.js.hbs +18 -0
  193. package/templates/base/tools/utils/index.js.hbs +1 -3
  194. package/templates/base/tools/utils/languages.js.hbs +15 -0
  195. package/templates/base/tools/utils/languages.test.js.hbs +16 -0
  196. package/templates/base/tools/utils/print.js.hbs +19 -13
  197. package/templates/base/tools/utils/print.test.js.hbs +60 -0
  198. package/templates/base/tools/utils/prompt-boolean.js.hbs +7 -0
  199. package/templates/base/tools/utils/prompt-boolean.test.js.hbs +54 -0
  200. package/templates/base/tools/utils/run-command.js.hbs +4 -2
  201. package/templates/base/tools/utils/run-command.test.js.hbs +19 -0
  202. package/templates/base/tools/utils/run-script.js.hbs +14 -3
  203. package/templates/base/tools/utils/run-script.test.js.hbs +40 -0
  204. package/templates/features/{deployHelper → docker}/.dockerignore.hbs +4 -4
  205. package/templates/features/docker/tools/docker/Dockerfile.template.hbs +51 -0
  206. package/templates/features/{deployHelper/tools/deployment/nginx.conf.hbs → docker/tools/docker/nginx.conf.template} +4 -2
  207. package/templates/features/docker/tools/docker/scripts/docker-build.js.hbs +20 -0
  208. package/templates/features/docker/tools/docker/scripts/docker-ports.js.hbs +48 -0
  209. package/templates/features/docker/tools/docker/scripts/docker-ports.test.js.hbs +52 -0
  210. package/templates/features/docker/tools/docker/scripts/docker-run.js.hbs +28 -0
  211. package/templates/features/docker/tools/docker/scripts/render-docker-template.js.hbs +23 -0
  212. package/templates/features/docker/tools/docker/scripts/render-docker-template.test.js.hbs +60 -0
  213. package/templates/features/docker/tools/docker/scripts/validate-docker.js.hbs +30 -0
  214. package/lib/src/context-builder.mjs +0 -40
  215. package/lib/src/file-generator.mjs +0 -109
  216. package/lib/src/json-generator.mjs +0 -31
  217. package/lib/src/package-manager.mjs +0 -139
  218. package/lib/src/print.mjs +0 -32
  219. package/lib/src/utils.mjs +0 -18
  220. package/lib/src/version.mjs +0 -1
  221. package/templates/base/builder.config.js.hbs +0 -36
  222. package/templates/base/src/app/components/common/anchor/anchor.component.ts.hbs +0 -32
  223. package/templates/base/src/app/components/common/button/button.component.ts.hbs +0 -40
  224. package/templates/base/src/app/dom.test.js.hbs +0 -13
  225. package/templates/base/src/app/services/example/example.service.ts.hbs +0 -18
  226. package/templates/base/src/app/views/home/home.view.test.js.hbs +0 -26
  227. package/templates/base/src/core/services/store/store.test.js.hbs +0 -8
  228. package/templates/base/src/core/services/store/store.ts.hbs +0 -39
  229. package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.test.js.hbs +0 -0
  230. package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.ts.hbs +0 -113
  231. package/templates/base/src/core/utils/button-manager/button-manager.utils.test.js.hbs +0 -249
  232. package/templates/base/src/core/utils/button-manager/button-manager.utils.ts.hbs +0 -131
  233. package/templates/base/src/core/utils/helpers/attributes.helper.ts.hbs +0 -50
  234. package/templates/base/src/core/utils/index.ts.hbs +0 -2
  235. package/templates/base/src/libs/index.ts.hbs +0 -4
  236. package/templates/base/src/libs/popover/helpers/focus-trap.helper.ts.hbs +0 -197
  237. package/templates/base/src/libs/popover/helpers/popover-dom.helper.ts.hbs +0 -75
  238. package/templates/base/src/libs/popover/popover.ts.hbs +0 -138
  239. package/templates/base/src/libs/snackbar/snackbar.ts.hbs +0 -75
  240. package/templates/base/src/styles/base/_functions.scss.hbs +0 -9
  241. package/templates/base/src/styles/core/_anchors.scss.hbs +0 -10
  242. package/templates/base/src/styles/core/_index.scss.hbs +0 -6
  243. package/templates/base/src/styles/core/_popover.scss.hbs +0 -96
  244. package/templates/base/src/styles/core/_snackbar.scss.hbs +0 -50
  245. package/templates/base/tools/builder/core/esbuild.js.hbs +0 -25
  246. package/templates/base/tools/builder/core/minify-html.js.hbs +0 -60
  247. package/templates/base/tools/builder/core/sass.js.hbs +0 -22
  248. package/templates/base/tools/builder/core/tsc.js.hbs +0 -12
  249. package/templates/base/tools/generator/templates/service.template.js.hbs +0 -17
  250. package/templates/base/tools/utils/export-flags.js.hbs +0 -6
  251. package/templates/features/deployHelper/tools/builder/core/compress-files.js.hbs +0 -56
  252. package/templates/features/deployHelper/tools/deployment/Dockerfile.hbs +0 -30
  253. package/templates/features/i18n/src/app/views/home/locales/en.json.hbs +0 -9
  254. package/templates/features/i18n/src/app/views/not-found/locales/en.json +0 -8
  255. package/templates/features/i18n/src/app/views/not-found/locales/fr.json +0 -8
  256. package/templates/features/i18n/src/core/config.ts.hbs +0 -3
  257. package/templates/features/i18n/src/core/services/i18n/i18n.test.js.hbs +0 -125
  258. package/templates/features/i18n/tools/generator/templates/json.template.js.hbs +0 -8
  259. package/templates/features/i18n/tools/utils/languages.js.hbs +0 -7
  260. package/templates/features/stylinNutin/src/styles/_custom-classes.scss.hbs +0 -9
  261. package/templates/features/stylinNutin/src/styles/base/_mixins.scss.hbs +0 -372
  262. package/templates/features/stylinNutin/src/styles/components/_index.scss.hbs +0 -3
  263. package/templates/features/stylinNutin/src/styles/core/_utilities.scss.hbs +0 -254
  264. package/templates/features/stylinNutin/src/styles/views/_index.scss.hbs +0 -0
  265. package/templates/features/stylinNutin/tools/generator/templates/scss.template.js.hbs +0 -4
  266. package/templates/features/template/src/app/views/home/home.view.html.hbs +0 -56
  267. package/templates/features/template/src/app/views/not-found/not-found.view.html.hbs +0 -19
  268. package/templates/features/template/tools/builder/core/merge-templates.js.hbs +0 -49
  269. package/templates/features/template/tools/generator/templates/html.template.js.hbs +0 -2
  270. package/templates/features/testinNutin/testin-nutin/core/index.js.hbs +0 -5
  271. package/templates/features/testinNutin/testin-nutin/core/src/utils/print.js.hbs +0 -64
  272. package/templates/features/testinNutin/testin-nutin/core/src/utils/test-queue.js.hbs +0 -64
  273. package/templates/features/testinNutin/testin-nutin/core/tests/globals-each-all.test.js.hbs +0 -28
  274. package/templates/features/testinNutin/testin-nutin/mocks/mock-store.js.hbs +0 -38
  275. package/templates/features/testinNutin/testin-nutin/runner.js.hbs +0 -36
  276. package/templates/features/testinNutin/testin-nutin/watch-tests.js.hbs +0 -21
  277. package/templates/features/testinNutin/testin-nutin.config.js.hbs +0 -14
  278. /package/lib/src/{template-compiler.mjs → common/template-compiler.mjs} +0 -0
  279. /package/templates/{features/i18n → base}/src/core/base-classes/base-component/helpers/i18n.helper.ts.hbs +0 -0
  280. /package/templates/{features/i18n → base}/src/core/services/i18n/languages.ts.hbs +0 -0
  281. /package/templates/base/tools/builder/{variables → core/app}/binary-extensions.js.hbs +0 -0
  282. /package/templates/base/tools/builder/core/{paths.js.hbs → app/paths.js.hbs} +0 -0
  283. /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/queue.js.hbs +0 -0
  284. /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/test-discovery.js.hbs +0 -0
  285. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-http-client.js.hbs +0 -0
  286. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-i18n.js.hbs +0 -0
  287. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-router.js.hbs +0 -0
@@ -1,32 +1,40 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { spawn } from 'child_process';
3
4
  import { print, runCommand } from '../utils/index.js';
4
5
 
5
6
  async function startDev() {
6
- try {
7
- console.clear();
8
- print.boldHead('🚀 Starting Dev Environment...');
9
-
10
- await runCommand('{{packageManager}}', ['run', 'build']);
11
-
12
- const { serve, watcher } = await Promise.all([
13
- runCommand('{{packageManager}}', ['run', 'serve:only']),
14
- runCommand('node', ['tools/dev/watcher.js'])
15
- ]);
7
+ console.clear();
8
+ print.blue('🚀 Starting Dev Environment...\n');
16
9
 
17
- serve.on('close', (code) => {
18
- print.error(`live-server exited with code ${code}`);
19
- process.exit(code);
20
- });
21
- watcher.on('close', (code) => {
22
- print.error(`watcher exited with code ${code}`);
23
- });
10
+ try {
11
+ await runCommand('{{packageManager}}', ['run', 'build', '--silent']);
24
12
  } catch (err) {
25
13
  print.boldError(`Dev startup failed: ${err.message}`);
14
+ process.exit(1);
26
15
  }
16
+
17
+ const serve = spawn(['{{packageManager}}', 'run', 'serve:only', '--silent'].join(' '), { stdio: 'inherit', shell: true });
18
+ const watcher = spawn(['node', 'tools/dev/watcher.js', '--silent'].join(' '), { stdio: 'inherit', shell: true });
19
+
20
+ serve.on('error', (err) => {
21
+ print.boldError(`live-server failed to start: ${err.message}`);
22
+ process.exit(1);
23
+ });
24
+ serve.on('close', (code) => {
25
+ print.error(`live-server exited with code ${code}`);
26
+ process.exit(code ?? 1);
27
+ });
28
+ watcher.on('error', (err) => {
29
+ print.boldError(`watcher failed to start: ${err.message}`);
30
+ process.exit(1);
31
+ });
32
+ watcher.on('close', (code) => {
33
+ print.error(`watcher exited with code ${code}`);
34
+ });
27
35
  }
28
36
 
29
37
  startDev().catch((err) => {
30
38
  print.boldError(`Unexpected error: ${err.message}`);
31
- exit(1);
39
+ process.exit(1);
32
40
  });
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import liveServer from 'live-server';
4
+ import { print } from '../utils/index.js';
4
5
 
5
6
  const params = {
6
7
  port: 9090,
@@ -20,4 +21,13 @@ const params = {
20
21
  ]
21
22
  };
22
23
 
23
- liveServer.start(params);
24
+ try {
25
+ liveServer.start(params);
26
+ } catch (err) {
27
+ if (err.code === 'EADDRINUSE') {
28
+ print.boldError(`Port ${params.port} is already in use — stop the process using it or change the dev port.`);
29
+ } else {
30
+ print.boldError(`live-server failed to start: ${err.message}`);
31
+ }
32
+ process.exit(1);
33
+ }
@@ -11,6 +11,10 @@ const watcher = chokidar.watch(['src'], {
11
11
  let isBuilding = false;
12
12
  let buildTimeout = null;
13
13
 
14
+ watcher.on('error', (err) => {
15
+ print.boldError(`\nWatcher error: ${err.message}`);
16
+ });
17
+
14
18
  watcher.on('change', (filePath) => {
15
19
  if (buildTimeout) {
16
20
  clearTimeout(buildTimeout);
@@ -24,15 +28,19 @@ watcher.on('change', (filePath) => {
24
28
  print.boldInfo(`\n🔄 File changed: ${path.relative(process.cwd(), filePath)}\n`);
25
29
  print.info('\nRebuilding...');
26
30
 
27
- const command = '{{packageManager}} run build';
28
-
29
- exec(command, (err, stdout, stderr) => {
31
+ const command = '{{packageManager}} run build --silent';
32
+
33
+ exec(command, { maxBuffer: 10 * 1024 * 1024 }, (err, stdout, stderr) => {
30
34
  if (stdout) process.stdout.write(stdout);
31
35
  if (stderr) process.stderr.write(stderr);
32
36
  if (err) {
33
- print.error(`\n❌ Build failed: ${err.message}`);
37
+ if (err.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER') {
38
+ print.boldError(`\nBuild output exceeded the buffer size — raise maxBuffer in tools/dev/watcher.js.`);
39
+ } else {
40
+ print.boldError(`\nBuild failed: ${err.message}`);
41
+ }
34
42
  } else {
35
- print.boldHead('Watching for changes...');
43
+ print.boldBlue('Watching for changes...');
36
44
  }
37
45
  isBuilding = false;
38
46
  });
@@ -40,5 +48,5 @@ watcher.on('change', (filePath) => {
40
48
  });
41
49
 
42
50
  watcher.on('ready', () => {
43
- print.boldHead('\nWatching for changes...\n');
51
+ print.boldBlue('Watching for changes...');
44
52
  });
@@ -1,15 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import path from "path";
4
- import { allFormats, getLastWord, print{{#if stylinNutin}}, promptBoolean{{/if}} } from "../utils/index.js";
5
- import { generateFile, appendToIndex{{#if i18n}}, generateJson{{/if}}{{#if stylinNutin}}, generateStylesheet{{/if}} } from "./handle-file.js";
6
- import { serviceTemplate, componentTemplate, viewTemplate{{#if template}}, htmlTemplate{{/if}} } from "./templates/index.js";
4
+ import { allFormats, getLastWord, print, promptBoolean, errorExit } from "../utils/index.js";
5
+ import { generateFile, appendToIndex, generateLocalesJson } from "./handle-file.js";
6
+ import { serviceTemplate, componentTemplate, viewTemplate, htmlTemplate, scssTemplate, testTemplate } from "./templates/index.js";
7
+ import nutinConfig from "../../nutin.config.js";
7
8
 
8
9
  // Constants and Setup
9
10
  const [, , rawType, rawFullPath] = process.argv;
10
11
 
11
12
  if (!rawType || !rawFullPath) {
12
13
  showUsageAndExit("Missing arguments.");
14
+ process.exit(1);
13
15
  }
14
16
 
15
17
  const type = allFormats(rawType);
@@ -19,55 +21,43 @@ const targetPath = path.join('src', 'app', `${type.kebab}s/${fullPath.kebab}`);
19
21
 
20
22
  // Creator Mapping
21
23
  const creators = {
22
- service: (name, targetPath) => {
23
- print.section(`Creating service: ${name.capitalized}`);
24
+ service: async (name, targetPath) => {
25
+ const suffix = 'service';
26
+ print.section(`Generating service: ${name.capitalized}`);
24
27
  try {
25
- generateFile({ name, targetPath, templateFn: serviceTemplate, suffix: 'service' });
26
- appendToIndex({ name, targetPath, suffix: 'service' });
28
+ generateFile({ name, targetPath, templateFn: serviceTemplate, suffix: suffix });
29
+ appendToIndex({ name, targetPath, suffix: suffix });
30
+ if (nutinConfig.generator.generateTest) await generateTest({ name, targetPath, suffix: suffix });
27
31
  } catch (err) {
28
32
  handleError("Failed to generate service", err);
29
33
  }
30
34
  },
31
- component: {{#if stylinNutin}}async {{/if}}(name, targetPath) => {
32
- print.section(`Creating component: ${name.capitalized}`);
33
- {{#if stylinNutin}}
34
- const doCreateStylesheet = await promptBoolean('Create component\'s stylesheet in styles/components ?');
35
- {{/if}}
35
+ component: async (name, targetPath) => {
36
+ const suffix = 'component';
37
+ print.section(`Generating component: ${name.capitalized}`);
36
38
 
37
39
  try {
38
- generateFile({ name, targetPath, templateFn: componentTemplate, suffix: 'component' });
39
- {{#if template}}
40
- generateFile({ name, targetPath, templateFn: htmlTemplate, suffix: 'component', extension: 'html' });
41
- {{/if}}
42
- {{#if i18n}}
43
- generateJson({ targetPath, name });
44
- {{/if}}
45
- {{#if stylinNutin}}
46
- if (doCreateStylesheet) generateStylesheet({ name, suffix: 'component' });
47
- {{/if}}
48
- appendToIndex({ name, targetPath, suffix: 'component' });
40
+ generateFile({ name, targetPath, templateFn: componentTemplate, suffix: suffix });
41
+ generateFile({ name, targetPath, templateFn: htmlTemplate, suffix: suffix, extension: 'html' });
42
+ if (nutinConfig.generator.generateStylesheet) generateFile({ name, targetPath, templateFn: scssTemplate, suffix: suffix, extension: 'scss' });
43
+ if (nutinConfig.generator.generateLocales) await generateLocales({ targetPath, name });
44
+ appendToIndex({ name, targetPath, suffix: suffix });
45
+ if (nutinConfig.generator.generateTest) await generateTest({ name, targetPath, suffix });
49
46
  } catch (err) {
50
47
  handleError("Failed to generate component", err);
51
48
  }
52
49
  },
53
- view: {{#if stylinNutin}}async {{/if}}(name, targetPath) => {
54
- print.section(`Creating view: ${name.capitalized}`);
55
- {{#if stylinNutin}}
56
- const doCreateStylesheet = await promptBoolean('Create component\'s stylesheet in styles/components ?');
57
- {{/if}}
50
+ view: async (name, targetPath) => {
51
+ const suffix = 'view';
52
+ print.section(`Generating view: ${name.capitalized}`);
58
53
 
59
54
  try {
60
- generateFile({ name, targetPath, templateFn: viewTemplate, suffix: 'view' });
61
- {{#if template}}
62
- generateFile({ name, targetPath, templateFn: htmlTemplate, suffix: 'view', extension: 'html' });
63
- {{/if}}
64
- {{#if i18n}}
65
- generateJson({ targetPath, name });
66
- {{/if}}
67
- {{#if stylinNutin}}
68
- if (doCreateStylesheet) generateStylesheet({ name, suffix: 'view' });
69
- {{/if}}
70
- appendToIndex({name, targetPath, suffix: 'view' });
55
+ generateFile({ name, targetPath, templateFn: viewTemplate, suffix: suffix });
56
+ generateFile({ name, targetPath, templateFn: htmlTemplate, suffix: suffix, extension: 'html' });
57
+ if (nutinConfig.generator.generateStylesheet) generateFile({ name, targetPath, templateFn: scssTemplate, suffix: suffix, extension: 'scss' });
58
+ if (nutinConfig.generator.generateLocales) await generateLocales({ targetPath, name });
59
+ appendToIndex({ name, targetPath, suffix: suffix });
60
+ if (nutinConfig.generator.generateTest) await generateTest({ name, targetPath, suffix });
71
61
  } catch (err) {
72
62
  handleError("Failed to generate view", err);
73
63
  }
@@ -78,22 +68,49 @@ const creators = {
78
68
  const create = creators[type.kebab];
79
69
 
80
70
  if (create) {
81
- {{#if stylinNutin}}await {{/if}}create(name, targetPath);
82
- print.boldSuccess(`\n${type.capitalized} ${name.capitalized} has been generated.\n`)
71
+ await create(name, targetPath);
72
+ print.boldSuccess(`\n${type.capitalized} ${name.capitalized} generated in ${targetPath}.\n`)
83
73
  } else {
84
74
  showUsageAndExit(`Unsupported type: '${type.kebab}'`);
75
+ process.exit(1);
85
76
  }
86
77
 
87
78
  // Helper Functions
79
+ async function generateTest({ targetPath, name, suffix }) {
80
+ let isGenerate = true;
81
+ if (!nutinConfig.testinNutin.includeApp) {
82
+ print.warn('⚠️ Enable includeApp in nutin.config.js testinNutin object to use test files.');
83
+ if (!process.stdin.isTTY) {
84
+ print.warn('Non-interactive shell detected — skipping test file generation.');
85
+ isGenerate = false;
86
+ } else {
87
+ isGenerate = await promptBoolean('Do you want to generate the test file anyway ?');
88
+ }
89
+ }
90
+ if (isGenerate) generateFile({ targetPath, name, templateFn: testTemplate, extension: 'test.js', suffix: suffix });
91
+ }
92
+
93
+ async function generateLocales({ targetPath, name }) {
94
+ let isGenerate = true;
95
+ if (!nutinConfig.i18n) {
96
+ print.warn('⚠️ Enable i18n in nutin.config.js to use json-based content per language.');
97
+ if (!process.stdin.isTTY) {
98
+ print.warn('Non-interactive shell detected — skipping locales file generation.');
99
+ isGenerate = false;
100
+ } else {
101
+ isGenerate = await promptBoolean('Do you want to generate the locales file(s) anyway ?');
102
+ }
103
+ }
104
+ if (isGenerate) generateLocalesJson({ targetPath, name });
105
+ }
106
+
88
107
  function showUsageAndExit(message) {
89
- print.boldError(`\n❌ ${message}`);
90
- print.boldError("Usage: npm run generate <type> <path>");
91
- print.boldError(`Supported types: ${Object.keys(creators).join(", ")}`);
108
+ print.boldError(`\n${message}`);
109
+ print.warn("Usage: {{packageManager}} run generate <type> <path>");
110
+ print.warn(`Supported types: ${Object.keys(creators).join(", ")}`);
92
111
  process.exit(1);
93
112
  }
94
113
 
95
114
  function handleError(context, error) {
96
- print.boldError(`\n❌ ${context}`);
97
- print.boldError(error instanceof Error ? error.message : error);
98
- process.exit(1);
115
+ errorExit(error, context);
99
116
  }
@@ -1,12 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { print{{#if i18n}}, LANGUAGES{{/if}} } from '../utils/index.js';
4
- {{#if i18n}}
5
- import { jsonTemplate } from './templates/index.js';
6
- {{/if}}
7
- {{#if stylinNutin}}
8
- import { scssTemplate } from './templates/index.js';
9
- {{/if}}
3
+ import { print, LANGUAGES } from '../utils/index.js';
4
+ import { localeTemplate } from './templates/index.js';
10
5
 
11
6
  export function generateFile({
12
7
  name,
@@ -16,7 +11,7 @@ export function generateFile({
16
11
  extension = 'ts',
17
12
  }) {
18
13
  fs.mkdirSync(targetPath, { recursive: true });
19
- const template = templateFn(name, targetPath);
14
+ const template = templateFn(name, targetPath, suffix);
20
15
  const filePath = `${targetPath}/${name.kebab}.${suffix}.${extension}`;
21
16
 
22
17
  if (fs.existsSync(filePath)) {
@@ -42,51 +37,29 @@ export function appendToIndex({ name, targetPath, suffix }) {
42
37
 
43
38
  try {
44
39
  fs.appendFileSync(indexFilePath, lineToAppend, 'utf8');
45
- print.info(`${suffix}s/index.ts updated.`);
40
+ print.gray(`${suffix}s/index.ts updated.`);
46
41
  } catch (err) {
47
- print.error(`Error appending line: ${err}`);
42
+ throw new Error(`Failed to update ${indexFilePath}: ${err.message}`, { cause: err });
48
43
  }
49
44
  }
50
45
 
51
- {{#if i18n}}
52
- export function generateJson({ targetPath, name }) {
46
+ export function generateLocalesJson({ targetPath, name }) {
53
47
  const localesDir = `${targetPath}/locales`;
54
48
  fs.mkdirSync(localesDir, { recursive: true });
55
49
 
56
- const template = targetPath.includes('view') ? jsonTemplate(name) : `{ "default": "${name.pascal} works !"}`;
50
+ const template = localeTemplate(name);
57
51
 
58
- // include "meta" keys for views, empty JSON for components
59
- LANGUAGES.forEach((lang) => {
60
- fs.writeFileSync(`${localesDir}/${lang}.json`, template);
61
- });
62
- }
63
-
64
- {{/if}}
65
- {{#if stylinNutin}}
66
- export function generateStylesheet({ name, suffix }) {
67
- const template = scssTemplate();
68
- const stylesPath = path.join('src', 'styles', `${suffix}s`);
69
- const filePath = path.join(stylesPath, `_${name.kebab}.${suffix}.scss`);
70
- const indexPath = path.join(stylesPath, `_index.scss`);
71
-
72
- if (!fs.existsSync(stylesPath) || !fs.existsSync(indexPath)) {
73
- print.boldError('Non existing path');
74
- process.exit(1);
75
- }
76
- if (fs.existsSync(filePath)) {
77
- print.boldError('A file with this name already exists');
78
- process.exit(1);
52
+ const failedLangs = [];
53
+ for (const lang of LANGUAGES) {
54
+ try {
55
+ fs.writeFileSync(`${localesDir}/${lang}.json`, template);
56
+ } catch (err) {
57
+ print.error(`Failed to write locale file for "${lang}": ${err.message}`);
58
+ failedLangs.push(lang);
59
+ }
79
60
  }
80
61
 
81
- fs.writeFileSync(filePath, template);
82
-
83
- const lineToAppend = `@forward "${name.kebab}.${suffix}";\n`;
84
-
85
- try {
86
- fs.appendFileSync(indexPath, lineToAppend, 'utf8');
87
- } catch (err) {
88
- print.error(`Error appending line: ${err}`);
62
+ if (failedLangs.length) {
63
+ throw new Error(`Failed to generate locale file(s) for: ${failedLangs.join(', ')}`);
89
64
  }
90
65
  }
91
-
92
- {{/if}}
@@ -0,0 +1,72 @@
1
+ import fs from 'fs';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import { generateFile, appendToIndex } from './handle-file.js';
5
+
6
+ describe('handle-file', () => {
7
+ let tmpDir;
8
+ let originalCwd;
9
+ let exitSpy;
10
+
11
+ beforeEach(() => {
12
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nutin-handle-file-'));
13
+ originalCwd = process.cwd();
14
+ exitSpy = spyOn(process, 'exit').andCallFake(() => {});
15
+ });
16
+
17
+ afterEach(() => {
18
+ exitSpy.restore();
19
+ process.chdir(originalCwd);
20
+ fs.rmSync(tmpDir, { recursive: true, force: true });
21
+ });
22
+
23
+ it('generateFile writes the template output to <targetPath>/<name>.<suffix>.<extension>', () => {
24
+ const targetPath = path.join(tmpDir, 'components', 'widget');
25
+ const name = { kebab: 'widget', pascal: 'Widget', camel: 'widget', capitalized: 'Widget' };
26
+
27
+ generateFile({ name, targetPath, templateFn: (n) => `content for ${n.kebab}`, suffix: 'component' });
28
+
29
+ const filePath = path.join(targetPath, 'widget.component.ts');
30
+ expect(fs.existsSync(filePath)).toBeTruthy();
31
+ expect(fs.readFileSync(filePath, 'utf8')).toBe('content for widget');
32
+ expect(exitSpy.callCount).toBe(0);
33
+ });
34
+
35
+ it('generateFile respects a custom extension', () => {
36
+ const targetPath = path.join(tmpDir, 'services', 'widget');
37
+ const name = { kebab: 'widget', pascal: 'Widget', camel: 'widget', capitalized: 'Widget' };
38
+
39
+ generateFile({ name, targetPath, templateFn: () => 'x', suffix: 'service', extension: 'js' });
40
+
41
+ expect(fs.existsSync(path.join(targetPath, 'widget.service.js'))).toBeTruthy();
42
+ });
43
+
44
+ it('generateFile calls process.exit(1) instead of overwriting an existing file', () => {
45
+ const targetPath = path.join(tmpDir, 'components', 'widget');
46
+ const name = { kebab: 'widget', pascal: 'Widget', camel: 'widget', capitalized: 'Widget' };
47
+ const templateFn = () => 'fixed content';
48
+
49
+ generateFile({ name, targetPath, templateFn, suffix: 'component' });
50
+ // the second call hits the already-exists guard, which prints via console.error
51
+ silenceConsole('error', () => generateFile({ name, targetPath, templateFn, suffix: 'component' }));
52
+
53
+ expect(exitSpy.callCount).toBe(1);
54
+ expect(exitSpy.lastCall).toEqual([1]);
55
+ });
56
+
57
+ it('appendToIndex appends an export line to the barrel three segments up from targetPath', () => {
58
+ process.chdir(tmpDir);
59
+ const basePath = path.join('src', 'app', 'components');
60
+ fs.mkdirSync(basePath, { recursive: true });
61
+ fs.writeFileSync(path.join(basePath, 'index.ts'), "export * from './existing.js';\n");
62
+
63
+ const targetPath = path.join('src', 'app', 'components', 'widget');
64
+ const name = { kebab: 'widget', pascal: 'Widget', camel: 'widget', capitalized: 'Widget' };
65
+
66
+ // appendToIndex prints a "index.ts updated" log via console.info
67
+ silenceConsole('info', () => appendToIndex({ name, targetPath, suffix: 'component' }));
68
+
69
+ const indexContent = fs.readFileSync(path.join(basePath, 'index.ts'), 'utf8');
70
+ expect(indexContent).toBe("export * from './existing.js';\nexport * from './widget/widget.component.js';\n");
71
+ });
72
+ });
@@ -1,11 +1,12 @@
1
- import { getRelToCore } from "../../utils/get-rel-to-core.js";
1
+ import { getRelToCore } from "../../../utils/get-rel-to-core.js";
2
2
 
3
3
  export const componentTemplate = (name, targetPath) => {
4
4
  const relToCore = getRelToCore(targetPath);
5
+ const htmlTemplate = '__TEMPLATE_PLACEHOLDER__';
5
6
 
6
7
  return `import { Component } from '${relToCore}';
7
8
 
8
- const templateFn = () => {{#if template}}\`__TEMPLATE_PLACEHOLDER__\`{{else}}\`<div>${name.pascal} works !</div>\`{{/if}};
9
+ const templateFn = () => \`${htmlTemplate}\`;
9
10
 
10
11
  export class ${name.pascal}Component extends Component {
11
12
  constructor(mountTarget: HTMLElement) {
@@ -0,0 +1,23 @@
1
+ import { componentTemplate } from './component.template.js';
2
+
3
+ describe('componentTemplate', () => {
4
+ it('renders a component class importing Component via the relative core path', () => {
5
+ const name = { pascal: 'Widget' };
6
+ const targetPath = 'src/app/components/widget';
7
+
8
+ // The generator always leaves the html body as a placeholder — the builder
9
+ // swaps in the .html sibling's content at build time.
10
+ expect(componentTemplate(name, targetPath)).toBe(
11
+ `import { Component } from '../../../core/index.js';
12
+
13
+ const templateFn = () => \`__TEMPLATE_PLACEHOLDER__\`;
14
+
15
+ export class WidgetComponent extends Component {
16
+ constructor(mountTarget: HTMLElement) {
17
+ super({templateFn, mountTarget});
18
+ }
19
+ }
20
+ `
21
+ );
22
+ });
23
+ });
@@ -0,0 +1,2 @@
1
+ export const htmlTemplate = (name) => `<div>${name.pascal} works !</div>
2
+ `;
@@ -0,0 +1,7 @@
1
+ import { htmlTemplate } from './html.template.js';
2
+
3
+ describe('htmlTemplate', () => {
4
+ it('renders a placeholder div with the component/view name', () => {
5
+ expect(htmlTemplate({ pascal: 'Widget' })).toBe('<div>Widget works !</div>\n');
6
+ });
7
+ });
@@ -1,12 +1,7 @@
1
- export * from './component.template.js';
2
- export * from './view.template.js';
3
- export * from './service.template.js';
4
- {{#if template}}
5
- export * from './html.template.js';
6
- {{/if}}
7
- {{#if i18n}}
8
- export * from './json.template.js';
9
- {{/if}}
10
- {{#if stylinNutin}}
11
- export * from './scss.template.js';
12
- {{/if}}
1
+ export * from './component/component.template.js';
2
+ export * from './view/view.template.js';
3
+ export * from './service/service.template.js';
4
+ export * from './locale/locale.template.js';
5
+ export * from './scss/scss.template.js';
6
+ export * from './html/html.template.js';
7
+ export * from './test/test.template.js';
@@ -0,0 +1,4 @@
1
+ export const localeTemplate = (name) => `{
2
+ "default": "${name.pascal} works !"
3
+ }
4
+ `;
@@ -0,0 +1,7 @@
1
+ import { localeTemplate } from './locale.template.js';
2
+
3
+ describe('localeTemplate', () => {
4
+ it('renders a locale JSON stub with a "default" key', () => {
5
+ expect(localeTemplate({ pascal: 'Widget' })).toBe('{\n "default": "Widget works !"\n}\n');
6
+ });
7
+ });
@@ -0,0 +1 @@
1
+ export const scssTemplate = () => `\n`;
@@ -0,0 +1,7 @@
1
+ import { scssTemplate } from './scss.template.js';
2
+
3
+ describe('scssTemplate', () => {
4
+ it('renders an empty stylesheet placeholder', () => {
5
+ expect(scssTemplate()).toBe('\n');
6
+ });
7
+ });
@@ -0,0 +1,17 @@
1
+ import { getRelToCore } from "../../../utils/get-rel-to-core.js";
2
+
3
+ export const serviceTemplate = (name, targetPath) => {
4
+ const relToCore = getRelToCore(targetPath);
5
+
6
+ return `import { Service } from '${relToCore}';
7
+
8
+ export class ${name.pascal}Service extends Service<${name.pascal}Service> {
9
+ constructor() {
10
+ super();
11
+ }
12
+
13
+ }
14
+
15
+ export const ${name.camel}Service = ${name.pascal}Service.getInstance();
16
+ `;
17
+ }
@@ -0,0 +1,22 @@
1
+ import { serviceTemplate } from './service.template.js';
2
+
3
+ describe('serviceTemplate', () => {
4
+ it('renders a Service subclass with a singleton export, importing Service via the relative core path', () => {
5
+ const name = { pascal: 'Widget', camel: 'widget' };
6
+ const targetPath = 'src/app/components/widget';
7
+
8
+ expect(serviceTemplate(name, targetPath)).toBe(
9
+ `import { Service } from '../../../core/index.js';
10
+
11
+ export class WidgetService extends Service<WidgetService> {
12
+ constructor() {
13
+ super();
14
+ }
15
+
16
+ }
17
+
18
+ export const widgetService = WidgetService.getInstance();
19
+ `
20
+ );
21
+ });
22
+ });
@@ -0,0 +1,10 @@
1
+ export const testTemplate = (name, targetPath, suffix) => {
2
+ const type = suffix.charAt(0).toUpperCase() + suffix.slice(1);
3
+
4
+ return `import { ${name.pascal}${type} } from '#root/dist/${targetPath}/${name.kebab}.${suffix}.js';
5
+
6
+ describe('${name.pascal}${type}', () => {
7
+ it.todo('Write tests for ${name.pascal}${type}');
8
+ });
9
+ `;
10
+ }
@@ -0,0 +1,27 @@
1
+ import { testTemplate } from './test.template.js';
2
+
3
+ describe('testTemplate', () => {
4
+ it('renders an it.todo stub importing the built output via #root/dist', () => {
5
+ const name = { pascal: 'Widget', kebab: 'widget' };
6
+ const targetPath = 'src/app/components/widget';
7
+
8
+ expect(testTemplate(name, targetPath, 'component')).toBe(
9
+ `import { WidgetComponent } from '#root/dist/src/app/components/widget/widget.component.js';
10
+
11
+ describe('WidgetComponent', () => {
12
+ it.todo('Write tests for WidgetComponent');
13
+ });
14
+ `
15
+ );
16
+ });
17
+
18
+ it('capitalizes only the first letter of the suffix for the "Type" suffix on the class name', () => {
19
+ const name = { pascal: 'Home', kebab: 'home' };
20
+ const targetPath = 'src/app/views/home';
21
+
22
+ const result = testTemplate(name, targetPath, 'view');
23
+
24
+ expect(result).toContain('HomeView');
25
+ expect(result).toContain("it.todo('Write tests for HomeView');");
26
+ });
27
+ });
@@ -1,11 +1,12 @@
1
- import { getRelToCore } from "../../utils/get-rel-to-core.js";
1
+ import { getRelToCore } from "../../../utils/get-rel-to-core.js";
2
2
 
3
3
  export const viewTemplate = (name, targetPath) => {
4
4
  const relToCore = getRelToCore(targetPath);
5
+ const htmlTemplate = '__TEMPLATE_PLACEHOLDER__';
5
6
 
6
7
  return `import { View } from '${relToCore}';
7
8
 
8
- const template = {{#if template}}\`__TEMPLATE_PLACEHOLDER__\`{{else}}\`<div>${name.pascal} works !</div>\`{{/if}};
9
+ const template = \`${htmlTemplate}\`;
9
10
 
10
11
  export class ${name.pascal}View extends View {
11
12
  constructor() {