@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,96 +0,0 @@
|
|
|
1
|
-
/* Prevent scroll when popover is active */
|
|
2
|
-
html.no-scroll {
|
|
3
|
-
overflow: hidden;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.popover-overlay {
|
|
7
|
-
z-index: 99;
|
|
8
|
-
position: fixed;
|
|
9
|
-
inset: 0;
|
|
10
|
-
backdrop-filter: blur(5px);
|
|
11
|
-
background-color: rgba(0, 0, 0, .1);
|
|
12
|
-
display: flex;
|
|
13
|
-
align-items: center;
|
|
14
|
-
justify-content: center;
|
|
15
|
-
opacity: 0;
|
|
16
|
-
animation: hide-pop 0.3s ease forwards;
|
|
17
|
-
&.show {
|
|
18
|
-
animation: show-pop 0.3s ease forwards;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.popover-wrapper {
|
|
23
|
-
overflow-y: auto;
|
|
24
|
-
position: relative;
|
|
25
|
-
overscroll-behavior: none;
|
|
26
|
-
border-radius: 1rem;
|
|
27
|
-
width: 90%;
|
|
28
|
-
height: 90%;
|
|
29
|
-
transform: scale(0.95);
|
|
30
|
-
opacity: 0;
|
|
31
|
-
transition: opacity 0.3s ease, transform 0.3s ease;
|
|
32
|
-
-moz-transition: opacity 0.3s ease, -moz-transform 0.3s ease;
|
|
33
|
-
-webkit-transition: opacity 0.3s ease, -webkit-transform 0.3s ease;
|
|
34
|
-
-o-transition: opacity 0.3s ease, -o-transform 0.3s ease;
|
|
35
|
-
&.show {
|
|
36
|
-
transform: scale(1);
|
|
37
|
-
-moz-transform: scale(1);
|
|
38
|
-
-webkit-transform: scale(1);
|
|
39
|
-
-o-transform: scale(1);
|
|
40
|
-
opacity: 1;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.popover-content {
|
|
45
|
-
position: relative;
|
|
46
|
-
height: 100%;
|
|
47
|
-
overflow-y: auto;
|
|
48
|
-
-webkit-overflow-scrolling: touch;
|
|
49
|
-
overscroll-behavior: contain;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.popover-close-button {
|
|
53
|
-
position: absolute;
|
|
54
|
-
top: 0.5rem;
|
|
55
|
-
right: 0.75rem;
|
|
56
|
-
background: none;
|
|
57
|
-
border: none;
|
|
58
|
-
font-size: 1.5rem;
|
|
59
|
-
cursor: pointer;
|
|
60
|
-
padding: 0 1rem;
|
|
61
|
-
&:focus:not(:focus-visible) {
|
|
62
|
-
}
|
|
63
|
-
&:focus-visible {
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.popover-buttons {
|
|
68
|
-
display: flex;
|
|
69
|
-
justify-content: flex-end;
|
|
70
|
-
gap: 1rem;
|
|
71
|
-
margin-top: 1.5rem;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.popover-buttons button {
|
|
75
|
-
background-color: inherit;
|
|
76
|
-
transition: ease-in-out 0.3s;
|
|
77
|
-
padding: 0.5rem 1rem;
|
|
78
|
-
font-size: 1rem;
|
|
79
|
-
cursor: pointer;
|
|
80
|
-
&:hover {
|
|
81
|
-
}
|
|
82
|
-
@media (hover: none) {
|
|
83
|
-
&:hover {
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
@keyframes show-pop {
|
|
89
|
-
from { opacity: 0 }
|
|
90
|
-
to { opacity: 1 }
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
@keyframes hide-pop {
|
|
94
|
-
from { opacity: 1 }
|
|
95
|
-
to { opacity: 0 }
|
|
96
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
@use "sass:map";
|
|
2
|
-
@use "variables" as *;
|
|
3
|
-
{{#if stylinNutin}}
|
|
4
|
-
@use "mixins";
|
|
5
|
-
{{/if}}
|
|
6
|
-
|
|
7
|
-
.app-snackbar {
|
|
8
|
-
position: fixed;
|
|
9
|
-
left: 50%;
|
|
10
|
-
transform: translateX(-50%);
|
|
11
|
-
{{#if stylinNutin}}
|
|
12
|
-
@include mixins.flex-center;
|
|
13
|
-
{{else}}
|
|
14
|
-
display: flex;
|
|
15
|
-
align-items: center;
|
|
16
|
-
justify-content: center;
|
|
17
|
-
{{/if}}
|
|
18
|
-
background: $snack-default;
|
|
19
|
-
color: white;
|
|
20
|
-
padding: 0.75rem 1.5rem;
|
|
21
|
-
border-radius: 0.5rem;
|
|
22
|
-
box-shadow: 0 2px 6px rgba(0,0,0,0.3);
|
|
23
|
-
gap: 1rem;
|
|
24
|
-
animation: fade-in 0.3s ease;
|
|
25
|
-
{{#if stylinNutin}}
|
|
26
|
-
@include mixins.respond-to(medium) {
|
|
27
|
-
min-width: 80%;
|
|
28
|
-
}
|
|
29
|
-
{{/if}}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.app-snackbar--bottom { bottom: 1rem; }
|
|
33
|
-
.app-snackbar--top { top: 1rem; }
|
|
34
|
-
|
|
35
|
-
.app-snackbar--success { background: $snack-success; }
|
|
36
|
-
.app-snackbar--error { background: $snack-error; }
|
|
37
|
-
.app-snackbar--info { background: $snack-info; }
|
|
38
|
-
|
|
39
|
-
.app-snackbar button {
|
|
40
|
-
background: transparent;
|
|
41
|
-
border: none;
|
|
42
|
-
color: #fff;
|
|
43
|
-
font-weight: bold;
|
|
44
|
-
cursor: pointer;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
@keyframes fade-in {
|
|
48
|
-
from { opacity: 0; transform: translateX(-50%) translateY(10px); }
|
|
49
|
-
to { opacity: 1; transform: translateX(-50%) translateY(0); }
|
|
50
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import esbuild from 'esbuild';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { exit } from 'process';
|
|
4
|
-
import { print, isVerbose } from '../../utils/index.js';
|
|
5
|
-
import { PATHS } from './paths.js';
|
|
6
|
-
import builderConfig from '../../../builder.config.js';
|
|
7
|
-
|
|
8
|
-
const ENTRY_FILE = path.join(PATHS.tempApp, 'main.ts');
|
|
9
|
-
const OUT_FILE = path.join(PATHS.tempSource, 'bundle.js');
|
|
10
|
-
|
|
11
|
-
async function build() {
|
|
12
|
-
await esbuild.build({
|
|
13
|
-
...builderConfig.esbuild,
|
|
14
|
-
entryPoints: [ENTRY_FILE],
|
|
15
|
-
outfile: OUT_FILE,
|
|
16
|
-
keepNames: true, // View names are used to update meta.title
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
if (isVerbose) print.boldInfo(`ESBuild complete.\n`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
build().catch((err) => {
|
|
23
|
-
print.boldError(`ESBuild failed: ${err.message}`);
|
|
24
|
-
exit(1);
|
|
25
|
-
});
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { minify } from 'html-minifier-terser';
|
|
2
|
-
{{#unless template}}
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import { exit } from 'process';
|
|
5
|
-
import { getFilesRecursive, print, isProd, isVerbose } from '../../utils/index.js';
|
|
6
|
-
import { PATHS } from './paths.js';
|
|
7
|
-
{{/unless}}
|
|
8
|
-
|
|
9
|
-
{{#if template}}export {{/if}}async function minifyHTML(html) {
|
|
10
|
-
return minify(html, {
|
|
11
|
-
collapseWhitespace: true,
|
|
12
|
-
removeComments: true,
|
|
13
|
-
removeRedundantAttributes: true,
|
|
14
|
-
removeScriptTypeAttributes: true,
|
|
15
|
-
removeStyleLinkTypeAttributes: true,
|
|
16
|
-
useShortDoctype: true,
|
|
17
|
-
keepClosingSlash: true,
|
|
18
|
-
minifyCSS: true,
|
|
19
|
-
minifyJS: true,
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
{{#unless template}}
|
|
24
|
-
const TEMPLATE_REGEX =
|
|
25
|
-
/const\s+(template|templateFn)\s*=?\s*(?:\(.*?\)\s*=>\s*)?`([\s\S]*?)`/gm;
|
|
26
|
-
|
|
27
|
-
async function minifyInlineHTML() {
|
|
28
|
-
const extension = isProd ? '.ts' : '.js';
|
|
29
|
-
const jsFiles = getFilesRecursive(PATHS.tempApp, extension);
|
|
30
|
-
|
|
31
|
-
for (const file of jsFiles) {
|
|
32
|
-
let code = fs.readFileSync(file, 'utf8');
|
|
33
|
-
let hasChanges = false;
|
|
34
|
-
|
|
35
|
-
const matches = [...code.matchAll(TEMPLATE_REGEX)];
|
|
36
|
-
|
|
37
|
-
if (matches.length) {
|
|
38
|
-
for (const match of matches) {
|
|
39
|
-
const [full, , html] = match;
|
|
40
|
-
const minified = await minifyHTML(html);
|
|
41
|
-
const minifiedBlock = full.replace(html, minified);
|
|
42
|
-
code = code.replace(full, minifiedBlock);
|
|
43
|
-
hasChanges = true;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (hasChanges) {
|
|
48
|
-
fs.writeFileSync(file, code, 'utf8');
|
|
49
|
-
if (isVerbose) print.info(`Minified inline HTML in: ${file}`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (isVerbose) print.boldInfo('Inline templates minified.\n');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
minifyInlineHTML().catch((err) => {
|
|
56
|
-
print.boldError(`Unexpected error: ${err.message}`);
|
|
57
|
-
exit(1);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
{{/unless}}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import * as sass from 'sass';
|
|
2
|
-
import * as fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { isVerbose, print } from '../../utils/index.js';
|
|
5
|
-
import { PATHS } from './paths.js';
|
|
6
|
-
import builderConfig from '../../../builder.config.js';
|
|
7
|
-
|
|
8
|
-
const stylesInput = path.join(PATHS.source, 'styles');
|
|
9
|
-
const stylesOutput = path.join(PATHS.tempSource, 'main.css');
|
|
10
|
-
|
|
11
|
-
const scssPath = (origin) => path.join(stylesInput, origin);
|
|
12
|
-
const scssOrigins = builderConfig.sass.paths;
|
|
13
|
-
|
|
14
|
-
const pathsToLoad = scssOrigins.map(origin => scssPath(origin));
|
|
15
|
-
|
|
16
|
-
sass.compileAsync(path.join(stylesInput, 'main.scss'), {
|
|
17
|
-
loadPaths: [ ...pathsToLoad ],
|
|
18
|
-
style: 'compressed'
|
|
19
|
-
}).then(result => {
|
|
20
|
-
fs.writeFileSync(stylesOutput, result.css);
|
|
21
|
-
if (isVerbose) print.boldInfo('Global styles compiled.\n');
|
|
22
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { runCommand, print, isVerbose } from "../../utils/index.js";
|
|
2
|
-
import { exit } from 'process';
|
|
3
|
-
|
|
4
|
-
async function compileTS() {
|
|
5
|
-
await runCommand('tsc', ['--project', 'tsconfig.json']);
|
|
6
|
-
if (isVerbose) print.boldInfo('TypeScript compiled.\n');
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
compileTS().catch((err) => {
|
|
10
|
-
print.boldError(`Unexpected error: ${err.message}`);
|
|
11
|
-
exit(1);
|
|
12
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
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} extends Service<${name.pascal}> {
|
|
9
|
-
constructor() {
|
|
10
|
-
super();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const ${name.pascal}Service = ${name.pascal}.getInstance();
|
|
16
|
-
`;
|
|
17
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync } from 'fs';
|
|
2
|
-
import { gzipSync
|
|
3
|
-
// BROTLI OPTIONAL
|
|
4
|
-
//, brotliCompressSync, constants
|
|
5
|
-
} from 'zlib';
|
|
6
|
-
import { print, getFilesRecursive, isVerbose } from '../../utils/index.js';
|
|
7
|
-
import { PATHS } from './paths.js';
|
|
8
|
-
import builderConfig from '../../../builder.config.js';
|
|
9
|
-
|
|
10
|
-
const compress = {
|
|
11
|
-
gzip: builderConfig.compression.gzip,
|
|
12
|
-
// BROTLI OPTIONAL
|
|
13
|
-
// brotli: builderConfig.compression.brotli,
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
function compressStaticAssets() {
|
|
17
|
-
if (
|
|
18
|
-
!compress.gzip
|
|
19
|
-
// BROTLI OPTIONAL
|
|
20
|
-
// && !compress.brotli
|
|
21
|
-
) return;
|
|
22
|
-
|
|
23
|
-
const files = getFilesRecursive(PATHS.tempSource, ['.js', '.css', '.json', '.svg', 'ttf', 'otf', 'eot']);
|
|
24
|
-
|
|
25
|
-
files.forEach(file => {
|
|
26
|
-
const content = readFileSync(file);
|
|
27
|
-
|
|
28
|
-
if (compress.gzip) {
|
|
29
|
-
const gzipped = gzipSync(content, {
|
|
30
|
-
level: 9,
|
|
31
|
-
memLevel: 9,
|
|
32
|
-
windowBits: 15
|
|
33
|
-
});
|
|
34
|
-
writeFileSync(`${file}.gz`, gzipped);
|
|
35
|
-
if (isVerbose) print.info(`Gzip compression: ${file}`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// BROTLI OPTIONAL
|
|
39
|
-
/*
|
|
40
|
-
if (compress.brotli) {
|
|
41
|
-
const brotlied = brotliCompressSync(content, {
|
|
42
|
-
params: {
|
|
43
|
-
[constants.BROTLI_PARAM_QUALITY]: 11,
|
|
44
|
-
[constants.BROTLI_PARAM_LGWIN]: 22,
|
|
45
|
-
[constants.BROTLI_PARAM_MODE]: constants.BROTLI_MODE_GENERIC,
|
|
46
|
-
[constants.BROTLI_PARAM_SIZE_HINT]: content.length
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
writeFileSync(`${file}.br`, brotlied);
|
|
50
|
-
if (isVerbose) print.info(`Brotli compression: ${file}`);
|
|
51
|
-
}
|
|
52
|
-
*/
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
compressStaticAssets();
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
ARG NODE_VERSION=22.3.0
|
|
2
|
-
ARG NGINX_VERSION=1.27-alpine
|
|
3
|
-
ARG PORT=9090
|
|
4
|
-
|
|
5
|
-
FROM node:${NODE_VERSION} AS builder
|
|
6
|
-
WORKDIR /usr/src/app
|
|
7
|
-
COPY ./src ./src
|
|
8
|
-
COPY ./package* .
|
|
9
|
-
COPY ./builder.config.js .
|
|
10
|
-
{{#if i18n}}
|
|
11
|
-
COPY ./config ./config
|
|
12
|
-
{{/if}}
|
|
13
|
-
COPY ./tools/builder ./tools/builder
|
|
14
|
-
COPY ./tools/deployment ./tools/deployment
|
|
15
|
-
COPY ./tools/utils ./tools/utils
|
|
16
|
-
RUN {{ciCommand}} && \
|
|
17
|
-
{{packageManager}} run build:prod
|
|
18
|
-
|
|
19
|
-
FROM nginx:${NGINX_VERSION}
|
|
20
|
-
|
|
21
|
-
RUN rm /etc/nginx/conf.d/default.conf
|
|
22
|
-
COPY --from=builder /usr/src/app/tools/deployment/nginx.conf /etc/nginx/conf.d/default.conf
|
|
23
|
-
COPY --from=builder /usr/src/app/dist/src /usr/share/nginx/html
|
|
24
|
-
|
|
25
|
-
EXPOSE ${PORT}
|
|
26
|
-
|
|
27
|
-
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
28
|
-
CMD curl -f http://localhost:${PORT}/health || exit 1
|
|
29
|
-
|
|
30
|
-
CMD ["nginx", "-g", "daemon off;"]
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { I18nService } from '#root/dist/src/core/services/index.js';
|
|
2
|
-
|
|
3
|
-
class FetchMock {
|
|
4
|
-
constructor() {
|
|
5
|
-
this.originalFetch = global.fetch;
|
|
6
|
-
this.mockResponses = new Map();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
mockTranslation(lang, data) {
|
|
10
|
-
this.mockResponses.set(`/locales/${lang}.json`, {
|
|
11
|
-
ok: true,
|
|
12
|
-
status: 200,
|
|
13
|
-
json: () => Promise.resolve(data)
|
|
14
|
-
});
|
|
15
|
-
return this;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
mockError(url, status = 404) {
|
|
19
|
-
this.mockResponses.set(url, {
|
|
20
|
-
ok: false,
|
|
21
|
-
status,
|
|
22
|
-
json: () => Promise.reject(new Error(`HTTP ${status}`))
|
|
23
|
-
});
|
|
24
|
-
return this;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
install() {
|
|
28
|
-
global.fetch = (url) => {
|
|
29
|
-
if (this.mockResponses.has(url)) {
|
|
30
|
-
const response = this.mockResponses.get(url);
|
|
31
|
-
return Promise.resolve(response);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return this.originalFetch ? this.originalFetch(url) : Promise.reject(new Error('fetch not available'));
|
|
35
|
-
};
|
|
36
|
-
return this;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
restore() {
|
|
40
|
-
global.fetch = this.originalFetch;
|
|
41
|
-
this.mockResponses.clear();
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const fetchMock = new FetchMock();
|
|
46
|
-
|
|
47
|
-
describe('i18n module', async () => {
|
|
48
|
-
let originalLanguage;
|
|
49
|
-
|
|
50
|
-
beforeEach(async () => {
|
|
51
|
-
I18nService.resetTranslations();
|
|
52
|
-
fetchMock
|
|
53
|
-
.mockTranslation('en', { home: { title : 'My App', subtitle: "English subtitle" }})
|
|
54
|
-
.mockTranslation('fr', { home: { title : 'Mon App' }})
|
|
55
|
-
.install();
|
|
56
|
-
});
|
|
57
|
-
afterEach(() => {
|
|
58
|
-
fetchMock.restore();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
beforeAll(() =>{
|
|
62
|
-
originalLanguage = navigator.language;
|
|
63
|
-
Object.defineProperty(navigator, 'language', {
|
|
64
|
-
writable: true,
|
|
65
|
-
configurable: true,
|
|
66
|
-
value: "en-US"
|
|
67
|
-
});
|
|
68
|
-
I18nService['_LANGUAGES'] = [ 'en', 'fr' ];
|
|
69
|
-
I18nService['_DEFAULT_LANGUAGE'] = 'en';
|
|
70
|
-
});
|
|
71
|
-
afterAll(() => {
|
|
72
|
-
Object.defineProperty(navigator, 'language', {
|
|
73
|
-
writable: true,
|
|
74
|
-
configurable: true,
|
|
75
|
-
value: originalLanguage
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should load and use English translations', async () => {
|
|
80
|
-
await I18nService.initTranslations();
|
|
81
|
-
expect(I18nService.currentLanguage).toBe('en');
|
|
82
|
-
expect(I18nService.translate('home.title')).toBe('My App');
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should load and use French translations', async () => {
|
|
86
|
-
Object.defineProperty(navigator, 'language', {
|
|
87
|
-
writable: true,
|
|
88
|
-
configurable: true,
|
|
89
|
-
value: "fr-FR"
|
|
90
|
-
});
|
|
91
|
-
await I18nService.initTranslations();
|
|
92
|
-
expect(I18nService.currentLanguage).toBe('fr');
|
|
93
|
-
expect(I18nService.translate('home.title')).toBe('Mon App');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should default to English translations', async () => {
|
|
97
|
-
// missing locale
|
|
98
|
-
Object.defineProperty(navigator, 'language', {
|
|
99
|
-
writable: true,
|
|
100
|
-
configurable: true,
|
|
101
|
-
value: "de-DE"
|
|
102
|
-
});
|
|
103
|
-
await I18nService.initTranslations();
|
|
104
|
-
expect(navigator.language).toBe('de-DE');
|
|
105
|
-
expect(I18nService.currentLanguage).toBe('en');
|
|
106
|
-
expect(I18nService.translate('home.title')).toBe('My App');
|
|
107
|
-
I18nService.resetTranslations();
|
|
108
|
-
|
|
109
|
-
// missing translation
|
|
110
|
-
Object.defineProperty(navigator, 'language', {
|
|
111
|
-
writable: true,
|
|
112
|
-
configurable: true,
|
|
113
|
-
value: "fr-FR"
|
|
114
|
-
});
|
|
115
|
-
await I18nService.initTranslations();
|
|
116
|
-
expect(navigator.language).toBe('fr-FR');
|
|
117
|
-
expect(I18nService.currentLanguage).toBe('fr');
|
|
118
|
-
expect(I18nService.translate('home.title')).toBe('Mon App');
|
|
119
|
-
expect(I18nService.translate('home.subtitle')).toBe('English subtitle');
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('should return key when translation is missing', () => {
|
|
123
|
-
expect(I18nService.translate('non.existent.key')).toBe('non.existent.key');
|
|
124
|
-
});
|
|
125
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
const langsPath = path.join(process.cwd(), 'config', 'languages.json');
|
|
5
|
-
const langs = JSON.parse(fs.readFileSync(langsPath, 'utf-8'));
|
|
6
|
-
export const LANGUAGES = langs.languages;
|
|
7
|
-
export const DEFAULT_LANGUAGE = langs.defaultLanguage;
|