@mouryaamit/nx-polystack 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -2
- package/USER-MANUAL.md +1968 -0
- package/dist/bin/cli.d.ts +1 -0
- package/dist/bin/cli.js +92 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/executors.json +32 -0
- package/dist/generators.json +47 -0
- package/dist/migrations.json +87 -0
- package/dist/runtime/env-secret.cjs +736 -0
- package/dist/src/cli/args.d.ts +18 -0
- package/dist/src/cli/args.js +67 -0
- package/dist/src/cli/args.js.map +1 -0
- package/dist/src/cli/commands/app.d.ts +3 -0
- package/dist/src/cli/commands/app.js +108 -0
- package/dist/src/cli/commands/app.js.map +1 -0
- package/dist/src/cli/commands/build.d.ts +8 -0
- package/dist/src/cli/commands/build.js +132 -0
- package/dist/src/cli/commands/build.js.map +1 -0
- package/dist/src/cli/commands/csp.d.ts +19 -0
- package/dist/src/cli/commands/csp.js +238 -0
- package/dist/src/cli/commands/csp.js.map +1 -0
- package/dist/src/cli/commands/encryption.d.ts +4 -0
- package/dist/src/cli/commands/encryption.js +261 -0
- package/dist/src/cli/commands/encryption.js.map +1 -0
- package/dist/src/cli/commands/env.d.ts +2 -0
- package/dist/src/cli/commands/env.js +74 -0
- package/dist/src/cli/commands/env.js.map +1 -0
- package/dist/src/cli/commands/hardening.d.ts +2 -0
- package/dist/src/cli/commands/hardening.js +176 -0
- package/dist/src/cli/commands/hardening.js.map +1 -0
- package/dist/src/cli/commands/index.d.ts +3 -0
- package/dist/src/cli/commands/index.js +45 -0
- package/dist/src/cli/commands/index.js.map +1 -0
- package/dist/src/cli/commands/infra.d.ts +25 -0
- package/dist/src/cli/commands/infra.js +85 -0
- package/dist/src/cli/commands/infra.js.map +1 -0
- package/dist/src/cli/commands/internal-migrate.d.ts +3 -0
- package/dist/src/cli/commands/internal-migrate.js +65 -0
- package/dist/src/cli/commands/internal-migrate.js.map +1 -0
- package/dist/src/cli/commands/lib.d.ts +2 -0
- package/dist/src/cli/commands/lib.js +70 -0
- package/dist/src/cli/commands/lib.js.map +1 -0
- package/dist/src/cli/commands/llm.d.ts +2 -0
- package/dist/src/cli/commands/llm.js +46 -0
- package/dist/src/cli/commands/llm.js.map +1 -0
- package/dist/src/cli/commands/migrate.d.ts +2 -0
- package/dist/src/cli/commands/migrate.js +230 -0
- package/dist/src/cli/commands/migrate.js.map +1 -0
- package/dist/src/cli/commands/new.d.ts +6 -0
- package/dist/src/cli/commands/new.js +97 -0
- package/dist/src/cli/commands/new.js.map +1 -0
- package/dist/src/cli/commands/preset.d.ts +2 -0
- package/dist/src/cli/commands/preset.js +47 -0
- package/dist/src/cli/commands/preset.js.map +1 -0
- package/dist/src/cli/commands/release.d.ts +3 -0
- package/dist/src/cli/commands/release.js +83 -0
- package/dist/src/cli/commands/release.js.map +1 -0
- package/dist/src/cli/commands/shared.d.ts +3 -0
- package/dist/src/cli/commands/shared.js +55 -0
- package/dist/src/cli/commands/shared.js.map +1 -0
- package/dist/src/cli/commands/update.d.ts +11 -0
- package/dist/src/cli/commands/update.js +120 -0
- package/dist/src/cli/commands/update.js.map +1 -0
- package/dist/src/cli/context.d.ts +18 -0
- package/dist/src/cli/context.js +66 -0
- package/dist/src/cli/context.js.map +1 -0
- package/dist/src/cli/exec.d.ts +9 -0
- package/dist/src/cli/exec.js +34 -0
- package/dist/src/cli/exec.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -0
- package/dist/src/cli/help.js +291 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/install-source.d.ts +16 -0
- package/dist/src/cli/install-source.js +49 -0
- package/dist/src/cli/install-source.js.map +1 -0
- package/dist/src/cli/launcher.d.ts +32 -0
- package/dist/src/cli/launcher.js +168 -0
- package/dist/src/cli/launcher.js.map +1 -0
- package/dist/src/cli/migrations.d.ts +25 -0
- package/dist/src/cli/migrations.js +35 -0
- package/dist/src/cli/migrations.js.map +1 -0
- package/dist/src/cli/run-tree.d.ts +9 -0
- package/dist/src/cli/run-tree.js +32 -0
- package/dist/src/cli/run-tree.js.map +1 -0
- package/dist/src/cli/types.d.ts +18 -0
- package/dist/src/cli/types.js +12 -0
- package/dist/src/cli/types.js.map +1 -0
- package/dist/src/cli/update-plan.d.ts +15 -0
- package/dist/src/cli/update-plan.js +40 -0
- package/dist/src/cli/update-plan.js.map +1 -0
- package/dist/src/cli/versions.d.ts +26 -0
- package/dist/src/cli/versions.js +83 -0
- package/dist/src/cli/versions.js.map +1 -0
- package/dist/src/executors/build/executor.d.ts +19 -0
- package/dist/src/executors/build/executor.js +251 -0
- package/dist/src/executors/build/executor.js.map +1 -0
- package/dist/src/executors/build/schema.d.ts +42 -0
- package/dist/src/executors/build/schema.json +104 -0
- package/dist/src/executors/capacitor/executor.d.ts +8 -0
- package/dist/src/executors/capacitor/executor.js +45 -0
- package/dist/src/executors/capacitor/executor.js.map +1 -0
- package/dist/src/executors/capacitor/schema.d.ts +10 -0
- package/dist/src/executors/capacitor/schema.json +24 -0
- package/dist/src/executors/clean/executor.d.ts +19 -0
- package/dist/src/executors/clean/executor.js +134 -0
- package/dist/src/executors/clean/executor.js.map +1 -0
- package/dist/src/executors/clean/schema.d.ts +6 -0
- package/dist/src/executors/clean/schema.json +21 -0
- package/dist/src/executors/flutter-build/executor.d.ts +8 -0
- package/dist/src/executors/flutter-build/executor.js +70 -0
- package/dist/src/executors/flutter-build/executor.js.map +1 -0
- package/dist/src/executors/flutter-build/schema.d.ts +10 -0
- package/dist/src/executors/flutter-build/schema.json +44 -0
- package/dist/src/executors/flutter-export/executor.d.ts +8 -0
- package/dist/src/executors/flutter-export/executor.js +36 -0
- package/dist/src/executors/flutter-export/executor.js.map +1 -0
- package/dist/src/executors/flutter-export/schema.d.ts +6 -0
- package/dist/src/executors/flutter-export/schema.json +28 -0
- package/dist/src/generators/app/files/angular/.eslintrc.json__template__ +28 -0
- package/dist/src/generators/app/files/angular/csp-allowlist.json__template__ +1 -0
- package/dist/src/generators/app/files/angular/server/README.md__template__ +31 -0
- package/dist/src/generators/app/files/angular/src/app/app-routing.module.ts__template__ +10 -0
- package/dist/src/generators/app/files/angular/src/app/app.component.html__template__ +4 -0
- package/dist/src/generators/app/files/angular/src/app/app.component.scss__template__ +1 -0
- package/dist/src/generators/app/files/angular/src/app/app.component.ts__template__ +9 -0
- package/dist/src/generators/app/files/angular/src/app/app.module.ts__template__ +13 -0
- package/dist/src/generators/app/files/angular/src/index.html__template__ +12 -0
- package/dist/src/generators/app/files/angular/src/main.ts__template__ +16 -0
- package/dist/src/generators/app/files/angular/src/styles.scss__template__ +1 -0
- package/dist/src/generators/app/files/angular/tsconfig.app.json__template__ +10 -0
- package/dist/src/generators/app/files/angular/tsconfig.json__template__ +25 -0
- package/dist/src/generators/app/files/angular/tsconfig.spec.json__template__ +8 -0
- package/dist/src/generators/app/files/flutter/.gitignore__template__ +10 -0
- package/dist/src/generators/app/files/flutter/analysis_options.yaml__template__ +8 -0
- package/dist/src/generators/app/files/flutter/lib/main.dart__template__ +23 -0
- package/dist/src/generators/app/files/flutter/pubspec.yaml__template__ +26 -0
- package/dist/src/generators/app/files/flutter/server/nginx.conf__template__ +35 -0
- package/dist/src/generators/app/files/ionic/.gitignore__template__ +7 -0
- package/dist/src/generators/app/files/ionic/capacitor.config.ts__template__ +19 -0
- package/dist/src/generators/app/files/ionic/package.json__template__ +14 -0
- package/dist/src/generators/app/files/ionic/src/app/app.component.html__template__ +3 -0
- package/dist/src/generators/app/files/ionic/src/app/app.component.scss__template__ +0 -0
- package/dist/src/generators/app/files/ionic/src/app/app.module.ts__template__ +16 -0
- package/dist/src/generators/app/files/ionic/src/index.html__template__ +17 -0
- package/dist/src/generators/app/files/ionic/src/styles.scss__template__ +12 -0
- package/dist/src/generators/app/generator.d.ts +15 -0
- package/dist/src/generators/app/generator.js +363 -0
- package/dist/src/generators/app/generator.js.map +1 -0
- package/dist/src/generators/app/schema.d.ts +19 -0
- package/dist/src/generators/app/schema.json +77 -0
- package/dist/src/generators/env/generator.d.ts +3 -0
- package/dist/src/generators/env/generator.js +454 -0
- package/dist/src/generators/env/generator.js.map +1 -0
- package/dist/src/generators/env/schema.d.ts +18 -0
- package/dist/src/generators/env/schema.json +47 -0
- package/dist/src/generators/infra/files/ci/commitlint/commitlint.config.js__template__ +6 -0
- package/dist/src/generators/infra/files/ci/common/tools/config/allowed-cycles.json__template__ +1 -0
- package/dist/src/generators/infra/files/ci/common/tools/scripts/check-cycles.js__template__ +201 -0
- package/dist/src/generators/infra/files/ci/github-actions/.github/workflows/ci.yml__template__ +68 -0
- package/dist/src/generators/infra/files/ci/github-actions/.github/workflows/pr-title.yml__template__ +36 -0
- package/dist/src/generators/infra/files/ci/jenkins/Jenkinsfile__template__ +45 -0
- package/dist/src/generators/infra/files/docs/.github/ISSUE_TEMPLATE/bug.yml__template__ +39 -0
- package/dist/src/generators/infra/files/docs/.github/ISSUE_TEMPLATE/config.yml__template__ +1 -0
- package/dist/src/generators/infra/files/docs/.github/ISSUE_TEMPLATE/feature.yml__template__ +23 -0
- package/dist/src/generators/infra/files/docs/.github/PULL_REQUEST_TEMPLATE.md__template__ +23 -0
- package/dist/src/generators/infra/files/docs/CODE_OF_CONDUCT.md__template__ +18 -0
- package/dist/src/generators/infra/files/docs/CONTRIBUTING.md__template__ +61 -0
- package/dist/src/generators/infra/files/docs/SECURITY.md__template__ +25 -0
- package/dist/src/generators/infra/files/quality/.husky/pre-push__template__ +2 -0
- package/dist/src/generators/infra/files/quality/.secretlintignore__template__ +7 -0
- package/dist/src/generators/infra/files/quality/.secretlintrc.json__template__ +7 -0
- package/dist/src/generators/infra/files/quality/knip.json__template__ +9 -0
- package/dist/src/generators/infra/files/upgrades/.github/workflows/dependency-upgrade.yml__template__ +80 -0
- package/dist/src/generators/infra/generator.d.ts +60 -0
- package/dist/src/generators/infra/generator.js +356 -0
- package/dist/src/generators/infra/generator.js.map +1 -0
- package/dist/src/generators/infra/options.d.ts +28 -0
- package/dist/src/generators/infra/options.js +80 -0
- package/dist/src/generators/infra/options.js.map +1 -0
- package/dist/src/generators/infra/schema.d.ts +19 -0
- package/dist/src/generators/infra/schema.json +59 -0
- package/dist/src/generators/lib/angular-lib.d.ts +27 -0
- package/dist/src/generators/lib/angular-lib.js +85 -0
- package/dist/src/generators/lib/angular-lib.js.map +1 -0
- package/dist/src/generators/lib/files/angular/component/src/index.ts__template__ +2 -0
- package/dist/src/generators/lib/files/angular/component/src/lib/__fileName__/__fileName__.component.html__template__ +1 -0
- package/dist/src/generators/lib/files/angular/component/src/lib/__fileName__/__fileName__.component.scss__template__ +3 -0
- package/dist/src/generators/lib/files/angular/component/src/lib/__fileName__/__fileName__.component.ts__template__ +9 -0
- package/dist/src/generators/lib/files/angular/component/src/lib/__fileName__.module.ts__template__ +11 -0
- package/dist/src/generators/lib/files/angular/config/.eslintrc.json__template__ +32 -0
- package/dist/src/generators/lib/files/angular/config/tsconfig.json__template__ +22 -0
- package/dist/src/generators/lib/files/angular/config/tsconfig.lib.json__template__ +12 -0
- package/dist/src/generators/lib/files/assets/README.md__template__ +13 -0
- package/dist/src/generators/lib/files/design-tokens/README.md__template__ +90 -0
- package/dist/src/generators/lib/files/design-tokens/generated/dart/pubspec.yaml__template__ +11 -0
- package/dist/src/generators/lib/files/design-tokens/src/index.ts__template__ +1 -0
- package/dist/src/generators/lib/files/design-tokens/style-dictionary.config.js__template__ +41 -0
- package/dist/src/generators/lib/files/flutter/.gitignore__template__ +7 -0
- package/dist/src/generators/lib/files/flutter/analysis_options.yaml__template__ +6 -0
- package/dist/src/generators/lib/files/flutter/lib/__snakeName__.dart__template__ +1 -0
- package/dist/src/generators/lib/files/flutter/lib/src/__snakeName__.dart__template__ +6 -0
- package/dist/src/generators/lib/files/flutter/pubspec.yaml__template__ +18 -0
- package/dist/src/generators/lib/files/flutter/test/__snakeName___test.dart__template__ +8 -0
- package/dist/src/generators/lib/files/ionic/src/index.ts__template__ +2 -0
- package/dist/src/generators/lib/files/ionic/src/lib/__fileName__/__fileName__.page.html__template__ +9 -0
- package/dist/src/generators/lib/files/ionic/src/lib/__fileName__/__fileName__.page.scss__template__ +3 -0
- package/dist/src/generators/lib/files/ionic/src/lib/__fileName__/__fileName__.page.ts__template__ +9 -0
- package/dist/src/generators/lib/files/ionic/src/lib/__fileName__.module.ts__template__ +12 -0
- package/dist/src/generators/lib/files/pii/README.md__template__ +35 -0
- package/dist/src/generators/lib/files/pii/src/index.ts__template__ +5 -0
- package/dist/src/generators/lib/files/pii/src/lib/pii-mask.directive.ts__template__ +30 -0
- package/dist/src/generators/lib/files/pii/src/lib/pii-mask.module.ts__template__ +17 -0
- package/dist/src/generators/lib/files/pii/src/lib/pii-mask.options.ts__template__ +6 -0
- package/dist/src/generators/lib/files/pii/src/lib/pii-mask.pipe.ts__template__ +14 -0
- package/dist/src/generators/lib/files/pii/src/lib/pii-mask.ts__template__ +117 -0
- package/dist/src/generators/lib/files/session/README.md__template__ +39 -0
- package/dist/src/generators/lib/files/session/src/index.ts__template__ +5 -0
- package/dist/src/generators/lib/files/session/src/lib/session-clock.ts__template__ +113 -0
- package/dist/src/generators/lib/files/session/src/lib/session-timeout.config.ts__template__ +8 -0
- package/dist/src/generators/lib/files/session/src/lib/session-timeout.module.ts__template__ +23 -0
- package/dist/src/generators/lib/files/session/src/lib/session-timeout.service.ts__template__ +289 -0
- package/dist/src/generators/lib/files/session/src/lib/session-warning/session-warning.component.html__template__ +21 -0
- package/dist/src/generators/lib/files/session/src/lib/session-warning/session-warning.component.scss__template__ +40 -0
- package/dist/src/generators/lib/files/session/src/lib/session-warning/session-warning.component.ts__template__ +105 -0
- package/dist/src/generators/lib/files/state/ngrx/README.md__template__ +33 -0
- package/dist/src/generators/lib/files/state/ngrx/src/index.ts__template__ +6 -0
- package/dist/src/generators/lib/files/state/ngrx/src/lib/__fileName__-state.module.ts__template__ +18 -0
- package/dist/src/generators/lib/files/state/ngrx/src/lib/__fileName__.actions.ts__template__ +12 -0
- package/dist/src/generators/lib/files/state/ngrx/src/lib/__fileName__.effects.ts__template__ +26 -0
- package/dist/src/generators/lib/files/state/ngrx/src/lib/__fileName__.models.ts__template__ +4 -0
- package/dist/src/generators/lib/files/state/ngrx/src/lib/__fileName__.reducer.ts__template__ +33 -0
- package/dist/src/generators/lib/files/state/ngrx/src/lib/__fileName__.selectors.ts__template__ +14 -0
- package/dist/src/generators/lib/files/state/simple-service/README.md__template__ +20 -0
- package/dist/src/generators/lib/files/state/simple-service/src/index.ts__template__ +2 -0
- package/dist/src/generators/lib/files/state/simple-service/src/lib/__fileName__.store.ts__template__ +58 -0
- package/dist/src/generators/lib/files/state/simple-service/src/lib/store.ts__template__ +34 -0
- package/dist/src/generators/lib/files/styles/README.md__template__ +39 -0
- package/dist/src/generators/lib/files/styles/src/_index.scss__template__ +3 -0
- package/dist/src/generators/lib/files/styles/src/mixins/_index.scss__template__ +13 -0
- package/dist/src/generators/lib/files/styles/src/themes/_index.scss__template__ +20 -0
- package/dist/src/generators/lib/files/styles/src/tokens/_index.scss__template__ +27 -0
- package/dist/src/generators/lib/files/ts/config/.eslintrc.json__template__ +10 -0
- package/dist/src/generators/lib/files/ts/config/tsconfig.json__template__ +14 -0
- package/dist/src/generators/lib/files/ts/config/tsconfig.lib.json__template__ +10 -0
- package/dist/src/generators/lib/files/ts/sample/src/index.ts__template__ +1 -0
- package/dist/src/generators/lib/files/ts/sample/src/lib/__fileName__.ts__template__ +4 -0
- package/dist/src/generators/lib/generator.d.ts +3 -0
- package/dist/src/generators/lib/generator.js +53 -0
- package/dist/src/generators/lib/generator.js.map +1 -0
- package/dist/src/generators/lib/lib-utils.d.ts +72 -0
- package/dist/src/generators/lib/lib-utils.js +170 -0
- package/dist/src/generators/lib/lib-utils.js.map +1 -0
- package/dist/src/generators/lib/schema.d.ts +31 -0
- package/dist/src/generators/lib/schema.json +63 -0
- package/dist/src/generators/lib/style-dictionary.d.ts +36 -0
- package/dist/src/generators/lib/style-dictionary.js +183 -0
- package/dist/src/generators/lib/style-dictionary.js.map +1 -0
- package/dist/src/generators/lib/types/angular.d.ts +2 -0
- package/dist/src/generators/lib/types/angular.js +20 -0
- package/dist/src/generators/lib/types/angular.js.map +1 -0
- package/dist/src/generators/lib/types/assets.d.ts +2 -0
- package/dist/src/generators/lib/types/assets.js +20 -0
- package/dist/src/generators/lib/types/assets.js.map +1 -0
- package/dist/src/generators/lib/types/design-tokens.d.ts +10 -0
- package/dist/src/generators/lib/types/design-tokens.js +78 -0
- package/dist/src/generators/lib/types/design-tokens.js.map +1 -0
- package/dist/src/generators/lib/types/flutter.d.ts +2 -0
- package/dist/src/generators/lib/types/flutter.js +28 -0
- package/dist/src/generators/lib/types/flutter.js.map +1 -0
- package/dist/src/generators/lib/types/index.d.ts +8 -0
- package/dist/src/generators/lib/types/index.js +31 -0
- package/dist/src/generators/lib/types/index.js.map +1 -0
- package/dist/src/generators/lib/types/ionic.d.ts +4 -0
- package/dist/src/generators/lib/types/ionic.js +35 -0
- package/dist/src/generators/lib/types/ionic.js.map +1 -0
- package/dist/src/generators/lib/types/pii.d.ts +3 -0
- package/dist/src/generators/lib/types/pii.js +19 -0
- package/dist/src/generators/lib/types/pii.js.map +1 -0
- package/dist/src/generators/lib/types/session.d.ts +3 -0
- package/dist/src/generators/lib/types/session.js +21 -0
- package/dist/src/generators/lib/types/session.js.map +1 -0
- package/dist/src/generators/lib/types/state.d.ts +5 -0
- package/dist/src/generators/lib/types/state.js +48 -0
- package/dist/src/generators/lib/types/state.js.map +1 -0
- package/dist/src/generators/lib/types/styles.d.ts +2 -0
- package/dist/src/generators/lib/types/styles.js +19 -0
- package/dist/src/generators/lib/types/styles.js.map +1 -0
- package/dist/src/generators/lib/types/ts.d.ts +5 -0
- package/dist/src/generators/lib/types/ts.js +30 -0
- package/dist/src/generators/lib/types/ts.js.map +1 -0
- package/dist/src/generators/llm/generator.d.ts +8 -0
- package/dist/src/generators/llm/generator.js +13 -0
- package/dist/src/generators/llm/generator.js.map +1 -0
- package/dist/src/generators/llm/schema.d.ts +4 -0
- package/dist/src/generators/llm/schema.json +16 -0
- package/dist/src/generators/migrate/adapters/angular-cli.d.ts +82 -0
- package/dist/src/generators/migrate/adapters/angular-cli.js +439 -0
- package/dist/src/generators/migrate/adapters/angular-cli.js.map +1 -0
- package/dist/src/generators/migrate/adapters/angular-workspace.d.ts +28 -0
- package/dist/src/generators/migrate/adapters/angular-workspace.js +397 -0
- package/dist/src/generators/migrate/adapters/angular-workspace.js.map +1 -0
- package/dist/src/generators/migrate/adapters/external.d.ts +23 -0
- package/dist/src/generators/migrate/adapters/external.js +230 -0
- package/dist/src/generators/migrate/adapters/external.js.map +1 -0
- package/dist/src/generators/migrate/adapters/flutter.d.ts +26 -0
- package/dist/src/generators/migrate/adapters/flutter.js +176 -0
- package/dist/src/generators/migrate/adapters/flutter.js.map +1 -0
- package/dist/src/generators/migrate/adapters/index.d.ts +34 -0
- package/dist/src/generators/migrate/adapters/index.js +136 -0
- package/dist/src/generators/migrate/adapters/index.js.map +1 -0
- package/dist/src/generators/migrate/adapters/ionic.d.ts +17 -0
- package/dist/src/generators/migrate/adapters/ionic.js +137 -0
- package/dist/src/generators/migrate/adapters/ionic.js.map +1 -0
- package/dist/src/generators/migrate/adapters/npm-workspaces.d.ts +23 -0
- package/dist/src/generators/migrate/adapters/npm-workspaces.js +734 -0
- package/dist/src/generators/migrate/adapters/npm-workspaces.js.map +1 -0
- package/dist/src/generators/migrate/adapters/nx-workspace.d.ts +47 -0
- package/dist/src/generators/migrate/adapters/nx-workspace.js +1037 -0
- package/dist/src/generators/migrate/adapters/nx-workspace.js.map +1 -0
- package/dist/src/generators/migrate/adapters/scaffold.d.ts +2 -0
- package/dist/src/generators/migrate/adapters/scaffold.js +200 -0
- package/dist/src/generators/migrate/adapters/scaffold.js.map +1 -0
- package/dist/src/generators/migrate/adapters/types.d.ts +184 -0
- package/dist/src/generators/migrate/adapters/types.js +63 -0
- package/dist/src/generators/migrate/adapters/types.js.map +1 -0
- package/dist/src/generators/migrate/angular-code-scan.d.ts +6 -0
- package/dist/src/generators/migrate/angular-code-scan.js +150 -0
- package/dist/src/generators/migrate/angular-code-scan.js.map +1 -0
- package/dist/src/generators/migrate/angular-config-files.d.ts +49 -0
- package/dist/src/generators/migrate/angular-config-files.js +158 -0
- package/dist/src/generators/migrate/angular-config-files.js.map +1 -0
- package/dist/src/generators/migrate/angular-project-json.d.ts +73 -0
- package/dist/src/generators/migrate/angular-project-json.js +352 -0
- package/dist/src/generators/migrate/angular-project-json.js.map +1 -0
- package/dist/src/generators/migrate/angular-workspace/aliases.d.ts +30 -0
- package/dist/src/generators/migrate/angular-workspace/aliases.js +73 -0
- package/dist/src/generators/migrate/angular-workspace/aliases.js.map +1 -0
- package/dist/src/generators/migrate/angular-workspace/eslint.d.ts +8 -0
- package/dist/src/generators/migrate/angular-workspace/eslint.js +38 -0
- package/dist/src/generators/migrate/angular-workspace/eslint.js.map +1 -0
- package/dist/src/generators/migrate/angular-workspace/ng-package.d.ts +4 -0
- package/dist/src/generators/migrate/angular-workspace/ng-package.js +16 -0
- package/dist/src/generators/migrate/angular-workspace/ng-package.js.map +1 -0
- package/dist/src/generators/migrate/angular-workspace/source.d.ts +15 -0
- package/dist/src/generators/migrate/angular-workspace/source.js +108 -0
- package/dist/src/generators/migrate/angular-workspace/source.js.map +1 -0
- package/dist/src/generators/migrate/angular17.d.ts +45 -0
- package/dist/src/generators/migrate/angular17.js +495 -0
- package/dist/src/generators/migrate/angular17.js.map +1 -0
- package/dist/src/generators/migrate/batch.d.ts +29 -0
- package/dist/src/generators/migrate/batch.js +211 -0
- package/dist/src/generators/migrate/batch.js.map +1 -0
- package/dist/src/generators/migrate/copy.d.ts +60 -0
- package/dist/src/generators/migrate/copy.js +224 -0
- package/dist/src/generators/migrate/copy.js.map +1 -0
- package/dist/src/generators/migrate/dependencies.d.ts +38 -0
- package/dist/src/generators/migrate/dependencies.js +196 -0
- package/dist/src/generators/migrate/dependencies.js.map +1 -0
- package/dist/src/generators/migrate/generator.d.ts +9 -0
- package/dist/src/generators/migrate/generator.js +347 -0
- package/dist/src/generators/migrate/generator.js.map +1 -0
- package/dist/src/generators/migrate/imports/rewrite.d.ts +46 -0
- package/dist/src/generators/migrate/imports/rewrite.js +382 -0
- package/dist/src/generators/migrate/imports/rewrite.js.map +1 -0
- package/dist/src/generators/migrate/ionic/capacitor-config.d.ts +24 -0
- package/dist/src/generators/migrate/ionic/capacitor-config.js +113 -0
- package/dist/src/generators/migrate/ionic/capacitor-config.js.map +1 -0
- package/dist/src/generators/migrate/ionic/packages.d.ts +34 -0
- package/dist/src/generators/migrate/ionic/packages.js +92 -0
- package/dist/src/generators/migrate/ionic/packages.js.map +1 -0
- package/dist/src/generators/migrate/ionic/shape.d.ts +32 -0
- package/dist/src/generators/migrate/ionic/shape.js +221 -0
- package/dist/src/generators/migrate/ionic/shape.js.map +1 -0
- package/dist/src/generators/migrate/ionic/skip.d.ts +3 -0
- package/dist/src/generators/migrate/ionic/skip.js +25 -0
- package/dist/src/generators/migrate/ionic/skip.js.map +1 -0
- package/dist/src/generators/migrate/names.d.ts +3 -0
- package/dist/src/generators/migrate/names.js +21 -0
- package/dist/src/generators/migrate/names.js.map +1 -0
- package/dist/src/generators/migrate/npm-deps.d.ts +28 -0
- package/dist/src/generators/migrate/npm-deps.js +63 -0
- package/dist/src/generators/migrate/npm-deps.js.map +1 -0
- package/dist/src/generators/migrate/npm-workspaces/pnpm-yaml.d.ts +10 -0
- package/dist/src/generators/migrate/npm-workspaces/pnpm-yaml.js +246 -0
- package/dist/src/generators/migrate/npm-workspaces/pnpm-yaml.js.map +1 -0
- package/dist/src/generators/migrate/npm-workspaces/source.d.ts +46 -0
- package/dist/src/generators/migrate/npm-workspaces/source.js +253 -0
- package/dist/src/generators/migrate/npm-workspaces/source.js.map +1 -0
- package/dist/src/generators/migrate/nx/build-scripts.d.ts +22 -0
- package/dist/src/generators/migrate/nx/build-scripts.js +147 -0
- package/dist/src/generators/migrate/nx/build-scripts.js.map +1 -0
- package/dist/src/generators/migrate/nx/detect.d.ts +3 -0
- package/dist/src/generators/migrate/nx/detect.js +43 -0
- package/dist/src/generators/migrate/nx/detect.js.map +1 -0
- package/dist/src/generators/migrate/nx/env-encryption.d.ts +35 -0
- package/dist/src/generators/migrate/nx/env-encryption.js +423 -0
- package/dist/src/generators/migrate/nx/env-encryption.js.map +1 -0
- package/dist/src/generators/migrate/nx/rewrite.d.ts +27 -0
- package/dist/src/generators/migrate/nx/rewrite.js +223 -0
- package/dist/src/generators/migrate/nx/rewrite.js.map +1 -0
- package/dist/src/generators/migrate/nx/selection.d.ts +25 -0
- package/dist/src/generators/migrate/nx/selection.js +173 -0
- package/dist/src/generators/migrate/nx/selection.js.map +1 -0
- package/dist/src/generators/migrate/nx/shared-folders.d.ts +58 -0
- package/dist/src/generators/migrate/nx/shared-folders.js +239 -0
- package/dist/src/generators/migrate/nx/shared-folders.js.map +1 -0
- package/dist/src/generators/migrate/nx/workspace-source.d.ts +58 -0
- package/dist/src/generators/migrate/nx/workspace-source.js +275 -0
- package/dist/src/generators/migrate/nx/workspace-source.js.map +1 -0
- package/dist/src/generators/migrate/pnpm.d.ts +42 -0
- package/dist/src/generators/migrate/pnpm.js +132 -0
- package/dist/src/generators/migrate/pnpm.js.map +1 -0
- package/dist/src/generators/migrate/report.d.ts +21 -0
- package/dist/src/generators/migrate/report.js +243 -0
- package/dist/src/generators/migrate/report.js.map +1 -0
- package/dist/src/generators/migrate/rollback/manifest.d.ts +84 -0
- package/dist/src/generators/migrate/rollback/manifest.js +162 -0
- package/dist/src/generators/migrate/rollback/manifest.js.map +1 -0
- package/dist/src/generators/migrate/rollback/recording-tree.d.ts +19 -0
- package/dist/src/generators/migrate/rollback/recording-tree.js +87 -0
- package/dist/src/generators/migrate/rollback/recording-tree.js.map +1 -0
- package/dist/src/generators/migrate/rollback/rollback.d.ts +29 -0
- package/dist/src/generators/migrate/rollback/rollback.js +271 -0
- package/dist/src/generators/migrate/rollback/rollback.js.map +1 -0
- package/dist/src/generators/migrate/schema.d.ts +41 -0
- package/dist/src/generators/migrate/schema.json +85 -0
- package/dist/src/generators/migrate/source.d.ts +26 -0
- package/dist/src/generators/migrate/source.js +70 -0
- package/dist/src/generators/migrate/source.js.map +1 -0
- package/dist/src/generators/preset/files/root/.editorconfig__template__ +15 -0
- package/dist/src/generators/preset/files/root/.eslintignore__template__ +2 -0
- package/dist/src/generators/preset/files/root/.eslintrc.json__template__ +38 -0
- package/dist/src/generators/preset/files/root/.gitattributes__template__ +12 -0
- package/dist/src/generators/preset/files/root/.gitignore__template__ +9 -0
- package/dist/src/generators/preset/files/root/.husky/commit-msg__template__ +1 -0
- package/dist/src/generators/preset/files/root/.husky/pre-commit__template__ +1 -0
- package/dist/src/generators/preset/files/root/.npmrc__template__ +4 -0
- package/dist/src/generators/preset/files/root/.nvmrc__template__ +1 -0
- package/dist/src/generators/preset/files/root/.prettierignore__template__ +6 -0
- package/dist/src/generators/preset/files/root/.prettierrc__template__ +7 -0
- package/dist/src/generators/preset/files/root/commitlint.config.js__template__ +6 -0
- package/dist/src/generators/preset/files/root/nx.json__template__ +30 -0
- package/dist/src/generators/preset/files/root/package.json__template__ +34 -0
- package/dist/src/generators/preset/files/root/tools/config/sri-cdn-allowlist.json__template__ +1 -0
- package/dist/src/generators/preset/files/root/tsconfig.base.json__template__ +18 -0
- package/dist/src/generators/preset/generator.d.ts +11 -0
- package/dist/src/generators/preset/generator.js +91 -0
- package/dist/src/generators/preset/generator.js.map +1 -0
- package/dist/src/generators/preset/schema.d.ts +20 -0
- package/dist/src/generators/preset/schema.json +86 -0
- package/dist/src/generators/shared-libs/generator.d.ts +4 -0
- package/dist/src/generators/shared-libs/generator.js +60 -0
- package/dist/src/generators/shared-libs/generator.js.map +1 -0
- package/dist/src/generators/shared-libs/schema.d.ts +6 -0
- package/dist/src/generators/shared-libs/schema.json +21 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +20 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib/csp/allowlist.d.ts +64 -0
- package/dist/src/lib/csp/allowlist.js +126 -0
- package/dist/src/lib/csp/allowlist.js.map +1 -0
- package/dist/src/lib/csp/import.d.ts +52 -0
- package/dist/src/lib/csp/import.js +291 -0
- package/dist/src/lib/csp/import.js.map +1 -0
- package/dist/src/lib/csp/render.d.ts +19 -0
- package/dist/src/lib/csp/render.js +116 -0
- package/dist/src/lib/csp/render.js.map +1 -0
- package/dist/src/lib/env/derive.d.ts +38 -0
- package/dist/src/lib/env/derive.js +115 -0
- package/dist/src/lib/env/derive.js.map +1 -0
- package/dist/src/lib/env-encryption/backup.d.ts +40 -0
- package/dist/src/lib/env-encryption/backup.js +234 -0
- package/dist/src/lib/env-encryption/backup.js.map +1 -0
- package/dist/src/lib/env-encryption/config.d.ts +50 -0
- package/dist/src/lib/env-encryption/config.js +173 -0
- package/dist/src/lib/env-encryption/config.js.map +1 -0
- package/dist/src/lib/env-encryption/domains.d.ts +9 -0
- package/dist/src/lib/env-encryption/domains.js +52 -0
- package/dist/src/lib/env-encryption/domains.js.map +1 -0
- package/dist/src/lib/env-encryption/encrypt.d.ts +48 -0
- package/dist/src/lib/env-encryption/encrypt.js +407 -0
- package/dist/src/lib/env-encryption/encrypt.js.map +1 -0
- package/dist/src/lib/env-encryption/env-file.d.ts +72 -0
- package/dist/src/lib/env-encryption/env-file.js +395 -0
- package/dist/src/lib/env-encryption/env-file.js.map +1 -0
- package/dist/src/lib/env-encryption/gcm.d.ts +51 -0
- package/dist/src/lib/env-encryption/gcm.js +76 -0
- package/dist/src/lib/env-encryption/gcm.js.map +1 -0
- package/dist/src/lib/env-encryption/key-material.d.ts +53 -0
- package/dist/src/lib/env-encryption/key-material.js +148 -0
- package/dist/src/lib/env-encryption/key-material.js.map +1 -0
- package/dist/src/lib/env-encryption/placeholders.d.ts +15 -0
- package/dist/src/lib/env-encryption/placeholders.js +93 -0
- package/dist/src/lib/env-encryption/placeholders.js.map +1 -0
- package/dist/src/lib/env-encryption/prepare.d.ts +43 -0
- package/dist/src/lib/env-encryption/prepare.js +245 -0
- package/dist/src/lib/env-encryption/prepare.js.map +1 -0
- package/dist/src/lib/env-encryption/sensitive.d.ts +2 -0
- package/dist/src/lib/env-encryption/sensitive.js +180 -0
- package/dist/src/lib/env-encryption/sensitive.js.map +1 -0
- package/dist/src/lib/env-encryption/stamp.d.ts +2 -0
- package/dist/src/lib/env-encryption/stamp.js +52 -0
- package/dist/src/lib/env-encryption/stamp.js.map +1 -0
- package/dist/src/lib/env-encryption/switch-gcm.d.ts +43 -0
- package/dist/src/lib/env-encryption/switch-gcm.js +371 -0
- package/dist/src/lib/env-encryption/switch-gcm.js.map +1 -0
- package/dist/src/lib/env-encryption/workspace.d.ts +10 -0
- package/dist/src/lib/env-encryption/workspace.js +48 -0
- package/dist/src/lib/env-encryption/workspace.js.map +1 -0
- package/dist/src/lib/hardening/files.d.ts +17 -0
- package/dist/src/lib/hardening/files.js +43 -0
- package/dist/src/lib/hardening/files.js.map +1 -0
- package/dist/src/lib/hardening/integrity.d.ts +24 -0
- package/dist/src/lib/hardening/integrity.js +112 -0
- package/dist/src/lib/hardening/integrity.js.map +1 -0
- package/dist/src/lib/hardening/leak-check.d.ts +15 -0
- package/dist/src/lib/hardening/leak-check.js +100 -0
- package/dist/src/lib/hardening/leak-check.js.map +1 -0
- package/dist/src/lib/hardening/ngsw.d.ts +7 -0
- package/dist/src/lib/hardening/ngsw.js +55 -0
- package/dist/src/lib/hardening/ngsw.js.map +1 -0
- package/dist/src/lib/hardening/obfuscate.d.ts +36 -0
- package/dist/src/lib/hardening/obfuscate.js +153 -0
- package/dist/src/lib/hardening/obfuscate.js.map +1 -0
- package/dist/src/lib/hardening/options.d.ts +36 -0
- package/dist/src/lib/hardening/options.js +143 -0
- package/dist/src/lib/hardening/options.js.map +1 -0
- package/dist/src/lib/hardening/source-maps.d.ts +7 -0
- package/dist/src/lib/hardening/source-maps.js +37 -0
- package/dist/src/lib/hardening/source-maps.js.map +1 -0
- package/dist/src/lib/hardening/strip.d.ts +55 -0
- package/dist/src/lib/hardening/strip.js +178 -0
- package/dist/src/lib/hardening/strip.js.map +1 -0
- package/dist/src/lib/helpers/encrypt-env.d.ts +13 -0
- package/dist/src/lib/helpers/encrypt-env.js +33 -0
- package/dist/src/lib/helpers/encrypt-env.js.map +1 -0
- package/dist/src/lib/helpers/inject-meta.d.ts +14 -0
- package/dist/src/lib/helpers/inject-meta.js +49 -0
- package/dist/src/lib/helpers/inject-meta.js.map +1 -0
- package/dist/src/lib/helpers/inject-nonce.d.ts +7 -0
- package/dist/src/lib/helpers/inject-nonce.js +59 -0
- package/dist/src/lib/helpers/inject-nonce.js.map +1 -0
- package/dist/src/lib/helpers/inject-sri.d.ts +11 -0
- package/dist/src/lib/helpers/inject-sri.js +92 -0
- package/dist/src/lib/helpers/inject-sri.js.map +1 -0
- package/dist/src/lib/helpers/strip-exif.d.ts +9 -0
- package/dist/src/lib/helpers/strip-exif.js +52 -0
- package/dist/src/lib/helpers/strip-exif.js.map +1 -0
- package/dist/src/lib/release/plan.d.ts +45 -0
- package/dist/src/lib/release/plan.js +76 -0
- package/dist/src/lib/release/plan.js.map +1 -0
- package/dist/src/lib/release/run.d.ts +46 -0
- package/dist/src/lib/release/run.js +160 -0
- package/dist/src/lib/release/run.js.map +1 -0
- package/dist/src/lib/utils/angular-deps.d.ts +22 -0
- package/dist/src/lib/utils/angular-deps.js +108 -0
- package/dist/src/lib/utils/angular-deps.js.map +1 -0
- package/dist/src/lib/utils/angular-project.d.ts +52 -0
- package/dist/src/lib/utils/angular-project.js +168 -0
- package/dist/src/lib/utils/angular-project.js.map +1 -0
- package/dist/src/lib/utils/app-dir.d.ts +17 -0
- package/dist/src/lib/utils/app-dir.js +52 -0
- package/dist/src/lib/utils/app-dir.js.map +1 -0
- package/dist/src/lib/utils/base-href.d.ts +26 -0
- package/dist/src/lib/utils/base-href.js +60 -0
- package/dist/src/lib/utils/base-href.js.map +1 -0
- package/dist/src/lib/utils/ci-resolve.d.ts +10 -0
- package/dist/src/lib/utils/ci-resolve.js +50 -0
- package/dist/src/lib/utils/ci-resolve.js.map +1 -0
- package/dist/src/lib/utils/csp-nonce.d.ts +34 -0
- package/dist/src/lib/utils/csp-nonce.js +142 -0
- package/dist/src/lib/utils/csp-nonce.js.map +1 -0
- package/dist/src/lib/utils/dependencies.d.ts +25 -0
- package/dist/src/lib/utils/dependencies.js +71 -0
- package/dist/src/lib/utils/dependencies.js.map +1 -0
- package/dist/src/lib/utils/devkit-deps.d.ts +19 -0
- package/dist/src/lib/utils/devkit-deps.js +34 -0
- package/dist/src/lib/utils/devkit-deps.js.map +1 -0
- package/dist/src/lib/utils/env-files.d.ts +18 -0
- package/dist/src/lib/utils/env-files.js +41 -0
- package/dist/src/lib/utils/env-files.js.map +1 -0
- package/dist/src/lib/utils/filesystem.d.ts +7 -0
- package/dist/src/lib/utils/filesystem.js +20 -0
- package/dist/src/lib/utils/filesystem.js.map +1 -0
- package/dist/src/lib/utils/flutter-web.d.ts +7 -0
- package/dist/src/lib/utils/flutter-web.js +56 -0
- package/dist/src/lib/utils/flutter-web.js.map +1 -0
- package/dist/src/lib/utils/knip.d.ts +16 -0
- package/dist/src/lib/utils/knip.js +71 -0
- package/dist/src/lib/utils/knip.js.map +1 -0
- package/dist/src/lib/utils/lint-staged.d.ts +5 -0
- package/dist/src/lib/utils/lint-staged.js +34 -0
- package/dist/src/lib/utils/lint-staged.js.map +1 -0
- package/dist/src/lib/utils/llm-block.d.ts +88 -0
- package/dist/src/lib/utils/llm-block.js +457 -0
- package/dist/src/lib/utils/llm-block.js.map +1 -0
- package/dist/src/lib/utils/node-engine.d.ts +9 -0
- package/dist/src/lib/utils/node-engine.js +63 -0
- package/dist/src/lib/utils/node-engine.js.map +1 -0
- package/dist/src/lib/utils/npm-scripts.d.ts +7 -0
- package/dist/src/lib/utils/npm-scripts.js +28 -0
- package/dist/src/lib/utils/npm-scripts.js.map +1 -0
- package/dist/src/lib/utils/nx-targets.d.ts +3 -0
- package/dist/src/lib/utils/nx-targets.js +25 -0
- package/dist/src/lib/utils/nx-targets.js.map +1 -0
- package/dist/src/lib/utils/project-json-files.d.ts +23 -0
- package/dist/src/lib/utils/project-json-files.js +73 -0
- package/dist/src/lib/utils/project-json-files.js.map +1 -0
- package/dist/src/lib/utils/quality.d.ts +71 -0
- package/dist/src/lib/utils/quality.js +295 -0
- package/dist/src/lib/utils/quality.js.map +1 -0
- package/dist/src/lib/utils/serve-port.d.ts +28 -0
- package/dist/src/lib/utils/serve-port.js +73 -0
- package/dist/src/lib/utils/serve-port.js.map +1 -0
- package/dist/src/lib/utils/shared-libs.d.ts +37 -0
- package/dist/src/lib/utils/shared-libs.js +152 -0
- package/dist/src/lib/utils/shared-libs.js.map +1 -0
- package/dist/src/lib/utils/ts-paths.d.ts +3 -0
- package/dist/src/lib/utils/ts-paths.js +31 -0
- package/dist/src/lib/utils/ts-paths.js.map +1 -0
- package/dist/src/lib/utils/workspace.d.ts +3 -0
- package/dist/src/lib/utils/workspace.js +15 -0
- package/dist/src/lib/utils/workspace.js.map +1 -0
- package/dist/src/migrate-sdk.d.ts +31 -0
- package/dist/src/migrate-sdk.js +35 -0
- package/dist/src/migrate-sdk.js.map +1 -0
- package/dist/src/migrations/add-csp-nonce-import/add-csp-nonce-import.d.ts +2 -0
- package/dist/src/migrations/add-csp-nonce-import/add-csp-nonce-import.js +40 -0
- package/dist/src/migrations/add-csp-nonce-import/add-csp-nonce-import.js.map +1 -0
- package/dist/src/migrations/add-executor-peers/add-executor-peers.d.ts +6 -0
- package/dist/src/migrations/add-executor-peers/add-executor-peers.js +21 -0
- package/dist/src/migrations/add-executor-peers/add-executor-peers.js.map +1 -0
- package/dist/src/migrations/add-lib-build-dependencies/add-lib-build-dependencies.d.ts +7 -0
- package/dist/src/migrations/add-lib-build-dependencies/add-lib-build-dependencies.js +47 -0
- package/dist/src/migrations/add-lib-build-dependencies/add-lib-build-dependencies.js.map +1 -0
- package/dist/src/migrations/add-lint-dependencies/add-lint-dependencies.d.ts +6 -0
- package/dist/src/migrations/add-lint-dependencies/add-lint-dependencies.js +27 -0
- package/dist/src/migrations/add-lint-dependencies/add-lint-dependencies.js.map +1 -0
- package/dist/src/migrations/add-lint-staged-config/add-lint-staged-config.d.ts +7 -0
- package/dist/src/migrations/add-lint-staged-config/add-lint-staged-config.js +22 -0
- package/dist/src/migrations/add-lint-staged-config/add-lint-staged-config.js.map +1 -0
- package/dist/src/migrations/angular-release-target/angular-release-target.d.ts +3 -0
- package/dist/src/migrations/angular-release-target/angular-release-target.js +80 -0
- package/dist/src/migrations/angular-release-target/angular-release-target.js.map +1 -0
- package/dist/src/migrations/app-clean-and-port/app-clean-and-port.d.ts +7 -0
- package/dist/src/migrations/app-clean-and-port/app-clean-and-port.js +89 -0
- package/dist/src/migrations/app-clean-and-port/app-clean-and-port.js.map +1 -0
- package/dist/src/migrations/env-encryption-config/env-encryption-config.d.ts +7 -0
- package/dist/src/migrations/env-encryption-config/env-encryption-config.js +42 -0
- package/dist/src/migrations/env-encryption-config/env-encryption-config.js.map +1 -0
- package/dist/src/migrations/env-encryption-key-sources/env-encryption-key-sources.d.ts +3 -0
- package/dist/src/migrations/env-encryption-key-sources/env-encryption-key-sources.js +15 -0
- package/dist/src/migrations/env-encryption-key-sources/env-encryption-key-sources.js.map +1 -0
- package/dist/src/migrations/fix-lint-script/fix-lint-script.d.ts +7 -0
- package/dist/src/migrations/fix-lint-script/fix-lint-script.js +27 -0
- package/dist/src/migrations/fix-lint-script/fix-lint-script.js.map +1 -0
- package/dist/src/migrations/flutter-web-platform/flutter-web-platform.d.ts +8 -0
- package/dist/src/migrations/flutter-web-platform/flutter-web-platform.js +35 -0
- package/dist/src/migrations/flutter-web-platform/flutter-web-platform.js.map +1 -0
- package/dist/src/migrations/plugin-repo-dev/plugin-repo-dev.d.ts +9 -0
- package/dist/src/migrations/plugin-repo-dev/plugin-repo-dev.js +42 -0
- package/dist/src/migrations/plugin-repo-dev/plugin-repo-dev.js.map +1 -0
- package/dist/src/migrations/prepush-audit-warn-only/prepush-audit-warn-only.d.ts +8 -0
- package/dist/src/migrations/prepush-audit-warn-only/prepush-audit-warn-only.js +30 -0
- package/dist/src/migrations/prepush-audit-warn-only/prepush-audit-warn-only.js.map +1 -0
- package/dist/src/migrations/quality-checks/quality-checks.d.ts +7 -0
- package/dist/src/migrations/quality-checks/quality-checks.js +46 -0
- package/dist/src/migrations/quality-checks/quality-checks.js.map +1 -0
- package/dist/src/migrations/release-hardening/release-hardening.d.ts +8 -0
- package/dist/src/migrations/release-hardening/release-hardening.js +98 -0
- package/dist/src/migrations/release-hardening/release-hardening.js.map +1 -0
- package/dist/src/migrations/sharp-security-update/sharp-security-update.d.ts +10 -0
- package/dist/src/migrations/sharp-security-update/sharp-security-update.js +40 -0
- package/dist/src/migrations/sharp-security-update/sharp-security-update.js.map +1 -0
- package/migrate/package.json +5 -0
- package/package.json +120 -4
- package/runtime/csp-nonce.js +109 -0
- package/runtime/env-secret.d.ts +63 -0
- package/runtime/env-secret.mjs +698 -0
package/USER-MANUAL.md
ADDED
|
@@ -0,0 +1,1968 @@
|
|
|
1
|
+
# @mouryaamit/nx-polystack — User Manual
|
|
2
|
+
|
|
3
|
+
**Version:** v0.4.0
|
|
4
|
+
**CLI binary:** `pstack`
|
|
5
|
+
**Audience:** Developers installing or using the package from npm
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Table of contents
|
|
10
|
+
|
|
11
|
+
1. [Overview](#1-overview)
|
|
12
|
+
2. [Installation](#2-installation)
|
|
13
|
+
3. [pstack CLI — quick reference](#3-pstack-cli--quick-reference)
|
|
14
|
+
- 3a. [pstack new — create a workspace](#3a-pstack-new--create-a-workspace)
|
|
15
|
+
- 3b. [pstack update — upgrade a workspace](#3b-pstack-update--upgrade-a-workspace)
|
|
16
|
+
- 3c. [pstack infra — repo docs, CI gates, quality checks](#3c-pstack-infra--repo-docs-ci-gates-quality-checks)
|
|
17
|
+
4. [pstack preset — bootstrap a workspace](#4-pstack-preset--bootstrap-a-workspace)
|
|
18
|
+
5. [pstack app — scaffold an application](#5-pstack-app--scaffold-an-application)
|
|
19
|
+
6. [Nx plugin usage — generators](#6-nx-plugin-usage--generators)
|
|
20
|
+
7. [Nx plugin usage — executors](#7-nx-plugin-usage--executors)
|
|
21
|
+
8. [Helper modules](#8-helper-modules)
|
|
22
|
+
9. [Release packaging](#9-release-packaging)
|
|
23
|
+
10. [Troubleshooting](#10-troubleshooting)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. Overview
|
|
28
|
+
|
|
29
|
+
`@mouryaamit/nx-polystack` is a reusable Nx plugin for scaffolding multi-technology monorepos
|
|
30
|
+
that target Angular, Ionic, Flutter, Android, and iOS from a single workspace. It ships:
|
|
31
|
+
|
|
32
|
+
| Feature | Available |
|
|
33
|
+
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
|
|
34
|
+
| `pstack` CLI binary — `preset` and `app` commands | v0.1.0 |
|
|
35
|
+
| `:preset` generator — workspace root skeleton | v0.1.0 |
|
|
36
|
+
| `:app --type=angular` generator — Angular 15 SPA shell | v0.1.0 |
|
|
37
|
+
| `:app --type=flutter` generator — Flutter project shell | v0.1.0 |
|
|
38
|
+
| `:build` executor — full Angular/Ionic build pipeline | v0.1.0 |
|
|
39
|
+
| `:flutter-build` executor — Flutter CLI wrapper | v0.1.0 |
|
|
40
|
+
| `:flutter-export` executor — FlutterFlow export integration | v0.1.0 |
|
|
41
|
+
| Helper library — encrypt-env, inject-meta, inject-nonce, inject-sri, strip-exif, ci-resolve | v0.1.0 |
|
|
42
|
+
| Global install (GitHub release asset) with delegation to the workspace copy | v0.3.0 |
|
|
43
|
+
| `pstack new <dir>` — create a workspace | v0.3.0 |
|
|
44
|
+
| `pstack update` — bump the pinned tag and run migrations | v0.3.0 |
|
|
45
|
+
| Migration runner (`migrations.json`, hidden `pstack _migrate`) | v0.3.0 |
|
|
46
|
+
| Angular apps build: `build` = Angular builder, `release` = hardened pipeline | v0.4.0 |
|
|
47
|
+
| Angular 15 (`~15.2.0`) added to `package.json` when the workspace has none | v0.4.0 |
|
|
48
|
+
| `:build` executor options `buildTarget` / `buildConfiguration`, custom envs (QA) | v0.4.0 |
|
|
49
|
+
| `angular-release-target` migration for apps generated by v0.3.x | v0.4.0 |
|
|
50
|
+
| Lint packages in new workspaces; missing Angular build/lint packages filled in per package | v0.4.1 |
|
|
51
|
+
| `:app --type=ionic` — Ionic 7 + Capacitor 5 app; `:capacitor` executor | v0.5.0 |
|
|
52
|
+
| Release hardening: leak check, source-map guard, strip comments, drop console (UAT/PROD) | v0.29.0 |
|
|
53
|
+
| Opt-in obfuscation, SRI for every chunk, runtime integrity check, ngsw hashes; `pstack hardening` | v0.30.0 |
|
|
54
|
+
| Obfuscation levels (light, medium, strong) and `obfuscateOptions` overrides | v0.31.0 |
|
|
55
|
+
| `pstack build --env=<env>` for all apps with a summary; base href per configuration (`pstack app --base-href`, `pstack release`) | v0.32.0 |
|
|
56
|
+
| `pstack csp`: `.htaccess` and `nginx.conf` from `csp-allowlist.json`, strict CSP with a per-request nonce (Apache SSI, Nginx sub_filter) | v0.33.0 |
|
|
57
|
+
| `pstack env --name=<env> --app=<a,b>\|--all`: add an environment later, copied from an existing one (placeholders for secrets, release config, Flutter, scripts) | v0.34.0 |
|
|
58
|
+
| App options: free dev-server port / `--port`, `clean` target, shared assets and styles (`pstack shared`), `--env-layout=per-env` | v0.35.0 |
|
|
59
|
+
| Quality: `typecheck` target and CI step, import/unused-imports ESLint warnings, non-blocking lint-staged (`pstack infra --lint-staged`) | v0.36.0 |
|
|
60
|
+
| Lib starters: `pstack lib --type=session` (idle/session timeout, cross-tab) and `--type=pii` (masking pipe and directive) | v0.37.0 |
|
|
61
|
+
| `pstack csp --import`: merge an existing policy (.htaccess, nginx.conf, header value, JSON) into csp-allowlist.json | v0.38.0 |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 2. Installation
|
|
66
|
+
|
|
67
|
+
### Option A — global install (recommended)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm i -g @mouryaamit/nx-polystack
|
|
71
|
+
pstack --version
|
|
72
|
+
pstack --help
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Requires npm 7+, which installs the `nx` and `@nx/devkit` peer dependencies next to the global package.
|
|
76
|
+
|
|
77
|
+
Note: `npm install` inside a new workspace (run by `pstack new`) downloads sharp's prebuilt binaries, so it needs network access.
|
|
78
|
+
|
|
79
|
+
### Option B — npx (no install)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npx --package=@mouryaamit/nx-polystack pstack new my-workspace
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Option C — dev dependency in a workspace
|
|
86
|
+
|
|
87
|
+
Add the plugin to an existing Nx workspace so Nx can discover its generators and executors:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm install --save-dev --save-exact @mouryaamit/nx-polystack
|
|
91
|
+
npx nx list @mouryaamit/nx-polystack
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### System requirements
|
|
95
|
+
|
|
96
|
+
| Requirement | Version |
|
|
97
|
+
| --------------------------- | ------- |
|
|
98
|
+
| Node | 20.x |
|
|
99
|
+
| npm | 10+ |
|
|
100
|
+
| Nx (workspace install only) | 17.x |
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 3. pstack CLI — quick reference
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
USAGE
|
|
108
|
+
pstack <command> [options]
|
|
109
|
+
|
|
110
|
+
COMMANDS
|
|
111
|
+
new <dir> Create a new polystack workspace in <dir> (installs deps, initialises git)
|
|
112
|
+
update Upgrade this workspace's nx-polystack version and run its migrations
|
|
113
|
+
preset Bootstrap a workspace root skeleton in the current directory
|
|
114
|
+
app Scaffold a new application into an existing workspace
|
|
115
|
+
env Add an environment to some or all apps later, copied from an existing one
|
|
116
|
+
(env file, build/serve/release configurations, Flutter env, npm scripts)
|
|
117
|
+
llm Write or refresh the generated workspace block in CLAUDE.md, AGENTS.md and
|
|
118
|
+
.github/copilot-instructions.md (app/lib/env refresh it automatically)
|
|
119
|
+
migrate Copy an existing project into the workspace, source never modified: a standalone
|
|
120
|
+
Angular CLI, Ionic/Capacitor or Flutter app (apps/<name>), the apps and libraries
|
|
121
|
+
of a multi-project Angular CLI repo (apps/, libs/), the Angular, Ionic and
|
|
122
|
+
Flutter projects of an Nx 15-17 workspace (same paths, names and aliases), or the
|
|
123
|
+
app and TypeScript library packages of an npm, Yarn or pnpm workspaces repo
|
|
124
|
+
(apps/, libs/)
|
|
125
|
+
infra Add repo docs, CI gates (affected lint/test/build, dependency cycles), quality
|
|
126
|
+
checks (knip, pre-push audit + secret scan) and a dependency-upgrade workflow
|
|
127
|
+
|
|
128
|
+
OPTIONS — new / preset
|
|
129
|
+
--npmScope=<scope> npm scope for the workspace (default: mouryaamit)
|
|
130
|
+
--baseBranch=<branch> Default git branch (default: master)
|
|
131
|
+
--infra=<parts> Run pstack infra with these parts: docs,ci,quality,upgrades | all |
|
|
132
|
+
none (default: all)
|
|
133
|
+
--ci=<providers> CI for the infra ci part: github-actions | jenkins (comma-separated;
|
|
134
|
+
default: github-actions)
|
|
135
|
+
--ci-cache, --flutter=<mode>, --upgrade-schedule=<s>, --upgrade-scope=<s>
|
|
136
|
+
passed to pstack infra
|
|
137
|
+
--llm=<tools> AI-assistant files, as pstack llm: claude | agents | copilot
|
|
138
|
+
(codex, openai-gpt → agents; comma-separated)
|
|
139
|
+
--projectDescription=<text> Short project description
|
|
140
|
+
--skipFormat Skip Prettier format pass
|
|
141
|
+
--skip-install new only — do not run npm install
|
|
142
|
+
--skip-git new only — do not initialise git
|
|
143
|
+
--force new only — allow creating inside another Nx workspace
|
|
144
|
+
|
|
145
|
+
OPTIONS — update
|
|
146
|
+
--to=<version> Target version (default: this CLI's version)
|
|
147
|
+
--allow-dirty Run with uncommitted changes
|
|
148
|
+
--force Allow downgrading
|
|
149
|
+
|
|
150
|
+
OPTIONS — app
|
|
151
|
+
--type=<type> App type: angular | ionic | flutter (required)
|
|
152
|
+
--name=<name> Application name (required)
|
|
153
|
+
--tags=<tags> Comma-separated Nx tags
|
|
154
|
+
--cspConnectSrc=<url> Angular only — pre-fill CSP connect-src in csp-allowlist.json
|
|
155
|
+
--dir=<path> Put the app in apps/<path>/<name> (v0.17.0+)
|
|
156
|
+
--port=<n> Dev-server port (default: the lowest free port from 4200; v0.35.0+)
|
|
157
|
+
--env-layout=<layout> Angular/Ionic — default | per-env (v0.35.0+)
|
|
158
|
+
|
|
159
|
+
OPTIONS — shared (--app or --all required; v0.35.0+)
|
|
160
|
+
--app=<a,b> Angular/Ionic apps to wire the shared assets and styles into
|
|
161
|
+
--all Every Angular/Ionic app
|
|
162
|
+
|
|
163
|
+
OPTIONS — env
|
|
164
|
+
--name=<name> Environment slug, e.g. qa, sit, staging (required)
|
|
165
|
+
--app=<a,b> | --all Apps to add it to (one of them is required)
|
|
166
|
+
--from=<env> Environment to copy (default uat); secret values become
|
|
167
|
+
${APP_ENV_KEY} placeholders filled at build time
|
|
168
|
+
--api-url=<url> API base URL of the new environment
|
|
169
|
+
--production[=false] production flag of the new Angular env file (default: as --from)
|
|
170
|
+
--base-href=<path> Base href of the new configuration (default: as --from)
|
|
171
|
+
--domains=<hosts> aes-gcm domain lock of the new release configuration
|
|
172
|
+
|
|
173
|
+
OPTIONS — migrate
|
|
174
|
+
--source=<path> Project to migrate: its repo root (required; read only)
|
|
175
|
+
--name=<name> App name, kebab-case (default: the Angular project name or
|
|
176
|
+
the pubspec name); for workspace sources the report name
|
|
177
|
+
--adapter=<id> Skip detection: angular-cli | flutter | nx-workspace | angular-workspace | ionic |
|
|
178
|
+
npm-workspaces, or an adapter listed in nx.json
|
|
179
|
+
--min-confidence=<n> Use the best adapter when it reaches n (0.50 to 1.00; default 0.80; v0.15.0+)
|
|
180
|
+
--dir=<path> Single-app sources: put the app in apps/<path>/<name> (v0.16.0+)
|
|
181
|
+
--detect Print the detection table (adapter, confidence, reasons) and
|
|
182
|
+
exit; writes nothing, works outside a workspace
|
|
183
|
+
--projects=<a,b> Workspace sources: projects to migrate (default: every supported one)
|
|
184
|
+
--no-deps Workspace sources: only the --projects named, not the libs they import
|
|
185
|
+
--prefix=<p> Workspace sources: rename projects to <p>-<name> (aliases kept)
|
|
186
|
+
--force-angular Migrate even when the workspace and the source use different
|
|
187
|
+
Angular majors (the report flags it)
|
|
188
|
+
--max-files=<n> Fail when more than n files would be copied (default: 20000)
|
|
189
|
+
--no-rewrite-imports Keep the copied imports as they were (v0.21.0+). By default,
|
|
190
|
+
relative imports into another moved project, imports through the
|
|
191
|
+
source baseUrl, @nrwl/* packages and relative SCSS paths are
|
|
192
|
+
rewritten in the copies; the report lists each one
|
|
193
|
+
--rollback=<name> Undo migration <name> (v0.13.0+): removes the files it created and
|
|
194
|
+
reverts its package.json/tsconfig/nx.json changes; anything edited
|
|
195
|
+
since is kept and listed in docs/migrations/<name>.rollback.md
|
|
196
|
+
--force With --rollback: remove or restore the edited items too
|
|
197
|
+
--config=<file> Run the migrations listed in a JSON batch file (v0.14.0+), all or
|
|
198
|
+
nothing: { "defaults": {...}, "migrations": [ { "source": ... } ] };
|
|
199
|
+
relative sources are resolved from the file's folder
|
|
200
|
+
Writes docs/migrations/<name>.md and <name>.manifest.json (for --rollback). Without
|
|
201
|
+
--adapter the most confident adapter is used if its confidence is at least 0.80.
|
|
202
|
+
|
|
203
|
+
OPTIONS — infra
|
|
204
|
+
--with=<parts> docs | ci | quality | upgrades, comma-separated, or all | none
|
|
205
|
+
(default: all)
|
|
206
|
+
--ci=<providers> github-actions | jenkins, comma-separated (default: github-actions);
|
|
207
|
+
the upgrade workflow is GitHub Actions only
|
|
208
|
+
--ci-cache GitHub Actions: cache the Nx cache directory between runs
|
|
209
|
+
--flutter=<mode> Set up Flutter in CI: auto (when a pubspec.yaml is under apps/ or
|
|
210
|
+
libs/) | on | off; default auto
|
|
211
|
+
--upgrade-schedule=<when> weekly (Monday 03:17 UTC) | monthly (1st, 03:17 UTC); default weekly
|
|
212
|
+
--upgrade-scope=<scope> polystack (pstack update) | nx-minor (also nx migrate within the
|
|
213
|
+
current Nx major); default polystack
|
|
214
|
+
--lint-staged=warn|block ESLint on commit: report only (warn) or block on errors (v0.36.0+)
|
|
215
|
+
--force Overwrite files that already exist (.husky/pre-push is always
|
|
216
|
+
appended to, never replaced)
|
|
217
|
+
Existing files are kept and listed; npm scripts and dependencies are only added when missing.
|
|
218
|
+
|
|
219
|
+
GLOBAL FLAGS
|
|
220
|
+
--dry-run, -d Preview changes without writing files
|
|
221
|
+
--verbose Verbose output
|
|
222
|
+
--help, -h Show this help
|
|
223
|
+
--version, -v Print version
|
|
224
|
+
|
|
225
|
+
Flag values must use --flag=value (a space-separated value is read as an argument).
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Version delegation.** Run inside a workspace that has `@mouryaamit/nx-polystack` in `node_modules`,
|
|
229
|
+
the global `pstack` hands `app`, `env`, `preset`, `migrate` and `infra` to that workspace's copy. `app`, `env`,
|
|
230
|
+
`migrate` and `infra` run from the workspace root (a relative `migrate --source` is made absolute first); `preset`
|
|
231
|
+
and any other command run from the current directory. `pstack migrate` needs nx-polystack 0.12.0 or newer (0.13.0 for `--rollback`, 0.14.0 for `--config`, 0.15.0 for `--min-confidence`, 0.16.0 for `--dir`) pinned
|
|
232
|
+
in the workspace, `pstack infra` 0.9.0 or newer. If the workspace
|
|
233
|
+
copy is older than the global CLI you get a one-line hint to run `pstack update`. `new`, `update`, and `help` /
|
|
234
|
+
`--help` / `--version` always run from the global CLI.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 3a. pstack new — create a workspace
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
pstack new <dir> [--npmScope=<scope>] [--baseBranch=<branch>] [--infra=…] [--ci=…] [--llm=…]
|
|
242
|
+
[--projectDescription=…] [--skip-install] [--skip-git] [--force] [--dry-run]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
1. Refuses a non-empty `<dir>`, and a `<dir>` inside another Nx workspace unless `--force`.
|
|
246
|
+
2. `--baseBranch` must match `/^[\w./-]+$/` (letters, digits, `_`, `.`, `/`, `-`).
|
|
247
|
+
3. Generates the same files as `pstack preset`, plus `@mouryaamit/nx-polystack` pinned to the CLI's version.
|
|
248
|
+
That includes the `pstack infra` files (§3c), all four parts by default; `--infra=none` skips them and
|
|
249
|
+
`--infra=docs,ci` (any subset) picks parts. `--ci` (default `github-actions`), `--ci-cache`, `--flutter`,
|
|
250
|
+
`--upgrade-schedule` and `--upgrade-scope` are passed to it.
|
|
251
|
+
4. Runs `git init -b <baseBranch>`, then `npm install`, then `git add -A` and
|
|
252
|
+
`git commit --no-verify -m "chore: initial polystack workspace"`. `git init` comes first because the generated
|
|
253
|
+
`prepare` script runs husky, which needs `.git`; `--no-verify` skips the hooks for that first commit.
|
|
254
|
+
Later commits run the pre-commit hook: `npx lint-staged`, configured in `package.json` (Prettier on
|
|
255
|
+
changed `ts/html/scss/json/md` files, `eslint --fix` on `ts`). Workspaces created before v0.18.1 had
|
|
256
|
+
no lint-staged config, so their commits failed; the 0.18.1 migration `add-lint-staged-config` adds it
|
|
257
|
+
(`pstack update`).
|
|
258
|
+
5. If git is missing or a git step fails, `pstack new` warns and continues without git. If `npm install` fails the
|
|
259
|
+
files stay in place; fix the error and re-run `npm install` there.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 3b. pstack update — upgrade a workspace
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
pstack update [--to=<version>] [--dry-run] [--allow-dirty] [--force]
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
1. Reads the pinned version of `@mouryaamit/nx-polystack` from `package.json` (`1.2.0`, or the installed
|
|
270
|
+
version for a range such as `^1.2.0`).
|
|
271
|
+
2. Target is `--to`, else the global CLI's version. Downgrades need `--force`. If the global CLI is older than the
|
|
272
|
+
workspace pin, `update` tells you to upgrade the global CLI first (or pass `--force`).
|
|
273
|
+
3. Needs a clean git tree unless `--allow-dirty`. The check covers only the workspace folder.
|
|
274
|
+
4. Installs with `npm install @mouryaamit/nx-polystack@<to> --save-dev --save-exact` (`--save-prod` if the plugin
|
|
275
|
+
is under `dependencies`), so npm rewrites `package.json` itself.
|
|
276
|
+
5. If the install fails, or the installed version is not the one requested, `package.json` and
|
|
277
|
+
`package-lock.json` are restored (a lockfile created by the failed install is deleted).
|
|
278
|
+
6. Runs every plugin migration newer than the old version and up to the new one, using the new version's code.
|
|
279
|
+
|
|
280
|
+
A failed migration stops the run; earlier ones stay applied. Review with `git diff`. `--verbose` is passed
|
|
281
|
+
through to the migration step.
|
|
282
|
+
|
|
283
|
+
`--dry-run` prints the planned change and exits before the dirty-tree check, so it works in a dirty tree.
|
|
284
|
+
|
|
285
|
+
**If migrations fail.** By then the plugin is already on the new version. `update` prints how to retry:
|
|
286
|
+
either `git checkout -- . && npm install` and then `pstack update` again, or, after fixing the cause, rerun only
|
|
287
|
+
the migrations with `npx pstack _migrate --from=<from> --to=<to>`.
|
|
288
|
+
|
|
289
|
+
**The 0.4.1 migration.** `add-lint-dependencies` adds the ESLint packages the root `.eslintrc.json` needs
|
|
290
|
+
(`eslint`, `@nx/eslint`, `@nx/eslint-plugin`, `@typescript-eslint/*`, `eslint-config-prettier`) when missing, and,
|
|
291
|
+
for Angular 15 workspaces, any missing build/lint package (`@angular-devkit/build-angular`, `@angular/compiler-cli`,
|
|
292
|
+
`@angular/cli`, `@nx/angular`, `@angular-eslint/*`) at the installed Angular version. It never changes an existing
|
|
293
|
+
version and never adds runtime packages. New workspaces from `pstack new` pin `nx` and `@nx/*` to `~17.0.6`.
|
|
294
|
+
|
|
295
|
+
**The 0.4.0 migration.** `angular-release-target` rewrites Angular apps generated by v0.3.x so `nx build <app>`
|
|
296
|
+
works and the hardened pipeline moves to `nx run <app>:release:<config>`. See "Upgrading from v0.3.x" in section 5.
|
|
297
|
+
|
|
298
|
+
**The 0.3.0 migration.** v0.3.0 makes `sharp` and `crypto-js` optional peers, so npm may stop installing them
|
|
299
|
+
automatically. The `add-executor-peers` migration adds `sharp@^0.33.0` and/or `crypto-js@^4.2.0` to
|
|
300
|
+
`devDependencies` when neither `dependencies` nor `devDependencies` already lists them.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## 3c. pstack infra — repo docs, CI gates, quality checks
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
pstack infra [--with=docs,ci,quality,upgrades] [--ci=github-actions,jenkins] [--ci-cache] [--flutter=auto|on|off]
|
|
308
|
+
[--upgrade-schedule=weekly|monthly] [--upgrade-scope=polystack|nx-minor] [--force] [--dry-run]
|
|
309
|
+
npx nx g @mouryaamit/nx-polystack:infra [same options]
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Adds the repo files and checks a team needs before the first pull request. `pstack new` (and
|
|
313
|
+
`:preset`) run it with every part by default; `--infra=none` or a subset (`--infra=docs,ci`) changes
|
|
314
|
+
that, and `--ci`, `--ci-cache`, `--flutter`, `--upgrade-schedule` and `--upgrade-scope` are passed through.
|
|
315
|
+
|
|
316
|
+
| Part | Files | package.json (only when missing) |
|
|
317
|
+
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
318
|
+
| `docs` | `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md` (Contributor Covenant 2.1 by link), `SECURITY.md`, `.github/PULL_REQUEST_TEMPLATE.md`, `.github/ISSUE_TEMPLATE/{bug,feature,config}.yml` | — |
|
|
319
|
+
| `ci` | GitHub: `.github/workflows/ci.yml`, `.github/workflows/pr-title.yml`; Jenkins: `Jenkinsfile`; both: `tools/scripts/check-cycles.js`, `tools/config/allowed-cycles.json` | `check:cycles`; GitHub: `@commitlint/cli` + `config-conventional` and `commitlint.config.js` if no commitlint config |
|
|
320
|
+
| `quality` | `knip.json`, `.secretlintrc.json`, `.secretlintignore`, `.husky/pre-push` | `stale-code`, `check:prepush`, `check:audit`; `knip`, `secretlint`, its recommended preset, `husky` (+ `prepare`) |
|
|
321
|
+
| `upgrades` | `.github/workflows/dependency-upgrade.yml` (GitHub Actions only) | — |
|
|
322
|
+
|
|
323
|
+
- **Never overwrites.** A file that exists is kept and listed at the end ("pass --force to
|
|
324
|
+
overwrite"); `--force` replaces it. `.husky/pre-push` is never replaced: the check is appended once,
|
|
325
|
+
after a `# nx-polystack:infra pre-push` marker line. npm scripts and dependencies are only added
|
|
326
|
+
when missing; a script that exists with another command is kept and listed. A second run changes
|
|
327
|
+
nothing.
|
|
328
|
+
- **Placeholders.** `<conduct-contact>` and `<security-contact>` are written as-is and listed under
|
|
329
|
+
"Fill in".
|
|
330
|
+
- **`ci.yml`** runs on pull requests and on pushes to the base branch (nx.json
|
|
331
|
+
`affected.defaultBase`, else `master`): checkout with full history, setup-node from `.nvmrc`,
|
|
332
|
+
`npm ci`, `nrwl/nx-set-shas` (`main-branch-name` = the base branch),
|
|
333
|
+
`npx nx affected -t lint typecheck test build --parallel=3`, `npm run check:cycles`. `--ci-cache` adds an
|
|
334
|
+
`actions/cache` step for the Nx cache (`.nx/cache`, or nx.json `cacheDirectory`).
|
|
335
|
+
- **Flutter.** `--flutter=auto|on|off` (default `auto`). With `auto`, when a `pubspec.yaml` exists
|
|
336
|
+
under `apps/` or `libs/`, `ci.yml` gets a `subosito/flutter-action@v2` step (`channel: stable`,
|
|
337
|
+
`cache: true`) after setup-node, and the `Jenkinsfile` runs `flutter --version` first in Install
|
|
338
|
+
(Flutter must be on the agent's PATH). A new workspace has no Flutter project yet: after
|
|
339
|
+
`pstack app --type=flutter`, run `pstack infra --with=ci --force` to add the step.
|
|
340
|
+
- **`pr-title.yml`** checks the pull request title with the workspace's own commitlint
|
|
341
|
+
(`echo "$TITLE" | npx --no-install commitlint`); no third-party action.
|
|
342
|
+
- **`Jenkinsfile`**: install, affected lint/test/build (base: `origin/$CHANGE_TARGET` for pull
|
|
343
|
+
requests, `HEAD~1` on the base branch, else `origin/<base>`), cycles.
|
|
344
|
+
- **Cycle gate.** `npm run check:cycles` reads the project graph (`nx graph --file=<tmp>.json`),
|
|
345
|
+
finds cycles (strongly connected groups, plus self-dependencies; `npm:` packages ignored) and fails
|
|
346
|
+
only on cycles not listed in `tools/config/allowed-cycles.json` (`[["app-a","lib-b"]]`, any order).
|
|
347
|
+
It is plain Node with no dependencies; `--graph=<file>` reads a saved graph instead.
|
|
348
|
+
- **Stale code.** `npm run stale-code` runs `knip --no-exit-code`: a report, never a failure.
|
|
349
|
+
`knip.json` lists the entry and project globs, the plugin under `ignoreDependencies`, and
|
|
350
|
+
`flutter`/`dart` under `ignoreBinaries` only when the workspace has Flutter. `pstack lib
|
|
351
|
+
--type=design-tokens` adds its `generated/**` and `src/lib/tokens.ts` outputs to the `ignore`
|
|
352
|
+
list of an existing `knip.json`. A `knip.json` written by v0.9.0 still has `**/dist/**`,
|
|
353
|
+
`libs/**/generated/**`, `crypto-js`/`sharp` and `dart` entries; knip prints them under
|
|
354
|
+
"Configuration hints" when they match nothing. The hints are harmless; delete those entries to
|
|
355
|
+
silence them.
|
|
356
|
+
- **Pre-push.** `npm run check:prepush` runs `secretlint "**/*"` first (node_modules, dist, .nx and
|
|
357
|
+
the lockfile are ignored), which blocks the push on a finding, then
|
|
358
|
+
`npm audit --omit=dev --audit-level=high` as a warning only, and ends with a line pointing to
|
|
359
|
+
`npm run check:audit`, the strict audit that fails on high or critical advisories. (Advisories
|
|
360
|
+
with no fix for the workspace's framework major would otherwise block every push.) The 0.9.1
|
|
361
|
+
migration `prepush-audit-warn-only` rewrites a `check:prepush` that is exactly the v0.9.0 default
|
|
362
|
+
and adds `check:audit` when missing.
|
|
363
|
+
- **Upgrade workflow.** Weekly (Monday 03:17 UTC) or `--upgrade-schedule=monthly` (the 1st, 03:17
|
|
364
|
+
UTC), plus a manual run. `polystack` scope: `pstack update --to=<latest release>`; `nx-minor` also
|
|
365
|
+
runs `nx migrate nx@<current major>`, `npm install` and the Nx migrations. Opens or updates the
|
|
366
|
+
`chore/dependency-upgrade` pull request (`chore(deps): scheduled dependency upgrade`) with
|
|
367
|
+
`peter-evans/create-pull-request@v6`, and `subosito/flutter-action@v2` when Flutter is set up. With only `--ci=jenkins` it is skipped, with a note.
|
|
368
|
+
|
|
369
|
+
- **Settings.** The upgrade workflow finds the latest version with `npm view` and needs "Allow GitHub
|
|
370
|
+
Actions to create and approve pull requests" in the repo settings.
|
|
371
|
+
|
|
372
|
+
- Actions are pinned to major tags: `actions/checkout@v4`, `actions/setup-node@v4`,
|
|
373
|
+
`nrwl/nx-set-shas@v4`, `actions/cache@v4`, `peter-evans/create-pull-request@v6`.
|
|
374
|
+
|
|
375
|
+
The llm block is refreshed and lists the new npm scripts. Through the global CLI, `pstack infra`
|
|
376
|
+
needs nx-polystack 0.9.0 or newer pinned in the workspace.
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
pstack infra # all parts, GitHub Actions
|
|
380
|
+
pstack infra --with=docs,ci --ci=jenkins # docs and a Jenkinsfile
|
|
381
|
+
pstack infra --with=upgrades --upgrade-schedule=monthly --upgrade-scope=nx-minor
|
|
382
|
+
pstack infra --with=docs --dry-run # preview
|
|
383
|
+
pstack infra --force # overwrite existing files with the templates
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## 4. pstack preset — bootstrap a workspace
|
|
389
|
+
|
|
390
|
+
Creates the complete Nx workspace root skeleton in the **current directory**. Run this in a
|
|
391
|
+
freshly created, empty directory.
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
pstack preset [options]
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Options
|
|
398
|
+
|
|
399
|
+
| Option | Default | Description |
|
|
400
|
+
| ----------------------------- | ---------------- | -------------------------------------------------------------------------------------------------- |
|
|
401
|
+
| `--npmScope=<scope>` | `mouryaamit` | npm scope written into `nx.json` and `tsconfig.base.json` path aliases |
|
|
402
|
+
| `--baseBranch=<branch>` | `master` | Default git branch (`defaultBase` in `nx.json`) |
|
|
403
|
+
| `--infra=<parts>` | `all` | Runs `:infra` (§3c) with these parts: `docs`, `ci`, `quality`, `upgrades`; or `all`, `none`. |
|
|
404
|
+
| `--ci=<providers>` | `github-actions` | CI for the `:infra` ci part. Values: `github-actions`, `jenkins`. Comma-separated for multiple. |
|
|
405
|
+
| `--llm=<tools>` | — | Runs `:llm` for these providers: `claude`, `agents`, `copilot` (`codex`, `openai-gpt` → `agents`). |
|
|
406
|
+
| `--projectDescription=<text>` | — | Short project description written into `package.json` |
|
|
407
|
+
| `--skipFormat` | false | Skip the Prettier format pass after generation |
|
|
408
|
+
| `--skipInstall` | false | No-op for `preset` (it never installs); kept for compatibility |
|
|
409
|
+
|
|
410
|
+
### What is generated
|
|
411
|
+
|
|
412
|
+
**Always generated (workspace root skeleton):**
|
|
413
|
+
|
|
414
|
+
```
|
|
415
|
+
nx.json
|
|
416
|
+
tsconfig.base.json
|
|
417
|
+
package.json
|
|
418
|
+
.nvmrc Node 20
|
|
419
|
+
.npmrc legacy-peer-deps=true
|
|
420
|
+
.editorconfig
|
|
421
|
+
.gitattributes
|
|
422
|
+
.gitignore
|
|
423
|
+
.prettierrc
|
|
424
|
+
.prettierignore
|
|
425
|
+
.eslintrc.json
|
|
426
|
+
.eslintignore
|
|
427
|
+
commitlint.config.js
|
|
428
|
+
.husky/
|
|
429
|
+
pre-commit
|
|
430
|
+
commit-msg
|
|
431
|
+
tools/config/
|
|
432
|
+
sri-cdn-allowlist.json
|
|
433
|
+
(nx.json also gets pstack.envEncryption — see "Env encryption settings (v0.25.0)")
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Repo infrastructure (`--infra`, default all parts; written by `:infra`, see §3c):** repo docs,
|
|
437
|
+
CI (`--ci=github-actions`: `.github/workflows/ci.yml` and `pr-title.yml`; `--ci=jenkins`: `Jenkinsfile`;
|
|
438
|
+
both: the dependency-cycle check), quality checks (knip, pre-push audit + secretlint) and, with GitHub
|
|
439
|
+
Actions, `.github/workflows/dependency-upgrade.yml`. The old `.github/workflows/build.yml` template is gone.
|
|
440
|
+
|
|
441
|
+
**Conditional — AI-assistant instructions (`--llm`, written by `:llm` after formatting):**
|
|
442
|
+
|
|
443
|
+
| Flag value | File |
|
|
444
|
+
| ---------------------- | --------------------------------- |
|
|
445
|
+
| `claude` | `CLAUDE.md` |
|
|
446
|
+
| `agents` | `AGENTS.md` |
|
|
447
|
+
| `codex` / `openai-gpt` | `AGENTS.md` (aliases of `agents`) |
|
|
448
|
+
| `copilot` | `.github/copilot-instructions.md` |
|
|
449
|
+
|
|
450
|
+
Unknown values fail with the supported list. `.codex/instructions.md` is no longer generated.
|
|
451
|
+
See `:llm` in §6 for the block these files get.
|
|
452
|
+
|
|
453
|
+
### Examples
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
# Minimal workspace
|
|
457
|
+
mkdir my-workspace && cd my-workspace
|
|
458
|
+
pstack preset --npmScope=acme
|
|
459
|
+
|
|
460
|
+
# Full setup — GitHub Actions CI + Claude AI config
|
|
461
|
+
pstack preset --npmScope=acme --ci=github-actions --llm=claude
|
|
462
|
+
|
|
463
|
+
# Jenkins CI + Claude + Copilot
|
|
464
|
+
pstack preset --npmScope=acme --ci=jenkins --llm=claude,copilot
|
|
465
|
+
|
|
466
|
+
# Skeleton only, no repo docs / CI / checks
|
|
467
|
+
pstack preset --npmScope=acme --infra=none
|
|
468
|
+
|
|
469
|
+
# Preview without writing
|
|
470
|
+
pstack preset --npmScope=acme --dry-run
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## 5. pstack app — scaffold an application
|
|
476
|
+
|
|
477
|
+
Adds a new application to an **existing Nx workspace**. Must be run from the workspace root
|
|
478
|
+
(where `nx.json` exists). If no `nx.json` is found, the command exits with an error.
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
pstack app --type=<type> --name=<name> [options]
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Options
|
|
485
|
+
|
|
486
|
+
| Option | Required | Description |
|
|
487
|
+
| ----------------------- | -------- | -------------------------------------------------------------------------- |
|
|
488
|
+
| `--type=<type>` | Yes | Application type: `angular`, `ionic` or `flutter` |
|
|
489
|
+
| `--name=<name>` | Yes | Application name — becomes `apps/<name>/` (or `apps/<dir>/<name>/`) |
|
|
490
|
+
| `--dir=<path>` | — | Put the app in `apps/<path>/<name>` (v0.17.0+, rules below) |
|
|
491
|
+
| `--tags=<tags>` | — | Comma-separated Nx tags (e.g. `platform:web,scope:app`) |
|
|
492
|
+
| `--cspConnectSrc=<url>` | — | Angular/Ionic — pre-fills the `connect-src` entry in `csp-allowlist.json` |
|
|
493
|
+
| `--appId=<id>` | — | Ionic only — Capacitor appId (default `com.example.<name without dashes>`) |
|
|
494
|
+
|
|
495
|
+
`--dir` takes kebab-case folders separated by `/` (at most three; not `dist`, `tmp`, `coverage` or
|
|
496
|
+
`out-tsc`; not through another project). Relative paths and build output (`dist/apps/<dir>/<name>`)
|
|
497
|
+
follow the folder; the project name, npm scripts, `environments/<name>/` and the
|
|
498
|
+
`@mouryaamit/<name>` alias stay keyed by name. A name another project already uses is refused, with
|
|
499
|
+
or without `--dir`. Needs nx-polystack 0.17.0 in the workspace and a 0.17.0 global CLI.
|
|
500
|
+
|
|
501
|
+
### What is generated — Angular (`--type=angular`)
|
|
502
|
+
|
|
503
|
+
```
|
|
504
|
+
apps/<name>/
|
|
505
|
+
project.json Nx targets: build, serve, release, lint, extract-i18n
|
|
506
|
+
tsconfig.json
|
|
507
|
+
tsconfig.app.json
|
|
508
|
+
tsconfig.spec.json
|
|
509
|
+
.eslintrc.json
|
|
510
|
+
csp-allowlist.json CSP overrides (per-app)
|
|
511
|
+
src/
|
|
512
|
+
index.html
|
|
513
|
+
main.ts platformBrowserDynamic().bootstrapModule(AppModule)
|
|
514
|
+
styles.scss
|
|
515
|
+
.htaccess Apache SPA routing, CSP with a per-request nonce, security headers (pstack csp)
|
|
516
|
+
app/
|
|
517
|
+
app.module.ts BrowserModule + HttpClientModule
|
|
518
|
+
app.component.ts OnPush change detection
|
|
519
|
+
app.component.html
|
|
520
|
+
app.component.scss
|
|
521
|
+
app-routing.module.ts Empty routes array
|
|
522
|
+
server/
|
|
523
|
+
nginx.conf Nginx try_files + security headers
|
|
524
|
+
README.md Deployment notes
|
|
525
|
+
|
|
526
|
+
environments/<name>/
|
|
527
|
+
environment.ts
|
|
528
|
+
environment.uat.ts
|
|
529
|
+
environment.prod.ts
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
**Also adds:**
|
|
533
|
+
|
|
534
|
+
- 6 npm scripts to root `package.json` (see the table below)
|
|
535
|
+
- `tsconfig.base.json` path alias: `@mouryaamit/<name>` → `apps/<name>/src`
|
|
536
|
+
- Nx tags: `scope:app`, `type:app`, `platform:web`
|
|
537
|
+
|
|
538
|
+
**Targets in `project.json`:**
|
|
539
|
+
|
|
540
|
+
| Target | Executor | What it does |
|
|
541
|
+
| ---------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
542
|
+
| `build` | `@angular-devkit/build-angular:browser` | Plain Angular build to `dist/apps/<name>`. Configurations `production` (default), `uat`, `development`; `production` and `uat` swap `environments/<name>/environment.ts` for the `.prod.ts` / `.uat.ts` file. Assets include `src/.htaccess`. |
|
|
543
|
+
| `serve` | `@angular-devkit/build-angular:dev-server` | Dev server; configurations `production` / `uat` / `development` point at the matching `build` configuration. Default `development`. |
|
|
544
|
+
| `release` | `@mouryaamit/nx-polystack:build` | Hardened pipeline that wraps `build` (`buildTarget: <name>:build`): env encryption, EXIF stripping, build meta, optional CSP nonce / SRI, and non-DEV release hardening (leak check, source maps, comments, console, obfuscation). Configurations `dev`, `uat`, `prod`; default `dev`. |
|
|
545
|
+
| `lint`, `extract-i18n` | `@nx/eslint:lint`, Angular extract-i18n | Unchanged. |
|
|
546
|
+
|
|
547
|
+
`nx build <name>` is a plain Angular build. Use `nx run <name>:release:prod` for the hardened build.
|
|
548
|
+
|
|
549
|
+
**npm scripts:**
|
|
550
|
+
|
|
551
|
+
| Script | Command |
|
|
552
|
+
| ------------------------------ | ------------------------------------------- |
|
|
553
|
+
| `serve:<name>` | `nx serve <name>` |
|
|
554
|
+
| `build:<name>:dev` | `nx run <name>:release:dev` |
|
|
555
|
+
| `build:<name>:uat` | `nx run <name>:release:uat` |
|
|
556
|
+
| `build:<name>:prod` | `nx run <name>:release:prod` |
|
|
557
|
+
| `build:<name>:prod:secure` | `nx run <name>:release:prod --secure` |
|
|
558
|
+
| `build:<name>:prod:secure:sri` | `nx run <name>:release:prod --secure --sri` |
|
|
559
|
+
|
|
560
|
+
**Angular version.** Generated apps target Angular 15. Packages are only ever added, never upgraded:
|
|
561
|
+
|
|
562
|
+
- No `@angular/core` in the workspace → the Angular 15 set (`~15.2.0`, TypeScript `~4.9.5`) plus the lint packages
|
|
563
|
+
(`@nx/angular`, `@nx/eslint` at the workspace's Nx version, `@angular-eslint/*` `~15.2.0`) is added.
|
|
564
|
+
- Angular 15 already installed → missing build and lint packages are added at your installed Angular version
|
|
565
|
+
(`@angular-devkit/build-angular`, `@angular/compiler-cli`, `@angular/cli`, `@nx/angular`, `@nx/eslint`,
|
|
566
|
+
`@angular-eslint/*`), plus the runtime packages the generated code imports (`@angular/common`, `compiler`,
|
|
567
|
+
`platform-browser`, `platform-browser-dynamic`, `router`, `rxjs`, `tslib`, `zone.js`). Existing versions are kept.
|
|
568
|
+
- Another Angular major → nothing is added; `pstack app` prints which packages to install at versions matching
|
|
569
|
+
your Angular. Angular 16–17 likely work with the generated files.
|
|
570
|
+
|
|
571
|
+
**Upgrading from v0.3.x.** Apps generated by older versions have a `build` target that runs the plugin executor and
|
|
572
|
+
cannot build. `pstack update` runs the `angular-release-target` migration, which moves that target to `release`,
|
|
573
|
+
gives `build` the Angular builder, renames `serve` configurations, and rewrites matching npm scripts to
|
|
574
|
+
`nx run <app>:release:<config>`. Details:
|
|
575
|
+
|
|
576
|
+
- Custom configurations (e.g. `qa`) are carried over to `build` and `release`.
|
|
577
|
+
- Only `nx run <app>:build:<config>` commands are rewritten in scripts (matched on word boundaries; a trailing `--` is dropped).
|
|
578
|
+
- Ionic and other non-Angular apps, and apps that already have a `release` target, are skipped (the latter with a warning).
|
|
579
|
+
- Re-running is a no-op.
|
|
580
|
+
|
|
581
|
+
### What is generated — Ionic (`--type=ionic`)
|
|
582
|
+
|
|
583
|
+
An Angular app (everything in the Angular section above) turned into an Ionic 7 + Capacitor 5 app:
|
|
584
|
+
|
|
585
|
+
- `src/app/app.module.ts` imports `IonicModule.forRoot()` and uses `IonicRouteStrategy`; `app.component.html` is
|
|
586
|
+
`<ion-app><ion-router-outlet>`; `index.html` has a mobile viewport (`viewport-fit=cover`); `styles.scss` imports the
|
|
587
|
+
Ionic core CSS; ionicons SVGs are copied to `/svg` by the build.
|
|
588
|
+
- `capacitor.config.ts` — `appId` (`--appId`), `appName`, `webDir: '../../dist/apps/<name>'`.
|
|
589
|
+
- `package.json` in the app folder — its own `@capacitor/core`, `android`, `ios` and `cli` (`~5.7.0`), kept out of
|
|
590
|
+
the root install; plus a `.gitignore` for its `node_modules` and native build output.
|
|
591
|
+
- `project.json`: `build` / `serve` / `release` as for Angular (`release.options.type: ionic`), and
|
|
592
|
+
`cap-sync`, `cap-open`, `cap-add` (executor `:capacitor`, platform given as `--platform=android|ios`).
|
|
593
|
+
- Root `package.json`: Angular 15 packages as for Angular apps, plus `@ionic/angular ~7.8.0` when missing.
|
|
594
|
+
`pstack app` then installs the root packages and the app's own package.json.
|
|
595
|
+
|
|
596
|
+
| Script | Command |
|
|
597
|
+
| ------------------------------------- | -------------------------------------------------------------------- |
|
|
598
|
+
| `build:<name>:<dev\|uat\|prod>` | `nx run <name>:release:<env>` |
|
|
599
|
+
| `build:<name>:<env>:android` / `:ios` | release build, then `nx run <name>:cap-sync --platform=android\|ios` |
|
|
600
|
+
| `open:<name>:android` / `:ios` | `nx run <name>:cap-open --platform=android\|ios` |
|
|
601
|
+
|
|
602
|
+
First native build:
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
pstack app --type=ionic --name=field-ops --appId=com.acme.fieldops
|
|
606
|
+
npx nx run field-ops:release:prod
|
|
607
|
+
npx nx run field-ops:cap-add --platform=android # once — creates apps/field-ops/android
|
|
608
|
+
npm run build:field-ops:prod:android # release build + cap sync
|
|
609
|
+
npm run open:field-ops:android # opens Android Studio
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
`pstack env --name=qa --app=<name>` adds `qa` to `build`, `serve` and `release`, plus `build:<name>:qa:android` / `:ios`.
|
|
613
|
+
|
|
614
|
+
Native prerequisites (Capacitor 5): Node 16+, JDK 17 and Android Studio Flamingo or newer for Android; Xcode 14.1+ and
|
|
615
|
+
CocoaPods for iOS (macOS only). On Linux, set `CAPACITOR_ANDROID_STUDIO_PATH` for `cap-open`.
|
|
616
|
+
|
|
617
|
+
### What is generated — Flutter (`--type=flutter`)
|
|
618
|
+
|
|
619
|
+
```
|
|
620
|
+
apps/<name>/
|
|
621
|
+
project.json Nx targets: flutter-build (3 configs), serve
|
|
622
|
+
pubspec.yaml
|
|
623
|
+
analysis_options.yaml
|
|
624
|
+
.gitignore
|
|
625
|
+
lib/
|
|
626
|
+
main.dart
|
|
627
|
+
web/
|
|
628
|
+
index.html loads flutter_bootstrap.js (no inline script); keeps $FLUTTER_BASE_HREF
|
|
629
|
+
manifest.json
|
|
630
|
+
server/
|
|
631
|
+
nginx.conf
|
|
632
|
+
|
|
633
|
+
environments/<name>/
|
|
634
|
+
env.dev.json
|
|
635
|
+
env.uat.json
|
|
636
|
+
env.prod.json
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
Web builds (`build-web`, `serve`) need Flutter 3.22 or later. Add icons under `web/` if you want them.
|
|
640
|
+
|
|
641
|
+
### Examples
|
|
642
|
+
|
|
643
|
+
```bash
|
|
644
|
+
# Angular SPA
|
|
645
|
+
pstack app --type=angular --name=portal
|
|
646
|
+
|
|
647
|
+
# Angular with tags and CSP entry
|
|
648
|
+
pstack app --type=angular --name=admin --tags=platform:web,scope:app --cspConnectSrc=https://api.example.com
|
|
649
|
+
|
|
650
|
+
# Flutter
|
|
651
|
+
pstack app --type=flutter --name=mobile --tags=platform:mobile
|
|
652
|
+
|
|
653
|
+
# Preview — no files written
|
|
654
|
+
pstack app --type=angular --name=portal --dry-run
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
## 6. Nx plugin usage — generators
|
|
660
|
+
|
|
661
|
+
When the plugin is installed as a dev dependency in an Nx workspace, generators can also be invoked
|
|
662
|
+
through Nx directly:
|
|
663
|
+
|
|
664
|
+
```bash
|
|
665
|
+
npx nx g @mouryaamit/nx-polystack:preset [options]
|
|
666
|
+
npx nx g @mouryaamit/nx-polystack:app --type=angular --name=portal [options]
|
|
667
|
+
|
|
668
|
+
# Preview without writing
|
|
669
|
+
npx nx g @mouryaamit/nx-polystack:app --type=angular --name=portal --dry-run
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
All options are identical to the `pstack` CLI flags. The `--dry-run` flag is supported by both Nx and
|
|
673
|
+
the `pstack` CLI.
|
|
674
|
+
|
|
675
|
+
### `:preset` generator schema
|
|
676
|
+
|
|
677
|
+
```jsonc
|
|
678
|
+
{
|
|
679
|
+
"npmScope": "mouryaamit", // string — default: "mouryaamit"
|
|
680
|
+
"baseBranch": "master", // string — default: "master"
|
|
681
|
+
"apps": "angular,flutter", // string — comma-separated app types (stored in nx.json)
|
|
682
|
+
"infra": "all", // string — :infra parts: docs,ci,quality,upgrades | all | none
|
|
683
|
+
"ci": "github-actions", // string — comma-separated CI providers (default: github-actions)
|
|
684
|
+
"ciCache": false, // boolean — passed to :infra
|
|
685
|
+
"flutter": "auto", // "auto" | "on" | "off" — passed to :infra
|
|
686
|
+
"upgradeSchedule": "weekly", // "weekly" | "monthly" — passed to :infra
|
|
687
|
+
"upgradeScope": "polystack", // "polystack" | "nx-minor" — passed to :infra
|
|
688
|
+
"llm": "claude,copilot", // string — comma-separated :llm providers
|
|
689
|
+
"projectDescription": "...", // string
|
|
690
|
+
"skipFormat": false, // boolean
|
|
691
|
+
"skipInstall": false // boolean
|
|
692
|
+
}
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### `:llm` generator / `pstack llm` (v0.7.0)
|
|
696
|
+
|
|
697
|
+
```bash
|
|
698
|
+
pstack llm [--providers=claude,agents,copilot] [--dry-run]
|
|
699
|
+
npx nx g @mouryaamit/nx-polystack:llm --providers=claude,agents,copilot
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
Writes a generated description of the workspace — npm scope, Nx / Angular / plugin versions, an apps
|
|
703
|
+
table (type detected from targets), environments, a libs table with import aliases, common commands
|
|
704
|
+
and rules — between `<!-- nx-polystack:start -->` and `<!-- nx-polystack:end -->` in `CLAUDE.md`
|
|
705
|
+
(`claude`), `AGENTS.md` (`agents`; `codex` and `openai-gpt` are aliases) and
|
|
706
|
+
`.github/copilot-instructions.md` (`copilot`). Default: all three.
|
|
707
|
+
|
|
708
|
+
A missing file is created with a title; a file with markers gets only the block replaced; a file
|
|
709
|
+
without markers gets the block appended; malformed markers stop the run with an error naming the
|
|
710
|
+
file. Text outside the block is never changed. `:app`, `:lib` and `:env` refresh the block in files
|
|
711
|
+
that already contain the markers. Through the global CLI, `pstack llm` needs nx-polystack 0.7.0 or
|
|
712
|
+
newer pinned in the workspace.
|
|
713
|
+
|
|
714
|
+
### `:migrate` generator / `pstack migrate` (v0.8.0, Nx import v0.10.0)
|
|
715
|
+
|
|
716
|
+
```bash
|
|
717
|
+
pstack migrate --source=<path> [--name=<app>] [--adapter=angular-cli|flutter|nx-workspace|angular-workspace|ionic] [--detect] [--dry-run] [--force-angular]
|
|
718
|
+
[--projects=<a,b>] [--no-deps] [--prefix=<p>]
|
|
719
|
+
npx nx g @mouryaamit/nx-polystack:migrate --source=<path> [same options]
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
Copies an existing standalone project into the workspace as `apps/<name>`, in the shape `pstack app`
|
|
723
|
+
produces. The source is only read; git history is not carried over.
|
|
724
|
+
|
|
725
|
+
- **Detection.** `angular-cli`: `angular.json` with exactly one application project, `@angular/core`,
|
|
726
|
+
the build `main` file. `flutter`: `pubspec.yaml` with the Flutter SDK, `lib/main.dart`. `nx.json`
|
|
727
|
+
disqualifies both; more than one Angular application project disqualifies `angular-cli`; an Ionic
|
|
728
|
+
app scores below the threshold. The best adapter is used at confidence ≥ 0.80; otherwise the
|
|
729
|
+
command stops with the table and suggests `--adapter`. `--detect` only prints the table.
|
|
730
|
+
- **Angular CLI apps.** Files copied without `node_modules`, `dist`, `.angular`, `.git`, IDE folders,
|
|
731
|
+
`coverage` and the workspace-level files. `project.json` is built from `angular.json`: every
|
|
732
|
+
target, every path option moved under `apps/<name>`, `dist/<x>` → `dist/apps/<name>`, target
|
|
733
|
+
references renamed, plus a polystack `release` target (`production` → `prod`, `development` →
|
|
734
|
+
`dev`, other configurations keep their name) and an `@nx/eslint:lint` target if missing. The
|
|
735
|
+
tsconfigs extend `tsconfig.base.json` (source `paths` merged in, clashes reported); the ESLint
|
|
736
|
+
config extends the root one (or the polystack one is generated). Source dependencies are added only
|
|
737
|
+
when missing (clashes reported); a different Angular major in the workspace stops the command
|
|
738
|
+
unless `--force-angular`. `serve:<name>` / `build:<name>:<env>` npm scripts are added; source
|
|
739
|
+
scripts are listed in the report. Environment files stay where they were.
|
|
740
|
+
- **Flutter apps.** Files are copied without `build`, `.dart_tool`, Pods, Gradle caches, generated
|
|
741
|
+
plugin lists and `flutter/ephemeral` folders. The app gets the `pstack app --type=flutter` targets
|
|
742
|
+
and npm scripts, without the FlutterFlow export. Missing `env/dev|uat|prod.json` files are created
|
|
743
|
+
as `{}`. The report notes pubspec path dependencies outside the source repo, product flavors and
|
|
744
|
+
extra `lib/main_*.dart` entrypoints.
|
|
745
|
+
- **Both.** In a git work tree only the files git lists are copied. Possible secrets (`.env*`,
|
|
746
|
+
keystores, `*.pem`, `key.properties`, Firebase configs, `.npmrc`) are never copied, and the report
|
|
747
|
+
lists them. File modes are kept. `--max-files` (default 20000) caps the copy. Angular 17+
|
|
748
|
+
application-builder sources are converted to Angular 15 builders (see Angular 17+ sources).
|
|
749
|
+
- **Report.** `docs/migrations/<name>.md`: adapter and confidence, copied/skipped counts and the
|
|
750
|
+
skipped paths, dependency and alias clashes, source scripts, Angular notes, and a next-steps
|
|
751
|
+
checklist. The llm block is refreshed.
|
|
752
|
+
- **Undo.** `pstack migrate --rollback=<name>` undoes a migration made with v0.13.0+ from
|
|
753
|
+
`docs/migrations/<name>.manifest.json`; what was edited since is kept and listed (`--force`
|
|
754
|
+
overrides, `--dry-run` previews). See the user manual §6.5.
|
|
755
|
+
- **Batches.** `pstack migrate --config=<file>` runs the migrations listed in a JSON file, all or
|
|
756
|
+
nothing; each entry gets its own report and manifest. See the user manual §6.5.
|
|
757
|
+
|
|
758
|
+
```bash
|
|
759
|
+
pstack migrate --source=../legacy-portal --detect
|
|
760
|
+
pstack migrate --source=../legacy-portal --name=portal
|
|
761
|
+
pstack migrate --source=../field_notes --adapter=flutter --dry-run
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
#### Importing from an Nx workspace (v0.10.0)
|
|
765
|
+
|
|
766
|
+
`pstack migrate --source=../nx-repo` copies the Angular apps, Angular/TS libs and Flutter projects
|
|
767
|
+
of an Nx 15–17 workspace into this one (`nx-workspace` adapter). Projects keep their paths, names and
|
|
768
|
+
import aliases, so no source file is rewritten.
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
pstack migrate --source=../nx-repo --detect # project kinds, what can be migrated
|
|
772
|
+
pstack migrate --source=../nx-repo # every supported project
|
|
773
|
+
pstack migrate --source=../nx-repo --projects=portal,admin # these, plus the libs they import
|
|
774
|
+
pstack migrate --source=../nx-repo --projects=portal --no-deps # only portal
|
|
775
|
+
pstack migrate --source=../nx-repo --prefix=legacy # projects named legacy-<name>
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
- Projects come from `project.json` files, `workspace.json` and an Nx `angular.json`. Kinds:
|
|
779
|
+
Angular app (`browser` / `webpack-browser` build), lib (no build, or an Angular, `js` or
|
|
780
|
+
run-commands build), Flutter app or package (`pubspec.yaml`), Ionic app (an Angular app with a
|
|
781
|
+
Capacitor or Ionic config; see below). e2e, Angular 17+ application-builder, Angular SSR,
|
|
782
|
+
React/Node and root projects are listed in the report as not supported yet.
|
|
783
|
+
- `--projects` brings the libs the named projects need: path-alias imports, `implicitDependencies`
|
|
784
|
+
and pubspec `path:` dependencies. `--no-deps` turns that off.
|
|
785
|
+
- `--prefix` renames the projects, their target references and implicit dependencies; paths and
|
|
786
|
+
aliases stay as they are.
|
|
787
|
+
- `@nrwl/*` executors become `@nx/*` (and `@nrwl/nx` in ESLint configs becomes `@nx`); the `@nx/*`
|
|
788
|
+
plugins they use, and the ng-packagr build packages for buildable Angular libs, are added at the
|
|
789
|
+
workspace's versions. The source's own Nx packages are not copied.
|
|
790
|
+
- Angular apps get the polystack `release` target, tags and npm scripts; Flutter apps get the
|
|
791
|
+
polystack Flutter targets, `env/*.json` and npm scripts.
|
|
792
|
+
- The source aliases of copied projects go into `tsconfig.base.json`, named inputs the targets use
|
|
793
|
+
into `nx.json`, and `jest.preset.js` when Jest targets need it. The report lists the root ESLint
|
|
794
|
+
`depConstraints`, `tsconfig` compiler options and options pointing outside the copied projects.
|
|
795
|
+
- Nothing is written when a project path, a project name or an alias already exists in the
|
|
796
|
+
workspace, or the Angular majors differ (`--force-angular`).
|
|
797
|
+
|
|
798
|
+
The report is `docs/migrations/<name>.md`; `--name` defaults to the source package name.
|
|
799
|
+
|
|
800
|
+
#### Multi-app Nx sources and shared folders (v0.24.0)
|
|
801
|
+
|
|
802
|
+
Nx sources with several apps (including Nx 15 repos on `@nrwl/*`) that keep shared files outside
|
|
803
|
+
their projects come over in one run:
|
|
804
|
+
|
|
805
|
+
- **Folders that are not projects** are copied to the same path. A folder is copied when the
|
|
806
|
+
projects use it:
|
|
807
|
+
|
|
808
|
+
- from `assets`, `styles`, `scripts`, `fileReplacements` and
|
|
809
|
+
`stylePreprocessorOptions.includePaths`;
|
|
810
|
+
- from `tsconfig.base.json` (`typeRoots`, `include`);
|
|
811
|
+
- from files the root npm scripts run (`node tools/scripts/build.js`);
|
|
812
|
+
- from imports that leave a project: relative imports, imports through `baseUrl: "."` such as
|
|
813
|
+
`environments/<app>/…`, and SCSS `@use`/`@import`/`@forward`.
|
|
814
|
+
|
|
815
|
+
Typical ones are an assets or styles folder under `libs/`, a root `environments/` folder and
|
|
816
|
+
`tools/`. Root files those scripts or options use (e.g. `postbuild.js`) are copied too. Files the
|
|
817
|
+
workspace already has (for example `tools/config/*.json`) are kept and listed. Possible secrets
|
|
818
|
+
(now also `*.key` and `*.pfx`) are never copied. Paths into projects that were not selected are
|
|
819
|
+
reported, not followed.
|
|
820
|
+
|
|
821
|
+
- **Root `package.json`:** `overrides`, `browser` and `engines` are carried over (missing keys
|
|
822
|
+
only; differing ones are listed). An `engines.node` range that leaves out the Node in the
|
|
823
|
+
workspace's `.nvmrc` is reported instead of carried (since v0.27.1), because the workspace
|
|
824
|
+
installs with `engine-strict`. A pnpm or Yarn workspace gets a note to move the overrides.
|
|
825
|
+
Source npm scripts the workspace does not have are kept, so a repo that builds through its own
|
|
826
|
+
scripts (`build:<app>:<env>` → `node tools/scripts/build.js --project=<app> --env=<env>`) can keep
|
|
827
|
+
using them. Scripts of the same name keep the source command, and the polystack ones are added
|
|
828
|
+
only for names that are free. Three kinds of scripts behave differently:
|
|
829
|
+
- Lifecycle scripts (`postinstall`, `prepare`, …) are never carried over; they are listed.
|
|
830
|
+
- Scripts that name a project that was not imported are dropped and listed.
|
|
831
|
+
- With `--prefix`, project names in nx/ng commands of the kept scripts (`nx <verb> <p>`,
|
|
832
|
+
`nx run <p>:…`, `--project=<p>`) are renamed. A custom script (`node build.js --project=<p>`)
|
|
833
|
+
keeps the source name, because it looks the name up itself (base hrefs, env folders); the
|
|
834
|
+
report lists these scripts, so you can update the `nx build` call inside them.
|
|
835
|
+
- **Release target:** added next to those scripts. A source's own `release` target is left as it
|
|
836
|
+
is.
|
|
837
|
+
|
|
838
|
+
- `envProject` comes from the build's `fileReplacements` (`environments/<x>/environment.<env>.ts`).
|
|
839
|
+
- In that per-env layout (`environment.dev.ts`, no `environment.ts`) the executor reads
|
|
840
|
+
`environment.<env>.ts` for UAT and PROD; DEV is not encrypted.
|
|
841
|
+
- Base hrefs come from `nx build … --base-href` flags in the npm scripts, or from a map in the
|
|
842
|
+
custom build script whose name says base href (`const BASE_HREF = { app: { uat: '/x/' } }` or
|
|
843
|
+
`{ app: '/x/' }`). Apps whose base hrefs can't be read, or are read differently from two maps,
|
|
844
|
+
are listed.
|
|
845
|
+
|
|
846
|
+
The report says to keep using the repo's scripts until the release target covers their extra
|
|
847
|
+
steps.
|
|
848
|
+
|
|
849
|
+
- **CSP nonce patch:** in Angular and Ionic apps, a `main.ts` side-effect import of a local nonce
|
|
850
|
+
patch that reads the nonce the way the library does (`window.__cspNonce` or the `csp-nonce` meta
|
|
851
|
+
tag) is replaced by `@mouryaamit/nx-polystack/runtime/csp-nonce`. Other local patches are kept,
|
|
852
|
+
with the library import added before them. Apps without one get the import first (after any
|
|
853
|
+
`/// <reference>` lines). Local patch files are not deleted.
|
|
854
|
+
- **Nx 15 specifics:**
|
|
855
|
+
- `@nrwl/*` executors and ESLint configs become `@nx/*`.
|
|
856
|
+
- Wildcard aliases (`@scope/lib/*`) of copied libraries are kept.
|
|
857
|
+
- `baseUrl` is set in `tsconfig.base.json` when the workspace has none and the code imports
|
|
858
|
+
through it.
|
|
859
|
+
- A Jest major below 29 gets a note: the workspace's `@nx/jest` needs Jest 29 and
|
|
860
|
+
`jest-preset-angular` 13.
|
|
861
|
+
|
|
862
|
+
#### CSP nonce at runtime (v0.24.0)
|
|
863
|
+
|
|
864
|
+
`@mouryaamit/nx-polystack/runtime/csp-nonce` is a small browser script that new Angular and Ionic
|
|
865
|
+
apps import first in `main.ts`. Under a strict Content-Security-Policy, Angular 15 and webpack add
|
|
866
|
+
`<style>`, `<script>` and stylesheet `<link>` elements at runtime without a nonce, and the browser
|
|
867
|
+
blocks them (Angular 15 has no built-in nonce support).
|
|
868
|
+
|
|
869
|
+
- **What it patches:** it gives these elements the page nonce when they are inserted, through any
|
|
870
|
+
of:
|
|
871
|
+
- `appendChild`/`insertBefore`/`replaceChild` on the document, on elements and on shadow roots;
|
|
872
|
+
- `append`/`prepend`/`before`/`after`/`replaceWith`/`insertAdjacentElement`.
|
|
873
|
+
- **Where the nonce comes from:** `window.__cspNonce`, or the `csp-nonce` meta tag that
|
|
874
|
+
`release --secure` writes. An SSI directive the server did not process, or a placeholder such as
|
|
875
|
+
`random-csp-nonce`, counts as no nonce, and nothing is patched.
|
|
876
|
+
- **Existing apps:** `pstack update` (migration `add-csp-nonce-import`) adds the import to apps
|
|
877
|
+
with the polystack release target. It never removes a local nonce patch import.
|
|
878
|
+
|
|
879
|
+
#### Env encryption settings (v0.25.0)
|
|
880
|
+
|
|
881
|
+
Release builds (`nx run <app>:release:<env>`) encrypt env values for every env except DEV. The
|
|
882
|
+
settings live in `nx.json`:
|
|
883
|
+
|
|
884
|
+
```json
|
|
885
|
+
"pstack": { "envEncryption": {
|
|
886
|
+
"mode": "listed",
|
|
887
|
+
"cipher": "cryptojs",
|
|
888
|
+
"keySources": ["commit"],
|
|
889
|
+
"metaName": "x-build",
|
|
890
|
+
"keys": { "default": [], "web": ["password", "token"] },
|
|
891
|
+
"format": "raw",
|
|
892
|
+
"profileFiles": [],
|
|
893
|
+
"publicKeys": ["production", "envName", "appName", "timeStamp"],
|
|
894
|
+
"stamp": { "timeField": "timeStamp", "branchField": "branch", "timezone": "UTC",
|
|
895
|
+
"format": "DD MMM YYYY hh:mm:ss A z" }
|
|
896
|
+
} }
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
- `mode: "listed"` (default) encrypts the keys of the env project (`keys.<envProject>`, else
|
|
900
|
+
`keys.default`), wherever `key: '<value>'` appears in the file (as before, the key is not
|
|
901
|
+
anchored: `key` also matches `apiKey:`). `keys.default` is empty unless you list keys, so nothing
|
|
902
|
+
is encrypted by default, as before v0.25.0. A listed key whose value is not a plain string is
|
|
903
|
+
left alone with a warning.
|
|
904
|
+
- `mode: "all"` encrypts every top-level string field except `publicKeys`. The stamp fields are
|
|
905
|
+
filled first and stay plain only when listed there: the default list has `timeStamp` but not the
|
|
906
|
+
branch field, so since v0.27.0 the branch is encrypted too (add it to `publicKeys` with
|
|
907
|
+
`pstack encryption --add-public=branch` to keep it plain). A stamp field that is not a string
|
|
908
|
+
literal is left as it is. Any other non-public field that is not a literal (a variable, a call,
|
|
909
|
+
`${…}` in a template), an entry without `key:` (shorthand, spread, computed key) or a missing
|
|
910
|
+
`environment = { … }` object fails the build. Profile values equal to a stamp value are not
|
|
911
|
+
encrypted for it.
|
|
912
|
+
Use it only when the app decrypts every field (`envReady` of `runtime/env-secret`, see Env
|
|
913
|
+
secrets in the browser).
|
|
914
|
+
- With `cryptojs` the ciphertext is unchanged: CryptoJS AES with the build's commit as the
|
|
915
|
+
passphrase, the same commit that goes into `<meta name="<metaName>">`. This is obfuscation; real
|
|
916
|
+
secrets belong on a server. The commit is taken as CI gives it: on GitHub Actions, GitLab,
|
|
917
|
+
Bitbucket, CircleCI and Azure that is the full 40-character SHA (meta tag and key still match).
|
|
918
|
+
Build errors never print values.
|
|
919
|
+
- Changing `metaName` needs the same change in apps that read the key from the meta tag.
|
|
920
|
+
- `cipher`: `cryptojs` (default) or `aes-gcm` (v0.28.0, see AES-GCM env encryption).
|
|
921
|
+
`keySources` (v0.28.0; replaces `keySource`, which `pstack update` renames) lists the
|
|
922
|
+
aes-gcm key factors (default `["commit"]`); `cryptojs` always uses the commit.
|
|
923
|
+
|
|
924
|
+
**Secrets out of git.** UAT/PROD env files may hold `${NAME}` placeholders in quoted strings. The
|
|
925
|
+
release build fills them from environment variables, then from `.env.local` at the workspace root
|
|
926
|
+
(`NAME=value` lines; gitignored), and fails listing every missing name. The dev env file must keep
|
|
927
|
+
literal values (`nx serve` does not fill placeholders); a placeholder there fails `release:dev`.
|
|
928
|
+
|
|
929
|
+
**Build stamp.** When the env file declares `timeStamp` / `branch` (the `stamp` field names), the
|
|
930
|
+
release build fills them with the build time (`timezone`, `format` tokens `YYYY MM MMM DD HH hh mm
|
|
931
|
+
ss A z`, optional `timezoneLabel` for `z`) and the branch. Branch and commit come from CI variables
|
|
932
|
+
(Jenkins, GitHub Actions, GitLab, Bitbucket, CircleCI, Azure Pipelines) or git. Text in `[ ]` is
|
|
933
|
+
kept as is (`[at] HH:mm`).
|
|
934
|
+
|
|
935
|
+
**Safe restores.** The env file is backed up under `node_modules/.cache/nx-polystack/env-backup`
|
|
936
|
+
and restored after the build, also when it fails; a build that was killed is repaired by the next
|
|
937
|
+
release build of that env file (unless the file was edited since; then it is kept). Release builds
|
|
938
|
+
that share an env file wait for each other (on one machine; builds in different containers
|
|
939
|
+
sharing one workspace are not coordinated). The Angular build runs with `--skip-nx-cache`. While a
|
|
940
|
+
release build runs, the env file holds filled and encrypted values: don't commit it then.
|
|
941
|
+
|
|
942
|
+
**`pstack encryption`** shows the settings; `--mode`, `--add-key` / `--remove-key`
|
|
943
|
+
(`--project=<envProject>`), `--add-public` / `--remove-public`, `--meta-name`, `--timezone` and
|
|
944
|
+
`--stamp-format` change them. Needs nx-polystack 0.25.0 in the workspace.
|
|
945
|
+
|
|
946
|
+
**Updating.** `pstack update` (migration `env-encryption-config`) moves
|
|
947
|
+
`tools/config/encrypt-keys.json` into `nx.json` with the same keys (mode `listed`), removes the
|
|
948
|
+
file and adds `.env.local` to `.gitignore`. Builds encrypt the same fields as before. Until then the
|
|
949
|
+
executor still reads the old file and prints a warning.
|
|
950
|
+
|
|
951
|
+
#### Env secrets in the browser (v0.26.0)
|
|
952
|
+
|
|
953
|
+
`@mouryaamit/nx-polystack/runtime/env-secret` decrypts what the release build encrypted
|
|
954
|
+
(`crypto-js` comes from the workspace's dependencies). Call it once in `main.ts`, before
|
|
955
|
+
`AppModule` is imported or bootstrapped:
|
|
956
|
+
|
|
957
|
+
```ts
|
|
958
|
+
import { environment } from '../../../environments/web/environment';
|
|
959
|
+
import {
|
|
960
|
+
envReadySync,
|
|
961
|
+
envSecret,
|
|
962
|
+
envSecretAsync,
|
|
963
|
+
} from '@mouryaamit/nx-polystack/runtime/env-secret';
|
|
964
|
+
|
|
965
|
+
envReadySync(environment, { sync: ['uname'] }); // or { inPlace: true }, or { sync: 'all' }
|
|
966
|
+
|
|
967
|
+
envSecret('uname'); // sync: decrypted at startup, or on first call and cached
|
|
968
|
+
await envSecretAsync('password'); // decrypted on every call, nothing kept
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
- `inPlace: true` decrypts every encrypted value of `environment` (nested objects and arrays too),
|
|
972
|
+
so code reading `environment.x` gets plaintext.
|
|
973
|
+
- `sync` decrypts the listed top-level fields (or `'all'`) at startup into a private cache, without
|
|
974
|
+
changing `environment`.
|
|
975
|
+
- `envReady()` is the same as a Promise; with `cipher: aes-gcm` it also decrypts `ENC2(...)`
|
|
976
|
+
values (see AES-GCM env encryption).
|
|
977
|
+
- `getBuildMeta()`, `decryptEnvValue(value)`, `isEncryptedValue(value)` and `decryptTree(obj)` (in
|
|
978
|
+
place, any object) are exported too. The module is an ES module; `require()` users such as Jest get
|
|
979
|
+
a CommonJS copy.
|
|
980
|
+
- Values that are not encrypted (`nx serve`, a plain build) are returned as they are. A value that
|
|
981
|
+
cannot be decrypted is returned unchanged with one console warning (never the value).
|
|
982
|
+
|
|
983
|
+
**Build side.** `format: "enc"` writes values as `ENC(<ciphertext>)` (new workspaces; a committed
|
|
984
|
+
value already in that form fails the build); `"raw"` keeps the bare ciphertext. `profileFiles`
|
|
985
|
+
(e.g. `["app.profile.ts"]`, next to the env file) are encrypted too: string values of
|
|
986
|
+
sensitive-looking keys at any depth (password, pin, otp, secret, uname, token, apiKey, clientId…;
|
|
987
|
+
not names of things such as `otpField`, `getOtp`, a bare `key`), and any string equal to a value
|
|
988
|
+
encrypted from the env file. `pstack encryption --format=enc --profile-files=app.profile.ts`
|
|
989
|
+
changes them.
|
|
990
|
+
|
|
991
|
+
**`:migrate`.** When an Nx source encrypts its env files with its own `tools/**/encrypt-env.js`
|
|
992
|
+
(`ENC(` marker and a `PUBLIC_ENV_KEYS` list), the workspace gets mode `all`, format `enc`, those
|
|
993
|
+
public keys, `profileFiles` when `app.profile.ts` exists and the stamp fields the env files
|
|
994
|
+
declare — unless the workspace's settings were already changed or other apps already build with
|
|
995
|
+
them (the settings apply to every app); then they are kept and the report lists the suggestion. A copied `env-secret.ts` of the
|
|
996
|
+
known shape (CryptoJS, `ENC(`, `envSecret` + `decryptEnvironment`, no other exports, key type
|
|
997
|
+
`string`) becomes a wrapper of the runtime module with the same exports, so `env-init.ts` and every
|
|
998
|
+
caller keep working; other shapes are kept and reported. In profile files, values equal to an
|
|
999
|
+
encrypted env value are encrypted only as property values or array items (never import paths,
|
|
1000
|
+
type literals or comparisons), and sensitive keys whose values are not plain strings are named in a
|
|
1001
|
+
warning.
|
|
1002
|
+
|
|
1003
|
+
#### AES-GCM env encryption (v0.28.0)
|
|
1004
|
+
|
|
1005
|
+
`pstack encryption --cipher=aes-gcm` switches release builds to AES-256-GCM (Web Crypto). Every
|
|
1006
|
+
build makes a new 32-byte random key and takes the UTC build time; your `keySources` (at least one
|
|
1007
|
+
of `commit`, `salt`, `env`, `custom`; `--key-sources=commit,salt`) are mixed in with HKDF-SHA256.
|
|
1008
|
+
Values are written as `ENC2(...)` and bound to the name of the property that holds them (array
|
|
1009
|
+
items: the array's property name), so a value moved to another field does not decrypt.
|
|
1010
|
+
|
|
1011
|
+
```bash
|
|
1012
|
+
pstack encryption --cipher=aes-gcm --key-sources=commit,salt
|
|
1013
|
+
pstack encryption --app=web --key-split=meta-bundle-asset
|
|
1014
|
+
pstack encryption --app=web --domains='uat=uat.example.com,example.in;prod=example.com'
|
|
1015
|
+
pstack encryption --app=web --domains=uat= # removes the uat list
|
|
1016
|
+
pstack encryption --app=web --include-www=false --on-mismatch=warn
|
|
1017
|
+
```
|
|
1018
|
+
|
|
1019
|
+
- The random key is split: one share in `<meta name="x-build">` (`metaName`), one in the bundle
|
|
1020
|
+
(`keySplit: meta-bundle`, the default), and with `meta-bundle-asset` a third in
|
|
1021
|
+
`assets/pstack-k.<hash>.bin`. The meta share and the asset go next to the served `index.html`
|
|
1022
|
+
(`<outputPath>`, or `<outputPath>/browser` for the Angular application builder); an aes-gcm
|
|
1023
|
+
build without an `index.html` there fails. `--app=<project>` sets `--key-split`, `--domains`,
|
|
1024
|
+
`--include-www` and `--on-mismatch` on that app's release target.
|
|
1025
|
+
- `salt`: `tools/config/env-salt`, created on first use; commit it; `--rotate-salt` renews it.
|
|
1026
|
+
`env`: `PSTACK_ENV_KEY` at build time. The `salt` and `env` values are written into the bundle,
|
|
1027
|
+
like the commit: use a dedicated random value, never a real secret. `custom`:
|
|
1028
|
+
`PSTACK_CUSTOM_KEY` at build time and `envReady(environment, { getKey })` in the app (e.g.
|
|
1029
|
+
fetched from your server) — the only source that stays out of the shipped files.
|
|
1030
|
+
- Domain lock per app and configuration: `--domains=<conf>=<hosts>[;<conf>=<hosts>…]`
|
|
1031
|
+
(`example.com` also allows `www.example.com` unless `--include-www=false`; `*.example.com` any
|
|
1032
|
+
subdomain; an empty list removes the lock). `--on-mismatch=block` (default) leaves the values
|
|
1033
|
+
encrypted on other hosts; `warn` decrypts with a console warning, for a rollout. `localhost`,
|
|
1034
|
+
`127.0.0.1`, `[::1]` and `capacitor:` / `ionic:` origins are never locked. It deters re-hosting
|
|
1035
|
+
a copied build; it is not protection.
|
|
1036
|
+
- The build fails before it touches any file when `PSTACK_ENV_KEY` / `PSTACK_CUSTOM_KEY` is
|
|
1037
|
+
missing for a listed source, a host is not valid (`@`, `\`, `%`, a wildcard on a single
|
|
1038
|
+
label or an IPv4 address, a path without a scheme) or `keySplit` is unknown. In
|
|
1039
|
+
`mode: "listed"`, a listed key found outside `environment = { … }` or without a property name
|
|
1040
|
+
fails the build too.
|
|
1041
|
+
- Switching rewrites `main.ts` to `await envReady(environment, { inPlace: true })` before
|
|
1042
|
+
bootstrap (with `metaName` when it is not `x-build`) and lists code that reads env fields at
|
|
1043
|
+
import time (those values are still encrypted then). `envSecret()` works after that (it throws on
|
|
1044
|
+
a value still in `ENC2(...)`); `envSecretAsync()` decrypts on use. `envReadySync()` leaves
|
|
1045
|
+
`ENC2(...)` values alone, so an `env-init.ts` that runs at import keeps working.
|
|
1046
|
+
- Objects outside `environment` (e.g. profiles): `await decryptTreeAsync(profile)` after
|
|
1047
|
+
`envReady`. An `env-secret.ts` wrapper written by `:migrate` has `decryptEnvironmentAsync(obj?)`
|
|
1048
|
+
(no argument: the environment); switching adds it to wrappers written before v0.28.0.
|
|
1049
|
+
- Web Crypto needs a secure context: serve the app over https (or localhost).
|
|
1050
|
+
- The key ships with the page (except `custom`), so this hides values; real secrets belong on a
|
|
1051
|
+
server.
|
|
1052
|
+
- `pstack update` (migration `env-encryption-key-sources`) renames `keySource` to `keySources`.
|
|
1053
|
+
|
|
1054
|
+
#### Importing an Ionic app (v0.11.0)
|
|
1055
|
+
|
|
1056
|
+
`pstack migrate --source=../ionic-app` imports a standalone Ionic Angular app that uses Capacitor
|
|
1057
|
+
(`@ionic/angular` plus a `capacitor.config.*`) with the `ionic` adapter. Ionic apps in an Nx import
|
|
1058
|
+
(`ionic-app` projects) get the same treatment. The app ends up in the shape `pstack app --type=ionic`
|
|
1059
|
+
generates:
|
|
1060
|
+
|
|
1061
|
+
- Native packages (Capacitor and Cordova plugins: `@capacitor/*`, names containing `capacitor`,
|
|
1062
|
+
`cordova-*`, `@awesome-cordova-plugins/*`, `@ionic-native/*`, and any installed package that
|
|
1063
|
+
declares a `capacitor` or `cordova` section) are listed in the app's own `package.json` at the
|
|
1064
|
+
source's versions, so `cap sync` finds them. The ones the copied code imports stay in the root
|
|
1065
|
+
`package.json` too, because the web build resolves them from there; the rest (the Capacitor CLI,
|
|
1066
|
+
platform packages, plugins used only natively) are only in the app's `package.json`.
|
|
1067
|
+
- With several Ionic apps in one Nx import, each app gets the platform packages, the plugins it or
|
|
1068
|
+
the shared code imports, and the plugins no copied code imports.
|
|
1069
|
+
- An Angular app with Capacitor but without `@ionic/angular` is handled the same way (no ionicons
|
|
1070
|
+
asset).
|
|
1071
|
+
- `android/` and `ios/` are copied without build output (Gradle `build` and `release` folders,
|
|
1072
|
+
Pods, DerivedData, the generated Cordova plugin projects, the web assets and config `cap sync`
|
|
1073
|
+
copies in) or `local.properties`.
|
|
1074
|
+
- The build output moves from `www` to `dist/apps/<app>`, and `webDir` in the Capacitor config
|
|
1075
|
+
points there. When `webDir` is not a plain string, the report says what to set.
|
|
1076
|
+
- The release target builds with `type: ionic`; `cap-sync`, `cap-open` and `cap-add` targets and
|
|
1077
|
+
the `build:<app>:<env>:android|ios` / `open:<app>:android|ios` scripts are added. `@nxext/*` and
|
|
1078
|
+
`@ionic/angular-toolkit` targets are dropped.
|
|
1079
|
+
- The report's Ionic section lists the package split, the `webDir` change, the platforms copied
|
|
1080
|
+
and any Cordova plugins to check against Capacitor.
|
|
1081
|
+
|
|
1082
|
+
```bash
|
|
1083
|
+
pstack migrate --source=../field-notes
|
|
1084
|
+
npm install
|
|
1085
|
+
npx nx run field-notes:release:prod
|
|
1086
|
+
npx nx run field-notes:cap-sync --platform=android
|
|
1087
|
+
```
|
|
1088
|
+
|
|
1089
|
+
Ionic 6 and Capacitor majors other than 5 are accepted with a note. Cordova-only apps (`config.xml`
|
|
1090
|
+
or `ionic.config.json` without a Capacitor config) are refused, in Nx imports too (kind
|
|
1091
|
+
`ionic-cordova`): move them to Capacitor first. Capacitor apps on the Angular 17+ application
|
|
1092
|
+
builder are converted like other Angular 17+ apps (v0.23.0).
|
|
1093
|
+
|
|
1094
|
+
#### Importing a multi-project Angular CLI workspace (v0.12.0)
|
|
1095
|
+
|
|
1096
|
+
`pstack migrate --source=../ng-repo` imports the apps and libraries of an Angular CLI repo whose
|
|
1097
|
+
`angular.json` has several projects (the `angular-workspace` adapter). A repo with a single project
|
|
1098
|
+
still goes to the `angular-cli` (or `ionic`) adapter.
|
|
1099
|
+
|
|
1100
|
+
```bash
|
|
1101
|
+
pstack migrate --source=../ng-repo --detect # projects and their kinds
|
|
1102
|
+
pstack migrate --source=../ng-repo # every supported project
|
|
1103
|
+
pstack migrate --source=../ng-repo --projects=portal # portal and the libraries it imports
|
|
1104
|
+
pstack migrate --source=../ng-repo --projects=admin --no-deps
|
|
1105
|
+
pstack migrate --source=../ng-repo --prefix=legacy # legacy-<name> projects and folders
|
|
1106
|
+
```
|
|
1107
|
+
|
|
1108
|
+
- Apps go to `apps/<name>`, libraries to `libs/<name>`. An app at the repo root (the usual first
|
|
1109
|
+
app) is copied without the `projects/` folder and the other projects' folders.
|
|
1110
|
+
- Library aliases that pointed at the build output (`"ui-kit": ["dist/ui-kit"]`) now point at the
|
|
1111
|
+
library source (`libs/ui-kit/src/public-api.ts`, or `lib.entryFile` from `ng-package.json`), so apps
|
|
1112
|
+
build without building the libraries first. Aliases into a project's source follow it to its new
|
|
1113
|
+
folder; others are listed in the report. Imports in the copied code are rewritten (see Import
|
|
1114
|
+
rewriting).
|
|
1115
|
+
- Libraries keep their ng-packagr build (`nx build <lib>`); `ng-package.json` `dest` becomes
|
|
1116
|
+
`dist/libs/<name>`. ng-packagr and its build packages are added when a library builds.
|
|
1117
|
+
- Apps get the release target and npm scripts; apps with a Capacitor config get the Ionic treatment.
|
|
1118
|
+
- Angular 17+ application-builder apps are converted to Angular 15 builders (v0.23.0);
|
|
1119
|
+
server-rendered apps (`angular-ssr`) and e2e-only projects are listed as not supported.
|
|
1120
|
+
- Before anything is written, folders, project names, aliases and the Angular major are checked.
|
|
1121
|
+
|
|
1122
|
+
#### Importing an npm, Yarn or pnpm workspaces repo (v0.18.0, pnpm v0.20.0)
|
|
1123
|
+
|
|
1124
|
+
`pstack migrate --source=../mono` imports a repo whose root `package.json` lists its packages under
|
|
1125
|
+
`workspaces` (npm, Yarn 1 or Yarn Berry, Plug'n'Play included), or whose `pnpm-workspace.yaml` lists
|
|
1126
|
+
them under `packages` (pnpm); this is the `npm-workspaces` adapter. Repos with `nx.json` or a root
|
|
1127
|
+
`angular.json` still go to the Nx and Angular adapters.
|
|
1128
|
+
|
|
1129
|
+
```bash
|
|
1130
|
+
pstack migrate --source=../mono --detect # packages and their kinds
|
|
1131
|
+
pstack migrate --source=../mono # every supported package
|
|
1132
|
+
pstack migrate --source=../mono --projects=@acme/web # web and the packages it imports
|
|
1133
|
+
pstack migrate --source=../mono --projects=web --no-deps
|
|
1134
|
+
pstack migrate --source=../mono --prefix=legacy # legacy-<name> projects and folders
|
|
1135
|
+
```
|
|
1136
|
+
|
|
1137
|
+
- Angular app packages (`angular.json` with one application) go to `apps/<name>` with the
|
|
1138
|
+
`angular-cli` treatment; those with a Capacitor config get the Ionic treatment.
|
|
1139
|
+
- TypeScript library packages (an entry from `ng-package.json`, `source`, `types` → `src/…`,
|
|
1140
|
+
`src/index.ts` or `index.ts`) go to `libs/<name>` with a lint target, and their **package name**
|
|
1141
|
+
becomes the tsconfig alias (`"@acme/utils": ["libs/utils/src/index.ts"]`), so imports between
|
|
1142
|
+
packages keep working unchanged.
|
|
1143
|
+
- Project names are the package names without scope (`@acme/web` → `web`); when two packages
|
|
1144
|
+
would share one, both keep their scope (`acme-utils`, `other-utils`). `--projects` takes package
|
|
1145
|
+
or project names.
|
|
1146
|
+
- Dependencies of the source root and the imported libraries are merged into the root
|
|
1147
|
+
`package.json`; app packages merge their own (Angular versions come from the app packages).
|
|
1148
|
+
Workspace packages (`workspace:*` or local versions) are left out; other local `file:`/`link:`
|
|
1149
|
+
paths inside an imported package follow it to its new folder. Lockfiles, `.yarnrc.yml`, `.yarn/`,
|
|
1150
|
+
`.pnp.*` and other root files are not copied; the workspace installs with npm. Outside git, the
|
|
1151
|
+
root `.gitignore` applies to every package.
|
|
1152
|
+
- A dependency on a workspace package that cannot be imported (an ESLint or tsconfig preset, a
|
|
1153
|
+
server) is listed in the report instead of stopping the import; imports of one still do.
|
|
1154
|
+
- Packages that are not Angular/Ionic apps or TypeScript libraries (React, Node servers, CLIs with
|
|
1155
|
+
`bin`) are listed as not supported. Subpath imports (`@acme/utils/x`) and the source root tsconfig
|
|
1156
|
+
options are listed in the report.
|
|
1157
|
+
- pnpm repos:
|
|
1158
|
+
- `catalog:` and `catalog:<name>` versions are taken from `pnpm-workspace.yaml`; an entry the
|
|
1159
|
+
catalogs do not define stops the import before anything is written.
|
|
1160
|
+
- Flat `overrides` (`pnpm.overrides` in `package.json` and `overrides` in `pnpm-workspace.yaml`)
|
|
1161
|
+
become npm `overrides`; entries with selectors (`a>b`, `pkg@<2`), removals (`-`) or
|
|
1162
|
+
`workspace:`/`link:`/`file:` values are listed in the report. An override of a package the
|
|
1163
|
+
import added as a direct dependency also sets that dependency's version (npm refuses an
|
|
1164
|
+
override that differs from it); one the workspace already depends on at another version is
|
|
1165
|
+
reported.
|
|
1166
|
+
- `patchedDependencies`, `.pnpmfile.cjs`, `.npmrc` and the other pnpm settings are listed in the
|
|
1167
|
+
report, not carried over. `pnpm-workspace.yaml`, `pnpm-lock.yaml` and `.pnpmfile.cjs` are not
|
|
1168
|
+
copied.
|
|
1169
|
+
- `pnpm-workspace.yaml` is read with a small reader: anchors, aliases, tags, block scalars
|
|
1170
|
+
(`|`, `>`) and flow lists over several lines stop the import with the line number.
|
|
1171
|
+
- The Nx, Angular CLI and Ionic imports resolve `catalog:` specs in the source `package.json` the
|
|
1172
|
+
same way; an unknown entry, or a `catalog:` spec without pnpm catalogs (Yarn catalogs are not
|
|
1173
|
+
read), stops the import.
|
|
1174
|
+
|
|
1175
|
+
#### Import rewriting (v0.21.0)
|
|
1176
|
+
|
|
1177
|
+
After the copy, `pstack migrate` rewrites imports in the copied code so it builds in its new place.
|
|
1178
|
+
The source is never changed, and `--rollback` removes the rewritten copies with the rest.
|
|
1179
|
+
|
|
1180
|
+
- **Into another moved project:** a relative import that reaches into another project that moved
|
|
1181
|
+
(`../../../utils/src`) becomes that library's alias when it points at the library entry
|
|
1182
|
+
(`@acme/utils`), otherwise a corrected relative path. The report lists the corrected ones so you
|
|
1183
|
+
can export what they need from the entry instead.
|
|
1184
|
+
- **Through the source `baseUrl`:** `import … from 'src/app/x'` becomes a relative path (or the
|
|
1185
|
+
library alias), unless the workspace `baseUrl` still resolves it to the same file.
|
|
1186
|
+
- **`@nrwl/*`:** becomes `@nx/*` (`@nrwl/nx-plugin` becomes `@nx/plugin`; `@nrwl/nx-cloud`,
|
|
1187
|
+
`@nrwl/tao` and `@nrwl/cli` are listed instead). The report names `@nx/*` packages the
|
|
1188
|
+
workspace does not declare yet.
|
|
1189
|
+
- **SCSS:** relative `@use`, `@import` and `@forward` paths that reach into another moved project
|
|
1190
|
+
are corrected; paths into the source's root `node_modules` point at the workspace's.
|
|
1191
|
+
- **Library subpaths** (npm, Yarn and pnpm imports): `@acme/utils/x` resolves through an added
|
|
1192
|
+
`@acme/utils/*` alias to the package folder.
|
|
1193
|
+
|
|
1194
|
+
Code files are `.ts`, `.tsx`, `.mts`, `.cts`, `.js`, `.jsx`, `.mjs` and `.cjs` (not `.d.ts`); the
|
|
1195
|
+
rewritten forms are `import`/`export … from`, `import()`, side-effect imports, `require()` and
|
|
1196
|
+
`jest.mock()` / `vi.mock()`. Imports that point outside the imported projects, or at a file that
|
|
1197
|
+
was not copied, are left as they are and listed, unless they still resolve in the workspace.
|
|
1198
|
+
Imports inside one copied project are never changed. ESM-style `.js` specifiers of `.ts` files
|
|
1199
|
+
and `?raw`-style suffixes are understood. A bare specifier is only taken as a `baseUrl` import
|
|
1200
|
+
when a file (or a folder with an `index`) exists there; one that is also a dependency in the
|
|
1201
|
+
source `package.json` is listed instead.
|
|
1202
|
+
Nx imports keep their paths, so their relative imports are left alone. The report's `## Imports`
|
|
1203
|
+
section lists every change. `--no-rewrite-imports` (or `"rewriteImports": false` in a `--config`
|
|
1204
|
+
file) keeps the copies as they were and the report lists what needs a hand edit, as before.
|
|
1205
|
+
|
|
1206
|
+
#### Writing your own adapter (v0.22.0)
|
|
1207
|
+
|
|
1208
|
+
When no built-in adapter fits a source, write one. `pstack migrate --new-adapter=<id>` writes a
|
|
1209
|
+
working starter (`tools/migrate/<id>.adapter.ts`, which imports a static site with an `index.html`)
|
|
1210
|
+
with a Jest spec and `tools/migrate/jest.config.js`, and lists it in `nx.json`:
|
|
1211
|
+
|
|
1212
|
+
```json
|
|
1213
|
+
{
|
|
1214
|
+
"pstack": {
|
|
1215
|
+
"migrateAdapters": ["./tools/migrate/legacy-site.adapter.ts", "@acme/pstack-adapter-x"]
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
```
|
|
1219
|
+
|
|
1220
|
+
Entries are workspace-relative `.js`/`.ts` files or installed package names. A module exports one
|
|
1221
|
+
adapter or a list (`default`, `adapters`, `adapter`, or `module.exports`).
|
|
1222
|
+
|
|
1223
|
+
- **TypeScript:** `.ts` files are transpiled with the workspace's `typescript` and its
|
|
1224
|
+
`tsconfig.base.json` options (no ts-node needed). `paths` aliases are not resolved, and
|
|
1225
|
+
`.mts`/`.cts` files are not supported.
|
|
1226
|
+
- **Adapter packages:** must be CommonJS, and should list nx-polystack as a peer dependency so
|
|
1227
|
+
they use the workspace's copy.
|
|
1228
|
+
- **Trust:** listed adapters run as code on `pstack migrate`, `--detect` included. List only
|
|
1229
|
+
adapters you trust, as with Nx plugins.
|
|
1230
|
+
|
|
1231
|
+
```ts
|
|
1232
|
+
import {
|
|
1233
|
+
copyIntoTree,
|
|
1234
|
+
defineMigrationAdapter,
|
|
1235
|
+
emptyReportData,
|
|
1236
|
+
MIGRATE_API_VERSION,
|
|
1237
|
+
recordCopy,
|
|
1238
|
+
sourceExists,
|
|
1239
|
+
} from '@mouryaamit/nx-polystack/migrate';
|
|
1240
|
+
|
|
1241
|
+
export default defineMigrationAdapter({
|
|
1242
|
+
apiVersion: MIGRATE_API_VERSION,
|
|
1243
|
+
id: 'legacy-site',
|
|
1244
|
+
label: 'legacy static site',
|
|
1245
|
+
detect: (dir) =>
|
|
1246
|
+
sourceExists(dir, 'site.conf')
|
|
1247
|
+
? { confidence: 0.9, reasons: ['site.conf'] }
|
|
1248
|
+
: { confidence: 0, reasons: ['no site.conf'] },
|
|
1249
|
+
defaultName: () => undefined,
|
|
1250
|
+
migrate(tree, ctx) {
|
|
1251
|
+
const data = emptyReportData();
|
|
1252
|
+
const copy = copyIntoTree(
|
|
1253
|
+
tree,
|
|
1254
|
+
ctx.sourceDir,
|
|
1255
|
+
ctx.projectRoot,
|
|
1256
|
+
{
|
|
1257
|
+
anyDepth: ['.git'],
|
|
1258
|
+
topLevel: [],
|
|
1259
|
+
},
|
|
1260
|
+
{ maxFiles: ctx.maxFiles },
|
|
1261
|
+
);
|
|
1262
|
+
recordCopy(data, copy, '');
|
|
1263
|
+
return data;
|
|
1264
|
+
},
|
|
1265
|
+
});
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
- **The SDK** (`@mouryaamit/nx-polystack/migrate`) has the adapter and report types, and the
|
|
1269
|
+
helpers the built-in adapters use:
|
|
1270
|
+
- `copyIntoTree`, which applies skip rules, leaves out possible secrets, honours `.gitignore`
|
|
1271
|
+
and enforces `--max-files`;
|
|
1272
|
+
- `recordCopy` and `emptyReportData`;
|
|
1273
|
+
- `mergeDependencies` and `classifyDependencySpec`;
|
|
1274
|
+
- the source readers, `kebabName`, `upTo` and `setProjectTags`.
|
|
1275
|
+
- **Same treatment as the built-ins:** listed adapters take part in `--detect` (inside a workspace),
|
|
1276
|
+
`--adapter=<id>`, `--config` and `--rollback`. Copies made with `copyIntoTree` + `recordCopy` get
|
|
1277
|
+
import rewriting and the report's skipped-paths and secrets lists.
|
|
1278
|
+
- **Checks:**
|
|
1279
|
+
- an adapter must declare `apiVersion: 1` (`MIGRATE_API_VERSION`);
|
|
1280
|
+
- its id must be kebab-case and used by no built-in or other listed adapter;
|
|
1281
|
+
- it needs `label`, `detect`, `defaultName` and `migrate` (plus `preflight` for
|
|
1282
|
+
`kind: 'workspace'`).
|
|
1283
|
+
Anything else stops the run, naming the `nx.json` entry.
|
|
1284
|
+
- **Ties and errors:** built-ins are tried first, so they win ties. An adapter whose `detect()`
|
|
1285
|
+
throws scores 0, with the error as its reason.
|
|
1286
|
+
- **CLI version:** the global `pstack` delegates to the workspace's nx-polystack, which must be
|
|
1287
|
+
v0.22.0 or later to load listed adapters.
|
|
1288
|
+
|
|
1289
|
+
#### Angular 17+ sources (v0.23.0)
|
|
1290
|
+
|
|
1291
|
+
`pstack migrate` imports Angular CLI apps built with the Angular 17+ application builder. The
|
|
1292
|
+
workspace builds with Angular 15, so the targets are converted to the Angular 15 builders. Covered:
|
|
1293
|
+
standalone Angular CLI apps, Ionic apps, multi-project Angular CLI workspaces, and Angular app
|
|
1294
|
+
packages of npm, Yarn and pnpm workspaces. Nx sources on the application builder are still listed as
|
|
1295
|
+
not supported.
|
|
1296
|
+
|
|
1297
|
+
- **Build target:** `@angular-devkit/build-angular:application` and `@angular/build:application`
|
|
1298
|
+
(and `:browser-esbuild` with `browser`/`server`/`ssr` options) become
|
|
1299
|
+
`@angular-devkit/build-angular:browser`. `browser` becomes `main`, an `outputPath` object becomes
|
|
1300
|
+
its `base`, an `index` object keeps `input` and `output`, and a `serviceWorker` path becomes
|
|
1301
|
+
`serviceWorker: true` plus `ngswConfigPath`. Asset objects without `output` get `"/"`. Missing
|
|
1302
|
+
`main`, `index`, `outputPath` and `tsConfig` are filled in, with `aot: true`; a configuration
|
|
1303
|
+
with `optimization: false` gets `buildOptimizer: false`. Options the browser builder does not
|
|
1304
|
+
have (`define`, `loader`, `externalDependencies`, `security`, …), and sub-options Angular 15
|
|
1305
|
+
rejects (`stylePreprocessorOptions.sass`, `optimization.styles.removeSpecialComments`, …), are
|
|
1306
|
+
dropped and listed. The output goes to `outputPath` itself, not to a `browser/` folder inside it.
|
|
1307
|
+
- **Other targets:** `@angular/build:dev-server`, `extract-i18n`, `karma` and `ng-packagr` become
|
|
1308
|
+
the `@angular-devkit/build-angular` builders. Every dev-server, extract-i18n and karma target of
|
|
1309
|
+
the project is checked against Angular 15: `buildTarget` becomes `browserTarget` (added when
|
|
1310
|
+
missing, as Angular 17+ defaults it), asset objects get `output: "/"`, and options Angular 15
|
|
1311
|
+
does not have (`prebundle`, `builderMode`, …) are dropped and listed. Other `@angular/build`
|
|
1312
|
+
targets (`unit-test`) are kept and listed: they cannot run on Angular 15.
|
|
1313
|
+
- **i18n:** a `subPath` (Angular 17.2+) is listed; Angular 15 names locale folders after the
|
|
1314
|
+
locale.
|
|
1315
|
+
- **tsconfig:** TypeScript 5-only compiler options are fixed for TypeScript 4.9:
|
|
1316
|
+
`moduleResolution: "bundler"` becomes `"node"`, `module: "preserve"` becomes `"es2022"`, an
|
|
1317
|
+
ES2023+ `target` or `lib` becomes ES2022, and `verbatimModuleSyntax`, `allowImportingTsExtensions`
|
|
1318
|
+
and the like are removed.
|
|
1319
|
+
- **Server rendering:** an app whose build sets `server`, `ssr`, `prerender` or `appShell` (or that
|
|
1320
|
+
has a server, ssr-dev-server, prerender or app-shell target) is refused before anything is
|
|
1321
|
+
written; in a workspace it is listed as `angular-ssr`. Angular 15 Universal apps (browser builder
|
|
1322
|
+
plus a server target) keep their builders and migrate as before.
|
|
1323
|
+
- **Code (report only):** the report's Angular section lists files that use Angular 16+ code
|
|
1324
|
+
Angular 15 cannot compile: template control flow (`@if`, `@for`, `@switch`, `@defer`, `@let`),
|
|
1325
|
+
signal APIs (`signal`, `computed`, `effect`, `input`, `output`, `model`, `viewChild`, …),
|
|
1326
|
+
`@angular/core/rxjs-interop`, and newer providers (`withFetch`, `provideAnimationsAsync`,
|
|
1327
|
+
`provideZoneChangeDetection`, …). Nothing is rewritten.
|
|
1328
|
+
- **Angular version:** a source on another Angular major still needs `--force-angular`; the
|
|
1329
|
+
workspace's Angular packages are kept.
|
|
1330
|
+
- **CLI version:** the global `pstack` delegates to the workspace's nx-polystack, which must be
|
|
1331
|
+
v0.23.0 or later.
|
|
1332
|
+
|
|
1333
|
+
### `:infra` generator / `pstack infra` (v0.9.0)
|
|
1334
|
+
|
|
1335
|
+
Same options as `pstack infra` (§3c): `with`, `ci`, `ciCache`, `flutter`, `upgradeSchedule`, `upgradeScope`,
|
|
1336
|
+
`force`, `skipFormat`.
|
|
1337
|
+
|
|
1338
|
+
```bash
|
|
1339
|
+
npx nx g @mouryaamit/nx-polystack:infra --with=docs,ci --ci=jenkins
|
|
1340
|
+
```
|
|
1341
|
+
|
|
1342
|
+
### `:app` generator schema
|
|
1343
|
+
|
|
1344
|
+
```jsonc
|
|
1345
|
+
{
|
|
1346
|
+
"name": "portal", // string — required
|
|
1347
|
+
"type": "angular", // "angular" | "flutter" — required
|
|
1348
|
+
"tags": ["platform:web"], // string[] — optional
|
|
1349
|
+
"cspConnectSrc": "https://..." // string — optional, angular only
|
|
1350
|
+
}
|
|
1351
|
+
```
|
|
1352
|
+
|
|
1353
|
+
---
|
|
1354
|
+
|
|
1355
|
+
## 7. Nx plugin usage — executors
|
|
1356
|
+
|
|
1357
|
+
Executors run as Nx targets after the plugin is installed as a dev dependency.
|
|
1358
|
+
|
|
1359
|
+
### `:build` — Angular / Ionic build pipeline
|
|
1360
|
+
|
|
1361
|
+
Replaces the legacy `tools/scripts/build.js` orchestrator. Runs the full pipeline:
|
|
1362
|
+
|
|
1363
|
+
```
|
|
1364
|
+
encrypt-env → nx build → restore env
|
|
1365
|
+
[→ leak check] (non-DEV, leakCheck)
|
|
1366
|
+
[→ source-map check] (non-DEV, sourceMaps)
|
|
1367
|
+
[→ strip / drop console] (non-DEV, stripComments / dropConsole)
|
|
1368
|
+
[→ obfuscate] (non-DEV, obfuscate: light)
|
|
1369
|
+
[→ SRI hash swap] (non-DEV, sri: true)
|
|
1370
|
+
→ strip-exif (PROD) → inject-meta
|
|
1371
|
+
[→ inject-nonce] (if secure: true)
|
|
1372
|
+
[→ inject-sri] (if sri: true; recomputes Angular's values)
|
|
1373
|
+
→ ngsw.json hashes (when present)
|
|
1374
|
+
```
|
|
1375
|
+
|
|
1376
|
+
The `nx build` step runs the app's Angular `build` target (`buildTarget`). Generated Angular apps register this
|
|
1377
|
+
executor as the `release` target; the Angular builder lives on `build`.
|
|
1378
|
+
|
|
1379
|
+
**`project.json` target example:**
|
|
1380
|
+
|
|
1381
|
+
```jsonc
|
|
1382
|
+
{
|
|
1383
|
+
"release": {
|
|
1384
|
+
"executor": "@mouryaamit/nx-polystack:build",
|
|
1385
|
+
"outputs": ["{options.outputPath}"],
|
|
1386
|
+
"options": {
|
|
1387
|
+
"type": "angular",
|
|
1388
|
+
"outputPath": "dist/apps/portal",
|
|
1389
|
+
"envProject": "portal",
|
|
1390
|
+
"buildTarget": "portal:build"
|
|
1391
|
+
},
|
|
1392
|
+
"configurations": {
|
|
1393
|
+
"dev": { "env": "DEV", "buildConfiguration": "development" },
|
|
1394
|
+
"uat": {
|
|
1395
|
+
"env": "UAT",
|
|
1396
|
+
"buildConfiguration": "uat",
|
|
1397
|
+
"leakCheck": "fail",
|
|
1398
|
+
"sourceMaps": "fail",
|
|
1399
|
+
"stripComments": true,
|
|
1400
|
+
"dropConsole": ["log", "debug", "warn"]
|
|
1401
|
+
},
|
|
1402
|
+
"prod": {
|
|
1403
|
+
"env": "PROD",
|
|
1404
|
+
"buildConfiguration": "production",
|
|
1405
|
+
"leakCheck": "fail",
|
|
1406
|
+
"sourceMaps": "fail",
|
|
1407
|
+
"stripComments": true,
|
|
1408
|
+
"dropConsole": ["log", "debug", "warn"]
|
|
1409
|
+
}
|
|
1410
|
+
},
|
|
1411
|
+
"defaultConfiguration": "dev"
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
```
|
|
1415
|
+
|
|
1416
|
+
**Schema options:**
|
|
1417
|
+
|
|
1418
|
+
| Option | Type | Default | Description |
|
|
1419
|
+
| -------------------- | ---------------------------- | ----------------- | ----------------------------------------------------------------------- |
|
|
1420
|
+
| `type` | `"angular" \| "ionic"` | — | App type |
|
|
1421
|
+
| `outputPath` | `string` | — | Build output directory |
|
|
1422
|
+
| `envProject` | `string` | — | Folder name under `environments/` |
|
|
1423
|
+
| `env` | `string` | — | `DEV`, `UAT`, `PROD` or custom (e.g. `QA`); set via Nx `configurations` |
|
|
1424
|
+
| `buildTarget` | `string` | `<project>:build` | Angular target to run, exactly `<project>:<target>` |
|
|
1425
|
+
| `buildConfiguration` | `string` | see below | Configuration of `buildTarget` |
|
|
1426
|
+
| `secure` | `boolean` | `false` | Inject CSP nonce SSI placeholders |
|
|
1427
|
+
| `sri` | `boolean` | `false` | Integrity for every chunk (`--subresource-integrity`, hashes refreshed) |
|
|
1428
|
+
| `leakCheck` | `fail\|warn\|off` | `off` | non-DEV: plaintext of encrypted env values in the output (below) |
|
|
1429
|
+
| `sourceMaps` | `fail\|warn\|off` | `off` | non-DEV: source maps in the output |
|
|
1430
|
+
| `stripComments` | `boolean` | `false` | non-DEV: remove comments from built JS, CSS, `index.html` |
|
|
1431
|
+
| `dropConsole` | `string[]` | `[]` | non-DEV: console methods removed from built JS |
|
|
1432
|
+
| `obfuscate` | `off\|light\|medium\|strong` | `off` | non-DEV: obfuscate main and lazy chunks (below) |
|
|
1433
|
+
| `obfuscateOptions` | `object` | — | non-DEV: javascript-obfuscator overrides on top of the level |
|
|
1434
|
+
| `harden` | `boolean` | `false` | Replaced: read as `stripComments` + `dropConsole` defaults; no script |
|
|
1435
|
+
| `baseHref` | `string` | — | Forwarded to Angular CLI `--base-href` |
|
|
1436
|
+
|
|
1437
|
+
**`buildTarget` / `buildConfiguration`.** The executor runs
|
|
1438
|
+
`npx nx run <buildTarget>:<buildConfiguration> --outputPath=<outputPath>`. When `buildConfiguration` is unset it
|
|
1439
|
+
falls back to `production` for `PROD`, `uat` for `UAT`, and `development` for anything else. `buildTarget` must be
|
|
1440
|
+
`<project>:<target>`; any other format is an error.
|
|
1441
|
+
|
|
1442
|
+
**Self-reference error.** `buildTarget` must not point at the target that is running (for example `portal:release`
|
|
1443
|
+
with `buildTarget: portal:release`). The executor stops with
|
|
1444
|
+
`buildTarget "<x>" points at this target. Run "pstack update" (migration angular-release-target) or set buildTarget to the Angular build target.`
|
|
1445
|
+
This is what an app generated by v0.3.x hits, because its `build` target used this executor.
|
|
1446
|
+
|
|
1447
|
+
**Custom environments (QA).** `env` is free-form. `env: "QA"` reads `environments/<envProject>/environment.qa.ts`
|
|
1448
|
+
(`DEV` reads `environment.ts`); EXIF stripping stays PROD-only. `pstack env --name=qa --app=portal` adds the `qa`
|
|
1449
|
+
configuration to `build`, `serve` and (when present) `release`, plus a `build:<app>:qa` npm script
|
|
1450
|
+
(see "Adding an environment later"):
|
|
1451
|
+
|
|
1452
|
+
```bash
|
|
1453
|
+
pstack env --name=qa --app=portal
|
|
1454
|
+
npx nx run portal:release:qa
|
|
1455
|
+
```
|
|
1456
|
+
|
|
1457
|
+
**Release hardening (v0.29.0).**
|
|
1458
|
+
|
|
1459
|
+
The polystack `release` target (`@mouryaamit/nx-polystack:build`) can check and clean the build
|
|
1460
|
+
output of a UAT or PROD release. The options are set per release configuration; DEV builds skip
|
|
1461
|
+
every step.
|
|
1462
|
+
|
|
1463
|
+
| Option | Values | New apps (uat, prod) | What it does |
|
|
1464
|
+
| --------------- | -------------------------------------------------------- | ------------------------ | ----------------------------------------------------------------------- |
|
|
1465
|
+
| `leakCheck` | `fail`, `warn`, `off` | `fail` | Plaintext of a value encrypted in this build found in the output |
|
|
1466
|
+
| `sourceMaps` | `fail`, `warn`, `off` | `fail` | `.map` files or `sourceMappingURL` comments in the output |
|
|
1467
|
+
| `stripComments` | boolean | `true` | Removes comments from the built JS, CSS and the served `index.html` |
|
|
1468
|
+
| `dropConsole` | list of `log`, `debug`, `warn`, `info`, `error`, `trace` | `["log","debug","warn"]` | Removes those console calls from the built JS (`info`/`error` are kept) |
|
|
1469
|
+
|
|
1470
|
+
```jsonc
|
|
1471
|
+
"uat": {
|
|
1472
|
+
"env": "UAT",
|
|
1473
|
+
"buildConfiguration": "uat",
|
|
1474
|
+
"leakCheck": "fail",
|
|
1475
|
+
"sourceMaps": "fail",
|
|
1476
|
+
"stripComments": true,
|
|
1477
|
+
"dropConsole": ["log", "debug", "warn"]
|
|
1478
|
+
}
|
|
1479
|
+
```
|
|
1480
|
+
|
|
1481
|
+
Absent options are off. `fail` lists every hit, then fails the build; `warn` lists them and
|
|
1482
|
+
continues. `LEAK_CHECK=warn` (or `fail`/`off`) overrides `leakCheck` for one run:
|
|
1483
|
+
|
|
1484
|
+
```bash
|
|
1485
|
+
LEAK_CHECK=warn npx nx run web:release:uat
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
**Order after the Angular build:** env files restored → leak check → source-map check → strip
|
|
1489
|
+
comments and drop console (one terser pass per JS file) → EXIF strip (PROD) → build meta, aes-gcm
|
|
1490
|
+
key share, CSP nonce, SRI. SRI hashes therefore cover the final files.
|
|
1491
|
+
|
|
1492
|
+
- **Leak check.** Looks for the plaintext of every value encrypted from the env and profile files
|
|
1493
|
+
(4 characters or longer) in the js, mjs, cjs, html, css, json, txt and map files of the served
|
|
1494
|
+
output (`3rdpartylicenses.txt` is skipped). Matches are whole tokens, raw or escaped (JSON,
|
|
1495
|
+
`\uXXXX`, and HTML entities in html files). Messages name the file and the env key, never the
|
|
1496
|
+
value. A value a profile file holds under a non-sensitive key (public by the app's own
|
|
1497
|
+
configuration) is only a warning.
|
|
1498
|
+
- **Source maps.** The hint names the Angular option to change: `"sourceMap": false` in the build
|
|
1499
|
+
configuration.
|
|
1500
|
+
- **Strip and drop console.** `assets/` is never touched. License comments (`/*! … */`) stay when
|
|
1501
|
+
only `dropConsole` is set. SSI (`<!--#…-->`) and IE conditional comments stay in html; html is
|
|
1502
|
+
left alone for SSR hydration (`index.csr.html` or `ngh` attributes). A file terser cannot parse
|
|
1503
|
+
fails the build, naming the file. The Angular service worker's `ngsw.json` hashes are
|
|
1504
|
+
recomputed at the end of the build (v0.30.0).
|
|
1505
|
+
- **terser.** The JS step loads terser from the workspace: keep `terser` in the root
|
|
1506
|
+
`devDependencies` (new apps and the migration add `^5.16.0`). Without it the build fails with "stripComments/dropConsole need terser in the
|
|
1507
|
+
workspace devDependencies".
|
|
1508
|
+
- **`harden`** is replaced. It used to run two scripts that workspaces do not have; now
|
|
1509
|
+
`harden: true` is read as `stripComments: true` plus `dropConsole: ["log","debug","warn"]` when
|
|
1510
|
+
those are unset, with a warning naming the new options. It runs no script.
|
|
1511
|
+
- **`pstack update`** (migration `release-hardening`, 0.29.0) turns the four options on for every
|
|
1512
|
+
release configuration whose `env` is `UAT` or `PROD` (values already set, in the configuration
|
|
1513
|
+
or the target options, are kept), removes `harden` (other non-DEV configurations it applied to
|
|
1514
|
+
get `stripComments` and `dropConsole` instead) and adds terser. Set `leakCheck`/`sourceMaps` to
|
|
1515
|
+
`"warn"` to report only.
|
|
1516
|
+
|
|
1517
|
+
**Obfuscation and integrity (v0.30.0).** Two more release options, also per configuration and
|
|
1518
|
+
skipped for DEV:
|
|
1519
|
+
|
|
1520
|
+
| Option | Values | Default | What it does |
|
|
1521
|
+
| ------------------ | ---------------------------------- | ------- | ----------------------------------------------------------------------------------------- |
|
|
1522
|
+
| `obfuscate` | `off`, `light`, `medium`, `strong` | `off` | Obfuscates main and the lazy chunks (runtime, polyfills, vendor, scripts, styles skipped) |
|
|
1523
|
+
| `obfuscateOptions` | object | — | javascript-obfuscator options on top of the level (CSP-safe subset) |
|
|
1524
|
+
| `sri` | boolean | `false` | Integrity for every chunk; with aes-gcm the app decrypts nothing without it |
|
|
1525
|
+
|
|
1526
|
+
```bash
|
|
1527
|
+
pstack hardening --app=web # show the settings
|
|
1528
|
+
pstack hardening --app=web --configuration=uat --obfuscate=light --sri
|
|
1529
|
+
pstack hardening --app=web --sri --drop-console=log,debug,warn # every non-DEV configuration
|
|
1530
|
+
```
|
|
1531
|
+
|
|
1532
|
+
- **Order:** checks → strip / drop console → obfuscate → SRI hash swap → EXIF, meta, key share,
|
|
1533
|
+
CSP nonce → SRI in index.html → `ngsw.json` hashes.
|
|
1534
|
+
- **`obfuscate`** uses `javascript-obfuscator` from the workspace (`pstack hardening` adds
|
|
1535
|
+
`^4.2.2`; run `npm install`). No migration turns it on. Levels, measured on a 2.8 MB Angular
|
|
1536
|
+
chunk (gzip growth):
|
|
1537
|
+
|
|
1538
|
+
| Level | Profile | Gzip |
|
|
1539
|
+
| -------- | ---------------------------------------------------------------------------------------------------------- | --------------------- |
|
|
1540
|
+
| `light` | short (mangled) names, half the strings in a rotated, shuffled array, no wrappers | ≈ +20% |
|
|
1541
|
+
| `medium` | hexadecimal names, three quarters of the strings, string-array wrappers | ≈ +67% |
|
|
1542
|
+
| `strong` | `medium`, plus rc4 string encoding and control-flow flattening (0.1) on the chunk holding the decrypt code | ≈ +210% on that chunk |
|
|
1543
|
+
|
|
1544
|
+
Every level is CSP-safe (`target: browser-no-eval`): no self-defending or debug protection,
|
|
1545
|
+
globals and properties are not renamed, and each file gets its own identifier prefix and a
|
|
1546
|
+
seed from its content. Main often holds the decrypt code and, in production builds without a
|
|
1547
|
+
vendor chunk, the Angular framework: measure start-up time. (v0.31.0: `light` was the
|
|
1548
|
+
`strong` profile in v0.30.x.)
|
|
1549
|
+
|
|
1550
|
+
- **`obfuscateOptions`** tunes the level, e.g. `{ "stringArrayThreshold": 0.3 }` or
|
|
1551
|
+
`{ "identifierNamesGenerator": "mangled" }`. Allowed keys: `stringArray`,
|
|
1552
|
+
`stringArrayThreshold`, `stringArrayRotate`, `stringArrayShuffle`, `stringArrayEncoding`,
|
|
1553
|
+
`stringArrayIndexShift`, `stringArrayWrappersCount`, `stringArrayWrappersType`,
|
|
1554
|
+
`stringArrayWrappersChainedCalls`, `identifierNamesGenerator`, `controlFlowFlattening`,
|
|
1555
|
+
`controlFlowFlatteningThreshold`, `deadCodeInjection`, `deadCodeInjectionThreshold`,
|
|
1556
|
+
`numbersToExpressions`, `simplify`, `splitStrings`, `splitStringsChunkLength`,
|
|
1557
|
+
`transformObjectKeys`, `unicodeEscapeSequence`, `reservedNames`, `reservedStrings`. Anything
|
|
1558
|
+
else (eval-based protection, domain lock, renaming globals or properties, the target) fails the
|
|
1559
|
+
build. `pstack hardening --obfuscate-options='{"stringArrayThreshold":0.3}'` sets it
|
|
1560
|
+
(`none` clears it).
|
|
1561
|
+
- **`sri: true`** passes `--subresource-integrity` to the Angular build, so the webpack runtime
|
|
1562
|
+
checks every lazy chunk and index.html carries `integrity` on its scripts and styles. The
|
|
1563
|
+
hashes Angular wrote are swapped for the hashes of the stripped and obfuscated files, and the
|
|
1564
|
+
index.html values are recomputed, so the browser refuses any file changed after the build. With
|
|
1565
|
+
cipher aes-gcm the build also sets `ri` in `__pstack`: `envReady` rejects with "integrity
|
|
1566
|
+
required" and decrypts nothing while a `<script src>` on the page has no `integrity`
|
|
1567
|
+
attribute. cryptojs builds get the browser check only. The application builder (esbuild) loads
|
|
1568
|
+
lazy chunks with `import()`, which carries no hash: the build warns that they are not covered.
|
|
1569
|
+
- **Integrity set in `angular.json`.** If the Angular build already wrote integrity
|
|
1570
|
+
(`subresourceIntegrity: true`) while pstack `sri` is off, the hashes are still swapped and
|
|
1571
|
+
refreshed after strip and obfuscate. After the swap, every hash in the webpack runtime must match
|
|
1572
|
+
an output file, else the build fails. A `deployUrl` is not supported with `sri`.
|
|
1573
|
+
- **Limits of the runtime check.** It covers same-origin `<script src>` (the files the build
|
|
1574
|
+
serves); third-party scripts such as a tag manager or chat widget are left to your CSP allowlist,
|
|
1575
|
+
and the build lists their hosts. It checks that the attribute is present (the browser checks the
|
|
1576
|
+
value) and does not cover inline scripts. (v0.30.1: v0.30.0 also required integrity on
|
|
1577
|
+
third-party scripts, which blocked decryption on pages that load them.)
|
|
1578
|
+
- **Service worker.** When the output has `ngsw.json`, its `hashTable` is recomputed after every
|
|
1579
|
+
rewrite, so the service worker accepts the final files. With `secure: true` the server rewrites
|
|
1580
|
+
`index.html` (the SSI nonce), so that one entry can never match.
|
|
1581
|
+
|
|
1582
|
+
**Release per environment (v0.32.0).** `pstack build` builds every app for one environment and
|
|
1583
|
+
prints a summary:
|
|
1584
|
+
|
|
1585
|
+
```bash
|
|
1586
|
+
pstack build --env=uat --all --dry-run # the plan only
|
|
1587
|
+
pstack build --env=uat --all
|
|
1588
|
+
pstack build --env=prod --projects=portal,admin --parallel=2 --continue --report=dist/build.json
|
|
1589
|
+
```
|
|
1590
|
+
|
|
1591
|
+
- **What it builds:** the release target (`@mouryaamit/nx-polystack:build`) of Angular and Ionic
|
|
1592
|
+
apps, and `build-web` of Flutter apps (`--flutter-platforms=web,android,ios` adds
|
|
1593
|
+
`build-android` / `build-ios`). The configuration is the one named after the env, else the one
|
|
1594
|
+
whose `env` option matches. Apps without one are listed, not failed.
|
|
1595
|
+
- **How:** `npx nx run <app>:<target>:<configuration>`, one at a time with the build output shown;
|
|
1596
|
+
`--parallel=N` (up to 8) runs N at once with each line prefixed by the app name. The first
|
|
1597
|
+
failure stops the run (the rest are listed as skipped) unless `--continue` is given. The exit
|
|
1598
|
+
code is 1 when a build failed.
|
|
1599
|
+
- **Summary:** status, time and output folder size per build, and the total time;
|
|
1600
|
+
`--report=<file>` writes it as JSON too. The size is of the whole output folder, so
|
|
1601
|
+
files left from an earlier build count too; builds of one app (Flutter platforms) never run
|
|
1602
|
+
side by side.
|
|
1603
|
+
|
|
1604
|
+
**Base href per configuration.** `pstack app --base-href=/portal/` writes `baseHref` on the `uat`
|
|
1605
|
+
and `prod` configurations of the release target (Flutter: `build-web`).
|
|
1606
|
+
`pstack release --app=portal` shows them; `--base-href=/portal/` sets every non-DEV
|
|
1607
|
+
configuration (or `--configuration=<name>` only), `--base-href=none` removes it.
|
|
1608
|
+
|
|
1609
|
+
**CSP and server config (v0.33.0).** Each Angular/Ionic app's `csp-allowlist.json` lists the
|
|
1610
|
+
extra sources its pages need; `pstack csp` writes `src/.htaccess` (Apache) and
|
|
1611
|
+
`server/nginx.conf` (Nginx) from it:
|
|
1612
|
+
|
|
1613
|
+
```bash
|
|
1614
|
+
pstack csp --app=portal # show the policy, write missing files
|
|
1615
|
+
pstack csp --app=portal --add=script-src:https://www.googletagmanager.com,connect-src:https://api.example.com
|
|
1616
|
+
pstack csp --app=portal --remove=connect-src:https://old.example.com
|
|
1617
|
+
pstack csp --app=portal --force # also replace hand-written files
|
|
1618
|
+
```
|
|
1619
|
+
|
|
1620
|
+
- **Allowlist keys:** `script-src`, `style-src`, `img-src`, `font-src`, `connect-src`,
|
|
1621
|
+
`frame-src`, `media-src`, `worker-src`, `manifest-src`, `form-action`, `frame-ancestors`, plus
|
|
1622
|
+
`permissions-policy` (a string). Sources are hosts (`https://api.example.com`,
|
|
1623
|
+
`https://*.example.com`, `wss://…`, with optional port and path), schemes (`https:`, `wss:`,
|
|
1624
|
+
`data:`, `blob:`), `'self'`, or `'wasm-unsafe-eval'` in `script-src`. Quoted keywords such as `'unsafe-inline'`/`'unsafe-eval'`, `*`,
|
|
1625
|
+
and `data:`/`blob:` in `script-src` are refused.
|
|
1626
|
+
- **Policy:** `script-src 'self' 'nonce-…'` and `style-src 'self' 'nonce-…'` plus the allowlist,
|
|
1627
|
+
`style-src-attr 'unsafe-inline'` (Angular `[style]` bindings), `img-src`/`font-src` with
|
|
1628
|
+
`data:`, `object-src 'none'`, `base-uri 'self'`, `form-action 'self'`,
|
|
1629
|
+
`frame-ancestors 'none'` (or the listed ones), `upgrade-insecure-requests`, plus
|
|
1630
|
+
X-Frame-Options, X-Content-Type-Options, Referrer-Policy, HSTS and Permissions-Policy.
|
|
1631
|
+
- **Nonce per request:** the release build with `secure: true` writes
|
|
1632
|
+
`<!--#echo var="CSP_NONCE" -->` into the nonce attributes and `<meta property="csp-nonce">`
|
|
1633
|
+
(placeholder nonces such as `random-csp-nonce` already in the page are replaced too; v0.32 and
|
|
1634
|
+
earlier wrote `UNIQUE_ID`). Apache fills it by SSI from `UNIQUE_ID` with `@` replaced (a nonce
|
|
1635
|
+
may not hold `@`); Nginx replaces it with `$request_id` through `sub_filter`. The CSP header carries
|
|
1636
|
+
the same value; `index.html` is sent with `Cache-Control: no-store`. `runtime/csp-nonce` gives
|
|
1637
|
+
the nonce to elements Angular adds later.
|
|
1638
|
+
- **Generated vs hand-written:** generated files start with
|
|
1639
|
+
`# Generated by pstack csp from csp-allowlist.json`; `pstack csp` rewrites those and missing
|
|
1640
|
+
ones, and keeps any other file unless `--force`.
|
|
1641
|
+
- **Critical CSS:** Angular's inlined critical CSS loads the stylesheet with an `onload`
|
|
1642
|
+
handler, which the strict `script-src` blocks; new apps set
|
|
1643
|
+
`optimization.styles.inlineCritical: false`, and `pstack csp` warns when a build still inlines
|
|
1644
|
+
it.
|
|
1645
|
+
- **Nginx and a base href:** the generated server block serves the app at `/`; adjust `root` and
|
|
1646
|
+
`location` when it lives under a base href.
|
|
1647
|
+
- **Apache requirements:** mod_rewrite, mod_headers, mod_include, mod_unique_id and mod_setenvif,
|
|
1648
|
+
and `AllowOverride FileInfo Options=IncludesNOEXEC` (or `All`) for the folder — the default
|
|
1649
|
+
`AllowOverride None` ignores the file, and without `Options` rights Apache answers 500.
|
|
1650
|
+
- **Nonce strength:** Nginx's `$request_id` is 16 random bytes per request. Apache's `UNIQUE_ID`
|
|
1651
|
+
is unique but not random per request (a per-process random part plus time and a counter), so
|
|
1652
|
+
someone who sees one response can guess later nonces from the same process; prefer Nginx, or a
|
|
1653
|
+
nonce from your app server, where that matters. A server that sets its own random `UNIQUE_ID` (for
|
|
1654
|
+
example through mod_lua, with mod_unique_id off) is used as is. A missing module fails closed: the header
|
|
1655
|
+
carries `'nonce-(null)'` and the page `(none)`, so scripts are blocked.
|
|
1656
|
+
- **Nginx notes:** needs nginx 1.11+ (`$request_id`) and `include mime.types` in the `http` block;
|
|
1657
|
+
`sub_filter` is skipped when a precompressed `index.html.gz`/`.br` is served (gzip_static).
|
|
1658
|
+
- **Tag managers:** an inline GTM snippet needs the page nonce (the release build adds it to inline
|
|
1659
|
+
scripts); the scripts GTM loads later must be listed in `script-src` and may need more.
|
|
1660
|
+
- **Upgrading from v0.32 or earlier:** the build placeholder changed from `UNIQUE_ID` to
|
|
1661
|
+
`CSP_NONCE`, and earlier generated `.htaccess`/`nginx.conf` files carry no marker, so
|
|
1662
|
+
`pstack csp` treats them as hand-written. Under an Apache `Alias` (URL path differs from the folder),
|
|
1663
|
+
add `RewriteBase /<base href>/`. Run `pstack csp --app=<app> --force` once (after
|
|
1664
|
+
copying any hand-made changes into `csp-allowlist.json`).
|
|
1665
|
+
|
|
1666
|
+
**Importing an existing policy (v0.38.0).** `--import` merges a CSP an app already has into its
|
|
1667
|
+
`csp-allowlist.json`, then renders the server files as usual:
|
|
1668
|
+
|
|
1669
|
+
```bash
|
|
1670
|
+
pstack csp --app=portal --import=apps/portal/src/.htaccess --dry-run # see what would change
|
|
1671
|
+
pstack csp --app=portal --import=apps/portal/src/.htaccess --force # merge, replace the old file
|
|
1672
|
+
pstack csp --app=portal --import=policy.json # { "script-src": [...], ... }
|
|
1673
|
+
pstack csp --app=portal --import="connect-src https://api.example.com; img-src https://cdn.example.com"
|
|
1674
|
+
```
|
|
1675
|
+
|
|
1676
|
+
- Sources: a `Content-Security-Policy` header value (inline or in a file), an Apache `.htaccess`
|
|
1677
|
+
(`Header … Content-Security-Policy "…"`) or Nginx config (`add_header …`; Report-Only headers are
|
|
1678
|
+
not read), or JSON — directive → sources, also under `directives` or `suggestedPolicy.directives`.
|
|
1679
|
+
A file path is read relative to the folder you run the command in.
|
|
1680
|
+
- The import is merged into what is there; existing entries are never removed. Imported sources
|
|
1681
|
+
an entry already allows are not added: duplicates (any case) and paths under a listed host
|
|
1682
|
+
(`https://cdn.example.com/x.js` when `https://cdn.example.com` is listed; `*.example.com` covers
|
|
1683
|
+
its subdomains; a host without a scheme covers `https://` only). A config with several CSP
|
|
1684
|
+
headers is merged with a note (a browser enforces each of them).
|
|
1685
|
+
- The report lists what was added (`+`), already allowed (`=`), refused by the strict policy and
|
|
1686
|
+
not taken by the generated policy, each with the reason. Refused / not taken:
|
|
1687
|
+
`'unsafe-inline'`, `'unsafe-eval'`, bare schemes in script/style-src, `http://` hosts, and
|
|
1688
|
+
directives the generated policy does not take (`script-src-elem`, `style-src-elem` — their hosts
|
|
1689
|
+
are listed so you can add them with `--add` — `object-src`, `default-src`, …). Nonces and hashes
|
|
1690
|
+
are skipped: the server adds the nonce per request.
|
|
1691
|
+
|
|
1692
|
+
**Adding an environment later (v0.34.0).** New apps always start with `dev`, `uat` and `prod`.
|
|
1693
|
+
`pstack env` adds another environment to some apps, or all of them, copied from an existing
|
|
1694
|
+
one:
|
|
1695
|
+
|
|
1696
|
+
```bash
|
|
1697
|
+
pstack env --name=qa --app=portal --api-url=https://qa.example.com/api
|
|
1698
|
+
pstack env --name=sit --app=portal,admin --from=prod --production=false --base-href=/sit/
|
|
1699
|
+
pstack env --name=perf --all
|
|
1700
|
+
```
|
|
1701
|
+
|
|
1702
|
+
For each app it adds:
|
|
1703
|
+
|
|
1704
|
+
- **Angular/Ionic:** `environments/<app>/environment.<env>.ts` copied from the `--from`
|
|
1705
|
+
environment's file (default `uat`, or `prod` for apps without `uat`). `envName` is set to the
|
|
1706
|
+
new env, api urls are replaced with `--api-url`, and `production` is set when
|
|
1707
|
+
`--production` is given. For apps with a release target, secret fields become
|
|
1708
|
+
`${<APP>_<ENV>_<KEY>}` placeholders (for example `${PORTAL_QA_PASSWORD}`), which the release
|
|
1709
|
+
build fills from CI variables or `.env.local` (a missing one fails the build): in `listed`
|
|
1710
|
+
mode the listed keys, in `all` mode the non-public fields that look sensitive (password, token,
|
|
1711
|
+
key, secret…) or already hold a placeholder. URLs and plain settings are copied. Apps without a
|
|
1712
|
+
release target get the values copied (nothing would fill a placeholder), and nested listed keys
|
|
1713
|
+
are copied with a note. The file goes where the release build reads it:
|
|
1714
|
+
`environments/<envProject>/environment.<env>.ts`.
|
|
1715
|
+
- **Angular `build` and `serve` configurations:** the source build configuration (budgets,
|
|
1716
|
+
optimisation, other file replacements) with the env file swapped.
|
|
1717
|
+
- **Release configuration:** the source one (hardening, obfuscation, SRI, base href) with `env`
|
|
1718
|
+
and `buildConfiguration` set. `--base-href` overrides the base href. The domain lock is not
|
|
1719
|
+
copied: pass `--domains`, or set it later with `pstack encryption --domains`.
|
|
1720
|
+
- **Flutter:** `env/<env>.json` copied (env name and api url updated; values are copied as
|
|
1721
|
+
they are — dart-defines have no placeholders), and `build-web`,
|
|
1722
|
+
`build-android` and `build-ios` configurations copied (`--base-href` on `build-web`).
|
|
1723
|
+
- **npm scripts** (`serve:`/`build:<app>:<env>`, Ionic `:android`/`:ios`, Flutter
|
|
1724
|
+
`:web`/`:apk`/`:ios`), and the AI-assistant block is refreshed.
|
|
1725
|
+
|
|
1726
|
+
`--app` or `--all` is required. Everything is checked first; a new env that already exists, or a
|
|
1727
|
+
missing `--from` configuration, stops the command with every problem listed and nothing
|
|
1728
|
+
written.
|
|
1729
|
+
|
|
1730
|
+
**App generator options (v0.35.0).** `pstack app` gives every new app a dev-server port, a `clean`
|
|
1731
|
+
target and, for Angular/Ionic, the shared assets and styles folders:
|
|
1732
|
+
|
|
1733
|
+
```bash
|
|
1734
|
+
pstack app --type=angular --name=admin # next free port from 4200
|
|
1735
|
+
pstack app --type=angular --name=admin --port=4300 # explicit port (1024-65535)
|
|
1736
|
+
pstack app --type=angular --name=admin --env-layout=per-env # environment.dev|uat|prod.ts
|
|
1737
|
+
pstack shared --all # wire the shared folders into existing apps
|
|
1738
|
+
nx run admin:clean # or npm run clean:admin
|
|
1739
|
+
```
|
|
1740
|
+
|
|
1741
|
+
- **Port.** The lowest port from 4200 that no app of the workspace serves on (a serve target
|
|
1742
|
+
without a port counts as 4200), set as `serve.options.port` (Flutter: the `flutter-build`
|
|
1743
|
+
executor's new `port` option, used for `--web-port`). A `--port` another app uses is refused.
|
|
1744
|
+
- **Shared assets and styles.** `libs/shared/assets` and `libs/shared/styles` are created on first
|
|
1745
|
+
use (projects `shared-assets` and `shared-styles`; a workspace that already has `libs/assets` /
|
|
1746
|
+
`libs/styles` uses those, and a `libs/shared` that is itself a library gets `libs/assets` and
|
|
1747
|
+
`libs/styles` instead). New Angular/Ionic apps copy the assets to `assets/shared/`, can
|
|
1748
|
+
`@use 'theme';` (the Sass include path holds the styles folder) and list both projects in
|
|
1749
|
+
`implicitDependencies`. `pstack shared --app=<a,b>|--all` does the same for existing apps.
|
|
1750
|
+
- **`--env-layout=per-env`** (Angular/Ionic): `environments/<app>/environment.{dev,uat,prod}.ts`
|
|
1751
|
+
and a shared `environments/environment.ts` (created when missing) that the app imports; the
|
|
1752
|
+
development, uat and production build configurations replace it with the app's file. The release
|
|
1753
|
+
build reads `environment.dev.ts` for DEV. The default layout is unchanged.
|
|
1754
|
+
- **`clean`** (`@mouryaamit/nx-polystack:clean`) removes `dist/<app root>` and
|
|
1755
|
+
`coverage/<app root>`; Flutter apps also run `flutter clean` (a warning when Flutter is not
|
|
1756
|
+
installed). Only paths below `dist/`, `coverage/` or `tmp/`, or the project's own output
|
|
1757
|
+
folders (`www`, `build`, … under its root), are removed; anything else is refused.
|
|
1758
|
+
- **`pstack update`** (migration `app-clean-and-port`) adds `clean` to apps without one (Angular
|
|
1759
|
+
outputs from the build `outputPath`) and, when several apps serve without a port (all on 4200),
|
|
1760
|
+
keeps 4200 for the first by name and gives the others the next free ports. It does not wire the
|
|
1761
|
+
shared folders.
|
|
1762
|
+
|
|
1763
|
+
**Quality checks (v0.36.0).** Type errors, broken imports and unused imports are caught before
|
|
1764
|
+
review:
|
|
1765
|
+
|
|
1766
|
+
```bash
|
|
1767
|
+
nx run portal:typecheck # tsc --noEmit -p apps/portal/tsconfig.app.json
|
|
1768
|
+
nx affected -t lint typecheck test build # what CI runs
|
|
1769
|
+
pstack infra --with=none --lint-staged=block # make ESLint block commits again (warn: report only)
|
|
1770
|
+
```
|
|
1771
|
+
|
|
1772
|
+
- **`typecheck`** on every app and lib with a `tsconfig.app.json` / `tsconfig.lib.json`
|
|
1773
|
+
(`nx:run-commands`, `tsc --noEmit -p …`), cached through nx.json `targetDefaults`. New
|
|
1774
|
+
Angular/Ionic apps and TypeScript libs get it; `pstack infra --with=quality` adds it to every
|
|
1775
|
+
project without one (for example after `pstack migrate`). CI runs it in the affected step.
|
|
1776
|
+
- **ESLint**: `import/no-unresolved` (resolved through `tsconfig.base.json` paths) and
|
|
1777
|
+
`unused-imports/no-unused-imports`, both warnings, in an override of the root `.eslintrc.json`;
|
|
1778
|
+
packages `eslint-plugin-import`, `eslint-import-resolver-typescript` and
|
|
1779
|
+
`eslint-plugin-unused-imports` (the version that matches the workspace's `@typescript-eslint`).
|
|
1780
|
+
- **lint-staged**: new workspaces run ESLint on commit through
|
|
1781
|
+
`tools/scripts/lint-staged-eslint.js` (the workspace ESLint, no npx), which fixes what it can and
|
|
1782
|
+
reports the rest without
|
|
1783
|
+
blocking the commit (Prettier still formats). `pstack infra --lint-staged=block|warn` switches.
|
|
1784
|
+
- **`pstack update`** (migration `quality-checks`) adds the typecheck targets, the nx.json default,
|
|
1785
|
+
the CI step (when the workflow has the standard `nx affected -t lint test build` line) and the
|
|
1786
|
+
ESLint warnings with their packages. It does not change the commit hook. Run
|
|
1787
|
+
`npx nx run-many -t typecheck` once afterwards: libraries are now type-checked as a whole.
|
|
1788
|
+
|
|
1789
|
+
**Session timeout and PII masking libs (v0.37.0).** Two Angular 15 starter libs, Angular and RxJS
|
|
1790
|
+
only (no third-party packages), buildable by default (`--variant=internal|buildable|publishable`):
|
|
1791
|
+
|
|
1792
|
+
```bash
|
|
1793
|
+
pstack lib --type=session --name=session # @<scope>/shared-session
|
|
1794
|
+
pstack lib --type=pii --name=pii-mask # @<scope>/shared-pii-mask
|
|
1795
|
+
```
|
|
1796
|
+
|
|
1797
|
+
- **`session`**: `SessionTimeoutService` with `start(loginTime?)`, `stop()`, `extend()`, `state$`
|
|
1798
|
+
(`stopped` / `active` / `warning` / `timedOut`), `warning$` (seconds left), `timeout$` (`idle` or
|
|
1799
|
+
`absolute`, once per session) and `stoppedElsewhere$` (another tab signed out);
|
|
1800
|
+
`SessionTimeoutModule.forRoot({ idleMs, warningMs, absoluteMs })` in the root module; a non-modal
|
|
1801
|
+
`<prefix>-session-warning` component (countdown, focus on its first button, screen-reader
|
|
1802
|
+
announcements at thresholds, `[texts]` for other languages). Tabs share activity, timeouts and
|
|
1803
|
+
logouts (BroadcastChannel, localStorage as fallback; the key includes the app's base path, so two
|
|
1804
|
+
apps on one domain stay apart); a tab waking from sleep checks the others' last activity before
|
|
1805
|
+
timing out. Bad start times are refused and unreadable times end the session (fail closed).
|
|
1806
|
+
Timers run outside Angular's zone; nothing runs during server-side rendering. It never signs
|
|
1807
|
+
anyone out or touches tokens: the app does that on `timeout$` and `stoppedElsewhere$`.
|
|
1808
|
+
- **`pii`**: `maskPii(value, format)`, the `piiMask` pipe and the `[<prefix>PiiMask]` directive
|
|
1809
|
+
(writes text, never HTML). Formats: `pan`, `aadhaar`, `mobile`, `email`, `account`, `card`, `ifsc`
|
|
1810
|
+
(shown as it is); custom formats and the mask character through `PiiMaskModule.forRoot(…)`. A
|
|
1811
|
+
value that does not match its format is masked completely, in any script (Devanagari digits,
|
|
1812
|
+
regional-script names); at most half of a value is ever shown. Display only: stored and sent
|
|
1813
|
+
values are unchanged.
|
|
1814
|
+
- The timing (`session-clock.ts`) and masking (`pii-mask.ts`) logic has no Angular imports, so it
|
|
1815
|
+
can be unit-tested directly.
|
|
1816
|
+
|
|
1817
|
+
**Running:**
|
|
1818
|
+
|
|
1819
|
+
```bash
|
|
1820
|
+
npx nx run portal:release:dev
|
|
1821
|
+
npx nx run portal:release:uat
|
|
1822
|
+
npx nx run portal:release:prod
|
|
1823
|
+
```
|
|
1824
|
+
|
|
1825
|
+
---
|
|
1826
|
+
|
|
1827
|
+
### `:capacitor` — Capacitor commands for Ionic apps
|
|
1828
|
+
|
|
1829
|
+
Runs `npx cap <command> <platform>` inside the app folder. If the app's `node_modules` is missing it runs
|
|
1830
|
+
`npm install` there first. `sync` and `copy` check that the web build exists (`dist/apps/<project>`, or `webDir`).
|
|
1831
|
+
|
|
1832
|
+
| Option | Description |
|
|
1833
|
+
| ---------- | ----------------------------------------------------------------------------------- |
|
|
1834
|
+
| `command` | `sync`, `open`, `add` or `copy` (set per target: `cap-sync`, `cap-open`, `cap-add`) |
|
|
1835
|
+
| `platform` | `android` or `ios` — pass as `--platform=android` |
|
|
1836
|
+
| `webDir` | Web build output relative to the workspace root (default `dist/apps/<project>`) |
|
|
1837
|
+
|
|
1838
|
+
```bash
|
|
1839
|
+
npx nx run field-ops:cap-sync --platform=android
|
|
1840
|
+
npx nx run field-ops:cap-open --platform=ios
|
|
1841
|
+
```
|
|
1842
|
+
|
|
1843
|
+
---
|
|
1844
|
+
|
|
1845
|
+
### `:flutter-build` — Flutter build wrapper
|
|
1846
|
+
|
|
1847
|
+
Wraps `flutter build` with `--dart-define-from-file` environment wiring and optional obfuscation.
|
|
1848
|
+
|
|
1849
|
+
```bash
|
|
1850
|
+
npx nx run mobile:flutter-build:web
|
|
1851
|
+
npx nx run mobile:flutter-build:apk
|
|
1852
|
+
npx nx run mobile:flutter-build:ios
|
|
1853
|
+
```
|
|
1854
|
+
|
|
1855
|
+
---
|
|
1856
|
+
|
|
1857
|
+
### `:flutter-export` — FlutterFlow export
|
|
1858
|
+
|
|
1859
|
+
Exports a FlutterFlow project into the local `apps/<name>/` directory using the FlutterFlow CLI.
|
|
1860
|
+
|
|
1861
|
+
```bash
|
|
1862
|
+
npx nx run mobile:flutter-export
|
|
1863
|
+
```
|
|
1864
|
+
|
|
1865
|
+
---
|
|
1866
|
+
|
|
1867
|
+
## 8. Helper modules
|
|
1868
|
+
|
|
1869
|
+
Import helpers directly from the package in your own scripts or tools:
|
|
1870
|
+
|
|
1871
|
+
```typescript
|
|
1872
|
+
import {
|
|
1873
|
+
resolveCiContext,
|
|
1874
|
+
encryptEnvFile,
|
|
1875
|
+
injectBuildMeta,
|
|
1876
|
+
injectCspNonce,
|
|
1877
|
+
injectSri,
|
|
1878
|
+
stripExif,
|
|
1879
|
+
addNpmScripts,
|
|
1880
|
+
addTsPath,
|
|
1881
|
+
generateAngularEnvFiles,
|
|
1882
|
+
mergeNxTargets,
|
|
1883
|
+
backupAndOverwrite,
|
|
1884
|
+
} from '@mouryaamit/nx-polystack';
|
|
1885
|
+
```
|
|
1886
|
+
|
|
1887
|
+
| Helper | Description |
|
|
1888
|
+
| ---------------------------------------- | ------------------------------------------------------------------------ |
|
|
1889
|
+
| `resolveCiContext()` | Resolves branch, commit SHA, and build number from CI env vars or git |
|
|
1890
|
+
| `encryptEnvFile(file, keys)` | AES-encrypts named keys in an environment TypeScript file |
|
|
1891
|
+
| `injectBuildMeta(distDir, ctx)` | Injects `<meta name="x-build">` into `dist/index.html` |
|
|
1892
|
+
| `injectCspNonce(distDir)` | Replaces nonce placeholders with SSI variables for Apache/Nginx |
|
|
1893
|
+
| `injectSri(distDir, allowlist)` | Adds `integrity=` + `crossorigin=` to local `<script>` and `<link>` tags |
|
|
1894
|
+
| `stripExif(dir)` | Recursively strips EXIF/IPTC/XMP metadata from images |
|
|
1895
|
+
| `addNpmScripts(tree, scripts)` | Adds entries to root `package.json` scripts (Nx Tree mutator) |
|
|
1896
|
+
| `addTsPath(tree, alias, path)` | Adds a path alias to `tsconfig.base.json` (Nx Tree mutator) |
|
|
1897
|
+
| `generateAngularEnvFiles(tree, name)` | Creates `environments/<name>/environment*.ts` stubs |
|
|
1898
|
+
| `mergeNxTargets(tree, project, targets)` | Merges targets into a project's `project.json` |
|
|
1899
|
+
| `backupAndOverwrite(src, dest)` | Creates a `.bak` copy of a file then overwrites it |
|
|
1900
|
+
|
|
1901
|
+
---
|
|
1902
|
+
|
|
1903
|
+
## 9. Release packaging
|
|
1904
|
+
|
|
1905
|
+
Releases are published to npm from this repository's `Publish` workflow when a `vX.Y.Z` tag is pushed.
|
|
1906
|
+
|
|
1907
|
+
---
|
|
1908
|
+
|
|
1909
|
+
## 10. Troubleshooting
|
|
1910
|
+
|
|
1911
|
+
### `pstack: command not found` after global install
|
|
1912
|
+
|
|
1913
|
+
Check that the npm global bin directory is in your `PATH`:
|
|
1914
|
+
|
|
1915
|
+
```bash
|
|
1916
|
+
npm config get prefix # e.g. /usr/local
|
|
1917
|
+
# Ensure /usr/local/bin is in PATH
|
|
1918
|
+
```
|
|
1919
|
+
|
|
1920
|
+
### `Error: no nx.json found in the current directory`
|
|
1921
|
+
|
|
1922
|
+
The `pstack app` command must be run from the root of an existing Nx workspace. Run `pstack preset` first
|
|
1923
|
+
if you are starting from scratch.
|
|
1924
|
+
|
|
1925
|
+
### Generator changes nothing (`Nothing to generate.`)
|
|
1926
|
+
|
|
1927
|
+
The target project path may already exist. Pass `--force` via Nx:
|
|
1928
|
+
|
|
1929
|
+
```bash
|
|
1930
|
+
npx nx g @mouryaamit/nx-polystack:app --type=angular --name=portal --force
|
|
1931
|
+
```
|
|
1932
|
+
|
|
1933
|
+
The `pstack` CLI does not support `--force` directly — use the Nx generator form for this.
|
|
1934
|
+
|
|
1935
|
+
### `Error: env is required` from the `:build` executor
|
|
1936
|
+
|
|
1937
|
+
The `:build` executor expects `env` to be set via an Nx configuration, not as a top-level option.
|
|
1938
|
+
Ensure your `project.json` has `configurations` with `"env": "DEV|UAT|PROD"`:
|
|
1939
|
+
|
|
1940
|
+
```jsonc
|
|
1941
|
+
"configurations": {
|
|
1942
|
+
"dev": { "env": "DEV" }
|
|
1943
|
+
}
|
|
1944
|
+
```
|
|
1945
|
+
|
|
1946
|
+
Then run with: `npx nx run <project>:build:dev`
|
|
1947
|
+
|
|
1948
|
+
### Shebang missing on `bin/cli.js`
|
|
1949
|
+
|
|
1950
|
+
Re-run `npm run build`. The build script automatically adds `#!/usr/bin/env node`
|
|
1951
|
+
if it was stripped by the TypeScript compiler.
|
|
1952
|
+
|
|
1953
|
+
### Version mismatch between `pstack --version` and installed package
|
|
1954
|
+
|
|
1955
|
+
`pstack --version` reads the `version` field from the bundled `package.json` at runtime. If the
|
|
1956
|
+
version shown differs from what was installed, you may have a stale global install:
|
|
1957
|
+
|
|
1958
|
+
```bash
|
|
1959
|
+
npm i -g @mouryaamit/nx-polystack@latest
|
|
1960
|
+
```
|
|
1961
|
+
|
|
1962
|
+
Inside a workspace whose local plugin version differs from the global CLI, `pstack -v` prints the global
|
|
1963
|
+
version followed by `workspace plugin: X`.
|
|
1964
|
+
|
|
1965
|
+
---
|
|
1966
|
+
|
|
1967
|
+
_See also:_
|
|
1968
|
+
_`README.md` — quick-start and plugin architecture_
|