@julianoczkowski/create-trimble-app 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -0
- package/bin/create-trimble-app.js +9 -0
- package/package.json +67 -0
- package/src/cli.js +134 -0
- package/src/frameworks.js +28 -0
- package/src/scaffold.js +209 -0
- package/src/utils/file.js +47 -0
- package/src/utils/git.js +140 -0
- package/src/utils/install.js +25 -0
- package/src/utils/logger.js +124 -0
- package/templates/angular/.cursor/commands/remove-dev-content.md +394 -0
- package/templates/angular/.cursor/mcp.json +13 -0
- package/templates/angular/.cursor/rules/modus-angular-20.mdc +82 -0
- package/templates/angular/.cursor/rules/modus-angular-accordion-state-management-short.mdc +45 -0
- package/templates/angular/.cursor/rules/modus-angular-accordion-state-management.mdc +322 -0
- package/templates/angular/.cursor/rules/modus-angular-best-practices.mdc +472 -0
- package/templates/angular/.cursor/rules/modus-angular-border-usage-short.mdc +48 -0
- package/templates/angular/.cursor/rules/modus-angular-border-usage.mdc +286 -0
- package/templates/angular/.cursor/rules/modus-angular-button-group-usage-short.mdc +47 -0
- package/templates/angular/.cursor/rules/modus-angular-button-group-usage.mdc +263 -0
- package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-checkbox-value-inversion.mdc +92 -0
- package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing-short.mdc +34 -0
- package/templates/angular/.cursor/rules/modus-angular-chrome-devtools-testing.mdc +185 -0
- package/templates/angular/.cursor/rules/modus-angular-color-usage-short.mdc +56 -0
- package/templates/angular/.cursor/rules/modus-angular-color-usage.mdc +208 -0
- package/templates/angular/.cursor/rules/modus-angular-components-reference.mdc +114 -0
- package/templates/angular/.cursor/rules/modus-angular-design-system.mdc +273 -0
- package/templates/angular/.cursor/rules/modus-angular-development-workflow-short.mdc +43 -0
- package/templates/angular/.cursor/rules/modus-angular-development-workflow.mdc +145 -0
- package/templates/angular/.cursor/rules/modus-angular-essentials.mdc +272 -0
- package/templates/angular/.cursor/rules/modus-angular-forms-validation-short.mdc +56 -0
- package/templates/angular/.cursor/rules/modus-angular-forms-validation.mdc +124 -0
- package/templates/angular/.cursor/rules/modus-angular-icon-names.mdc +70 -0
- package/templates/angular/.cursor/rules/modus-angular-icons-short.mdc +40 -0
- package/templates/angular/.cursor/rules/modus-angular-icons.mdc +137 -0
- package/templates/angular/.cursor/rules/modus-angular-implementation-guides-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-implementation-guides.mdc +301 -0
- package/templates/angular/.cursor/rules/modus-angular-integration-short.mdc +60 -0
- package/templates/angular/.cursor/rules/modus-angular-integration.mdc +1096 -0
- package/templates/angular/.cursor/rules/modus-angular-master.mdc +164 -0
- package/templates/angular/.cursor/rules/modus-angular-modal-usage-short.mdc +51 -0
- package/templates/angular/.cursor/rules/modus-angular-modal-usage.mdc +115 -0
- package/templates/angular/.cursor/rules/modus-angular-navbar-usage-short.mdc +49 -0
- package/templates/angular/.cursor/rules/modus-angular-navbar-usage.mdc +146 -0
- package/templates/angular/.cursor/rules/modus-angular-no-emojis.mdc +66 -0
- package/templates/angular/.cursor/rules/modus-angular-opacity-utilities-short.mdc +43 -0
- package/templates/angular/.cursor/rules/modus-angular-opacity-utilities.mdc +160 -0
- package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu-short.mdc +51 -0
- package/templates/angular/.cursor/rules/modus-angular-select-vs-dropdown-menu.mdc +83 -0
- package/templates/angular/.cursor/rules/modus-angular-semantic-html-short.mdc +36 -0
- package/templates/angular/.cursor/rules/modus-angular-semantic-html.mdc +81 -0
- package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage-short.mdc +50 -0
- package/templates/angular/.cursor/rules/modus-angular-side-navigation-usage.mdc +136 -0
- package/templates/angular/.cursor/rules/modus-angular-table-usage-short.mdc +52 -0
- package/templates/angular/.cursor/rules/modus-angular-table-usage.mdc +151 -0
- package/templates/angular/.cursor/rules/modus-angular-tailwind-usage-short.mdc +44 -0
- package/templates/angular/.cursor/rules/modus-angular-tailwind-usage.mdc +242 -0
- package/templates/angular/.cursor/rules/modus-angular-themes-short.mdc +54 -0
- package/templates/angular/.cursor/rules/modus-angular-themes.mdc +222 -0
- package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage-short.mdc +52 -0
- package/templates/angular/.cursor/rules/modus-angular-utility-panel-usage.mdc +130 -0
- package/templates/angular/.cursor/rules/ux/gestalt-laws-detailed.mdc +514 -0
- package/templates/angular/.cursor/rules/ux/ux-ui-foundations.mdc +235 -0
- package/templates/angular/.cursor/skills/run-lint-checks/SKILL.md +169 -0
- package/templates/angular/.editorconfig +17 -0
- package/templates/angular/.github/dependabot.yml +19 -0
- package/templates/angular/.github/workflows/a11y-check.yml +135 -0
- package/templates/angular/.github/workflows/ci.yml +44 -0
- package/templates/angular/.husky/pre-commit +32 -0
- package/templates/angular/.postcssrc.json +5 -0
- package/templates/angular/.vscode/extensions.json +4 -0
- package/templates/angular/.vscode/launch.json +20 -0
- package/templates/angular/.vscode/tasks.json +42 -0
- package/templates/angular/CLAUDE.md +148 -0
- package/templates/angular/README.md +92 -0
- package/templates/angular/amplify.yml +25 -0
- package/templates/angular/angular.json +106 -0
- package/templates/angular/data/modusIcons.ts +861 -0
- package/templates/angular/package-lock.json +11030 -0
- package/templates/angular/package.json +66 -0
- package/templates/angular/public/angular-icon.svg +12 -0
- package/templates/angular/public/favicon.ico +0 -0
- package/templates/angular/public/modus-icons.css +49 -0
- package/templates/angular/public/vite.svg +1 -0
- package/templates/angular/scripts/README.md +410 -0
- package/templates/angular/scripts/check-border-violations.js +352 -0
- package/templates/angular/scripts/check-icon-names.js +402 -0
- package/templates/angular/scripts/check-inline-styles.js +292 -0
- package/templates/angular/scripts/check-modus-colors.js +282 -0
- package/templates/angular/scripts/check-modus-icons.js +263 -0
- package/templates/angular/scripts/check-opacity-utilities.js +426 -0
- package/templates/angular/scripts/check-semantic-html.js +452 -0
- package/templates/angular/scripts/check-typescript.js +109 -0
- package/templates/angular/src/app/app.config.ts +29 -0
- package/templates/angular/src/app/app.css +0 -0
- package/templates/angular/src/app/app.html +4 -0
- package/templates/angular/src/app/app.routes.ts +351 -0
- package/templates/angular/src/app/app.spec.ts +27 -0
- package/templates/angular/src/app/app.ts +47 -0
- package/templates/angular/src/app/components/README.md +77 -0
- package/templates/angular/src/app/components/index.ts +53 -0
- package/templates/angular/src/app/components/modus-accordion.component.ts +50 -0
- package/templates/angular/src/app/components/modus-alert.component.ts +133 -0
- package/templates/angular/src/app/components/modus-autocomplete.component.ts +262 -0
- package/templates/angular/src/app/components/modus-avatar.component.ts +75 -0
- package/templates/angular/src/app/components/modus-badge.component.ts +84 -0
- package/templates/angular/src/app/components/modus-breadcrumbs.component.ts +65 -0
- package/templates/angular/src/app/components/modus-button-group.component.ts +82 -0
- package/templates/angular/src/app/components/modus-button.component.ts +292 -0
- package/templates/angular/src/app/components/modus-card.component.ts +73 -0
- package/templates/angular/src/app/components/modus-checkbox.component.ts +117 -0
- package/templates/angular/src/app/components/modus-chip.component.ts +97 -0
- package/templates/angular/src/app/components/modus-collapse.component.ts +118 -0
- package/templates/angular/src/app/components/modus-date.component.ts +165 -0
- package/templates/angular/src/app/components/modus-dropdown-menu.component.ts +108 -0
- package/templates/angular/src/app/components/modus-file-dropzone.component.ts +121 -0
- package/templates/angular/src/app/components/modus-handle.component.ts +96 -0
- package/templates/angular/src/app/components/modus-icon.component.ts +81 -0
- package/templates/angular/src/app/components/modus-input-feedback.component.ts +54 -0
- package/templates/angular/src/app/components/modus-input-label.component.ts +62 -0
- package/templates/angular/src/app/components/modus-loader.component.ts +48 -0
- package/templates/angular/src/app/components/modus-logo.component.ts +115 -0
- package/templates/angular/src/app/components/modus-menu-item.component.ts +116 -0
- package/templates/angular/src/app/components/modus-menu.component.ts +58 -0
- package/templates/angular/src/app/components/modus-modal.component.ts +70 -0
- package/templates/angular/src/app/components/modus-navbar.component.ts +303 -0
- package/templates/angular/src/app/components/modus-number-input.component.ts +174 -0
- package/templates/angular/src/app/components/modus-pagination.component.ts +74 -0
- package/templates/angular/src/app/components/modus-panel.component.ts +61 -0
- package/templates/angular/src/app/components/modus-progress.component.ts +62 -0
- package/templates/angular/src/app/components/modus-radio.component.ts +102 -0
- package/templates/angular/src/app/components/modus-rating.component.ts +80 -0
- package/templates/angular/src/app/components/modus-select.component.ts +131 -0
- package/templates/angular/src/app/components/modus-side-navigation.component.ts +90 -0
- package/templates/angular/src/app/components/modus-skeleton.component.ts +54 -0
- package/templates/angular/src/app/components/modus-slider.component.ts +132 -0
- package/templates/angular/src/app/components/modus-stepper.component.ts +65 -0
- package/templates/angular/src/app/components/modus-switch.component.ts +118 -0
- package/templates/angular/src/app/components/modus-table.component.ts +204 -0
- package/templates/angular/src/app/components/modus-tabs.component.ts +82 -0
- package/templates/angular/src/app/components/modus-text-input.component.ts +221 -0
- package/templates/angular/src/app/components/modus-textarea.component.ts +168 -0
- package/templates/angular/src/app/components/modus-theme-switcher.component.ts +45 -0
- package/templates/angular/src/app/components/modus-time-input.component.ts +172 -0
- package/templates/angular/src/app/components/modus-toast.component.ts +63 -0
- package/templates/angular/src/app/components/modus-toolbar.component.ts +43 -0
- package/templates/angular/src/app/components/modus-tooltip.component.ts +83 -0
- package/templates/angular/src/app/components/modus-typography.component.ts +79 -0
- package/templates/angular/src/app/components/modus-utility-panel.component.ts +275 -0
- package/templates/angular/src/app/components/theme-demo.component.ts +1242 -0
- package/templates/angular/src/app/data/component-demos.ts +360 -0
- package/templates/angular/src/app/data/modus-icons.ts +806 -0
- package/templates/angular/src/app/demos/accordion/accordion-demo.component.ts +212 -0
- package/templates/angular/src/app/demos/alert/alert-demo.component.ts +108 -0
- package/templates/angular/src/app/demos/autocomplete/autocomplete-demo.component.ts +174 -0
- package/templates/angular/src/app/demos/avatar/avatar-demo.component.ts +149 -0
- package/templates/angular/src/app/demos/badge/badge-demo.component.ts +148 -0
- package/templates/angular/src/app/demos/breadcrumbs/breadcrumbs-demo.component.ts +96 -0
- package/templates/angular/src/app/demos/button/button-demo.component.ts +256 -0
- package/templates/angular/src/app/demos/button-group/button-group-demo.component.ts +215 -0
- package/templates/angular/src/app/demos/card/card-demo.component.ts +180 -0
- package/templates/angular/src/app/demos/checkbox/checkbox-demo.component.ts +71 -0
- package/templates/angular/src/app/demos/chip/chip-demo.component.ts +183 -0
- package/templates/angular/src/app/demos/date/date-demo.component.ts +193 -0
- package/templates/angular/src/app/demos/dropdown/dropdown-demo.component.ts +196 -0
- package/templates/angular/src/app/demos/file-dropzone/file-dropzone-demo.component.ts +176 -0
- package/templates/angular/src/app/demos/handle/handle-demo.component.ts +265 -0
- package/templates/angular/src/app/demos/icon/icon-demo.component.ts +65 -0
- package/templates/angular/src/app/demos/input-feedback/input-feedback-demo.component.ts +189 -0
- package/templates/angular/src/app/demos/input-label/input-label-demo.component.ts +330 -0
- package/templates/angular/src/app/demos/loader/loader-demo.component.ts +143 -0
- package/templates/angular/src/app/demos/logo/logo-demo.component.ts +191 -0
- package/templates/angular/src/app/demos/menu/menu-demo.component.ts +72 -0
- package/templates/angular/src/app/demos/modal/modal-demo.component.ts +278 -0
- package/templates/angular/src/app/demos/navbar/navbar-demo.component.ts +135 -0
- package/templates/angular/src/app/demos/number-input/number-input-demo.component.ts +175 -0
- package/templates/angular/src/app/demos/pagination/pagination-demo.component.ts +134 -0
- package/templates/angular/src/app/demos/panel/panel-demo.component.ts +235 -0
- package/templates/angular/src/app/demos/progress/progress-demo.component.ts +169 -0
- package/templates/angular/src/app/demos/radio/radio-demo.component.ts +161 -0
- package/templates/angular/src/app/demos/rating/rating-demo.component.ts +97 -0
- package/templates/angular/src/app/demos/select/select-demo.component.ts +107 -0
- package/templates/angular/src/app/demos/shared/demo-example-clean.component.ts +41 -0
- package/templates/angular/src/app/demos/shared/demo-example.component.ts +42 -0
- package/templates/angular/src/app/demos/shared/demo-page.component.ts +97 -0
- package/templates/angular/src/app/demos/shared/index.ts +3 -0
- package/templates/angular/src/app/demos/side-navigation/side-navigation-demo.component.ts +524 -0
- package/templates/angular/src/app/demos/skeleton/skeleton-demo.component.ts +112 -0
- package/templates/angular/src/app/demos/slider/slider-demo.component.ts +76 -0
- package/templates/angular/src/app/demos/stepper/stepper-demo.component.ts +79 -0
- package/templates/angular/src/app/demos/switch/switch-demo.component.ts +113 -0
- package/templates/angular/src/app/demos/table/table-demo.component.ts +405 -0
- package/templates/angular/src/app/demos/tabs/tabs-demo.component.ts +318 -0
- package/templates/angular/src/app/demos/text-input/text-input-demo.component.ts +160 -0
- package/templates/angular/src/app/demos/textarea/textarea-demo.component.ts +95 -0
- package/templates/angular/src/app/demos/theme-switcher/theme-switcher-demo.component.ts +38 -0
- package/templates/angular/src/app/demos/time-input/time-input-demo.component.ts +130 -0
- package/templates/angular/src/app/demos/toast/toast-demo.component.ts +258 -0
- package/templates/angular/src/app/demos/toolbar/toolbar-demo.component.ts +54 -0
- package/templates/angular/src/app/demos/tooltip/tooltip-demo.component.ts +163 -0
- package/templates/angular/src/app/demos/utility-panel/utility-panel-demo.component.ts +197 -0
- package/templates/angular/src/app/dev/dev-config.ts +119 -0
- package/templates/angular/src/app/dev/dev-panel/dev-panel.component.ts +215 -0
- package/templates/angular/src/app/dev/dev-panel.service.ts +63 -0
- package/templates/angular/src/app/dev/index.ts +8 -0
- package/templates/angular/src/app/dev/theme-switcher-dropdown/theme-switcher-dropdown.component.ts +134 -0
- package/templates/angular/src/app/dev-pages/color-palette/color-palette.component.ts +229 -0
- package/templates/angular/src/app/dev-pages/components-gallery/components-gallery.component.ts +486 -0
- package/templates/angular/src/app/dev-pages/icons/icons.component.ts +149 -0
- package/templates/angular/src/app/pages/home/home.component.ts +251 -0
- package/templates/angular/src/app/services/README.md +57 -0
- package/templates/angular/src/app/services/theme.service.ts +163 -0
- package/templates/angular/src/environments/environment.development.ts +8 -0
- package/templates/angular/src/environments/environment.ts +8 -0
- package/templates/angular/src/index.html +14 -0
- package/templates/angular/src/main.ts +6 -0
- package/templates/angular/src/styles.css +1328 -0
- package/templates/angular/tsconfig.app.json +15 -0
- package/templates/angular/tsconfig.json +35 -0
- package/templates/angular/tsconfig.spec.json +14 -0
- package/templates/config.json +23 -0
- package/templates/react/.cursor/commands/remove-dev-content.md +311 -0
- package/templates/react/.cursor/mcp.json +13 -0
- package/templates/react/.cursor/rules/README.md +240 -0
- package/templates/react/.cursor/rules/border-usage-guidelines-short.mdc +22 -0
- package/templates/react/.cursor/rules/border-usage-guidelines.mdc +380 -0
- package/templates/react/.cursor/rules/chrome-devtools-testing-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/development-workflow-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/development-workflow-react.mdc +292 -0
- package/templates/react/.cursor/rules/implementation-guides-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/implementation-guides-react.mdc +446 -0
- package/templates/react/.cursor/rules/modus-accordion-state-management-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-accordion-state-management-react.mdc +445 -0
- package/templates/react/.cursor/rules/modus-button-group-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-button-group-usage-react.mdc +117 -0
- package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-checkbox-value-inversion-react.mdc +492 -0
- package/templates/react/.cursor/rules/modus-color-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-color-usage-react.mdc +420 -0
- package/templates/react/.cursor/rules/modus-components-reference.mdc +366 -0
- package/templates/react/.cursor/rules/modus-icon-names.mdc +63 -0
- package/templates/react/.cursor/rules/modus-icons-react-short.mdc +24 -0
- package/templates/react/.cursor/rules/modus-icons-react.mdc +402 -0
- package/templates/react/.cursor/rules/modus-modal-implementation-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-modal-implementation-react.mdc +831 -0
- package/templates/react/.cursor/rules/modus-navbar-side-navigation-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-navbar-side-navigation-react.mdc +247 -0
- package/templates/react/.cursor/rules/modus-no-emojis-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-opacity-utilities-react-short.mdc +70 -0
- package/templates/react/.cursor/rules/modus-opacity-utilities-react.mdc +208 -0
- package/templates/react/.cursor/rules/modus-react-best-practices-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-best-practices.mdc +508 -0
- package/templates/react/.cursor/rules/modus-react-essentials.mdc +209 -0
- package/templates/react/.cursor/rules/modus-react-integration-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-integration.mdc +509 -0
- package/templates/react/.cursor/rules/modus-react-key-warnings-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-react-key-warnings.mdc +805 -0
- package/templates/react/.cursor/rules/modus-react-master.mdc +160 -0
- package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-select-vs-dropdown-menu-react.mdc +442 -0
- package/templates/react/.cursor/rules/modus-semantic-html-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-semantic-html-react.mdc +427 -0
- package/templates/react/.cursor/rules/modus-tailwind-usage-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-tailwind-usage-react.mdc +642 -0
- package/templates/react/.cursor/rules/modus-themes-react-short.mdc +23 -0
- package/templates/react/.cursor/rules/modus-themes-react.mdc +506 -0
- package/templates/react/.cursor/rules/ux/gestalt-laws-detailed.mdc +456 -0
- package/templates/react/.cursor/rules/ux/ux-ui-foundations.mdc +211 -0
- package/templates/react/.cursor/skills/create-modus-form-component/SKILL.md +518 -0
- package/templates/react/.cursor/skills/create-modus-wrapper-component/SKILL.md +252 -0
- package/templates/react/.cursor/skills/fix-modus-component-event-issues/SKILL.md +345 -0
- package/templates/react/.cursor/skills/handle-modus-checkbox-value-bug/SKILL.md +202 -0
- package/templates/react/.cursor/skills/implement-modus-modal-with-refs/SKILL.md +386 -0
- package/templates/react/.cursor/skills/integrate-modus-icons/SKILL.md +300 -0
- package/templates/react/.cursor/skills/run-lint-checks/SKILL.md +235 -0
- package/templates/react/.cursor/skills/set-up-modus-event-listeners/SKILL.md +284 -0
- package/templates/react/.cursor/skills/style-modus-components-with-tailwind/SKILL.md +382 -0
- package/templates/react/.env.development +3 -0
- package/templates/react/.env.production +3 -0
- package/templates/react/.github/CODEOWNERS +28 -0
- package/templates/react/.github/ISSUE_TEMPLATE/bug_report.yml +176 -0
- package/templates/react/.github/ISSUE_TEMPLATE/config.yml +20 -0
- package/templates/react/.github/ISSUE_TEMPLATE/documentation.yml +115 -0
- package/templates/react/.github/ISSUE_TEMPLATE/feature_request.yml +171 -0
- package/templates/react/.github/ISSUE_TEMPLATE/question.yml +139 -0
- package/templates/react/.github/copilot-instructions.md +80 -0
- package/templates/react/.github/instructions/components.instructions.md +82 -0
- package/templates/react/.github/instructions/demos.instructions.md +82 -0
- package/templates/react/.github/instructions/pages.instructions.md +76 -0
- package/templates/react/.github/instructions/styles.instructions.md +77 -0
- package/templates/react/.github/instructions/typescript.instructions.md +101 -0
- package/templates/react/.github/pull_request_template.md +188 -0
- package/templates/react/.github/workflows/ci.yml +43 -0
- package/templates/react/.github/workflows/claude-code-review.yml +44 -0
- package/templates/react/.github/workflows/claude.yml +50 -0
- package/templates/react/.husky/pre-commit +28 -0
- package/templates/react/.vscode/extensions.json +8 -0
- package/templates/react/CLAUDE.md +119 -0
- package/templates/react/CODE_OF_CONDUCT.md +79 -0
- package/templates/react/CONTRIBUTING.md +65 -0
- package/templates/react/LICENSE +21 -0
- package/templates/react/README.md +728 -0
- package/templates/react/SECURITY.md +50 -0
- package/templates/react/eslint.config.js +23 -0
- package/templates/react/index.html +13 -0
- package/templates/react/package-lock.json +5209 -0
- package/templates/react/package.json +49 -0
- package/templates/react/postcss.config.js +6 -0
- package/templates/react/public/react.svg +1 -0
- package/templates/react/public/vite.svg +1 -0
- package/templates/react/readme_assets/getting_started_header.png +0 -0
- package/templates/react/readme_assets/hero.png +0 -0
- package/templates/react/readme_assets/modus_comp.png +0 -0
- package/templates/react/readme_assets/modus_figma_mcp.png +0 -0
- package/templates/react/readme_assets/teaser_comp.gif +0 -0
- package/templates/react/scripts/README.md +343 -0
- package/templates/react/scripts/check-border-violations.js +483 -0
- package/templates/react/scripts/check-icon-names.js +486 -0
- package/templates/react/scripts/check-inline-styles.js +364 -0
- package/templates/react/scripts/check-modus-colors.js +247 -0
- package/templates/react/scripts/check-modus-icons.js +256 -0
- package/templates/react/scripts/check-opacity-utilities.js +481 -0
- package/templates/react/scripts/check-semantic-html.js +476 -0
- package/templates/react/scripts/check-typescript.js +109 -0
- package/templates/react/src/App.css +42 -0
- package/templates/react/src/App.tsx +54 -0
- package/templates/react/src/assets/react.svg +1 -0
- package/templates/react/src/components/DemoExample.tsx +61 -0
- package/templates/react/src/components/DemoPage.tsx +81 -0
- package/templates/react/src/components/ModusAccordion.tsx +89 -0
- package/templates/react/src/components/ModusAlert.tsx +85 -0
- package/templates/react/src/components/ModusAutocomplete.tsx +207 -0
- package/templates/react/src/components/ModusAvatar.tsx +50 -0
- package/templates/react/src/components/ModusBadge.tsx +82 -0
- package/templates/react/src/components/ModusBreadcrumbs.tsx +75 -0
- package/templates/react/src/components/ModusButton.tsx +244 -0
- package/templates/react/src/components/ModusButtonGroup.tsx +91 -0
- package/templates/react/src/components/ModusCard.tsx +70 -0
- package/templates/react/src/components/ModusCheckbox.tsx +168 -0
- package/templates/react/src/components/ModusChip.tsx +93 -0
- package/templates/react/src/components/ModusDate.tsx +154 -0
- package/templates/react/src/components/ModusDropdownMenu.tsx +148 -0
- package/templates/react/src/components/ModusFileDropzone.tsx +140 -0
- package/templates/react/src/components/ModusHandle.tsx +101 -0
- package/templates/react/src/components/ModusIcon.tsx +49 -0
- package/templates/react/src/components/ModusInputFeedback.tsx +52 -0
- package/templates/react/src/components/ModusInputLabel.tsx +50 -0
- package/templates/react/src/components/ModusLoader.tsx +42 -0
- package/templates/react/src/components/ModusLogo.tsx +102 -0
- package/templates/react/src/components/ModusMenu.tsx +119 -0
- package/templates/react/src/components/ModusMenuItem.tsx +86 -0
- package/templates/react/src/components/ModusModal.tsx +145 -0
- package/templates/react/src/components/ModusNavbar.tsx +504 -0
- package/templates/react/src/components/ModusNumberInput.tsx +230 -0
- package/templates/react/src/components/ModusPagination.tsx +94 -0
- package/templates/react/src/components/ModusPanel.tsx +92 -0
- package/templates/react/src/components/ModusProgress.tsx +70 -0
- package/templates/react/src/components/ModusProvider.tsx +18 -0
- package/templates/react/src/components/ModusRadio.tsx +114 -0
- package/templates/react/src/components/ModusRating.tsx +108 -0
- package/templates/react/src/components/ModusSelect.tsx +171 -0
- package/templates/react/src/components/ModusSideNavigation.tsx +149 -0
- package/templates/react/src/components/ModusSkeleton.tsx +42 -0
- package/templates/react/src/components/ModusSlider.tsx +128 -0
- package/templates/react/src/components/ModusStepper.tsx +85 -0
- package/templates/react/src/components/ModusSwitch.tsx +130 -0
- package/templates/react/src/components/ModusTable.tsx +309 -0
- package/templates/react/src/components/ModusTabs.tsx +114 -0
- package/templates/react/src/components/ModusTextInput.tsx +179 -0
- package/templates/react/src/components/ModusTextarea.tsx +164 -0
- package/templates/react/src/components/ModusThemeSwitcher.tsx +58 -0
- package/templates/react/src/components/ModusTimeInput.tsx +176 -0
- package/templates/react/src/components/ModusToast.tsx +207 -0
- package/templates/react/src/components/ModusToolbar.tsx +70 -0
- package/templates/react/src/components/ModusTooltip.tsx +97 -0
- package/templates/react/src/components/ModusUtilityPanel.tsx +198 -0
- package/templates/react/src/components/ThemeSwitcherDropdown.tsx +117 -0
- package/templates/react/src/components/ThemeToggleSimple.tsx +157 -0
- package/templates/react/src/config/routes.ts +196 -0
- package/templates/react/src/contexts/ThemeContext.tsx +81 -0
- package/templates/react/src/contexts/ThemeContextData.tsx +89 -0
- package/templates/react/src/data/modusIcons.ts +865 -0
- package/templates/react/src/demos/accordion-demo/page.tsx +236 -0
- package/templates/react/src/demos/alert-demo/page.tsx +94 -0
- package/templates/react/src/demos/autocomplete-demo/page.tsx +166 -0
- package/templates/react/src/demos/avatar-demo/page.tsx +135 -0
- package/templates/react/src/demos/badge-demo/page.tsx +174 -0
- package/templates/react/src/demos/breadcrumbs-demo/page.tsx +88 -0
- package/templates/react/src/demos/button-demo/page.tsx +261 -0
- package/templates/react/src/demos/button-group-demo/page.tsx +231 -0
- package/templates/react/src/demos/card-demo/page.tsx +241 -0
- package/templates/react/src/demos/checkbox-demo/page.tsx +79 -0
- package/templates/react/src/demos/chip-demo/page.tsx +197 -0
- package/templates/react/src/demos/date-demo/page.tsx +179 -0
- package/templates/react/src/demos/dropdown-demo/page.tsx +150 -0
- package/templates/react/src/demos/file-dropzone-demo/page.tsx +186 -0
- package/templates/react/src/demos/handle-demo/page.tsx +313 -0
- package/templates/react/src/demos/icon-demo/page.tsx +72 -0
- package/templates/react/src/demos/input-feedback-demo/page.tsx +202 -0
- package/templates/react/src/demos/input-label-demo/page.tsx +392 -0
- package/templates/react/src/demos/loader-demo/page.tsx +138 -0
- package/templates/react/src/demos/logo-demo/page.tsx +292 -0
- package/templates/react/src/demos/menu-demo/page.tsx +70 -0
- package/templates/react/src/demos/modal-demo/page.tsx +332 -0
- package/templates/react/src/demos/navbar-demo/page.tsx +141 -0
- package/templates/react/src/demos/number-input-demo/page.tsx +180 -0
- package/templates/react/src/demos/pagination-demo/page.tsx +147 -0
- package/templates/react/src/demos/panel-demo/page.tsx +376 -0
- package/templates/react/src/demos/progress-demo/page.tsx +185 -0
- package/templates/react/src/demos/radio-demo/page.tsx +242 -0
- package/templates/react/src/demos/rating-demo/page.tsx +97 -0
- package/templates/react/src/demos/select-demo/page.tsx +111 -0
- package/templates/react/src/demos/side-navigation-demo/page.tsx +775 -0
- package/templates/react/src/demos/skeleton-demo/page.tsx +107 -0
- package/templates/react/src/demos/slider-demo/page.tsx +78 -0
- package/templates/react/src/demos/stepper-demo/page.tsx +86 -0
- package/templates/react/src/demos/switch-demo/page.tsx +146 -0
- package/templates/react/src/demos/table-demo/page.tsx +489 -0
- package/templates/react/src/demos/tabs-demo/page.tsx +187 -0
- package/templates/react/src/demos/text-input-demo/page.tsx +151 -0
- package/templates/react/src/demos/textarea-demo/page.tsx +73 -0
- package/templates/react/src/demos/theme-switcher-demo/page.tsx +26 -0
- package/templates/react/src/demos/time-input-demo/page.tsx +148 -0
- package/templates/react/src/demos/toast-demo/page.tsx +302 -0
- package/templates/react/src/demos/toolbar-demo/page.tsx +49 -0
- package/templates/react/src/demos/tooltip-demo/page.tsx +209 -0
- package/templates/react/src/demos/typography-test/page.tsx +28 -0
- package/templates/react/src/demos/utility-panel-demo/page.tsx +197 -0
- package/templates/react/src/dev/DevPanel.tsx +219 -0
- package/templates/react/src/dev/DevPanelContext.ts +14 -0
- package/templates/react/src/dev/DevPanelProvider.tsx +63 -0
- package/templates/react/src/dev/DevRoutes.tsx +98 -0
- package/templates/react/src/dev/config.ts +127 -0
- package/templates/react/src/dev/index.ts +8 -0
- package/templates/react/src/dev/useDevPanel.ts +17 -0
- package/templates/react/src/dev-pages/ColorPalettePage.tsx +347 -0
- package/templates/react/src/dev-pages/ComponentsGalleryPage.tsx +489 -0
- package/templates/react/src/dev-pages/IconsPage.tsx +137 -0
- package/templates/react/src/dev-pages/index.ts +3 -0
- package/templates/react/src/hooks/useTheme.ts +15 -0
- package/templates/react/src/index.css +635 -0
- package/templates/react/src/main.tsx +14 -0
- package/templates/react/src/pages/HomePage.tsx +283 -0
- package/templates/react/src/vite-env.d.ts +9 -0
- package/templates/react/tailwind.config.js +58 -0
- package/templates/react/tsconfig.app.json +27 -0
- package/templates/react/tsconfig.json +7 -0
- package/templates/react/tsconfig.node.json +25 -0
- package/templates/react/vite.config.ts +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Create Modus App
|
|
2
|
+
|
|
3
|
+
Interactive CLI to scaffold Modus 2.0 web component applications for React and Angular.
|
|
4
|
+
|
|
5
|
+
**Templates are bundled directly** - no external downloads, works fully offline.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @julianoczkowski/create-trimble-app
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- š¦ **Bundled Templates** - Templates included in package, no network required
|
|
16
|
+
- š **Secure** - No runtime external dependencies
|
|
17
|
+
- āļø **React** - React + Vite + Modus 2.0 Components + Cursor Rules
|
|
18
|
+
- š
°ļø **Angular** - Angular + Modus 2.0 Web Components + Cursor Rules
|
|
19
|
+
- šÆ **Interactive** - Beautiful CLI with framework selection
|
|
20
|
+
- ā” **Fast** - Local file copy, instant setup
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Interactive Mode (Recommended)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx @julianoczkowski/create-trimble-app
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This will guide you through:
|
|
31
|
+
|
|
32
|
+
1. Framework selection (React or Angular)
|
|
33
|
+
2. Installation location choice
|
|
34
|
+
3. Project name input
|
|
35
|
+
4. Optional dependency installation
|
|
36
|
+
|
|
37
|
+
### Command Line Options
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Create with project name
|
|
41
|
+
npx @julianoczkowski/create-trimble-app my-app
|
|
42
|
+
|
|
43
|
+
# Specify framework
|
|
44
|
+
npx @julianoczkowski/create-trimble-app my-app --framework react
|
|
45
|
+
|
|
46
|
+
# Install in current folder
|
|
47
|
+
npx @julianoczkowski/create-trimble-app --current-folder
|
|
48
|
+
|
|
49
|
+
# Preview without creating files
|
|
50
|
+
npx @julianoczkowski/create-trimble-app my-app --dry-run
|
|
51
|
+
|
|
52
|
+
# Enable verbose output
|
|
53
|
+
npx @julianoczkowski/create-trimble-app my-app --verbose
|
|
54
|
+
|
|
55
|
+
# Show CLI information
|
|
56
|
+
npx @julianoczkowski/create-trimble-app --info
|
|
57
|
+
|
|
58
|
+
# Skip dependency installation
|
|
59
|
+
npx @julianoczkowski/create-trimble-app my-app --no-install
|
|
60
|
+
|
|
61
|
+
# Show help
|
|
62
|
+
npx @julianoczkowski/create-trimble-app --help
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## CLI Options
|
|
66
|
+
|
|
67
|
+
| Option | Description |
|
|
68
|
+
| ------------------------ | -------------------------------------- |
|
|
69
|
+
| `[project-name]` | Name of the project to create |
|
|
70
|
+
| `-f, --framework <name>` | Framework to use (react, angular) |
|
|
71
|
+
| `--current-folder` | Install in current folder |
|
|
72
|
+
| `--dry-run` | Preview what would be created |
|
|
73
|
+
| `--verbose` | Enable verbose output for debugging |
|
|
74
|
+
| `--info` | Show information about this CLI |
|
|
75
|
+
| `--no-install` | Skip automatic dependency installation |
|
|
76
|
+
| `-v, --version` | Display version number |
|
|
77
|
+
| `-h, --help` | Display help |
|
|
78
|
+
|
|
79
|
+
## Supported Frameworks
|
|
80
|
+
|
|
81
|
+
| Framework | Description | What's Included |
|
|
82
|
+
| -------------- | ------------ | -------------------------------------------------------------------------------------------------------- |
|
|
83
|
+
| āļø **React** | React + Vite | Modus 2.0 Components, TypeScript, Tailwind CSS, 40+ Cursor Rules, GitHub Templates, Code Quality Scripts |
|
|
84
|
+
| š
°ļø **Angular** | Angular 20+ | Modus 2.0 Web Components, TypeScript, Tailwind CSS, 11 Cursor Rules, GitHub Workflows, Demo Components |
|
|
85
|
+
|
|
86
|
+
## What's Included in Each Template
|
|
87
|
+
|
|
88
|
+
Both templates come fully configured with:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
your-project/
|
|
92
|
+
āāā .cursor/ # Cursor IDE rules for Modus development
|
|
93
|
+
āāā .github/ # Issue templates, PR template, CI workflows
|
|
94
|
+
āāā .husky/ # Git hooks (pre-commit)
|
|
95
|
+
āāā .vscode/ # VS Code extensions & settings
|
|
96
|
+
āāā docs/ # Documentation
|
|
97
|
+
āāā scripts/ # Code quality check scripts
|
|
98
|
+
āāā src/ # Source code with demo components
|
|
99
|
+
āāā package.json # All dependencies configured
|
|
100
|
+
āāā README.md # Getting started guide
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Architecture
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
107
|
+
ā npx create-trimble-app ā
|
|
108
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
|
|
109
|
+
ā 1. Parse CLI arguments (Commander.js) ā
|
|
110
|
+
ā 2. Interactive prompts (if needed) ā
|
|
111
|
+
ā 3. Copy bundled template (local file copy) ā
|
|
112
|
+
ā 4. Update package.json with project name ā
|
|
113
|
+
ā 5. Install dependencies (optional) ā
|
|
114
|
+
ā 6. Show success message ā
|
|
115
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
For detailed architecture documentation, see [docs/architecture.md](docs/architecture.md).
|
|
119
|
+
|
|
120
|
+
## Security
|
|
121
|
+
|
|
122
|
+
This CLI is designed with security as a priority:
|
|
123
|
+
|
|
124
|
+
- **No External Downloads** - Templates are bundled in the npm package
|
|
125
|
+
- **Works Offline** - No network required to create projects
|
|
126
|
+
- **npm Provenance** - Published with provenance attestation
|
|
127
|
+
- **Minimal Dependencies** - Only essential runtime dependencies
|
|
128
|
+
|
|
129
|
+
Unlike other scaffolding tools that download templates from GitHub at runtime, this CLI bundles templates directly. This eliminates:
|
|
130
|
+
|
|
131
|
+
- Supply chain attacks from compromised repositories
|
|
132
|
+
- Network failures during project creation
|
|
133
|
+
- Version drift between CLI and templates
|
|
134
|
+
|
|
135
|
+
## Requirements
|
|
136
|
+
|
|
137
|
+
- Node.js 18 or higher
|
|
138
|
+
- npm, yarn, or pnpm
|
|
139
|
+
|
|
140
|
+
## Development
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Clone this repository
|
|
144
|
+
git clone https://github.com/julianoczkowski/create-trimble-app.git
|
|
145
|
+
cd create-trimble-app
|
|
146
|
+
|
|
147
|
+
# Install dependencies
|
|
148
|
+
npm install
|
|
149
|
+
|
|
150
|
+
# Run locally
|
|
151
|
+
npm run dev
|
|
152
|
+
|
|
153
|
+
# Run tests
|
|
154
|
+
npm test
|
|
155
|
+
|
|
156
|
+
# Test specific commands
|
|
157
|
+
node bin/create-trimble-app.js --help
|
|
158
|
+
node bin/create-trimble-app.js my-app --framework react --dry-run
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
For detailed testing instructions, see [docs/local-testing.md](docs/local-testing.md).
|
|
162
|
+
|
|
163
|
+
## Documentation
|
|
164
|
+
|
|
165
|
+
| Document | Description |
|
|
166
|
+
| -------------------------------------- | ------------------------------ |
|
|
167
|
+
| [Architecture](docs/architecture.md) | How the CLI works internally |
|
|
168
|
+
| [Local Testing](docs/local-testing.md) | How to test during development |
|
|
169
|
+
|
|
170
|
+
## Contributing
|
|
171
|
+
|
|
172
|
+
1. Fork the repository
|
|
173
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
174
|
+
3. Run tests (`npm test`)
|
|
175
|
+
4. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
176
|
+
5. Push to the branch (`git push origin feature/amazing-feature`)
|
|
177
|
+
6. Open a Pull Request
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
MIT Ā© Julian Oczkowski
|
|
182
|
+
|
|
183
|
+
## Related
|
|
184
|
+
|
|
185
|
+
- [Modus Web Components Documentation](https://trimble-oss.github.io/modus-wc-2.0/main/?path=/docs/documentation-getting-started--docs)
|
|
186
|
+
- [Modus Icons](https://modus-icons.trimble.com/)
|
|
187
|
+
- [Trimble Modus Design System](https://modus.trimble.com)
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
**Made with ā¤ļø for the Modus community**
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@julianoczkowski/create-trimble-app",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Interactive CLI to scaffold Modus 2.0 web component applications for React and Angular - templates bundled, works offline",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/cli.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-trimble-app": "bin/create-trimble-app.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"src/",
|
|
13
|
+
"templates/"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"dev": "node bin/create-trimble-app.js",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:watch": "vitest",
|
|
19
|
+
"test:coverage": "vitest run --coverage",
|
|
20
|
+
"lint": "eslint src/",
|
|
21
|
+
"prepublishOnly": "npm run test && npm audit"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"modus",
|
|
25
|
+
"web-components",
|
|
26
|
+
"cli",
|
|
27
|
+
"scaffold",
|
|
28
|
+
"react",
|
|
29
|
+
"angular",
|
|
30
|
+
"trimble",
|
|
31
|
+
"create-app",
|
|
32
|
+
"boilerplate",
|
|
33
|
+
"starter",
|
|
34
|
+
"template",
|
|
35
|
+
"offline"
|
|
36
|
+
],
|
|
37
|
+
"author": "Julian Oczkowski",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/julianoczkowski/create-trimble-app.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/julianoczkowski/create-trimble-app/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/julianoczkowski/create-trimble-app#readme",
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public",
|
|
52
|
+
"registry": "https://registry.npmjs.org"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"chalk": "^5.3.0",
|
|
56
|
+
"commander": "^12.1.0",
|
|
57
|
+
"execa": "^8.0.1",
|
|
58
|
+
"ora": "^8.0.1",
|
|
59
|
+
"prompts": "^2.4.2",
|
|
60
|
+
"update-notifier": "^7.0.0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
64
|
+
"eslint": "^9.0.0",
|
|
65
|
+
"vitest": "^4.0.18"
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { readFileSync } from "fs";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import { dirname, join } from "path";
|
|
8
|
+
import { scaffold } from "./scaffold.js";
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
|
|
13
|
+
// Load package.json for version info
|
|
14
|
+
const packageJsonPath = join(__dirname, "..", "package.json");
|
|
15
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
16
|
+
|
|
17
|
+
// Check for updates (non-blocking)
|
|
18
|
+
async function checkForUpdates() {
|
|
19
|
+
try {
|
|
20
|
+
const { default: updateNotifier } = await import("update-notifier");
|
|
21
|
+
const notifier = updateNotifier({
|
|
22
|
+
pkg: packageJson,
|
|
23
|
+
updateCheckInterval: 1000 * 60 * 60 * 24, // 1 day
|
|
24
|
+
});
|
|
25
|
+
notifier.notify({ isGlobal: true });
|
|
26
|
+
} catch {
|
|
27
|
+
// Silently ignore update check failures
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const program = new Command();
|
|
32
|
+
|
|
33
|
+
program
|
|
34
|
+
.name("create-trimble-app")
|
|
35
|
+
.description(
|
|
36
|
+
"Interactive CLI to scaffold Modus 2.0 web component applications",
|
|
37
|
+
)
|
|
38
|
+
.version(packageJson.version, "-v, --version", "Display version number")
|
|
39
|
+
.argument("[project-name]", "Name of the project to create")
|
|
40
|
+
.option(
|
|
41
|
+
"-f, --framework <name>",
|
|
42
|
+
"Framework to use (react, angular)",
|
|
43
|
+
validateFramework,
|
|
44
|
+
)
|
|
45
|
+
.option(
|
|
46
|
+
"--current-folder",
|
|
47
|
+
"Install in current folder and use folder name as project name",
|
|
48
|
+
)
|
|
49
|
+
.option("--no-install", "Skip automatic dependency installation")
|
|
50
|
+
.option("--dry-run", "Preview what would be created without making changes")
|
|
51
|
+
.option("--verbose", "Enable verbose output for debugging")
|
|
52
|
+
.option("--info", "Show information about this CLI")
|
|
53
|
+
.addHelpText(
|
|
54
|
+
"after",
|
|
55
|
+
`
|
|
56
|
+
${chalk.cyan("Examples:")}
|
|
57
|
+
${chalk.gray("# Interactive mode - choose framework and name")}
|
|
58
|
+
$ npx @julianoczkowski/create-trimble-app
|
|
59
|
+
|
|
60
|
+
${chalk.gray("# Create a React project")}
|
|
61
|
+
$ npx @julianoczkowski/create-trimble-app my-app --framework react
|
|
62
|
+
|
|
63
|
+
${chalk.gray("# Create an Angular project")}
|
|
64
|
+
$ npx @julianoczkowski/create-trimble-app my-app --framework angular
|
|
65
|
+
|
|
66
|
+
${chalk.gray("# Install in current folder")}
|
|
67
|
+
$ npx @julianoczkowski/create-trimble-app --current-folder
|
|
68
|
+
|
|
69
|
+
${chalk.gray("# Preview without creating files")}
|
|
70
|
+
$ npx @julianoczkowski/create-trimble-app my-app --dry-run
|
|
71
|
+
|
|
72
|
+
${chalk.cyan("Frameworks:")}
|
|
73
|
+
${chalk.white("react")} - React with Vite and Modus 2.0 Components
|
|
74
|
+
${chalk.white("angular")} - Angular with Modus 2.0 Web Components
|
|
75
|
+
|
|
76
|
+
${chalk.cyan("Security:")}
|
|
77
|
+
Templates are bundled directly in this CLI package.
|
|
78
|
+
No external downloads - works offline, always consistent.
|
|
79
|
+
Use ${chalk.yellow("--info")} for more details.
|
|
80
|
+
|
|
81
|
+
${chalk.cyan("More information:")}
|
|
82
|
+
${chalk.blue("https://github.com/julianoczkowski/create-trimble-app")}
|
|
83
|
+
`,
|
|
84
|
+
)
|
|
85
|
+
.action(async (projectName, options) => {
|
|
86
|
+
// Check for updates in background
|
|
87
|
+
checkForUpdates();
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
await scaffold({
|
|
91
|
+
projectName,
|
|
92
|
+
framework: options.framework,
|
|
93
|
+
currentFolder: options.currentFolder,
|
|
94
|
+
install: options.install,
|
|
95
|
+
dryRun: options.dryRun,
|
|
96
|
+
verbose: options.verbose,
|
|
97
|
+
showInfo: options.info,
|
|
98
|
+
});
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error(chalk.red("Error:"), error.message);
|
|
101
|
+
if (options.verbose) {
|
|
102
|
+
console.error(chalk.gray(error.stack));
|
|
103
|
+
}
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Validate framework option
|
|
110
|
+
* @param {string} value - Framework name
|
|
111
|
+
* @returns {string} - Validated framework name
|
|
112
|
+
*/
|
|
113
|
+
function validateFramework(value) {
|
|
114
|
+
const validFrameworks = ["react", "angular"];
|
|
115
|
+
const lowercaseValue = value.toLowerCase();
|
|
116
|
+
|
|
117
|
+
if (!validFrameworks.includes(lowercaseValue)) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`Invalid framework "${value}". Valid options: ${validFrameworks.join(", ")}`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return lowercaseValue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Export for testing
|
|
127
|
+
export async function cli(args = process.argv) {
|
|
128
|
+
await program.parseAsync(args);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Run CLI if this is the main module
|
|
132
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
133
|
+
cli();
|
|
134
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { join, dirname } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
|
|
8
|
+
export function loadFrameworks() {
|
|
9
|
+
try {
|
|
10
|
+
const configPath = join(__dirname, "../templates/config.json");
|
|
11
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
12
|
+
|
|
13
|
+
return Object.entries(config.frameworks)
|
|
14
|
+
.filter(([_id, framework]) => !framework.disabled)
|
|
15
|
+
.map(([id, framework]) => ({
|
|
16
|
+
id,
|
|
17
|
+
...framework,
|
|
18
|
+
}));
|
|
19
|
+
} catch (error) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Failed to load framework configurations: ${error.message}`,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getFrameworkById(frameworks, id) {
|
|
27
|
+
return frameworks.find((framework) => framework.id === id);
|
|
28
|
+
}
|
package/src/scaffold.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import prompts from "prompts";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { loadFrameworks, getFrameworkById } from "./frameworks.js";
|
|
5
|
+
import {
|
|
6
|
+
updatePackageJson,
|
|
7
|
+
validateProjectName,
|
|
8
|
+
getCurrentFolderName,
|
|
9
|
+
} from "./utils/file.js";
|
|
10
|
+
import { installDependencies } from "./utils/install.js";
|
|
11
|
+
import { copyTemplate, getDetailedErrorMessage } from "./utils/git.js";
|
|
12
|
+
import { logger } from "./utils/logger.js";
|
|
13
|
+
|
|
14
|
+
export async function scaffold(options = {}) {
|
|
15
|
+
const { verbose = false, dryRun = false } = options;
|
|
16
|
+
|
|
17
|
+
// Set verbose mode
|
|
18
|
+
if (verbose) {
|
|
19
|
+
process.env.VERBOSE = "true";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Show welcome screen
|
|
23
|
+
logger.welcome();
|
|
24
|
+
|
|
25
|
+
// Show security notice if requested
|
|
26
|
+
if (options.showInfo) {
|
|
27
|
+
logger.securityNotice();
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const frameworks = loadFrameworks();
|
|
32
|
+
|
|
33
|
+
// 1. Framework Selection
|
|
34
|
+
let framework = options.framework;
|
|
35
|
+
|
|
36
|
+
if (!framework) {
|
|
37
|
+
const result = await prompts({
|
|
38
|
+
type: "select",
|
|
39
|
+
name: "framework",
|
|
40
|
+
message: "Select your framework:",
|
|
41
|
+
choices: frameworks.map((f) => ({
|
|
42
|
+
title: `${f.badge} ${f.name}`,
|
|
43
|
+
description: f.description + (f.note ? ` (${f.note})` : ""),
|
|
44
|
+
value: f.id,
|
|
45
|
+
})),
|
|
46
|
+
});
|
|
47
|
+
framework = result.framework;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!framework) {
|
|
51
|
+
console.log(chalk.yellow("X Cancelled"));
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const config = getFrameworkById(frameworks, framework);
|
|
56
|
+
|
|
57
|
+
if (!config) {
|
|
58
|
+
console.error(chalk.red(`Error: Unknown framework "${framework}"`));
|
|
59
|
+
console.log(
|
|
60
|
+
chalk.yellow(
|
|
61
|
+
`Available frameworks: ${frameworks.map((f) => f.id).join(", ")}`,
|
|
62
|
+
),
|
|
63
|
+
);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 2. Installation Location Choice
|
|
68
|
+
let installInCurrentFolder = options.currentFolder;
|
|
69
|
+
let projectName = options.projectName;
|
|
70
|
+
|
|
71
|
+
if (!installInCurrentFolder && !projectName) {
|
|
72
|
+
const currentFolderName = getCurrentFolderName();
|
|
73
|
+
|
|
74
|
+
const result = await prompts({
|
|
75
|
+
type: "select",
|
|
76
|
+
name: "installLocation",
|
|
77
|
+
message: "Where would you like to install your app?",
|
|
78
|
+
choices: [
|
|
79
|
+
{
|
|
80
|
+
title: `š Install in current directory (${currentFolderName})`,
|
|
81
|
+
description: "Use the current folder as your project directory",
|
|
82
|
+
value: "current",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
title: "š Create new directory",
|
|
86
|
+
description: "Create a new folder for your project",
|
|
87
|
+
value: "new",
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (!result.installLocation) {
|
|
93
|
+
console.log(chalk.yellow("X Cancelled"));
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
installInCurrentFolder = result.installLocation === "current";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 3. Project Name
|
|
101
|
+
if (installInCurrentFolder) {
|
|
102
|
+
projectName = getCurrentFolderName();
|
|
103
|
+
console.log(chalk.blue(`š Using current folder name: ${projectName}`));
|
|
104
|
+
} else if (!projectName) {
|
|
105
|
+
const result = await prompts({
|
|
106
|
+
type: "text",
|
|
107
|
+
name: "projectName",
|
|
108
|
+
message: "Project name:",
|
|
109
|
+
initial: "my-modus-app",
|
|
110
|
+
validate: (name) => validateProjectName(name, false),
|
|
111
|
+
});
|
|
112
|
+
projectName = result.projectName;
|
|
113
|
+
} else {
|
|
114
|
+
const validation = validateProjectName(projectName, false);
|
|
115
|
+
if (validation !== true) {
|
|
116
|
+
console.error(chalk.red(`Error: ${validation}`));
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!projectName) {
|
|
122
|
+
console.log(chalk.yellow("X Cancelled"));
|
|
123
|
+
process.exit(0);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const projectPath = installInCurrentFolder ? "." : projectName;
|
|
127
|
+
|
|
128
|
+
// Dry-run mode: show what would be created without executing
|
|
129
|
+
if (dryRun) {
|
|
130
|
+
console.log(chalk.cyan("\nš Dry-run mode - no changes will be made\n"));
|
|
131
|
+
console.log(chalk.white("Would create project with:"));
|
|
132
|
+
console.log(chalk.gray(` Framework: ${config.name}`));
|
|
133
|
+
console.log(chalk.gray(` Project name: ${projectName}`));
|
|
134
|
+
console.log(
|
|
135
|
+
chalk.gray(
|
|
136
|
+
` Location: ${installInCurrentFolder ? "Current directory" : `New directory: ${projectName}`}`,
|
|
137
|
+
),
|
|
138
|
+
);
|
|
139
|
+
console.log(chalk.gray(` Template: Bundled (included in CLI package)`));
|
|
140
|
+
console.log();
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 4. Copy Template
|
|
145
|
+
const spinner = ora(`š¦ Creating ${config.name} project...`).start();
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
await copyTemplate(framework, projectPath);
|
|
149
|
+
spinner.succeed(chalk.green(`Project created successfully!`));
|
|
150
|
+
|
|
151
|
+
// 5. Update package.json with project name
|
|
152
|
+
try {
|
|
153
|
+
await updatePackageJson(projectPath, {
|
|
154
|
+
name: projectName,
|
|
155
|
+
});
|
|
156
|
+
logger.success("Updated project configuration");
|
|
157
|
+
} catch (error) {
|
|
158
|
+
logger.warning("Could not update package.json name");
|
|
159
|
+
if (verbose) {
|
|
160
|
+
console.log(chalk.gray(` Error: ${error.message}`));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} catch (error) {
|
|
164
|
+
spinner.fail(chalk.red(`Failed to create project`));
|
|
165
|
+
const detailedMessage = getDetailedErrorMessage(error);
|
|
166
|
+
console.error(chalk.red(`\n${detailedMessage}`));
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Visual separator before dependency installation
|
|
171
|
+
console.log(chalk.gray("ā".repeat(60)));
|
|
172
|
+
|
|
173
|
+
// 6. Install Dependencies (optional)
|
|
174
|
+
let install = options.install;
|
|
175
|
+
|
|
176
|
+
if (install === undefined) {
|
|
177
|
+
const result = await prompts({
|
|
178
|
+
type: "confirm",
|
|
179
|
+
name: "install",
|
|
180
|
+
message: "š¦ Install dependencies now (default: yes)?",
|
|
181
|
+
initial: true,
|
|
182
|
+
});
|
|
183
|
+
install = result.install;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (install) {
|
|
187
|
+
const installSpinner = ora("Installing dependencies...").start();
|
|
188
|
+
try {
|
|
189
|
+
await installDependencies(projectPath);
|
|
190
|
+
installSpinner.succeed(chalk.green("Dependencies installed"));
|
|
191
|
+
} catch (error) {
|
|
192
|
+
installSpinner.fail(chalk.red("Failed to install dependencies"));
|
|
193
|
+
console.error(chalk.red(error.message));
|
|
194
|
+
console.log(
|
|
195
|
+
chalk.yellow(`\nš” You can install dependencies manually by running:`),
|
|
196
|
+
);
|
|
197
|
+
const installCommand = installInCurrentFolder
|
|
198
|
+
? "npm install"
|
|
199
|
+
: `cd ${projectName} && npm install`;
|
|
200
|
+
console.log(chalk.cyan(` ${installCommand}`));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Visual separator before final success message
|
|
205
|
+
console.log(chalk.gray("ā".repeat(60)));
|
|
206
|
+
|
|
207
|
+
// 7. Success Message
|
|
208
|
+
logger.nextSteps(projectName, config.name, install, installInCurrentFolder);
|
|
209
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
2
|
+
import { join, basename } from "path";
|
|
3
|
+
import { cwd } from "process";
|
|
4
|
+
|
|
5
|
+
export async function updatePackageJson(projectPath, updates) {
|
|
6
|
+
const packageJsonPath = join(projectPath, "package.json");
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
if (!existsSync(packageJsonPath)) {
|
|
10
|
+
throw new Error("package.json not found in template");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
14
|
+
|
|
15
|
+
// Update only specified fields
|
|
16
|
+
Object.assign(packageJson, updates);
|
|
17
|
+
|
|
18
|
+
writeFileSync(
|
|
19
|
+
packageJsonPath,
|
|
20
|
+
JSON.stringify(packageJson, null, 2) + "\n",
|
|
21
|
+
"utf-8"
|
|
22
|
+
);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Failed to update package.json: ${error.message}. Contact julian_oczkowski@trimble.com`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getCurrentFolderName() {
|
|
31
|
+
return basename(cwd());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function validateProjectName(name, isCurrentFolder = false) {
|
|
35
|
+
if (!name) return "Project name is required";
|
|
36
|
+
|
|
37
|
+
if (!/^[a-z0-9-_]+$/i.test(name)) {
|
|
38
|
+
return "Project name can't contain spaces. It can only contain letters, numbers, dashes.";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Skip directory existence check if installing in current folder
|
|
42
|
+
if (!isCurrentFolder && existsSync(name)) {
|
|
43
|
+
return `Directory "${name}" already exists`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return true;
|
|
47
|
+
}
|