@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.
- package/CHANGELOG.md +89 -9
- package/README.md +20 -35
- package/bin/add-feature.mjs +9 -0
- package/bin/cli.mjs +8 -0
- package/bin/create-app.mjs +5 -4
- package/bin/update-app.mjs +9 -0
- package/lib/index.mjs +76 -25
- package/lib/src/add-feature/feature-adder.mjs +83 -0
- package/lib/src/add-feature/feature-context-builder.mjs +25 -0
- package/lib/src/add-feature/nutin-config-updater.mjs +29 -0
- package/lib/src/add-feature/package-json-updater.mjs +49 -0
- package/lib/src/common/feature-registry.mjs +11 -0
- package/lib/src/common/file-generator.mjs +159 -0
- package/lib/src/common/meta-bootstrap-prompt.mjs +33 -0
- package/lib/src/common/package-data.mjs +10 -0
- package/lib/src/common/package-json-helper.mjs +103 -0
- package/lib/src/common/project-meta.mjs +54 -0
- package/lib/src/create-app/context-builder.mjs +21 -0
- package/lib/src/{git-manager.mjs → create-app/git-manager.mjs} +2 -2
- package/lib/src/create-app/json-manager.mjs +73 -0
- package/lib/src/{prompts.mjs → create-app/new-app-prompt.mjs} +6 -6
- package/lib/src/{project-generator.mjs → create-app/project-generator.mjs} +10 -8
- package/lib/src/create-app/success-message.mjs +14 -0
- package/lib/src/update-app/conflict-report-writer.mjs +31 -0
- package/lib/src/update-app/fetch-old-templates.mjs +61 -0
- package/lib/src/update-app/project-updater.mjs +136 -0
- package/lib/src/update-app/template-differ.mjs +124 -0
- package/lib/src/update-app/update-context-builder.mjs +25 -0
- package/lib/src/update-app/update-summary-printer.mjs +22 -0
- package/lib/src/update-app/version-compare.mjs +12 -0
- package/lib/src/utils/print.mjs +36 -0
- package/lib/src/utils/promise-exec-alias.mjs +4 -0
- package/package.json +17 -12
- package/templates/base/.gitignore.hbs +6 -1
- package/templates/base/AGENTS.md.hbs +169 -0
- package/templates/base/GETTING_STARTED.md.hbs +227 -0
- package/templates/base/README.md.hbs +8 -17
- package/templates/base/config/languages.json.hbs +6 -0
- package/templates/base/config/seo.json.hbs +12 -0
- package/templates/base/nutin.config.js.hbs +51 -0
- package/templates/base/src/app/components/index.ts.hbs +1 -2
- package/templates/base/src/app/globals.d.ts.hbs +3 -19
- package/templates/base/src/{libs/guards → app}/guards.ts.hbs +1 -5
- package/templates/base/src/app/main.ts.hbs +7 -26
- package/templates/base/src/app/services/index.ts.hbs +1 -1
- package/templates/base/src/app/views/home/home.view.html.hbs +7 -0
- package/templates/base/src/app/views/home/home.view.ts.hbs +1 -56
- package/templates/base/src/app/views/index.ts.hbs +1 -0
- package/templates/base/src/app/views/not-found/not-found.view.html.hbs +8 -0
- package/templates/base/src/app/views/not-found/not-found.view.ts.hbs +4 -37
- package/templates/base/src/core/base-classes/base-component/base-component.test.js.hbs +158 -0
- package/templates/base/src/core/base-classes/base-component/base-component.ts.hbs +68 -35
- package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.test.js.hbs +124 -0
- package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.ts.hbs +9 -8
- package/templates/base/src/core/base-classes/base-component/helpers/children.helper.test.js.hbs +74 -0
- package/templates/base/src/core/base-classes/base-component/helpers/children.helper.ts.hbs +1 -1
- package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.test.js.hbs +145 -0
- package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.ts.hbs +7 -1
- package/templates/base/src/core/base-classes/base-component/helpers/event.helper.test.js.hbs +88 -0
- package/templates/base/src/core/base-classes/base-component/helpers/event.helper.ts.hbs +2 -2
- package/templates/base/src/core/base-classes/base-component/helpers/i18n.helper.test.js.hbs +62 -0
- package/templates/base/src/core/base-classes/base-component/helpers/pipe.helper.test.js.hbs +82 -0
- package/templates/base/src/core/base-classes/base-component/helpers/security.helper.test.js.hbs +142 -0
- package/templates/base/src/core/base-classes/base-component/helpers/security.helper.ts.hbs +67 -22
- package/templates/base/src/core/base-classes/base-component/helpers/token.helper.test.js.hbs +183 -0
- package/templates/base/src/core/base-classes/component/component.test.js.hbs +85 -0
- package/templates/base/src/core/base-classes/component/component.ts.hbs +24 -33
- package/templates/base/src/core/base-classes/component/helpers/config.helper.test.js.hbs +58 -0
- package/templates/base/src/core/base-classes/component/helpers/data-binding.helper.test.js.hbs +75 -0
- package/templates/base/src/core/base-classes/service/service.test.js.hbs +150 -0
- package/templates/base/src/core/base-classes/service/service.ts.hbs +26 -20
- package/templates/base/src/core/base-classes/view/view.test.js.hbs +74 -0
- package/templates/base/src/core/base-classes/view/view.ts.hbs +17 -41
- package/templates/base/src/core/config.ts.hbs +7 -0
- package/templates/base/src/core/index.ts.hbs +0 -3
- package/templates/base/src/core/internals.d.ts.hbs +27 -0
- package/templates/base/src/core/nutin-config.d.ts.hbs +4 -0
- package/templates/base/src/core/services/event-bus/event-bus.test.js.hbs +67 -3
- package/templates/base/src/core/services/event-bus/event-bus.ts.hbs +9 -4
- package/templates/base/src/core/services/event-bus/index.ts.hbs +3 -0
- package/templates/base/src/core/services/event-bus/lifecycle.facade.test.js.hbs +123 -0
- package/templates/base/src/core/services/event-bus/lifecycle.facade.ts.hbs +61 -0
- package/templates/base/src/core/services/event-bus/navigation.facade.test.js.hbs +46 -0
- package/templates/base/src/core/services/event-bus/navigation.facade.ts.hbs +25 -0
- package/templates/base/src/core/services/globals/globals.test.js.hbs +149 -0
- package/templates/base/src/core/services/globals/globals.ts.hbs +95 -0
- package/templates/base/src/core/services/http-client/helpers/http-builder.helper.test.js.hbs +25 -0
- package/templates/base/src/core/services/http-client/helpers/http-manager.helper.test.js.hbs +20 -0
- package/templates/base/src/core/services/http-client/http-client.test.js.hbs +43 -0
- package/templates/base/src/core/services/i18n/i18n.test.js.hbs +270 -0
- package/templates/{features/i18n → base}/src/core/services/i18n/i18n.ts.hbs +22 -4
- package/templates/base/src/core/services/index.ts.hbs +5 -6
- package/templates/base/src/core/services/pipe-registry/pipe-registry.test.js.hbs +60 -1
- package/templates/base/src/core/services/pipe-registry/pipe-registry.ts.hbs +1 -1
- package/templates/base/src/core/services/pipe-registry/pipes.test.js.hbs +128 -0
- package/templates/base/src/{libs/pipes → core/services/pipe-registry}/pipes.ts.hbs +8 -5
- package/templates/base/src/core/services/router/helpers/navigation-manager.helper.test.js.hbs +149 -6
- package/templates/base/src/core/services/router/helpers/navigation-manager.helper.ts.hbs +40 -29
- package/templates/base/src/core/services/router/helpers/route-guard-manager.helper.test.js.hbs +27 -0
- package/templates/base/src/core/services/router/helpers/view-render-manager.helper.test.js.hbs +83 -17
- package/templates/base/src/core/services/router/helpers/view-render-manager.helper.ts.hbs +14 -38
- package/templates/base/src/core/services/router/router.test.js.hbs +226 -2
- package/templates/base/src/core/services/router/router.ts.hbs +40 -8
- package/templates/base/src/index.html.hbs +2 -6
- package/templates/base/src/styles/_styles.scss.hbs +102 -43
- package/templates/base/src/styles/base/_variables.scss.hbs +1 -86
- package/templates/base/src/styles/main.scss.hbs +1 -18
- package/templates/base/src/styles/tailwind.css.hbs +2 -0
- package/templates/base/tools/builder/builder.config.js.hbs +40 -0
- package/templates/base/tools/builder/builder.js.hbs +24 -26
- package/templates/base/tools/builder/core/app/binary-extensions.test.js.hbs +16 -0
- package/templates/base/tools/builder/core/app/compile-ts.js.hbs +16 -0
- package/templates/base/tools/builder/core/{copy-static.js.hbs → app/copy-static.js.hbs} +27 -34
- package/templates/base/tools/builder/core/app/validate-routes.js.hbs +77 -0
- package/templates/base/tools/builder/core/finalize-build.js.hbs +16 -7
- package/templates/base/tools/builder/core/{add-tags.js.hbs → html-index/add-tags.js.hbs} +2 -2
- package/templates/base/tools/builder/core/html-index/add-tags.test.js.hbs +56 -0
- package/templates/base/tools/builder/core/{validate-html.js.hbs → html-index/validate-html.js.hbs} +5 -11
- package/templates/base/tools/builder/core/html-templates/merge-templates.js.hbs +152 -0
- package/templates/base/tools/builder/core/html-templates/minify-html.js.hbs +15 -0
- package/templates/base/tools/builder/core/html-templates/process-html-templates.js.hbs +8 -0
- package/templates/{features/i18n/tools/builder/core → base/tools/builder/core/i18n}/build-i18n.js.hbs +6 -17
- package/templates/base/tools/builder/core/prod-bundle/compress-files.js.hbs +37 -0
- package/templates/base/tools/builder/core/prod-bundle/esbuild.js.hbs +30 -0
- package/templates/base/tools/builder/core/{hash-files.js.hbs → prod-bundle/hash-files.js.hbs} +14 -11
- package/templates/base/tools/builder/core/seo/generate-robots-txt.js.hbs +51 -0
- package/templates/base/tools/builder/core/seo/generate-seo-files.js.hbs +16 -0
- package/templates/base/tools/builder/core/seo/generate-seo-html.js.hbs +128 -0
- package/templates/base/tools/builder/core/seo/generate-sitemap-xml.js.hbs +43 -0
- package/templates/base/tools/builder/core/seo/html-substitutions.js.hbs +99 -0
- package/templates/base/tools/builder/core/seo/i18n-resolution.js.hbs +66 -0
- package/templates/base/tools/builder/core/seo/route-output.js.hbs +64 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-bundle.js.hbs +54 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-polyfills.js.hbs +132 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-render.js.hbs +95 -0
- package/templates/base/tools/builder/core/styles/sass.js.hbs +40 -0
- package/templates/base/tools/builder/core/styles/tailwind.js.hbs +84 -0
- package/templates/base/tools/dev/dev-serve.js.hbs +26 -18
- package/templates/base/tools/dev/serve.js.hbs +11 -1
- package/templates/base/tools/dev/watcher.js.hbs +14 -6
- package/templates/base/tools/generator/generator.js.hbs +64 -47
- package/templates/base/tools/generator/handle-file.js.hbs +17 -44
- package/templates/base/tools/generator/handle-file.test.js.hbs +72 -0
- package/templates/base/tools/generator/templates/{component.template.js.hbs → component/component.template.js.hbs} +3 -2
- package/templates/base/tools/generator/templates/component/component.template.test.js.hbs +23 -0
- package/templates/base/tools/generator/templates/html/html.template.js.hbs +2 -0
- package/templates/base/tools/generator/templates/html/html.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/index.js.hbs +7 -12
- package/templates/base/tools/generator/templates/locale/locale.template.js.hbs +4 -0
- package/templates/base/tools/generator/templates/locale/locale.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/scss/scss.template.js.hbs +1 -0
- package/templates/base/tools/generator/templates/scss/scss.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/service/service.template.js.hbs +17 -0
- package/templates/base/tools/generator/templates/service/service.template.test.js.hbs +22 -0
- package/templates/base/tools/generator/templates/test/test.template.js.hbs +10 -0
- package/templates/base/tools/generator/templates/test/test.template.test.js.hbs +27 -0
- package/templates/base/tools/generator/templates/{view.template.js.hbs → view/view.template.js.hbs} +3 -2
- package/templates/base/tools/generator/templates/view/view.template.test.js.hbs +24 -0
- package/templates/base/tools/testin-nutin/core/coverage/collect-coverage.js.hbs +39 -0
- package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.js.hbs +115 -0
- package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.test.js.hbs +74 -0
- package/templates/base/tools/testin-nutin/core/coverage/write-summary-report.js.hbs +54 -0
- package/templates/base/tools/testin-nutin/core/coverage/write-uncovered-report.js.hbs +44 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/assertion-lib.js.hbs +62 -24
- package/templates/base/tools/testin-nutin/core/globals/clock.js.hbs +206 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/jsdom-setup.js.hbs +19 -6
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/register-test-globals.js.hbs +13 -4
- package/templates/base/tools/testin-nutin/core/globals/silence-console.js.hbs +23 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/spyon.js.hbs +2 -0
- package/templates/base/tools/testin-nutin/core/index.js.hbs +9 -0
- package/templates/base/tools/testin-nutin/core/printer.js.hbs +85 -0
- package/templates/base/tools/testin-nutin/core/queue/queue.test.js.hbs +46 -0
- package/templates/base/tools/testin-nutin/core/queue/test-discovery.test.js.hbs +46 -0
- package/templates/base/tools/testin-nutin/core/queue/test-queue.js.hbs +154 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/core/tests/assertions.test.js.hbs +27 -0
- package/templates/base/tools/testin-nutin/core/tests/clock.test.js.hbs +118 -0
- package/templates/base/tools/testin-nutin/core/tests/globals-each-all.test.js.hbs +28 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/create-mock-method.js.hbs +2 -1
- package/templates/base/tools/testin-nutin/mocks/create-mock-method.test.js.hbs +64 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-event-bus.js.hbs +3 -2
- package/templates/base/tools/testin-nutin/mocks/mock-event-bus.test.js.hbs +66 -0
- package/templates/base/tools/testin-nutin/mocks/mock-http-client.test.js.hbs +26 -0
- package/templates/base/tools/testin-nutin/mocks/mock-i18n.test.js.hbs +61 -0
- package/templates/base/tools/testin-nutin/mocks/mock-router.test.js.hbs +29 -0
- package/templates/base/tools/testin-nutin/runner.js.hbs +100 -0
- package/templates/base/tools/testin-nutin/watch-tests.js.hbs +37 -0
- package/templates/base/tools/utils/error-exit.js.hbs +8 -0
- package/templates/base/tools/utils/format.js.hbs +10 -10
- package/templates/base/tools/utils/format.test.js.hbs +45 -0
- package/templates/base/tools/utils/get-files-recursive.js.hbs +6 -1
- package/templates/base/tools/utils/get-files-recursive.test.js.hbs +49 -0
- package/templates/base/tools/utils/get-rel-to-core.test.js.hbs +18 -0
- package/templates/base/tools/utils/index.js.hbs +1 -3
- package/templates/base/tools/utils/languages.js.hbs +15 -0
- package/templates/base/tools/utils/languages.test.js.hbs +16 -0
- package/templates/base/tools/utils/print.js.hbs +19 -13
- package/templates/base/tools/utils/print.test.js.hbs +60 -0
- package/templates/base/tools/utils/prompt-boolean.js.hbs +7 -0
- package/templates/base/tools/utils/prompt-boolean.test.js.hbs +54 -0
- package/templates/base/tools/utils/run-command.js.hbs +4 -2
- package/templates/base/tools/utils/run-command.test.js.hbs +19 -0
- package/templates/base/tools/utils/run-script.js.hbs +14 -3
- package/templates/base/tools/utils/run-script.test.js.hbs +40 -0
- package/templates/features/{deployHelper → docker}/.dockerignore.hbs +4 -4
- package/templates/features/docker/tools/docker/Dockerfile.template.hbs +51 -0
- package/templates/features/{deployHelper/tools/deployment/nginx.conf.hbs → docker/tools/docker/nginx.conf.template} +4 -2
- package/templates/features/docker/tools/docker/scripts/docker-build.js.hbs +20 -0
- package/templates/features/docker/tools/docker/scripts/docker-ports.js.hbs +48 -0
- package/templates/features/docker/tools/docker/scripts/docker-ports.test.js.hbs +52 -0
- package/templates/features/docker/tools/docker/scripts/docker-run.js.hbs +28 -0
- package/templates/features/docker/tools/docker/scripts/render-docker-template.js.hbs +23 -0
- package/templates/features/docker/tools/docker/scripts/render-docker-template.test.js.hbs +60 -0
- package/templates/features/docker/tools/docker/scripts/validate-docker.js.hbs +30 -0
- package/lib/src/context-builder.mjs +0 -40
- package/lib/src/file-generator.mjs +0 -109
- package/lib/src/json-generator.mjs +0 -31
- package/lib/src/package-manager.mjs +0 -139
- package/lib/src/print.mjs +0 -32
- package/lib/src/utils.mjs +0 -18
- package/lib/src/version.mjs +0 -1
- package/templates/base/builder.config.js.hbs +0 -36
- package/templates/base/src/app/components/common/anchor/anchor.component.ts.hbs +0 -32
- package/templates/base/src/app/components/common/button/button.component.ts.hbs +0 -40
- package/templates/base/src/app/dom.test.js.hbs +0 -13
- package/templates/base/src/app/services/example/example.service.ts.hbs +0 -18
- package/templates/base/src/app/views/home/home.view.test.js.hbs +0 -26
- package/templates/base/src/core/services/store/store.test.js.hbs +0 -8
- package/templates/base/src/core/services/store/store.ts.hbs +0 -39
- package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.test.js.hbs +0 -0
- package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.ts.hbs +0 -113
- package/templates/base/src/core/utils/button-manager/button-manager.utils.test.js.hbs +0 -249
- package/templates/base/src/core/utils/button-manager/button-manager.utils.ts.hbs +0 -131
- package/templates/base/src/core/utils/helpers/attributes.helper.ts.hbs +0 -50
- package/templates/base/src/core/utils/index.ts.hbs +0 -2
- package/templates/base/src/libs/index.ts.hbs +0 -4
- package/templates/base/src/libs/popover/helpers/focus-trap.helper.ts.hbs +0 -197
- package/templates/base/src/libs/popover/helpers/popover-dom.helper.ts.hbs +0 -75
- package/templates/base/src/libs/popover/popover.ts.hbs +0 -138
- package/templates/base/src/libs/snackbar/snackbar.ts.hbs +0 -75
- package/templates/base/src/styles/base/_functions.scss.hbs +0 -9
- package/templates/base/src/styles/core/_anchors.scss.hbs +0 -10
- package/templates/base/src/styles/core/_index.scss.hbs +0 -6
- package/templates/base/src/styles/core/_popover.scss.hbs +0 -96
- package/templates/base/src/styles/core/_snackbar.scss.hbs +0 -50
- package/templates/base/tools/builder/core/esbuild.js.hbs +0 -25
- package/templates/base/tools/builder/core/minify-html.js.hbs +0 -60
- package/templates/base/tools/builder/core/sass.js.hbs +0 -22
- package/templates/base/tools/builder/core/tsc.js.hbs +0 -12
- package/templates/base/tools/generator/templates/service.template.js.hbs +0 -17
- package/templates/base/tools/utils/export-flags.js.hbs +0 -6
- package/templates/features/deployHelper/tools/builder/core/compress-files.js.hbs +0 -56
- package/templates/features/deployHelper/tools/deployment/Dockerfile.hbs +0 -30
- package/templates/features/i18n/src/app/views/home/locales/en.json.hbs +0 -9
- package/templates/features/i18n/src/app/views/not-found/locales/en.json +0 -8
- package/templates/features/i18n/src/app/views/not-found/locales/fr.json +0 -8
- package/templates/features/i18n/src/core/config.ts.hbs +0 -3
- package/templates/features/i18n/src/core/services/i18n/i18n.test.js.hbs +0 -125
- package/templates/features/i18n/tools/generator/templates/json.template.js.hbs +0 -8
- package/templates/features/i18n/tools/utils/languages.js.hbs +0 -7
- package/templates/features/stylinNutin/src/styles/_custom-classes.scss.hbs +0 -9
- package/templates/features/stylinNutin/src/styles/base/_mixins.scss.hbs +0 -372
- package/templates/features/stylinNutin/src/styles/components/_index.scss.hbs +0 -3
- package/templates/features/stylinNutin/src/styles/core/_utilities.scss.hbs +0 -254
- package/templates/features/stylinNutin/src/styles/views/_index.scss.hbs +0 -0
- package/templates/features/stylinNutin/tools/generator/templates/scss.template.js.hbs +0 -4
- package/templates/features/template/src/app/views/home/home.view.html.hbs +0 -56
- package/templates/features/template/src/app/views/not-found/not-found.view.html.hbs +0 -19
- package/templates/features/template/tools/builder/core/merge-templates.js.hbs +0 -49
- package/templates/features/template/tools/generator/templates/html.template.js.hbs +0 -2
- package/templates/features/testinNutin/testin-nutin/core/index.js.hbs +0 -5
- package/templates/features/testinNutin/testin-nutin/core/src/utils/print.js.hbs +0 -64
- package/templates/features/testinNutin/testin-nutin/core/src/utils/test-queue.js.hbs +0 -64
- package/templates/features/testinNutin/testin-nutin/core/tests/globals-each-all.test.js.hbs +0 -28
- package/templates/features/testinNutin/testin-nutin/mocks/mock-store.js.hbs +0 -38
- package/templates/features/testinNutin/testin-nutin/runner.js.hbs +0 -36
- package/templates/features/testinNutin/testin-nutin/watch-tests.js.hbs +0 -21
- package/templates/features/testinNutin/testin-nutin.config.js.hbs +0 -14
- /package/lib/src/{template-compiler.mjs → common/template-compiler.mjs} +0 -0
- /package/templates/{features/i18n → base}/src/core/base-classes/base-component/helpers/i18n.helper.ts.hbs +0 -0
- /package/templates/{features/i18n → base}/src/core/services/i18n/languages.ts.hbs +0 -0
- /package/templates/base/tools/builder/{variables → core/app}/binary-extensions.js.hbs +0 -0
- /package/templates/base/tools/builder/core/{paths.js.hbs → app/paths.js.hbs} +0 -0
- /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/queue.js.hbs +0 -0
- /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/test-discovery.js.hbs +0 -0
- /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-http-client.js.hbs +0 -0
- /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-i18n.js.hbs +0 -0
- /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
|
-
|
|
7
|
-
|
|
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
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
5
|
-
import { generateFile, appendToIndex
|
|
6
|
-
import { serviceTemplate, componentTemplate, viewTemplate
|
|
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
|
-
|
|
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:
|
|
26
|
-
appendToIndex({ name, targetPath, suffix:
|
|
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:
|
|
32
|
-
|
|
33
|
-
{
|
|
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:
|
|
39
|
-
{
|
|
40
|
-
generateFile({ name, targetPath, templateFn:
|
|
41
|
-
{
|
|
42
|
-
{
|
|
43
|
-
|
|
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:
|
|
54
|
-
|
|
55
|
-
{
|
|
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:
|
|
61
|
-
{
|
|
62
|
-
generateFile({ name, targetPath, templateFn:
|
|
63
|
-
{
|
|
64
|
-
{
|
|
65
|
-
|
|
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
|
-
|
|
82
|
-
print.boldSuccess(`\n${type.capitalized} ${name.capitalized}
|
|
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
|
|
90
|
-
print.
|
|
91
|
-
print.
|
|
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
|
-
|
|
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
|
|
4
|
-
{
|
|
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.
|
|
40
|
+
print.gray(`${suffix}s/index.ts updated.`);
|
|
46
41
|
} catch (err) {
|
|
47
|
-
|
|
42
|
+
throw new Error(`Failed to update ${indexFilePath}: ${err.message}`, { cause: err });
|
|
48
43
|
}
|
|
49
44
|
}
|
|
50
45
|
|
|
51
|
-
{
|
|
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 =
|
|
50
|
+
const template = localeTemplate(name);
|
|
57
51
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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 "
|
|
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 = () => {
|
|
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
|
+
});
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
export * from './component.template.js';
|
|
2
|
-
export * from './view.template.js';
|
|
3
|
-
export * from './service.template.js';
|
|
4
|
-
|
|
5
|
-
export * from './
|
|
6
|
-
|
|
7
|
-
|
|
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 @@
|
|
|
1
|
+
export const scssTemplate = () => `\n`;
|
|
@@ -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
|
+
});
|
package/templates/base/tools/generator/templates/{view.template.js.hbs → view/view.template.js.hbs}
RENAMED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { getRelToCore } from "
|
|
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 = {
|
|
9
|
+
const template = \`${htmlTemplate}\`;
|
|
9
10
|
|
|
10
11
|
export class ${name.pascal}View extends View {
|
|
11
12
|
constructor() {
|