@nutin/cli 1.3.0 → 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 (284) hide show
  1. package/CHANGELOG.md +122 -8
  2. package/README.md +21 -37
  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 +81 -30
  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/create-app/new-app-prompt.mjs +51 -0
  22. package/lib/src/{project-generator.mjs → create-app/project-generator.mjs} +15 -13
  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 -15
  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 +81 -31
  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 +38 -23
  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 +41 -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 +13 -14
  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 +27 -40
  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/config.helper.ts.hbs +17 -0
  70. package/templates/base/src/core/base-classes/component/helpers/data-binding.helper.test.js.hbs +75 -0
  71. package/templates/base/src/core/base-classes/service/service.test.js.hbs +150 -0
  72. package/templates/base/src/core/base-classes/service/service.ts.hbs +26 -20
  73. package/templates/base/src/core/base-classes/view/view.test.js.hbs +74 -0
  74. package/templates/base/src/core/base-classes/view/view.ts.hbs +17 -41
  75. package/templates/base/src/core/config.ts.hbs +7 -0
  76. package/templates/base/src/core/index.ts.hbs +0 -3
  77. package/templates/base/src/core/internals.d.ts.hbs +27 -0
  78. package/templates/base/src/core/nutin-config.d.ts.hbs +4 -0
  79. package/templates/base/src/core/services/event-bus/event-bus.test.js.hbs +67 -3
  80. package/templates/base/src/core/services/event-bus/event-bus.ts.hbs +9 -4
  81. package/templates/base/src/core/services/event-bus/index.ts.hbs +3 -0
  82. package/templates/base/src/core/services/event-bus/lifecycle.facade.test.js.hbs +123 -0
  83. package/templates/base/src/core/services/event-bus/lifecycle.facade.ts.hbs +61 -0
  84. package/templates/base/src/core/services/event-bus/navigation.facade.test.js.hbs +46 -0
  85. package/templates/base/src/core/services/event-bus/navigation.facade.ts.hbs +25 -0
  86. package/templates/base/src/core/services/globals/globals.test.js.hbs +149 -0
  87. package/templates/base/src/core/services/globals/globals.ts.hbs +95 -0
  88. package/templates/base/src/core/services/http-client/helpers/http-builder.helper.test.js.hbs +25 -0
  89. package/templates/base/src/core/services/http-client/helpers/http-manager.helper.test.js.hbs +20 -0
  90. package/templates/base/src/core/services/http-client/http-client.test.js.hbs +43 -0
  91. package/templates/base/src/core/services/i18n/i18n.test.js.hbs +270 -0
  92. package/templates/{features/i18n → base}/src/core/services/i18n/i18n.ts.hbs +60 -9
  93. package/templates/base/src/core/services/index.ts.hbs +5 -6
  94. package/templates/base/src/core/services/pipe-registry/pipe-registry.test.js.hbs +60 -1
  95. package/templates/base/src/core/services/pipe-registry/pipe-registry.ts.hbs +1 -1
  96. package/templates/base/src/core/services/pipe-registry/pipes.test.js.hbs +128 -0
  97. package/templates/base/src/{libs/pipes → core/services/pipe-registry}/pipes.ts.hbs +8 -5
  98. package/templates/base/src/core/services/router/helpers/navigation-manager.helper.test.js.hbs +149 -6
  99. package/templates/base/src/core/services/router/helpers/navigation-manager.helper.ts.hbs +42 -30
  100. package/templates/base/src/core/services/router/helpers/route-guard-manager.helper.test.js.hbs +27 -0
  101. package/templates/base/src/core/services/router/helpers/view-render-manager.helper.test.js.hbs +83 -17
  102. package/templates/base/src/core/services/router/helpers/view-render-manager.helper.ts.hbs +13 -70
  103. package/templates/base/src/core/services/router/router.test.js.hbs +226 -2
  104. package/templates/base/src/core/services/router/router.ts.hbs +40 -9
  105. package/templates/base/src/index.html.hbs +2 -6
  106. package/templates/base/src/styles/_styles.scss.hbs +102 -43
  107. package/templates/base/src/styles/base/_variables.scss.hbs +1 -85
  108. package/templates/base/src/styles/main.scss.hbs +1 -18
  109. package/templates/base/src/styles/tailwind.css.hbs +2 -0
  110. package/templates/base/tools/builder/builder.config.js.hbs +40 -0
  111. package/templates/base/tools/builder/builder.js.hbs +24 -26
  112. package/templates/base/tools/builder/core/app/binary-extensions.test.js.hbs +16 -0
  113. package/templates/base/tools/builder/core/app/compile-ts.js.hbs +16 -0
  114. package/templates/base/tools/builder/core/{copy-static.js.hbs → app/copy-static.js.hbs} +27 -34
  115. package/templates/base/tools/builder/core/app/validate-routes.js.hbs +77 -0
  116. package/templates/base/tools/builder/core/finalize-build.js.hbs +16 -7
  117. package/templates/base/tools/builder/core/{add-tags.js.hbs → html-index/add-tags.js.hbs} +2 -2
  118. package/templates/base/tools/builder/core/html-index/add-tags.test.js.hbs +56 -0
  119. package/templates/base/tools/builder/core/{validate-html.js.hbs → html-index/validate-html.js.hbs} +5 -11
  120. package/templates/base/tools/builder/core/html-templates/merge-templates.js.hbs +152 -0
  121. package/templates/base/tools/builder/core/html-templates/minify-html.js.hbs +15 -0
  122. package/templates/base/tools/builder/core/html-templates/process-html-templates.js.hbs +8 -0
  123. package/templates/{features/i18n/tools/builder/core → base/tools/builder/core/i18n}/build-i18n.js.hbs +6 -17
  124. package/templates/base/tools/builder/core/prod-bundle/compress-files.js.hbs +37 -0
  125. package/templates/base/tools/builder/core/prod-bundle/esbuild.js.hbs +30 -0
  126. package/templates/base/tools/builder/core/{hash-files.js.hbs → prod-bundle/hash-files.js.hbs} +14 -11
  127. package/templates/base/tools/builder/core/seo/generate-robots-txt.js.hbs +51 -0
  128. package/templates/base/tools/builder/core/seo/generate-seo-files.js.hbs +16 -0
  129. package/templates/base/tools/builder/core/seo/generate-seo-html.js.hbs +128 -0
  130. package/templates/base/tools/builder/core/seo/generate-sitemap-xml.js.hbs +43 -0
  131. package/templates/base/tools/builder/core/seo/html-substitutions.js.hbs +99 -0
  132. package/templates/base/tools/builder/core/seo/i18n-resolution.js.hbs +66 -0
  133. package/templates/base/tools/builder/core/seo/route-output.js.hbs +64 -0
  134. package/templates/base/tools/builder/core/seo/ssr/ssr-bundle.js.hbs +54 -0
  135. package/templates/base/tools/builder/core/seo/ssr/ssr-polyfills.js.hbs +132 -0
  136. package/templates/base/tools/builder/core/seo/ssr/ssr-render.js.hbs +95 -0
  137. package/templates/base/tools/builder/core/styles/sass.js.hbs +40 -0
  138. package/templates/base/tools/builder/core/styles/tailwind.js.hbs +84 -0
  139. package/templates/base/tools/dev/dev-serve.js.hbs +26 -18
  140. package/templates/base/tools/dev/serve.js.hbs +11 -1
  141. package/templates/base/tools/dev/watcher.js.hbs +14 -6
  142. package/templates/base/tools/generator/generator.js.hbs +64 -47
  143. package/templates/base/tools/generator/handle-file.js.hbs +17 -44
  144. package/templates/base/tools/generator/handle-file.test.js.hbs +72 -0
  145. package/templates/base/tools/generator/templates/{component.template.js.hbs → component/component.template.js.hbs} +3 -2
  146. package/templates/base/tools/generator/templates/component/component.template.test.js.hbs +23 -0
  147. package/templates/base/tools/generator/templates/html/html.template.js.hbs +2 -0
  148. package/templates/base/tools/generator/templates/html/html.template.test.js.hbs +7 -0
  149. package/templates/base/tools/generator/templates/index.js.hbs +7 -12
  150. package/templates/base/tools/generator/templates/locale/locale.template.js.hbs +4 -0
  151. package/templates/base/tools/generator/templates/locale/locale.template.test.js.hbs +7 -0
  152. package/templates/base/tools/generator/templates/scss/scss.template.js.hbs +1 -0
  153. package/templates/base/tools/generator/templates/scss/scss.template.test.js.hbs +7 -0
  154. package/templates/base/tools/generator/templates/service/service.template.js.hbs +17 -0
  155. package/templates/base/tools/generator/templates/service/service.template.test.js.hbs +22 -0
  156. package/templates/base/tools/generator/templates/test/test.template.js.hbs +10 -0
  157. package/templates/base/tools/generator/templates/test/test.template.test.js.hbs +27 -0
  158. package/templates/base/tools/generator/templates/{view.template.js.hbs → view/view.template.js.hbs} +3 -2
  159. package/templates/base/tools/generator/templates/view/view.template.test.js.hbs +24 -0
  160. package/templates/base/tools/testin-nutin/core/coverage/collect-coverage.js.hbs +39 -0
  161. package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.js.hbs +115 -0
  162. package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.test.js.hbs +74 -0
  163. package/templates/base/tools/testin-nutin/core/coverage/write-summary-report.js.hbs +54 -0
  164. package/templates/base/tools/testin-nutin/core/coverage/write-uncovered-report.js.hbs +44 -0
  165. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/assertion-lib.js.hbs +62 -24
  166. package/templates/base/tools/testin-nutin/core/globals/clock.js.hbs +206 -0
  167. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/jsdom-setup.js.hbs +19 -6
  168. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/register-test-globals.js.hbs +13 -4
  169. package/templates/base/tools/testin-nutin/core/globals/silence-console.js.hbs +23 -0
  170. package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/spyon.js.hbs +2 -0
  171. package/templates/base/tools/testin-nutin/core/index.js.hbs +9 -0
  172. package/templates/base/tools/testin-nutin/core/printer.js.hbs +85 -0
  173. package/templates/base/tools/testin-nutin/core/queue/queue.test.js.hbs +46 -0
  174. package/templates/base/tools/testin-nutin/core/queue/test-discovery.test.js.hbs +46 -0
  175. package/templates/base/tools/testin-nutin/core/queue/test-queue.js.hbs +154 -0
  176. package/templates/{features/testinNutin → base/tools}/testin-nutin/core/tests/assertions.test.js.hbs +27 -0
  177. package/templates/base/tools/testin-nutin/core/tests/clock.test.js.hbs +118 -0
  178. package/templates/base/tools/testin-nutin/core/tests/globals-each-all.test.js.hbs +28 -0
  179. package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/create-mock-method.js.hbs +2 -1
  180. package/templates/base/tools/testin-nutin/mocks/create-mock-method.test.js.hbs +64 -0
  181. package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-event-bus.js.hbs +3 -2
  182. package/templates/base/tools/testin-nutin/mocks/mock-event-bus.test.js.hbs +66 -0
  183. package/templates/base/tools/testin-nutin/mocks/mock-http-client.test.js.hbs +26 -0
  184. package/templates/base/tools/testin-nutin/mocks/mock-i18n.test.js.hbs +61 -0
  185. package/templates/base/tools/testin-nutin/mocks/mock-router.test.js.hbs +29 -0
  186. package/templates/base/tools/testin-nutin/runner.js.hbs +100 -0
  187. package/templates/base/tools/testin-nutin/watch-tests.js.hbs +37 -0
  188. package/templates/base/tools/utils/error-exit.js.hbs +8 -0
  189. package/templates/base/tools/utils/format.js.hbs +10 -10
  190. package/templates/base/tools/utils/format.test.js.hbs +45 -0
  191. package/templates/base/tools/utils/get-files-recursive.js.hbs +6 -1
  192. package/templates/base/tools/utils/get-files-recursive.test.js.hbs +49 -0
  193. package/templates/base/tools/utils/get-rel-to-core.test.js.hbs +18 -0
  194. package/templates/base/tools/utils/index.js.hbs +1 -3
  195. package/templates/base/tools/utils/languages.js.hbs +15 -0
  196. package/templates/base/tools/utils/languages.test.js.hbs +16 -0
  197. package/templates/base/tools/utils/print.js.hbs +19 -13
  198. package/templates/base/tools/utils/print.test.js.hbs +60 -0
  199. package/templates/base/tools/utils/prompt-boolean.js.hbs +7 -0
  200. package/templates/base/tools/utils/prompt-boolean.test.js.hbs +54 -0
  201. package/templates/base/tools/utils/run-command.js.hbs +4 -2
  202. package/templates/base/tools/utils/run-command.test.js.hbs +19 -0
  203. package/templates/base/tools/utils/run-script.js.hbs +14 -3
  204. package/templates/base/tools/utils/run-script.test.js.hbs +40 -0
  205. package/templates/features/{deployHelper → docker}/.dockerignore.hbs +4 -4
  206. package/templates/features/docker/tools/docker/Dockerfile.template.hbs +51 -0
  207. package/templates/features/{deployHelper/tools/deployment/nginx.conf.hbs → docker/tools/docker/nginx.conf.template} +4 -2
  208. package/templates/features/docker/tools/docker/scripts/docker-build.js.hbs +20 -0
  209. package/templates/features/docker/tools/docker/scripts/docker-ports.js.hbs +48 -0
  210. package/templates/features/docker/tools/docker/scripts/docker-ports.test.js.hbs +52 -0
  211. package/templates/features/docker/tools/docker/scripts/docker-run.js.hbs +28 -0
  212. package/templates/features/docker/tools/docker/scripts/render-docker-template.js.hbs +23 -0
  213. package/templates/features/docker/tools/docker/scripts/render-docker-template.test.js.hbs +60 -0
  214. package/templates/features/docker/tools/docker/scripts/validate-docker.js.hbs +30 -0
  215. package/lib/src/context-builder.mjs +0 -35
  216. package/lib/src/file-generator.mjs +0 -109
  217. package/lib/src/json-generator.mjs +0 -31
  218. package/lib/src/package-manager.mjs +0 -139
  219. package/lib/src/print.mjs +0 -31
  220. package/lib/src/prompts.mjs +0 -123
  221. package/lib/src/utils.mjs +0 -18
  222. package/lib/src/version.mjs +0 -1
  223. package/templates/base/builder.config.js.hbs +0 -35
  224. package/templates/base/src/app/components/common/anchor/anchor.component.ts.hbs +0 -32
  225. package/templates/base/src/app/components/common/button/button.component.ts.hbs +0 -40
  226. package/templates/base/src/app/dom.test.js.hbs +0 -13
  227. package/templates/base/src/app/services/example/example.service.ts.hbs +0 -18
  228. package/templates/base/src/app/views/home/home.view.test.js.hbs +0 -26
  229. package/templates/base/src/core/services/store/store.test.js.hbs +0 -8
  230. package/templates/base/src/core/services/store/store.ts.hbs +0 -39
  231. package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.test.js.hbs +0 -0
  232. package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.ts.hbs +0 -85
  233. package/templates/base/src/core/utils/button-manager/button-manager.utils.test.js.hbs +0 -249
  234. package/templates/base/src/core/utils/button-manager/button-manager.utils.ts.hbs +0 -108
  235. package/templates/base/src/core/utils/helpers/attributes.helper.ts.hbs +0 -50
  236. package/templates/base/src/core/utils/index.ts.hbs +0 -2
  237. package/templates/base/src/libs/index.ts.hbs +0 -4
  238. package/templates/base/src/libs/popover/popover.ts.hbs +0 -145
  239. package/templates/base/src/libs/snackbar/snackbar.ts.hbs +0 -72
  240. package/templates/base/src/styles/base/_functions.scss.hbs +0 -9
  241. package/templates/base/src/styles/core/_libs.scss.hbs +0 -132
  242. package/templates/base/tools/builder/core/esbuild.js.hbs +0 -25
  243. package/templates/base/tools/builder/core/minify-html.js.hbs +0 -60
  244. package/templates/base/tools/builder/core/sass.js.hbs +0 -22
  245. package/templates/base/tools/builder/core/tsc.js.hbs +0 -12
  246. package/templates/base/tools/generator/templates/service.template.js.hbs +0 -17
  247. package/templates/base/tools/utils/export-flags.js.hbs +0 -6
  248. package/templates/features/deployHelper/tools/builder/core/compress-files.js.hbs +0 -56
  249. package/templates/features/deployHelper/tools/deployment/Dockerfile.hbs +0 -30
  250. package/templates/features/i18n/src/app/views/home/locales/en.json.hbs +0 -9
  251. package/templates/features/i18n/src/app/views/not-found/locales/en.json +0 -8
  252. package/templates/features/i18n/src/app/views/not-found/locales/fr.json +0 -8
  253. package/templates/features/i18n/src/core/config.ts.hbs +0 -3
  254. package/templates/features/i18n/src/core/services/i18n/i18n.test.js.hbs +0 -125
  255. package/templates/features/i18n/tools/generator/templates/json.template.js.hbs +0 -8
  256. package/templates/features/i18n/tools/utils/languages.js.hbs +0 -7
  257. package/templates/features/stylinNutin/src/styles/_custom-classes.scss.hbs +0 -9
  258. package/templates/features/stylinNutin/src/styles/base/_mixins.scss.hbs +0 -372
  259. package/templates/features/stylinNutin/src/styles/components/_index.scss.hbs +0 -3
  260. package/templates/features/stylinNutin/src/styles/core/_utilities.scss.hbs +0 -240
  261. package/templates/features/stylinNutin/src/styles/views/_index.scss.hbs +0 -0
  262. package/templates/features/stylinNutin/tools/generator/templates/scss.template.js.hbs +0 -4
  263. package/templates/features/template/src/app/views/home/home.view.html.hbs +0 -56
  264. package/templates/features/template/src/app/views/not-found/not-found.view.html.hbs +0 -19
  265. package/templates/features/template/tools/builder/core/merge-templates.js.hbs +0 -49
  266. package/templates/features/template/tools/generator/templates/html.template.js.hbs +0 -2
  267. package/templates/features/testinNutin/testin-nutin/core/index.js.hbs +0 -5
  268. package/templates/features/testinNutin/testin-nutin/core/src/utils/print.js.hbs +0 -64
  269. package/templates/features/testinNutin/testin-nutin/core/src/utils/test-queue.js.hbs +0 -64
  270. package/templates/features/testinNutin/testin-nutin/core/tests/globals-each-all.test.js.hbs +0 -28
  271. package/templates/features/testinNutin/testin-nutin/mocks/mock-store.js.hbs +0 -38
  272. package/templates/features/testinNutin/testin-nutin/runner.js.hbs +0 -36
  273. package/templates/features/testinNutin/testin-nutin/watch-tests.js.hbs +0 -21
  274. package/templates/features/testinNutin/testin-nutin.config.js.hbs +0 -14
  275. /package/lib/src/{template-compiler.mjs → common/template-compiler.mjs} +0 -0
  276. /package/templates/{features/i18n → base}/src/core/base-classes/base-component/helpers/i18n.helper.ts.hbs +0 -0
  277. /package/templates/{features/i18n → base}/src/core/services/i18n/languages.ts.hbs +0 -0
  278. /package/templates/base/tools/builder/{variables → core/app}/binary-extensions.js.hbs +0 -0
  279. /package/templates/base/tools/builder/core/{paths.js.hbs → app/paths.js.hbs} +0 -0
  280. /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/queue.js.hbs +0 -0
  281. /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/test-discovery.js.hbs +0 -0
  282. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-http-client.js.hbs +0 -0
  283. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-i18n.js.hbs +0 -0
  284. /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-router.js.hbs +0 -0
@@ -1,35 +0,0 @@
1
- import { getCiCommand } from './package-manager.mjs';
2
- import { packageVersion } from './version.mjs';
3
-
4
- export const defaults = {
5
- projectName: 'my-nutin-app',
6
- packageManager: 'npm',
7
- stylinNutin: true,
8
- template: true,
9
- i18n: false,
10
- deployHelper: false,
11
- testinNutin: false,
12
- transition: false
13
- };
14
-
15
- export class ContextBuilder {
16
- buildContext(answers) {
17
- const version = packageVersion;
18
- const ciCommand = getCiCommand(answers.packageManager);
19
-
20
- return {
21
- projectName: answers.projectName,
22
- packageManager: answers.packageManager,
23
-
24
- template: answers.template ?? defaults.template,
25
- stylinNutin: answers.stylinNutin ?? defaults.stylinNutin,
26
- i18n: answers.i18n ?? defaults.i18n,
27
- deployHelper: answers.deployHelper ?? defaults.deployHelper,
28
- testinNutin: answers.testinNutin ?? defaults.testinNutin,
29
- transition: answers.transition ?? defaults.transition,
30
-
31
- ciCommand: ciCommand,
32
- version: version
33
- };
34
- }
35
- }
@@ -1,109 +0,0 @@
1
- import path from 'path';
2
- import { fileURLToPath } from 'url';
3
- import * as fsExtra from 'fs-extra';
4
- import { TemplateCompiler } from './template-compiler.mjs';
5
- import { print } from './print.mjs';
6
-
7
- const fs = fsExtra.default;
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = path.dirname(__filename);
10
-
11
- const BINARY_EXTENSIONS = new Set([
12
- '.png', '.jpg', '.jpeg', '.gif', '.webp', '.avif', '.svg',
13
- '.ico', '.woff', '.woff2', '.ttf', '.otf', '.eot',
14
- '.mp4', '.webm', '.mp3', '.wav', '.ogg',
15
- '.pdf', '.zip', '.tar', '.gz'
16
- ]);
17
-
18
- export class FileGenerator {
19
- constructor() {
20
- this.compiler = new TemplateCompiler();
21
- }
22
-
23
- async generateProjectFromTemplates(projectPath, context) {
24
- const templateDir = this.getTemplateDirectory();
25
-
26
- print.section('📝 Processing templates...');
27
- await this.processTemplateDirectory(templateDir, projectPath, context);
28
-
29
- await this.processFeatureTemplates(projectPath, context);
30
- }
31
-
32
- getTemplateDirectory() {
33
- return path.join(__dirname, '..', '..', 'templates', 'base');
34
- }
35
-
36
- async processTemplateDirectory(templateDir, outputDir, context) {
37
- if (!(await fs.pathExists(templateDir))) {
38
- throw new Error(`Template directory not found: ${templateDir}`);
39
- }
40
-
41
- const entries = await fs.readdir(templateDir, { withFileTypes: true });
42
-
43
- for (const entry of entries) {
44
- if (entry.name === '.DS_Store') continue;
45
-
46
- const templatePath = path.join(templateDir, entry.name);
47
-
48
- if (entry.isDirectory()) {
49
- const outputPath = path.join(outputDir, entry.name);
50
- await fs.ensureDir(outputPath);
51
- await this.processTemplateDirectory(templatePath, outputPath, context);
52
- } else {
53
- await this.processTemplateFile(templatePath, outputDir, entry.name, context);
54
- }
55
- }
56
- }
57
-
58
- async processFeatureTemplates(projectPath, context) {
59
- const featuresDir = path.join(__dirname, '..', '..', 'templates', 'features');
60
-
61
- if (!(await fs.pathExists(featuresDir))) {
62
- return;
63
- }
64
-
65
- const features = [ 'template', 'i18n', 'stylinNutin', 'testinNutin', 'deployHelper' ];
66
-
67
- for (const feature of features) {
68
- if (context[feature]) {
69
- const featureTemplateDir = path.join(featuresDir, feature);
70
-
71
- if (await fs.pathExists(featureTemplateDir)) {
72
- print.info(` 🔧 Adding ${feature} feature...`);
73
- await this.processTemplateDirectory(featureTemplateDir, projectPath, context);
74
- }
75
- }
76
- }
77
- }
78
-
79
- async processTemplateFile(templatePath, outputDir, fileName, context) {
80
- if (fileName.includes("test.js") && !(context.testinNutin)) {
81
- return;
82
- }
83
-
84
- const fileExt = path.extname(fileName).toLowerCase();
85
-
86
- if (BINARY_EXTENSIONS.has(fileExt)) {
87
- const outputPath = path.join(outputDir, fileName);
88
- await fs.copy(templatePath, outputPath);
89
- // print.info(`📄 Copied: ${fileName}`);
90
- } else if (fileName.endsWith('.hbs')) {
91
-
92
- const outputFileName = fileName.replace('.hbs', '');
93
- const outputPath = path.join(outputDir, outputFileName);
94
-
95
- try {
96
- const compiledContent = await this.compiler.compileFile(templatePath, context);
97
- await fs.writeFile(outputPath, compiledContent);
98
- // print.info(`📝 Generated: ${outputFileName}`);
99
- } catch (error) {
100
- print.boldError(`❌ Failed to process template: ${fileName}`);
101
- throw error;
102
- }
103
- } else {
104
- const outputPath = path.join(outputDir, fileName);
105
- await fs.copy(templatePath, outputPath);
106
- // print.info(`📄 Copied: ${fileName}`);
107
- }
108
- }
109
- }
@@ -1,31 +0,0 @@
1
- import path from 'path';
2
- import * as fsExtra from 'fs-extra';
3
- import { generatePackageJson, generateTsconfigJson } from './package-manager.mjs';
4
-
5
- const fs = fsExtra.default;
6
-
7
- export class JsonGenerator {
8
- async generateJsonFiles(projectPath, context) {
9
- await generatePackageJson(projectPath, context);
10
- await generateTsconfigJson(projectPath, context);
11
- this.generateConfigFiles(projectPath, context);
12
- }
13
-
14
- async generateConfigFiles(projectPath, context) {
15
- const configPath = path.join(projectPath, 'config');
16
-
17
- if (context.i18n) {
18
- await fs.ensureDir(configPath);
19
- await this.generateLanguageConfig(configPath);
20
- }
21
- }
22
-
23
- async generateLanguageConfig(configPath) {
24
- const languages = {
25
- "languages": [ "en" ],
26
- "defaultLanguage": "en"
27
- };
28
-
29
- await fs.writeJSON(path.join(configPath, 'languages.json'), languages, { spaces: 2 });
30
- }
31
- }
@@ -1,139 +0,0 @@
1
- import { promiseExec } from './utils.mjs';
2
- import { print } from './print.mjs';
3
- import * as fsExtra from 'fs-extra';
4
- import * as path from 'path';
5
-
6
- const fs = fsExtra.default;
7
-
8
- export async function installDependencies(projectPath, packageManager) {
9
- print.section(`📦 Installing dependencies with ${packageManager}...`);
10
-
11
- const installCommand = getInstallCommand(packageManager);
12
- await promiseExec(installCommand, { cwd: projectPath });
13
- }
14
-
15
- export function getCiCommand(packageManager) {
16
- switch (packageManager) {
17
- case 'yarn':
18
- return 'yarn install --frozen-lockfile';
19
- case 'pnpm':
20
- return 'pnpm install --frozen-lockfile';
21
- case 'bun':
22
- return 'bun install --frozen-lockfile'
23
- default:
24
- return 'npm ci';
25
- }
26
- }
27
-
28
- function getInstallCommand(packageManager) {
29
- switch (packageManager) {
30
- case 'yarn':
31
- return 'yarn install';
32
- case 'pnpm':
33
- return 'pnpm install';
34
- case 'bun':
35
- return 'bun install'
36
- default:
37
- return 'npm install';
38
- }
39
- }
40
-
41
- function getScripts(context) {
42
- const { testinNutin, packageManager, projectName, deployHelper } = context;
43
-
44
- const baseScripts = {
45
- "build": "node tools/builder/builder.js",
46
- "build:prod": "NODE_ENV=production node tools/builder/builder.js",
47
- "serve:only": "node tools/dev/serve.js",
48
- "serve": `${packageManager} run build && ${packageManager} run serve:only`,
49
- "dev": "node tools/dev/dev-serve.js",
50
- "generate": "node tools/generator/generator.js"
51
- };
52
-
53
- const deployHelperScripts = {
54
- "docker:build": `docker build -t ${projectName} -f tools/deployment/Dockerfile .`,
55
- "docker:run": `docker run -p 9090:9090 ${projectName}:latest`,
56
- "patch": `${packageManager} version patch -m 'CI/CD: Bump version to %s'`,
57
- "minor": `${packageManager} version minor -m 'CI/CD: Bump version to %s'`,
58
- "major": `${packageManager} version major -m 'CI/CD: Bump version to %s'`
59
- }
60
-
61
- const testinNutinScripts = {
62
- "test": "node testin-nutin/runner.js",
63
- "test:rebuild": `${packageManager} run build && ${packageManager} run test`,
64
- "test:watch": `${packageManager} run build && node testin-nutin/watch-tests.js`
65
- }
66
-
67
- let scripts = { ...baseScripts };
68
-
69
- if (testinNutin) scripts = { ...scripts, ...testinNutinScripts };
70
- if (deployHelper) scripts = { ...scripts, ...deployHelperScripts };
71
-
72
- return scripts;
73
- }
74
-
75
- export async function generatePackageJson(projectPath, context) {
76
- const { testinNutin, projectName } = context;
77
-
78
- const devDependencies = {
79
- "chokidar": "^4.0.3",
80
- "esbuild": "^0.25.12",
81
- "html-minifier-terser": "^7.2.0",
82
- "live-server": "^1.2.2",
83
- "sass": "^1.89.0",
84
- "typescript": "^5.8.3",
85
- ...(testinNutin && {
86
- "jsdom": "^26.1.0",
87
- })
88
- };
89
-
90
- const scripts = getScripts(context);
91
-
92
- const packageJson = {
93
- "name": projectName,
94
- "version": "0.1.0",
95
- "type": "module",
96
- ...(testinNutin && {
97
- "imports": {
98
- "#root/*.js": "./*.js"
99
- }
100
- }),
101
- scripts,
102
- devDependencies,
103
- ...(testinNutin && {
104
- "engines": {
105
- "node": ">=20.19.0"
106
- }
107
- })
108
- };
109
-
110
- await fs.writeJSON(path.join(projectPath, 'package.json'), packageJson, { spaces: 2 });
111
- }
112
-
113
- export async function generateTsconfigJson(projectPath, context) {
114
- const tsconfig = {
115
- "compilerOptions": {
116
- "baseUrl": "./",
117
- "paths": {},
118
- "target": "ESNext",
119
- "module": "NodeNext",
120
- "moduleResolution": "NodeNext",
121
- "rootDir": "src",
122
- "outDir": "dist-build/src",
123
- "strict": true,
124
- "skipLibCheck": true,
125
- "forceConsistentCasingInFileNames": true,
126
- "noUncheckedIndexedAccess": true,
127
- "esModuleInterop": true,
128
- "allowSyntheticDefaultImports": true,
129
- "lib": ["es2022", "DOM"],
130
- "removeComments": true,
131
- "resolveJsonModule": true,
132
- "typeRoots": ["src/types", "node_modules/@types"]
133
- },
134
- "include": ["src/app", "src/core", "src/libs"],
135
- "exclude": ["node_modules"]
136
- };
137
-
138
- await fs.writeJSON(path.join(projectPath, 'tsconfig.json'), tsconfig, { spaces: 2 });
139
- }
package/lib/src/print.mjs DELETED
@@ -1,31 +0,0 @@
1
- export const chalk = {
2
- green: (s) => `\x1b[32m${s}\x1b[0m`,
3
- red: (s) => `\x1b[31m${s}\x1b[0m`,
4
- blue: (s) => `\x1b[34m${s}\x1b[0m`,
5
- yellow: (s) => `\x1b[33m${s}\x1b[0m`,
6
- cyan: (s) => `\x1b[36m${s}\x1b[0m`,
7
- purple: (s) => `\x1b[35m${s}\x1b[0m`,
8
- gray: (s) => `\x1b[90m${s}\x1b[0m`,
9
- boldGreen: (s) => `\x1b[1;32m${s}\x1b[0m`,
10
- boldRed: (s) => `\x1b[1;31m${s}\x1b[0m`,
11
- boldBlue: (s) => `\x1b[1;34m${s}\x1b[0m`,
12
- boldYellow: (s) => `\x1b[1;33m${s}\x1b[0m`,
13
- boldCyan: (s) => `\x1b[1;36m${s}\x1b[0m`,
14
- boldPurple: (s) => `\x1b[1;35m${s}\x1b[0m`,
15
- };
16
-
17
- export const print = {
18
- head: (s) => console.log(`${chalk.purple(s)}`),
19
- boldHead : (s) => console.log(`${chalk.boldPurple(s)}`),
20
- section: (s) => console.log(`${chalk.yellow(s)}`),
21
- boldSection: (s) => console.log(`${chalk.boldYellow(s)}`),
22
- info: (s) => console.log(`${chalk.green(s)}`),
23
- boldInfo: (s) => console.log(`${chalk.boldGreen(s)}`),
24
- success: (s) => console.log(`${chalk.cyan(s)}`),
25
- boldSuccess: (s) => console.log(`${chalk.boldCyan(s)}`),
26
- error: (s) => console.error(`${chalk.red(s)}`),
27
- boldError: (s) => console.error(`${chalk.boldRed(s)}`),
28
- grayError: (s) => console.error(`${chalk.gray(s)}`),
29
- blue: (s) => console.log(`${chalk.blue(s)}`),
30
- boldBlue: (s) => console.log(`${chalk.boldBlue(s)}`),
31
- }
@@ -1,123 +0,0 @@
1
- import inquirer from 'inquirer';
2
- import { defaults } from './context-builder.mjs';
3
-
4
- export async function promptUser(initialName, cliOptions = {}) {
5
-
6
- let projectName = initialName;
7
- if (!projectName) {
8
- const nameAnswer = await inquirer.prompt([
9
- {
10
- type: 'input',
11
- name: 'projectName',
12
- message: 'Project name:',
13
- default: defaults.projectName,
14
- validate: validateProjectName
15
- }
16
- ]);
17
- projectName = nameAnswer.projectName;
18
- }
19
-
20
- let packageManager = cliOptions.packageManager;
21
- if (!packageManager) {
22
- const pmAnswer = await inquirer.prompt([
23
- {
24
- type: 'list',
25
- name: 'packageManager',
26
- message: 'Package manager:',
27
- choices: ['npm', 'yarn', 'pnpm', 'bun'],
28
- default: defaults.packageManager
29
- }
30
- ]);
31
- packageManager = pmAnswer.packageManager;
32
- }
33
-
34
- if (cliOptions.defaults) {
35
- return {
36
- projectName,
37
- packageManager,
38
- stylinNutin: cliOptions.stylinNutin,
39
- template: cliOptions.template,
40
- i18n: cliOptions.i18n,
41
- deployHelper: cliOptions.deployHelper,
42
- testinNutin: cliOptions.testinNutin,
43
- transition: cliOptions.transitions
44
- };
45
- }
46
-
47
- const questions = [];
48
-
49
- if (cliOptions.stylinNutin === undefined) {
50
- questions.push({
51
- type: 'confirm',
52
- name: 'stylinNutin',
53
- message: 'Use built-in SCSS utility classes ?',
54
- default: defaults.stylinNutin
55
- });
56
- }
57
-
58
- if (cliOptions.template === undefined) {
59
- questions.push({
60
- type: 'confirm',
61
- name: 'template',
62
- message: 'Use external templates ?',
63
- default: defaults.template
64
- });
65
- }
66
-
67
- if (cliOptions.i18n === undefined) {
68
- questions.push({
69
- type: 'confirm',
70
- name: 'i18n',
71
- message: 'Use i18n with json-based content ?',
72
- default: defaults.i18n
73
- });
74
- }
75
-
76
- if (cliOptions.deployHelper === undefined) {
77
- questions.push({
78
- type: 'confirm',
79
- name: 'deployHelper',
80
- message: 'Use Docker & deployment helpers ?',
81
- default: defaults.deployHelper
82
- });
83
- }
84
-
85
- if (cliOptions.testinNutin === undefined) {
86
- questions.push({
87
- type: 'confirm',
88
- name: 'testinNutin',
89
- message: 'Use testin-nutin toolkit?',
90
- default: defaults.testinNutin
91
- });
92
- }
93
-
94
- if (cliOptions.transition === undefined) {
95
- questions.push({
96
- type: 'confirm',
97
- name: 'transition',
98
- message: 'Use animated view transitions?',
99
- default: defaults.transition
100
- });
101
- }
102
-
103
- const answers = questions.length > 0 ? await inquirer.prompt(questions) : {};
104
-
105
- return {
106
- projectName,
107
- packageManager,
108
- template: cliOptions.template ?? answers.template,
109
- stylinNutin: cliOptions.stylinNutin ?? answers.stylinNutin,
110
- i18n: cliOptions.i18n ?? answers.i18n,
111
- deployHelper: cliOptions.deployHelper ?? answers.deployHelper,
112
- transition: cliOptions.transition ?? answers.transition,
113
- testinNutin: cliOptions.testinNutin ?? answers.testinNutin
114
- };
115
- }
116
-
117
- function validateProjectName(input) {
118
- if (!input.trim()) return 'Project name is required';
119
- if (!/^[a-z0-9-_]+$/.test(input)) {
120
- return 'Use only lowercase letters, numbers, hyphens, and underscores';
121
- }
122
- return true;
123
- }
package/lib/src/utils.mjs DELETED
@@ -1,18 +0,0 @@
1
- import { exec } from 'child_process';
2
- import { promisify } from 'util';
3
- import { print } from './print.mjs';
4
-
5
- export const promiseExec = promisify(exec);
6
-
7
- export function displaySuccessMessage(answers) {
8
- const { projectName, packageManager, deployHelper } = answers;
9
- print.boldSuccess('\n🎉 Your project is ready!');
10
- print.boldInfo(`Documentation on https://www.nutin.org`);
11
-
12
- if (packageManager === 'pnpm' || packageManager === 'bun') {
13
- if (deployHelper) print.boldError(`You'll need to modify the Dockerfile to support ${packageManager}`)
14
- }
15
-
16
- print.info('Next steps:');
17
- print.info(` cd ${projectName} && ${packageManager} run serve\n`);
18
- }
@@ -1 +0,0 @@
1
- export const packageVersion = '1.3.0';
@@ -1,35 +0,0 @@
1
- export default {
2
- esbuild: {
3
- bundle: true,
4
- minify: true,
5
- sourcemap: false,
6
- platform: 'browser',
7
- format: 'esm',
8
- target: ['es2015'],
9
- legalComments: 'none',
10
- loader: {
11
- '.json': 'json',
12
- },
13
- define: {
14
- 'process.env.NODE_ENV': '"production"',
15
- },
16
- },
17
- sass: {
18
- paths: [
19
- 'base',
20
- 'core',
21
- {{#if stylinNutin}}
22
- 'components',
23
- 'views',
24
- {{/if}}
25
- ], // in styles/
26
- },
27
- {{#if deployHelper}}
28
- compression: {
29
- gzip: true,
30
- // BROTLI OPTIONAL
31
- // brotli: false,
32
- },
33
- {{/if}}
34
- verbose: false,
35
- }
@@ -1,32 +0,0 @@
1
- import { AnchorManager, Component, IAnchorConfig } from '../../../../core/index.js';
2
-
3
- /**
4
- * ```typescript
5
- * interface IAnchorConfig {
6
- // prefix href with '#' for internal anchor
7
- href: string;
8
- target?: string;
9
- textContent?: string;
10
- {{#if i18n}}
11
- i18nKey?: string;
12
- {{/if}}
13
- className?: string;
14
- style?: string;
15
- // use regular pipe syntax for arguments / chaining
16
- pipes?: string;
17
- tagName?: keyof HTMLElementTagNameMap;
18
- }
19
- ```
20
- */
21
- export class AnchorComponent extends Component<HTMLAnchorElement, IAnchorConfig> {
22
-
23
- constructor(mountTarget: HTMLElement, config: IAnchorConfig) {
24
- super({
25
- mountTarget,
26
- tagName: config.tagName,
27
- config,
28
- normalizeKeys: ['style', 'pipes', 'className']
29
- });
30
- new AnchorManager(config, this.element);
31
- }
32
- }
@@ -1,40 +0,0 @@
1
- import { BaseButton, Component } from '../../../../core/index.js';
2
-
3
- /**
4
- * ```typescript
5
- interface IAttributesConfig {
6
- {{#if i18n}}
7
- i18nKey?: string;
8
- {{/if}}
9
- textContent?: string;
10
- className?: string;
11
- style?: string;
12
- // use regular pipe syntax for arguments / chaining
13
- pipes?: string;
14
- }
15
-
16
- interface BaseButton extends IAttributesConfig {
17
- callback: () => void;
18
- }
19
-
20
- interface ButtonContainerOptions {
21
- containerClassName?: string;
22
- containerStyles?: string;
23
- }
24
- ```
25
- * Note : To ensure 'this' is bound properly
26
- * ```typescript
27
- // Will handle 'this' inside doStuff
28
- * { callback: () => this.doStuff() }
29
- * // Will still work, but won't handle 'this' inside doStuff
30
- * { callback: this.doStuff }
31
- * ```
32
- */
33
- export class ButtonComponent extends Component<HTMLButtonElement> {
34
- constructor(mountTarget: HTMLElement, button: BaseButton) {
35
- super({
36
- mountTarget,
37
- props: { buttons: [button] }
38
- });
39
- }
40
- }
@@ -1,13 +0,0 @@
1
- describe('App container', () => {
2
- it('should be defined', () => {
3
- const appContainer = document.getElementById('app');
4
- expect(appContainer).toBeDefined();
5
- });
6
- it('should have title', () => {
7
- expect(document.title).toEqual('{{projectName}}');
8
- });
9
- it('should have meta description', () => {
10
- const desc = document.querySelector('meta[name="description"]').content;
11
- expect(desc).toEqual('{{projectName}}');
12
- });
13
- });
@@ -1,18 +0,0 @@
1
- import { Service } from "../../../core/index.js";
2
-
3
- export class Example extends Service<Example> {
4
- constructor() {
5
- super();
6
- this.registerCallback();
7
- }
8
-
9
- protected registerCallback(): void {
10
- console.debug('No cleanup callbacks registered for service: Example')
11
- }
12
-
13
- protected onDestroy(): void {
14
- this.dispose();
15
- }
16
- }
17
-
18
- export const exampleService = Example.getInstance();
@@ -1,26 +0,0 @@
1
- import { HomeView } from '#root/dist/src/app/views/index.js';
2
-
3
- let view;
4
-
5
- describe('HomeView', () => {
6
- beforeAll(() => {
7
- view = new HomeView();
8
- });
9
-
10
- it('should be defined', () => {
11
- expect(view).toBeDefined();
12
- });
13
- {{#if i18n}}
14
- it('should have title with i18n key', () => {
15
- const h1 = view.element.querySelector('h1');
16
- expect(h1).toBeDefined();
17
- expect(h1.textContent).toBe('home.title');
18
- });
19
- {{else}}
20
- it('should have title', () => {
21
- const h1 = view.element.querySelector('h1');
22
- expect(h1).toBeDefined();
23
- expect(h1.textContent).toBe('{{projectName}}');
24
- });
25
- {{/if}}
26
- })
@@ -1,8 +0,0 @@
1
- import { AppStore } from '#root/dist/src/core/services/index.js'
2
-
3
- describe('store', () => {
4
- it('should set & get values properly', () => {
5
- AppStore.set('foo', 123);
6
- expect(AppStore.get('foo')).toBe(123)
7
- });
8
- })