@launch77/cli 1.2.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/.eslintrc.json +6 -0
- package/dist/app-templates/webapp/.env.ci +6 -0
- package/dist/app-templates/webapp/.env.example +9 -0
- package/dist/app-templates/webapp/.eslintrc.json +6 -0
- package/dist/app-templates/webapp/README.md.hbs +80 -0
- package/dist/app-templates/webapp/app/about/page.tsx.hbs +41 -0
- package/dist/app-templates/webapp/app/dashboard/page.tsx.hbs +51 -0
- package/dist/app-templates/webapp/app/globals.css +31 -0
- package/dist/app-templates/webapp/app/layout.tsx.hbs +26 -0
- package/dist/app-templates/webapp/app/page.tsx.hbs +30 -0
- package/dist/app-templates/webapp/next.config.js +99 -0
- package/dist/app-templates/webapp/package.json.hbs +30 -0
- package/dist/app-templates/webapp/postcss.config.js +6 -0
- package/dist/app-templates/webapp/tailwind.config.ts +24 -0
- package/dist/app-templates/webapp/tsconfig.json +29 -0
- package/dist/app-templates/webapp/vercel.json.hbs +7 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +29 -0
- package/dist/cli.js.map +1 -0
- package/dist/infrastructure/filesystem.d.ts +41 -0
- package/dist/infrastructure/filesystem.d.ts.map +1 -0
- package/dist/infrastructure/filesystem.js +61 -0
- package/dist/infrastructure/filesystem.js.map +1 -0
- package/dist/infrastructure/npm.d.ts +9 -0
- package/dist/infrastructure/npm.d.ts.map +1 -0
- package/dist/infrastructure/npm.js +17 -0
- package/dist/infrastructure/npm.js.map +1 -0
- package/dist/infrastructure/template-engine.d.ts +12 -0
- package/dist/infrastructure/template-engine.d.ts.map +1 -0
- package/dist/infrastructure/template-engine.js +40 -0
- package/dist/infrastructure/template-engine.js.map +1 -0
- package/dist/infrastructure/template-generator.d.ts +9 -0
- package/dist/infrastructure/template-generator.d.ts.map +1 -0
- package/dist/infrastructure/template-generator.js +19 -0
- package/dist/infrastructure/template-generator.js.map +1 -0
- package/dist/infrastructure/template.d.ts +20 -0
- package/dist/infrastructure/template.d.ts.map +1 -0
- package/dist/infrastructure/template.js +53 -0
- package/dist/infrastructure/template.js.map +1 -0
- package/dist/modules/app/commands/create-app.d.ts +3 -0
- package/dist/modules/app/commands/create-app.d.ts.map +1 -0
- package/dist/modules/app/commands/create-app.js +51 -0
- package/dist/modules/app/commands/create-app.js.map +1 -0
- package/dist/modules/app/commands/delete-app.d.ts +3 -0
- package/dist/modules/app/commands/delete-app.d.ts.map +1 -0
- package/dist/modules/app/commands/delete-app.js +109 -0
- package/dist/modules/app/commands/delete-app.js.map +1 -0
- package/dist/modules/app/commands/generate-manifest.d.ts +3 -0
- package/dist/modules/app/commands/generate-manifest.d.ts.map +1 -0
- package/dist/modules/app/commands/generate-manifest.js +62 -0
- package/dist/modules/app/commands/generate-manifest.js.map +1 -0
- package/dist/modules/app/commands/validate-manifest.d.ts +3 -0
- package/dist/modules/app/commands/validate-manifest.d.ts.map +1 -0
- package/dist/modules/app/commands/validate-manifest.js +68 -0
- package/dist/modules/app/commands/validate-manifest.js.map +1 -0
- package/dist/modules/app/errors/app-errors.d.ts +19 -0
- package/dist/modules/app/errors/app-errors.d.ts.map +1 -0
- package/dist/modules/app/errors/app-errors.js +37 -0
- package/dist/modules/app/errors/app-errors.js.map +1 -0
- package/dist/modules/app/index.d.ts +10 -0
- package/dist/modules/app/index.d.ts.map +1 -0
- package/dist/modules/app/index.js +11 -0
- package/dist/modules/app/index.js.map +1 -0
- package/dist/modules/app/lib/manifest-schema.d.ts +39 -0
- package/dist/modules/app/lib/manifest-schema.d.ts.map +1 -0
- package/dist/modules/app/lib/manifest-schema.js +44 -0
- package/dist/modules/app/lib/manifest-schema.js.map +1 -0
- package/dist/modules/app/services/app-svc.d.ts +15 -0
- package/dist/modules/app/services/app-svc.d.ts.map +1 -0
- package/dist/modules/app/services/app-svc.js +90 -0
- package/dist/modules/app/services/app-svc.js.map +1 -0
- package/dist/modules/app/services/manifest-svc.d.ts +28 -0
- package/dist/modules/app/services/manifest-svc.d.ts.map +1 -0
- package/dist/modules/app/services/manifest-svc.js +119 -0
- package/dist/modules/app/services/manifest-svc.js.map +1 -0
- package/dist/modules/app/types/app-types.d.ts +21 -0
- package/dist/modules/app/types/app-types.d.ts.map +1 -0
- package/dist/modules/app/types/app-types.js +5 -0
- package/dist/modules/app/types/app-types.js.map +1 -0
- package/dist/modules/catalog/commands/generate.d.ts +9 -0
- package/dist/modules/catalog/commands/generate.d.ts.map +1 -0
- package/dist/modules/catalog/commands/generate.js +94 -0
- package/dist/modules/catalog/commands/generate.js.map +1 -0
- package/dist/modules/catalog/commands/scan.d.ts +9 -0
- package/dist/modules/catalog/commands/scan.d.ts.map +1 -0
- package/dist/modules/catalog/commands/scan.js +43 -0
- package/dist/modules/catalog/commands/scan.js.map +1 -0
- package/dist/modules/catalog/config/catalog-config.d.ts +49 -0
- package/dist/modules/catalog/config/catalog-config.d.ts.map +1 -0
- package/dist/modules/catalog/config/catalog-config.js +116 -0
- package/dist/modules/catalog/config/catalog-config.js.map +1 -0
- package/dist/modules/catalog/config/catalog-config.test.d.ts +2 -0
- package/dist/modules/catalog/config/catalog-config.test.d.ts.map +1 -0
- package/dist/modules/catalog/config/catalog-config.test.js +362 -0
- package/dist/modules/catalog/config/catalog-config.test.js.map +1 -0
- package/dist/modules/catalog/index.d.ts +9 -0
- package/dist/modules/catalog/index.d.ts.map +1 -0
- package/dist/modules/catalog/index.js +9 -0
- package/dist/modules/catalog/index.js.map +1 -0
- package/dist/modules/catalog/parsers/typescript-parser.d.ts +15 -0
- package/dist/modules/catalog/parsers/typescript-parser.d.ts.map +1 -0
- package/dist/modules/catalog/parsers/typescript-parser.js +82 -0
- package/dist/modules/catalog/parsers/typescript-parser.js.map +1 -0
- package/dist/modules/catalog/scanners/metadata-extractor.d.ts +10 -0
- package/dist/modules/catalog/scanners/metadata-extractor.d.ts.map +1 -0
- package/dist/modules/catalog/scanners/metadata-extractor.js +122 -0
- package/dist/modules/catalog/scanners/metadata-extractor.js.map +1 -0
- package/dist/modules/catalog/scanners/metadata-validator.d.ts +6 -0
- package/dist/modules/catalog/scanners/metadata-validator.d.ts.map +1 -0
- package/dist/modules/catalog/scanners/metadata-validator.js +57 -0
- package/dist/modules/catalog/scanners/metadata-validator.js.map +1 -0
- package/dist/modules/catalog/scanners/ui-component-scanner.d.ts +11 -0
- package/dist/modules/catalog/scanners/ui-component-scanner.d.ts.map +1 -0
- package/dist/modules/catalog/scanners/ui-component-scanner.js +147 -0
- package/dist/modules/catalog/scanners/ui-component-scanner.js.map +1 -0
- package/dist/modules/catalog/schemas/catalog-ui-components.schema.json +161 -0
- package/dist/modules/catalog/schemas/schemas/catalog-ui-components.schema.json +145 -0
- package/dist/modules/catalog/services/catalog-generator-svc.d.ts +27 -0
- package/dist/modules/catalog/services/catalog-generator-svc.d.ts.map +1 -0
- package/dist/modules/catalog/services/catalog-generator-svc.js +100 -0
- package/dist/modules/catalog/services/catalog-generator-svc.js.map +1 -0
- package/dist/modules/catalog/services/catalog-generator-svc.test.d.ts +2 -0
- package/dist/modules/catalog/services/catalog-generator-svc.test.d.ts.map +1 -0
- package/dist/modules/catalog/services/catalog-generator-svc.test.js +201 -0
- package/dist/modules/catalog/services/catalog-generator-svc.test.js.map +1 -0
- package/dist/modules/catalog/services/catalog-svc.d.ts +39 -0
- package/dist/modules/catalog/services/catalog-svc.d.ts.map +1 -0
- package/dist/modules/catalog/services/catalog-svc.js +163 -0
- package/dist/modules/catalog/services/catalog-svc.js.map +1 -0
- package/dist/modules/catalog/types/catalog-types.d.ts +120 -0
- package/dist/modules/catalog/types/catalog-types.d.ts.map +1 -0
- package/dist/modules/catalog/types/catalog-types.js +5 -0
- package/dist/modules/catalog/types/catalog-types.js.map +1 -0
- package/dist/modules/catalog/utils/examples-generator.d.ts +6 -0
- package/dist/modules/catalog/utils/examples-generator.d.ts.map +1 -0
- package/dist/modules/catalog/utils/examples-generator.js +55 -0
- package/dist/modules/catalog/utils/examples-generator.js.map +1 -0
- package/dist/modules/catalog/utils/quality-reporter.d.ts +13 -0
- package/dist/modules/catalog/utils/quality-reporter.d.ts.map +1 -0
- package/dist/modules/catalog/utils/quality-reporter.js +64 -0
- package/dist/modules/catalog/utils/quality-reporter.js.map +1 -0
- package/dist/modules/catalog/validators/component-name-validator.d.ts +20 -0
- package/dist/modules/catalog/validators/component-name-validator.d.ts.map +1 -0
- package/dist/modules/catalog/validators/component-name-validator.js +33 -0
- package/dist/modules/catalog/validators/component-name-validator.js.map +1 -0
- package/dist/modules/catalog/validators/component-name-validator.test.d.ts +2 -0
- package/dist/modules/catalog/validators/component-name-validator.test.d.ts.map +1 -0
- package/dist/modules/catalog/validators/component-name-validator.test.js +196 -0
- package/dist/modules/catalog/validators/component-name-validator.test.js.map +1 -0
- package/dist/modules/deploy/commands/deploy-init-action.d.ts +12 -0
- package/dist/modules/deploy/commands/deploy-init-action.d.ts.map +1 -0
- package/dist/modules/deploy/commands/deploy-init-action.js +220 -0
- package/dist/modules/deploy/commands/deploy-init-action.js.map +1 -0
- package/dist/modules/deploy/commands/deploy-init.d.ts +6 -0
- package/dist/modules/deploy/commands/deploy-init.d.ts.map +1 -0
- package/dist/modules/deploy/commands/deploy-init.js +16 -0
- package/dist/modules/deploy/commands/deploy-init.js.map +1 -0
- package/dist/modules/deploy/commands/deploy-logs-action.d.ts +12 -0
- package/dist/modules/deploy/commands/deploy-logs-action.d.ts.map +1 -0
- package/dist/modules/deploy/commands/deploy-logs-action.js +113 -0
- package/dist/modules/deploy/commands/deploy-logs-action.js.map +1 -0
- package/dist/modules/deploy/commands/deploy-logs.d.ts +6 -0
- package/dist/modules/deploy/commands/deploy-logs.d.ts.map +1 -0
- package/dist/modules/deploy/commands/deploy-logs.js +17 -0
- package/dist/modules/deploy/commands/deploy-logs.js.map +1 -0
- package/dist/modules/deploy/commands/deploy-status-action.d.ts +8 -0
- package/dist/modules/deploy/commands/deploy-status-action.d.ts.map +1 -0
- package/dist/modules/deploy/commands/deploy-status-action.js +153 -0
- package/dist/modules/deploy/commands/deploy-status-action.js.map +1 -0
- package/dist/modules/deploy/commands/deploy-status.d.ts +6 -0
- package/dist/modules/deploy/commands/deploy-status.d.ts.map +1 -0
- package/dist/modules/deploy/commands/deploy-status.js +13 -0
- package/dist/modules/deploy/commands/deploy-status.js.map +1 -0
- package/dist/modules/deploy/index.d.ts +7 -0
- package/dist/modules/deploy/index.d.ts.map +1 -0
- package/dist/modules/deploy/index.js +7 -0
- package/dist/modules/deploy/index.js.map +1 -0
- package/dist/modules/deploy/services/deploy-svc.d.ts +17 -0
- package/dist/modules/deploy/services/deploy-svc.d.ts.map +1 -0
- package/dist/modules/deploy/services/deploy-svc.js +25 -0
- package/dist/modules/deploy/services/deploy-svc.js.map +1 -0
- package/dist/modules/deploy/utils/vercel-extended.d.ts +63 -0
- package/dist/modules/deploy/utils/vercel-extended.d.ts.map +1 -0
- package/dist/modules/deploy/utils/vercel-extended.js +238 -0
- package/dist/modules/deploy/utils/vercel-extended.js.map +1 -0
- package/dist/modules/plugin/commands/plugin-install.d.ts +3 -0
- package/dist/modules/plugin/commands/plugin-install.d.ts.map +1 -0
- package/dist/modules/plugin/commands/plugin-install.js +45 -0
- package/dist/modules/plugin/commands/plugin-install.js.map +1 -0
- package/dist/modules/plugin/errors/plugin-errors.d.ts +16 -0
- package/dist/modules/plugin/errors/plugin-errors.d.ts.map +1 -0
- package/dist/modules/plugin/errors/plugin-errors.js +39 -0
- package/dist/modules/plugin/errors/plugin-errors.js.map +1 -0
- package/dist/modules/plugin/index.d.ts +6 -0
- package/dist/modules/plugin/index.d.ts.map +1 -0
- package/dist/modules/plugin/index.js +9 -0
- package/dist/modules/plugin/index.js.map +1 -0
- package/dist/modules/plugin/lib/plugin-registry.d.ts +15 -0
- package/dist/modules/plugin/lib/plugin-registry.d.ts.map +1 -0
- package/dist/modules/plugin/lib/plugin-registry.js +47 -0
- package/dist/modules/plugin/lib/plugin-registry.js.map +1 -0
- package/dist/modules/plugin/services/plugin-svc.d.ts +10 -0
- package/dist/modules/plugin/services/plugin-svc.d.ts.map +1 -0
- package/dist/modules/plugin/services/plugin-svc.js +44 -0
- package/dist/modules/plugin/services/plugin-svc.js.map +1 -0
- package/dist/modules/plugin/types/plugin-types.d.ts +19 -0
- package/dist/modules/plugin/types/plugin-types.d.ts.map +1 -0
- package/dist/modules/plugin/types/plugin-types.js +2 -0
- package/dist/modules/plugin/types/plugin-types.js.map +1 -0
- package/dist/modules/startup/commands/create-startup.d.ts +3 -0
- package/dist/modules/startup/commands/create-startup.d.ts.map +1 -0
- package/dist/modules/startup/commands/create-startup.js +43 -0
- package/dist/modules/startup/commands/create-startup.js.map +1 -0
- package/dist/modules/startup/errors/startup-errors.d.ts +13 -0
- package/dist/modules/startup/errors/startup-errors.d.ts.map +1 -0
- package/dist/modules/startup/errors/startup-errors.js +25 -0
- package/dist/modules/startup/errors/startup-errors.js.map +1 -0
- package/dist/modules/startup/index.d.ts +5 -0
- package/dist/modules/startup/index.d.ts.map +1 -0
- package/dist/modules/startup/index.js +7 -0
- package/dist/modules/startup/index.js.map +1 -0
- package/dist/modules/startup/services/startup-service.d.ts +7 -0
- package/dist/modules/startup/services/startup-service.d.ts.map +1 -0
- package/dist/modules/startup/services/startup-service.js +43 -0
- package/dist/modules/startup/services/startup-service.js.map +1 -0
- package/dist/modules/startup/types/startup-types.d.ts +8 -0
- package/dist/modules/startup/types/startup-types.d.ts.map +1 -0
- package/dist/modules/startup/types/startup-types.js +2 -0
- package/dist/modules/startup/types/startup-types.js.map +1 -0
- package/dist/modules/startup/utils/startup-validators.d.ts +8 -0
- package/dist/modules/startup/utils/startup-validators.d.ts.map +1 -0
- package/dist/modules/startup/utils/startup-validators.js +17 -0
- package/dist/modules/startup/utils/startup-validators.js.map +1 -0
- package/dist/modules/workspace/commands/init-workspace.d.ts +3 -0
- package/dist/modules/workspace/commands/init-workspace.d.ts.map +1 -0
- package/dist/modules/workspace/commands/init-workspace.js +54 -0
- package/dist/modules/workspace/commands/init-workspace.js.map +1 -0
- package/dist/modules/workspace/errors/workspace-errors.d.ts +10 -0
- package/dist/modules/workspace/errors/workspace-errors.d.ts.map +1 -0
- package/dist/modules/workspace/errors/workspace-errors.js +19 -0
- package/dist/modules/workspace/errors/workspace-errors.js.map +1 -0
- package/dist/modules/workspace/index.d.ts +5 -0
- package/dist/modules/workspace/index.d.ts.map +1 -0
- package/dist/modules/workspace/index.js +7 -0
- package/dist/modules/workspace/index.js.map +1 -0
- package/dist/modules/workspace/services/workspace-service.d.ts +6 -0
- package/dist/modules/workspace/services/workspace-service.d.ts.map +1 -0
- package/dist/modules/workspace/services/workspace-service.js +46 -0
- package/dist/modules/workspace/services/workspace-service.js.map +1 -0
- package/dist/modules/workspace/types/workspace-types.d.ts +8 -0
- package/dist/modules/workspace/types/workspace-types.d.ts.map +1 -0
- package/dist/modules/workspace/types/workspace-types.js +2 -0
- package/dist/modules/workspace/types/workspace-types.js.map +1 -0
- package/dist/modules/workspace/utils/workspace-validators.d.ts +8 -0
- package/dist/modules/workspace/utils/workspace-validators.d.ts.map +1 -0
- package/dist/modules/workspace/utils/workspace-validators.js +17 -0
- package/dist/modules/workspace/utils/workspace-validators.js.map +1 -0
- package/dist/plugins/theme/package.json +32 -0
- package/dist/plugins/theme/plugin.json +9 -0
- package/dist/plugins/theme/src/generator.ts +92 -0
- package/dist/plugins/theme/src/utils/config-modifier.ts +142 -0
- package/dist/plugins/theme/src/utils/css-modifier.ts +89 -0
- package/dist/plugins/theme/templates/app/theme-test/page.tsx +156 -0
- package/dist/plugins/theme/templates/src/modules/theme/README.md +209 -0
- package/dist/plugins/theme/templates/src/modules/theme/config/brand.css +23 -0
- package/dist/plugins/theme/tsconfig.json +14 -0
- package/dist/plugins/theme/tsup.config.ts +10 -0
- package/dist/templates/startup/apps/.gitkeep +8 -0
- package/dist/templates/templates/startup/apps/.gitkeep +8 -0
- package/dist/templates/templates/workspace/.eslintignore +7 -0
- package/dist/templates/templates/workspace/.eslintrc.js +38 -0
- package/dist/templates/templates/workspace/.husky/pre-push +24 -0
- package/dist/templates/templates/workspace/.launch77/workspace.json +3 -0
- package/dist/templates/templates/workspace/.lintstagedrc.json +4 -0
- package/dist/templates/templates/workspace/.prettierrc +9 -0
- package/dist/templates/templates/workspace/README.md +62 -0
- package/dist/templates/templates/workspace/app-templates/.gitkeep +1 -0
- package/dist/templates/templates/workspace/apps/.gitkeep +1 -0
- package/dist/templates/templates/workspace/libraries/.gitkeep +1 -0
- package/dist/templates/templates/workspace/package.json +31 -0
- package/dist/templates/templates/workspace/plugins/.gitkeep +1 -0
- package/dist/templates/templates/workspace/tsconfig.json +22 -0
- package/dist/templates/templates/workspace/turbo.json +25 -0
- package/dist/templates/workspace/.launch77/workspace.json +3 -0
- package/dist/templates/workspace/README.md +62 -0
- package/dist/templates/workspace/app-templates/.gitkeep +1 -0
- package/dist/templates/workspace/apps/.gitkeep +1 -0
- package/dist/templates/workspace/libraries/.gitkeep +1 -0
- package/dist/templates/workspace/package.json +21 -0
- package/dist/templates/workspace/plugins/.gitkeep +1 -0
- package/dist/templates/workspace/tsconfig.json +22 -0
- package/dist/templates/workspace/turbo.json +25 -0
- package/dist/utils/launch77-context.d.ts +16 -0
- package/dist/utils/launch77-context.d.ts.map +1 -0
- package/dist/utils/launch77-context.js +111 -0
- package/dist/utils/launch77-context.js.map +1 -0
- package/dist/utils/launch77-validation.d.ts +17 -0
- package/dist/utils/launch77-validation.d.ts.map +1 -0
- package/dist/utils/launch77-validation.js +44 -0
- package/dist/utils/launch77-validation.js.map +1 -0
- package/dist/utils/monorepo.d.ts +19 -0
- package/dist/utils/monorepo.d.ts.map +1 -0
- package/dist/utils/monorepo.js +100 -0
- package/dist/utils/monorepo.js.map +1 -0
- package/dist/utils/validation.d.ts +32 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +92 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/utils/version.d.ts +7 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +16 -0
- package/dist/utils/version.js.map +1 -0
- package/launch77-cli-1.2.0.tgz +0 -0
- package/package.json +48 -0
- package/src/cli.ts +34 -0
- package/src/infrastructure/filesystem.ts +69 -0
- package/src/infrastructure/npm.ts +18 -0
- package/src/infrastructure/template-engine.ts +48 -0
- package/src/infrastructure/template-generator.ts +26 -0
- package/src/infrastructure/template.ts +66 -0
- package/src/modules/app/commands/create-app.ts +60 -0
- package/src/modules/app/commands/delete-app.ts +123 -0
- package/src/modules/app/commands/generate-manifest.ts +75 -0
- package/src/modules/app/commands/validate-manifest.ts +78 -0
- package/src/modules/app/errors/app-errors.ts +41 -0
- package/src/modules/app/index.ts +16 -0
- package/src/modules/app/lib/manifest-schema.ts +65 -0
- package/src/modules/app/services/app-svc.ts +115 -0
- package/src/modules/app/services/manifest-svc.ts +144 -0
- package/src/modules/app/types/app-types.ts +27 -0
- package/src/modules/catalog/commands/generate.ts +115 -0
- package/src/modules/catalog/commands/scan.ts +48 -0
- package/src/modules/catalog/config/catalog-config.test.ts +404 -0
- package/src/modules/catalog/config/catalog-config.ts +130 -0
- package/src/modules/catalog/index.ts +9 -0
- package/src/modules/catalog/parsers/typescript-parser.ts +93 -0
- package/src/modules/catalog/scanners/metadata-extractor.ts +134 -0
- package/src/modules/catalog/scanners/metadata-validator.ts +67 -0
- package/src/modules/catalog/scanners/ui-component-scanner.ts +185 -0
- package/src/modules/catalog/schemas/catalog-ui-components.schema.json +145 -0
- package/src/modules/catalog/services/catalog-generator-svc.test.ts +233 -0
- package/src/modules/catalog/services/catalog-generator-svc.ts +124 -0
- package/src/modules/catalog/services/catalog-svc.ts +222 -0
- package/src/modules/catalog/types/catalog-types.ts +149 -0
- package/src/modules/catalog/utils/examples-generator.ts +68 -0
- package/src/modules/catalog/utils/quality-reporter.ts +76 -0
- package/src/modules/catalog/validators/component-name-validator.test.ts +233 -0
- package/src/modules/catalog/validators/component-name-validator.ts +43 -0
- package/src/modules/deploy/commands/deploy-init-action.ts +247 -0
- package/src/modules/deploy/commands/deploy-init.ts +19 -0
- package/src/modules/deploy/commands/deploy-logs-action.ts +135 -0
- package/src/modules/deploy/commands/deploy-logs.ts +20 -0
- package/src/modules/deploy/commands/deploy-status-action.ts +175 -0
- package/src/modules/deploy/commands/deploy-status.ts +16 -0
- package/src/modules/deploy/index.ts +7 -0
- package/src/modules/deploy/services/deploy-svc.ts +31 -0
- package/src/modules/deploy/utils/vercel-extended.ts +286 -0
- package/src/modules/plugin/commands/plugin-install.ts +51 -0
- package/src/modules/plugin/errors/plugin-errors.ts +44 -0
- package/src/modules/plugin/index.ts +14 -0
- package/src/modules/plugin/lib/launch77-workspace.code-workspace +14 -0
- package/src/modules/plugin/lib/plugin-registry.ts +59 -0
- package/src/modules/plugin/services/plugin-svc.ts +53 -0
- package/src/modules/plugin/types/plugin-types.ts +21 -0
- package/src/modules/startup/commands/create-startup.ts +53 -0
- package/src/modules/startup/errors/startup-errors.ts +23 -0
- package/src/modules/startup/index.ts +11 -0
- package/src/modules/startup/services/startup-service.ts +57 -0
- package/src/modules/startup/types/startup-types.ts +8 -0
- package/src/modules/startup/utils/startup-validators.ts +19 -0
- package/src/modules/workspace/commands/init-workspace.ts +63 -0
- package/src/modules/workspace/errors/workspace-errors.ts +16 -0
- package/src/modules/workspace/index.ts +11 -0
- package/src/modules/workspace/services/workspace-service.ts +59 -0
- package/src/modules/workspace/types/workspace-types.ts +8 -0
- package/src/modules/workspace/utils/workspace-validators.ts +19 -0
- package/src/utils/launch77-context.ts +152 -0
- package/src/utils/launch77-validation.ts +59 -0
- package/src/utils/monorepo.ts +137 -0
- package/src/utils/validation.ts +117 -0
- package/src/utils/version.ts +16 -0
- package/templates/startup/apps/.gitkeep +8 -0
- package/templates/workspace/.eslintignore +7 -0
- package/templates/workspace/.eslintrc.js +38 -0
- package/templates/workspace/.husky/pre-push +24 -0
- package/templates/workspace/.launch77/workspace.json +3 -0
- package/templates/workspace/.lintstagedrc.json +4 -0
- package/templates/workspace/.prettierrc +9 -0
- package/templates/workspace/README.md +62 -0
- package/templates/workspace/app-templates/.gitkeep +1 -0
- package/templates/workspace/apps/.gitkeep +1 -0
- package/templates/workspace/libraries/.gitkeep +1 -0
- package/templates/workspace/package.json +31 -0
- package/templates/workspace/plugins/.gitkeep +1 -0
- package/templates/workspace/tsconfig.json +22 -0
- package/templates/workspace/turbo.json +25 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the Launch77 catalog system
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Catalog File Structure
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* UI Component catalog structure
|
|
11
|
+
* Generated by individual component libraries during build
|
|
12
|
+
*/
|
|
13
|
+
export interface UiComponentCatalog {
|
|
14
|
+
$schema?: string
|
|
15
|
+
catalogType: 'ui-components'
|
|
16
|
+
catalogVersion: string
|
|
17
|
+
packageName: string
|
|
18
|
+
packageVersion: string
|
|
19
|
+
generatedAt: string
|
|
20
|
+
components: UiComponent[]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Component Metadata
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Complete UI component metadata in catalog
|
|
29
|
+
*/
|
|
30
|
+
export interface UiComponent {
|
|
31
|
+
id: string
|
|
32
|
+
kind: 'ui_component'
|
|
33
|
+
name: string
|
|
34
|
+
packageName: string
|
|
35
|
+
category: string
|
|
36
|
+
description: string
|
|
37
|
+
tags: string[]
|
|
38
|
+
props?: string[]
|
|
39
|
+
sourcePath?: string
|
|
40
|
+
library?: string
|
|
41
|
+
guidance?: ComponentGuidance
|
|
42
|
+
example?: string
|
|
43
|
+
examples?: ComponentExamples
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Component usage guidance
|
|
48
|
+
*/
|
|
49
|
+
export interface ComponentGuidance {
|
|
50
|
+
whenToUse: string
|
|
51
|
+
whenNotToUse: string
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Component examples reference
|
|
56
|
+
*/
|
|
57
|
+
export interface ComponentExamples {
|
|
58
|
+
module: string
|
|
59
|
+
export: string
|
|
60
|
+
sourcePath: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Component metadata extracted from JSDoc
|
|
65
|
+
*/
|
|
66
|
+
export interface ComponentMetadata {
|
|
67
|
+
description: string
|
|
68
|
+
category: string
|
|
69
|
+
whenToUse: string
|
|
70
|
+
whenNotToUse: string
|
|
71
|
+
tags: string[]
|
|
72
|
+
example: string
|
|
73
|
+
ignored: boolean
|
|
74
|
+
ignoreReason?: string
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Validation
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Validation result for a single component
|
|
83
|
+
*/
|
|
84
|
+
export interface ValidationResult {
|
|
85
|
+
valid: boolean
|
|
86
|
+
errors: string[]
|
|
87
|
+
warnings: string[]
|
|
88
|
+
componentName: string
|
|
89
|
+
filePath: string
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Quality report for catalog generation
|
|
94
|
+
*/
|
|
95
|
+
export interface QualityReport {
|
|
96
|
+
totalComponents: number
|
|
97
|
+
withMetadata: number
|
|
98
|
+
missingMetadata: number
|
|
99
|
+
excluded: number
|
|
100
|
+
errors: ValidationResult[]
|
|
101
|
+
warnings: ValidationResult[]
|
|
102
|
+
qualityScore: number
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ============================================================================
|
|
106
|
+
// Configuration
|
|
107
|
+
// ============================================================================
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Catalog generation configuration
|
|
111
|
+
*/
|
|
112
|
+
export interface CatalogConfig {
|
|
113
|
+
type: 'ui-components'
|
|
114
|
+
packageName: string
|
|
115
|
+
sourceDir: string
|
|
116
|
+
componentsDir: string
|
|
117
|
+
exportsFile: string
|
|
118
|
+
outputFile: string
|
|
119
|
+
catalogVersion: string
|
|
120
|
+
validation: ValidationConfig
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Validation rules configuration
|
|
125
|
+
*/
|
|
126
|
+
export interface ValidationConfig {
|
|
127
|
+
strict: boolean
|
|
128
|
+
requireCategory: boolean
|
|
129
|
+
requireDescription: boolean
|
|
130
|
+
minDescriptionLength: number
|
|
131
|
+
requireWhenToUse: boolean
|
|
132
|
+
requireWhenNotToUse: boolean
|
|
133
|
+
minTags: number
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// Generation Results
|
|
138
|
+
// ============================================================================
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Result of catalog generation
|
|
142
|
+
*/
|
|
143
|
+
export interface GenerationResult {
|
|
144
|
+
success: boolean
|
|
145
|
+
catalogFile: string
|
|
146
|
+
qualityReport: QualityReport
|
|
147
|
+
errors: ValidationResult[]
|
|
148
|
+
warnings: ValidationResult[]
|
|
149
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as path from 'path'
|
|
2
|
+
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
|
|
5
|
+
import type { UiComponent } from '../types/catalog-types.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate examples.generated.ts files for each library that has components with examples
|
|
9
|
+
*/
|
|
10
|
+
export async function generateExamplesFiles(components: UiComponent[], launch77Root: string): Promise<void> {
|
|
11
|
+
// Group components by package
|
|
12
|
+
const componentsByPackage = new Map<string, UiComponent[]>()
|
|
13
|
+
|
|
14
|
+
for (const component of components) {
|
|
15
|
+
if (component.examples) {
|
|
16
|
+
const existing = componentsByPackage.get(component.packageName) || []
|
|
17
|
+
existing.push(component)
|
|
18
|
+
componentsByPackage.set(component.packageName, existing)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Generate examples file for each package
|
|
23
|
+
for (const [packageName, packageComponents] of componentsByPackage) {
|
|
24
|
+
// Determine library path based on package name
|
|
25
|
+
// Extract library name from scoped package (e.g., @launch77/ui -> ui)
|
|
26
|
+
const libraryName = packageName.split('/').pop() || packageName
|
|
27
|
+
const libraryPath = path.join(launch77Root, 'libraries', libraryName)
|
|
28
|
+
const examplesFilePath = path.join(libraryPath, 'src', 'examples.generated.ts')
|
|
29
|
+
|
|
30
|
+
// Generate content
|
|
31
|
+
const content = generateExamplesContent(packageComponents, libraryName)
|
|
32
|
+
|
|
33
|
+
// Write file
|
|
34
|
+
await fs.writeFile(examplesFilePath, content, 'utf-8')
|
|
35
|
+
|
|
36
|
+
console.log(` ✓ Generated ${packageName}/examples`)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function generateExamplesContent(components: UiComponent[], _libraryName: string): string {
|
|
41
|
+
const lines: string[] = ['// AUTO-GENERATED by launch77 scan - DO NOT EDIT', "// This file is automatically generated when running 'launch77 scan'", '// To add new examples, create a ComponentName.examples.tsx file next to your component', '']
|
|
42
|
+
|
|
43
|
+
// Sort components alphabetically for deterministic output
|
|
44
|
+
const sortedComponents = [...components].sort((a, b) => a.name.localeCompare(b.name))
|
|
45
|
+
|
|
46
|
+
// Add export statements
|
|
47
|
+
for (const component of sortedComponents) {
|
|
48
|
+
if (component.examples && component.examples.sourcePath) {
|
|
49
|
+
// Extract relative path from sourcePath
|
|
50
|
+
// e.g., "launch77/libraries/ui/src/components/Button/Button.examples.tsx"
|
|
51
|
+
// becomes "./components/Button/Button.examples"
|
|
52
|
+
const sourcePath = component.examples.sourcePath
|
|
53
|
+
const srcIndex = sourcePath.indexOf('/src/')
|
|
54
|
+
if (srcIndex !== -1) {
|
|
55
|
+
const relativePath = sourcePath
|
|
56
|
+
.substring(srcIndex + 5) // Skip "/src/"
|
|
57
|
+
.replace(/\.tsx$/, '') // Remove extension
|
|
58
|
+
|
|
59
|
+
// Export structured examples using ComponentNameExamples convention
|
|
60
|
+
// e.g., Button -> ButtonExamples, CTAButton -> CTAButtonExamples
|
|
61
|
+
const structuredExportName = `${component.name}Examples`
|
|
62
|
+
lines.push(`export { ${structuredExportName} } from './${relativePath}'`)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return lines.join('\n') + '\n'
|
|
68
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate and display catalog quality reports
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import chalk from 'chalk'
|
|
6
|
+
|
|
7
|
+
import type { ValidationResult, QualityReport } from '../types/catalog-types.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generate quality report from validation results
|
|
11
|
+
*/
|
|
12
|
+
export function generateQualityReport(totalScanned: number, excluded: number, validations: ValidationResult[]): QualityReport {
|
|
13
|
+
const errors = validations.filter((v) => !v.valid)
|
|
14
|
+
const withMetadata = validations.filter((v) => v.valid)
|
|
15
|
+
|
|
16
|
+
const qualityScore = totalScanned > 0 ? Math.round((withMetadata.length / totalScanned) * 100) : 100
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
totalComponents: totalScanned,
|
|
20
|
+
withMetadata: withMetadata.length,
|
|
21
|
+
missingMetadata: errors.length,
|
|
22
|
+
excluded,
|
|
23
|
+
errors,
|
|
24
|
+
warnings: validations.filter((v) => v.warnings.length > 0),
|
|
25
|
+
qualityScore,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Print quality report to console
|
|
31
|
+
*/
|
|
32
|
+
export function printQualityReport(report: QualityReport, strict: boolean): void {
|
|
33
|
+
console.log(chalk.blue('\n📊 Catalog Quality Report\n'))
|
|
34
|
+
console.log(chalk.gray(` Total components scanned: ${report.totalComponents}`))
|
|
35
|
+
console.log(chalk.green(` ✓ With metadata: ${report.withMetadata} (${report.qualityScore}%)`))
|
|
36
|
+
|
|
37
|
+
if (report.missingMetadata > 0) {
|
|
38
|
+
console.log(chalk.red(` ✗ Missing metadata: ${report.missingMetadata}`))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (report.excluded > 0) {
|
|
42
|
+
console.log(chalk.gray(` ℹ Excluded: ${report.excluded}`))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Show errors
|
|
46
|
+
if (report.errors.length > 0) {
|
|
47
|
+
console.log(chalk.red('\n ❌ Components missing metadata:\n'))
|
|
48
|
+
report.errors.forEach((err) => {
|
|
49
|
+
console.log(chalk.red(` - ${err.componentName}`))
|
|
50
|
+
console.log(chalk.gray(` ${err.filePath}`))
|
|
51
|
+
err.errors.forEach((e) => console.log(chalk.gray(` • ${e}`)))
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Show warnings (limit to 5)
|
|
56
|
+
if (report.warnings.length > 0 && !strict) {
|
|
57
|
+
console.log(chalk.yellow('\n ⚠️ Metadata warnings:\n'))
|
|
58
|
+
report.warnings.slice(0, 5).forEach((warn) => {
|
|
59
|
+
console.log(chalk.yellow(` - ${warn.componentName}`))
|
|
60
|
+
warn.warnings.forEach((w) => console.log(chalk.gray(` • ${w}`)))
|
|
61
|
+
})
|
|
62
|
+
if (report.warnings.length > 5) {
|
|
63
|
+
console.log(chalk.gray(`\n ... and ${report.warnings.length - 5} more`))
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log()
|
|
68
|
+
|
|
69
|
+
// Help message if there are errors
|
|
70
|
+
if (report.errors.length > 0) {
|
|
71
|
+
console.log(chalk.blue('💡 To fix:\n'))
|
|
72
|
+
console.log(chalk.gray(' • Add @launch77-component JSDoc to public components'))
|
|
73
|
+
console.log(chalk.gray(' • Add @launch77-ignore to exclude internal components'))
|
|
74
|
+
console.log(chalk.gray(' • See: launch77/docs/CATALOG_METADATA_GUIDE.md\n'))
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { validateComponentName } from './component-name-validator.js'
|
|
4
|
+
|
|
5
|
+
describe('validateComponentName', () => {
|
|
6
|
+
describe('valid names', () => {
|
|
7
|
+
test('single word PascalCase', () => {
|
|
8
|
+
expect(validateComponentName('Button').valid).toBe(true)
|
|
9
|
+
expect(validateComponentName('Alert').valid).toBe(true)
|
|
10
|
+
expect(validateComponentName('Input').valid).toBe(true)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test('multi-word PascalCase', () => {
|
|
14
|
+
expect(validateComponentName('AlertDialog').valid).toBe(true)
|
|
15
|
+
expect(validateComponentName('FormField').valid).toBe(true)
|
|
16
|
+
expect(validateComponentName('NavigationMenu').valid).toBe(true)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('with numbers', () => {
|
|
20
|
+
expect(validateComponentName('Button2').valid).toBe(true)
|
|
21
|
+
expect(validateComponentName('Alert3D').valid).toBe(true)
|
|
22
|
+
expect(validateComponentName('H1').valid).toBe(true)
|
|
23
|
+
expect(validateComponentName('Input123').valid).toBe(true)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('common abbreviations', () => {
|
|
27
|
+
expect(validateComponentName('HTTPClient').valid).toBe(true)
|
|
28
|
+
expect(validateComponentName('URLInput').valid).toBe(true)
|
|
29
|
+
expect(validateComponentName('APIKey').valid).toBe(true)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('long valid names', () => {
|
|
33
|
+
const name50 = 'A'.repeat(50)
|
|
34
|
+
expect(validateComponentName(name50).valid).toBe(true)
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('invalid names - symbols and special characters', () => {
|
|
39
|
+
test('special symbols', () => {
|
|
40
|
+
const result1 = validateComponentName('===')
|
|
41
|
+
expect(result1.valid).toBe(false)
|
|
42
|
+
expect(result1.errors[0]).toContain('PascalCase')
|
|
43
|
+
|
|
44
|
+
const result2 = validateComponentName('!!!')
|
|
45
|
+
expect(result2.valid).toBe(false)
|
|
46
|
+
|
|
47
|
+
const result3 = validateComponentName('@@@')
|
|
48
|
+
expect(result3.valid).toBe(false)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('with special characters', () => {
|
|
52
|
+
const result1 = validateComponentName('Button$')
|
|
53
|
+
expect(result1.valid).toBe(false)
|
|
54
|
+
expect(result1.errors[0]).toContain('PascalCase')
|
|
55
|
+
|
|
56
|
+
const result2 = validateComponentName('Alert#Icon')
|
|
57
|
+
expect(result2.valid).toBe(false)
|
|
58
|
+
|
|
59
|
+
const result3 = validateComponentName('Form_Field')
|
|
60
|
+
expect(result3.valid).toBe(false)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('with hyphens', () => {
|
|
64
|
+
const result = validateComponentName('Alert-Dialog')
|
|
65
|
+
expect(result.valid).toBe(false)
|
|
66
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('with spaces', () => {
|
|
70
|
+
const result1 = validateComponentName('My Button')
|
|
71
|
+
expect(result1.valid).toBe(false)
|
|
72
|
+
|
|
73
|
+
const result2 = validateComponentName('Alert Dialog')
|
|
74
|
+
expect(result2.valid).toBe(false)
|
|
75
|
+
|
|
76
|
+
const result3 = validateComponentName(' Button')
|
|
77
|
+
expect(result3.valid).toBe(false)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('with dots', () => {
|
|
81
|
+
const result = validateComponentName('Button.Icon')
|
|
82
|
+
expect(result.valid).toBe(false)
|
|
83
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
describe('invalid names - casing', () => {
|
|
88
|
+
test('lowercase', () => {
|
|
89
|
+
const result = validateComponentName('button')
|
|
90
|
+
expect(result.valid).toBe(false)
|
|
91
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test('camelCase', () => {
|
|
95
|
+
const result = validateComponentName('alertDialog')
|
|
96
|
+
expect(result.valid).toBe(false)
|
|
97
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('snake_case', () => {
|
|
101
|
+
const result = validateComponentName('alert_dialog')
|
|
102
|
+
expect(result.valid).toBe(false)
|
|
103
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('SCREAMING_SNAKE_CASE', () => {
|
|
107
|
+
const result = validateComponentName('ALERT_DIALOG')
|
|
108
|
+
expect(result.valid).toBe(false)
|
|
109
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test('kebab-case', () => {
|
|
113
|
+
const result = validateComponentName('alert-dialog')
|
|
114
|
+
expect(result.valid).toBe(false)
|
|
115
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
describe('invalid names - numbers', () => {
|
|
120
|
+
test('only numbers', () => {
|
|
121
|
+
const result = validateComponentName('123')
|
|
122
|
+
expect(result.valid).toBe(false)
|
|
123
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('starting with number', () => {
|
|
127
|
+
const result = validateComponentName('3DButton')
|
|
128
|
+
expect(result.valid).toBe(false)
|
|
129
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
describe('invalid names - empty and length', () => {
|
|
134
|
+
test('empty string', () => {
|
|
135
|
+
const result = validateComponentName('')
|
|
136
|
+
expect(result.valid).toBe(false)
|
|
137
|
+
expect(result.errors[0]).toContain('cannot be empty')
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
test('exceeds maximum length', () => {
|
|
141
|
+
const name51 = 'A'.repeat(51)
|
|
142
|
+
const result = validateComponentName(name51)
|
|
143
|
+
expect(result.valid).toBe(false)
|
|
144
|
+
expect(result.errors[0]).toContain('maximum length')
|
|
145
|
+
expect(result.errors[0]).toContain('50')
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test('very long name', () => {
|
|
149
|
+
const name100 = 'A'.repeat(100)
|
|
150
|
+
const result = validateComponentName(name100)
|
|
151
|
+
expect(result.valid).toBe(false)
|
|
152
|
+
expect(result.errors[0]).toContain('maximum length')
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
describe('multiple errors', () => {
|
|
157
|
+
test('empty string has one error', () => {
|
|
158
|
+
const result = validateComponentName('')
|
|
159
|
+
expect(result.errors.length).toBeGreaterThan(0)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('lowercase name has error', () => {
|
|
163
|
+
const result = validateComponentName('button')
|
|
164
|
+
expect(result.errors.length).toBeGreaterThanOrEqual(1)
|
|
165
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
test('symbol-only name has error', () => {
|
|
169
|
+
const result = validateComponentName('$$$')
|
|
170
|
+
expect(result.valid).toBe(false)
|
|
171
|
+
expect(result.errors.length).toBeGreaterThan(0)
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
describe('edge cases', () => {
|
|
176
|
+
test('single letter uppercase', () => {
|
|
177
|
+
expect(validateComponentName('A').valid).toBe(true)
|
|
178
|
+
expect(validateComponentName('Z').valid).toBe(true)
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
test('exactly 50 characters', () => {
|
|
182
|
+
const name = 'A'.repeat(50)
|
|
183
|
+
expect(validateComponentName(name).valid).toBe(true)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
test('51 characters', () => {
|
|
187
|
+
const name = 'A'.repeat(51)
|
|
188
|
+
expect(validateComponentName(name).valid).toBe(false)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
test('unicode characters', () => {
|
|
192
|
+
const result = validateComponentName('Buttoné')
|
|
193
|
+
expect(result.valid).toBe(false)
|
|
194
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
test('emoji', () => {
|
|
198
|
+
const result = validateComponentName('Button😀')
|
|
199
|
+
expect(result.valid).toBe(false)
|
|
200
|
+
expect(result.errors[0]).toContain('PascalCase')
|
|
201
|
+
})
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
describe('common real-world component names', () => {
|
|
205
|
+
test('UI library components', () => {
|
|
206
|
+
expect(validateComponentName('Dialog').valid).toBe(true)
|
|
207
|
+
expect(validateComponentName('Popover').valid).toBe(true)
|
|
208
|
+
expect(validateComponentName('Tooltip').valid).toBe(true)
|
|
209
|
+
expect(validateComponentName('Select').valid).toBe(true)
|
|
210
|
+
expect(validateComponentName('Checkbox').valid).toBe(true)
|
|
211
|
+
expect(validateComponentName('RadioGroup').valid).toBe(true)
|
|
212
|
+
expect(validateComponentName('Accordion').valid).toBe(true)
|
|
213
|
+
expect(validateComponentName('Tabs').valid).toBe(true)
|
|
214
|
+
expect(validateComponentName('Card').valid).toBe(true)
|
|
215
|
+
expect(validateComponentName('Badge').valid).toBe(true)
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
test('form components', () => {
|
|
219
|
+
expect(validateComponentName('FormField').valid).toBe(true)
|
|
220
|
+
expect(validateComponentName('FormError').valid).toBe(true)
|
|
221
|
+
expect(validateComponentName('FormHelperText').valid).toBe(true)
|
|
222
|
+
expect(validateComponentName('TextField').valid).toBe(true)
|
|
223
|
+
expect(validateComponentName('TextArea').valid).toBe(true)
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
test('navigation components', () => {
|
|
227
|
+
expect(validateComponentName('Navbar').valid).toBe(true)
|
|
228
|
+
expect(validateComponentName('Sidebar').valid).toBe(true)
|
|
229
|
+
expect(validateComponentName('Breadcrumbs').valid).toBe(true)
|
|
230
|
+
expect(validateComponentName('NavigationMenu').valid).toBe(true)
|
|
231
|
+
})
|
|
232
|
+
})
|
|
233
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate component names for Launch77 catalog
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const VALID_COMPONENT_NAME = /^[A-Z][a-zA-Z0-9]*$/
|
|
6
|
+
const MAX_COMPONENT_NAME_LENGTH = 50
|
|
7
|
+
|
|
8
|
+
export interface ComponentNameValidation {
|
|
9
|
+
valid: boolean
|
|
10
|
+
errors: string[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Validate a component name against Launch77 naming conventions
|
|
15
|
+
*
|
|
16
|
+
* Rules:
|
|
17
|
+
* - Must start with uppercase letter (A-Z)
|
|
18
|
+
* - Only alphanumeric characters (no symbols, spaces, or special characters)
|
|
19
|
+
* - Maximum 50 characters
|
|
20
|
+
*
|
|
21
|
+
* @param name - Component name to validate
|
|
22
|
+
* @returns Validation result with errors if invalid
|
|
23
|
+
*/
|
|
24
|
+
export function validateComponentName(name: string): ComponentNameValidation {
|
|
25
|
+
const errors: string[] = []
|
|
26
|
+
|
|
27
|
+
if (!name || name.length === 0) {
|
|
28
|
+
errors.push('Component name cannot be empty')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (name.length > MAX_COMPONENT_NAME_LENGTH) {
|
|
32
|
+
errors.push(`Component name exceeds maximum length of ${MAX_COMPONENT_NAME_LENGTH} characters`)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!VALID_COMPONENT_NAME.test(name)) {
|
|
36
|
+
errors.push('Component name must be PascalCase (start with uppercase letter A-Z, alphanumeric only)')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
valid: errors.length === 0,
|
|
41
|
+
errors,
|
|
42
|
+
}
|
|
43
|
+
}
|