create-fluxstack 1.0.1 → 1.0.3
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/.claude/settings.local.json +63 -0
- package/.dockerignore +50 -0
- package/.env.example +53 -0
- package/.gitattributes +2 -0
- package/.github/workflows/ci-build-tests.yml +480 -0
- package/.github/workflows/dependency-management.yml +324 -0
- package/.github/workflows/release-validation.yml +355 -0
- package/.kiro/specs/fluxstack-architecture-optimization/design.md +700 -0
- package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +127 -0
- package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +330 -0
- package/CLAUDE.md +200 -0
- package/Dockerfile +58 -0
- package/Dockerfile.backend +52 -0
- package/Dockerfile.frontend +54 -0
- package/ENV_TESTING_REPORT.md +292 -0
- package/FRAMEWORK_ROADMAP.md +183 -0
- package/FRONTEND_TESTS_README.md +287 -0
- package/README-Docker.md +85 -0
- package/TEST_RESULTS.md +130 -0
- package/ai-context/00-QUICK-START.md +86 -0
- package/ai-context/README.md +88 -0
- package/ai-context/development/eden-treaty-guide.md +362 -0
- package/ai-context/development/patterns.md +382 -0
- package/ai-context/examples/crud-complete.md +626 -0
- package/ai-context/project/architecture.md +399 -0
- package/ai-context/project/overview.md +213 -0
- package/ai-context/recent-changes/eden-treaty-refactor.md +281 -0
- package/ai-context/recent-changes/type-inference-fix.md +223 -0
- package/ai-context/reference/environment-vars.md +384 -0
- package/ai-context/reference/troubleshooting.md +407 -0
- package/bun.lock +21 -11
- package/bunfig.toml +16 -0
- package/config/fluxstack.config.ts +48 -0
- package/create-fluxstack.ts +2 -3
- package/create-test-app.ts +156 -0
- package/docker-compose.microservices.yml +75 -0
- package/docker-compose.simple.yml +57 -0
- package/docker-compose.yml +71 -0
- package/docs/dynamic-environment-variables.md +380 -0
- package/eslint.config.js +23 -0
- package/examples/dynamic-env-usage.ts +283 -0
- package/examples/hybrid-env-strategy.ts +212 -0
- package/examples/simplified-env-usage.ts +251 -0
- package/flux-cli.ts +214 -0
- package/fluxstack.config.ts +318 -0
- package/meu-app-teste/README.md +44 -0
- package/meu-app-teste/app/client/README.md +69 -0
- package/meu-app-teste/app/client/frontend-only.ts +12 -0
- package/meu-app-teste/app/client/index.html +13 -0
- package/meu-app-teste/app/client/public/vite.svg +1 -0
- package/meu-app-teste/app/client/src/App.css +883 -0
- package/meu-app-teste/app/client/src/App.tsx +669 -0
- package/meu-app-teste/app/client/src/assets/react.svg +1 -0
- package/meu-app-teste/app/client/src/components/TestPage.tsx +453 -0
- package/meu-app-teste/app/client/src/index.css +51 -0
- package/meu-app-teste/app/client/src/lib/eden-api.ts +110 -0
- package/meu-app-teste/app/client/src/main.tsx +10 -0
- package/meu-app-teste/app/client/src/vite-env.d.ts +1 -0
- package/meu-app-teste/app/client/tsconfig.app.json +43 -0
- package/meu-app-teste/app/client/tsconfig.json +7 -0
- package/meu-app-teste/app/client/tsconfig.node.json +25 -0
- package/meu-app-teste/app/server/app.ts +10 -0
- package/meu-app-teste/app/server/backend-only.ts +15 -0
- package/meu-app-teste/app/server/controllers/users.controller.ts +69 -0
- package/meu-app-teste/app/server/index.ts +104 -0
- package/meu-app-teste/app/server/routes/index.ts +25 -0
- package/meu-app-teste/app/server/routes/users.routes.ts +121 -0
- package/meu-app-teste/app/server/types/index.ts +1 -0
- package/meu-app-teste/app/shared/types/index.ts +18 -0
- package/meu-app-teste/bun.lock +1053 -0
- package/meu-app-teste/core/__tests__/integration.test.ts +227 -0
- package/meu-app-teste/core/build/index.ts +186 -0
- package/meu-app-teste/core/cli/command-registry.ts +334 -0
- package/meu-app-teste/core/cli/index.ts +394 -0
- package/meu-app-teste/core/cli/plugin-discovery.ts +200 -0
- package/meu-app-teste/core/client/standalone.ts +57 -0
- package/meu-app-teste/core/config/__tests__/config-loader.test.ts +591 -0
- package/meu-app-teste/core/config/__tests__/config-merger.test.ts +657 -0
- package/meu-app-teste/core/config/__tests__/env-converter.test.ts +372 -0
- package/meu-app-teste/core/config/__tests__/env-processor.test.ts +431 -0
- package/meu-app-teste/core/config/__tests__/env.test.ts +452 -0
- package/meu-app-teste/core/config/__tests__/integration.test.ts +418 -0
- package/meu-app-teste/core/config/__tests__/loader.test.ts +331 -0
- package/meu-app-teste/core/config/__tests__/schema.test.ts +129 -0
- package/meu-app-teste/core/config/__tests__/validator.test.ts +318 -0
- package/meu-app-teste/core/config/env-dynamic.ts +326 -0
- package/meu-app-teste/core/config/env.ts +597 -0
- package/meu-app-teste/core/config/index.ts +317 -0
- package/meu-app-teste/core/config/loader.ts +546 -0
- package/meu-app-teste/core/config/runtime-config.ts +322 -0
- package/meu-app-teste/core/config/schema.ts +694 -0
- package/meu-app-teste/core/config/validator.ts +540 -0
- package/meu-app-teste/core/framework/__tests__/server.test.ts +233 -0
- package/meu-app-teste/core/framework/client.ts +132 -0
- package/meu-app-teste/core/framework/index.ts +8 -0
- package/meu-app-teste/core/framework/server.ts +501 -0
- package/meu-app-teste/core/framework/types.ts +63 -0
- package/meu-app-teste/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
- package/meu-app-teste/core/plugins/__tests__/manager.test.ts +398 -0
- package/meu-app-teste/core/plugins/__tests__/monitoring.test.ts +401 -0
- package/meu-app-teste/core/plugins/__tests__/registry.test.ts +335 -0
- package/meu-app-teste/core/plugins/built-in/index.ts +142 -0
- package/meu-app-teste/core/plugins/built-in/logger/index.ts +180 -0
- package/meu-app-teste/core/plugins/built-in/monitoring/README.md +193 -0
- package/meu-app-teste/core/plugins/built-in/monitoring/index.ts +912 -0
- package/meu-app-teste/core/plugins/built-in/static/index.ts +289 -0
- package/meu-app-teste/core/plugins/built-in/swagger/index.ts +229 -0
- package/meu-app-teste/core/plugins/built-in/vite/index.ts +316 -0
- package/meu-app-teste/core/plugins/config.ts +348 -0
- package/meu-app-teste/core/plugins/discovery.ts +350 -0
- package/meu-app-teste/core/plugins/executor.ts +351 -0
- package/meu-app-teste/core/plugins/index.ts +195 -0
- package/meu-app-teste/core/plugins/manager.ts +583 -0
- package/meu-app-teste/core/plugins/registry.ts +424 -0
- package/meu-app-teste/core/plugins/types.ts +254 -0
- package/meu-app-teste/core/server/framework.ts +123 -0
- package/meu-app-teste/core/server/index.ts +8 -0
- package/meu-app-teste/core/server/plugins/database.ts +182 -0
- package/meu-app-teste/core/server/plugins/logger.ts +47 -0
- package/meu-app-teste/core/server/plugins/swagger.ts +34 -0
- package/meu-app-teste/core/server/standalone.ts +91 -0
- package/meu-app-teste/core/templates/create-project.ts +455 -0
- package/meu-app-teste/core/types/api.ts +169 -0
- package/meu-app-teste/core/types/build.ts +174 -0
- package/meu-app-teste/core/types/config.ts +68 -0
- package/meu-app-teste/core/types/index.ts +127 -0
- package/meu-app-teste/core/types/plugin.ts +94 -0
- package/meu-app-teste/core/utils/__tests__/errors.test.ts +139 -0
- package/meu-app-teste/core/utils/__tests__/helpers.test.ts +297 -0
- package/meu-app-teste/core/utils/__tests__/logger.test.ts +141 -0
- package/meu-app-teste/core/utils/env-runtime-v2.ts +232 -0
- package/meu-app-teste/core/utils/env-runtime.ts +252 -0
- package/meu-app-teste/core/utils/errors/codes.ts +115 -0
- package/meu-app-teste/core/utils/errors/handlers.ts +63 -0
- package/meu-app-teste/core/utils/errors/index.ts +81 -0
- package/meu-app-teste/core/utils/helpers.ts +180 -0
- package/meu-app-teste/core/utils/index.ts +18 -0
- package/meu-app-teste/core/utils/logger/index.ts +161 -0
- package/meu-app-teste/core/utils/logger.ts +106 -0
- package/meu-app-teste/core/utils/monitoring/index.ts +212 -0
- package/meu-app-teste/package.json +92 -0
- package/meu-app-teste/tsconfig.json +51 -0
- package/meu-app-teste/vite.config.ts +42 -0
- package/my-final-test/README.md +44 -0
- package/my-final-test/app/client/README.md +69 -0
- package/my-final-test/app/client/frontend-only.ts +12 -0
- package/my-final-test/app/client/index.html +13 -0
- package/my-final-test/app/client/public/vite.svg +1 -0
- package/my-final-test/app/client/src/App.css +883 -0
- package/my-final-test/app/client/src/App.tsx +669 -0
- package/my-final-test/app/client/src/assets/react.svg +1 -0
- package/my-final-test/app/client/src/components/TestPage.tsx +453 -0
- package/my-final-test/app/client/src/index.css +51 -0
- package/my-final-test/app/client/src/lib/eden-api.ts +110 -0
- package/my-final-test/app/client/src/main.tsx +10 -0
- package/my-final-test/app/client/src/vite-env.d.ts +1 -0
- package/my-final-test/app/client/tsconfig.app.json +43 -0
- package/my-final-test/app/client/tsconfig.json +7 -0
- package/my-final-test/app/client/tsconfig.node.json +25 -0
- package/my-final-test/app/server/app.ts +10 -0
- package/my-final-test/app/server/backend-only.ts +15 -0
- package/my-final-test/app/server/controllers/users.controller.ts +69 -0
- package/my-final-test/app/server/index.ts +104 -0
- package/my-final-test/app/server/routes/index.ts +25 -0
- package/my-final-test/app/server/routes/users.routes.ts +121 -0
- package/my-final-test/app/server/types/index.ts +1 -0
- package/my-final-test/app/shared/types/index.ts +18 -0
- package/my-final-test/bun.lock +993 -0
- package/my-final-test/core/__tests__/integration.test.ts +227 -0
- package/my-final-test/core/build/index.ts +186 -0
- package/my-final-test/core/cli/command-registry.ts +334 -0
- package/my-final-test/core/cli/index.ts +394 -0
- package/my-final-test/core/cli/plugin-discovery.ts +200 -0
- package/my-final-test/core/client/standalone.ts +57 -0
- package/my-final-test/core/config/__tests__/config-loader.test.ts +591 -0
- package/my-final-test/core/config/__tests__/config-merger.test.ts +657 -0
- package/my-final-test/core/config/__tests__/env-converter.test.ts +372 -0
- package/my-final-test/core/config/__tests__/env-processor.test.ts +431 -0
- package/my-final-test/core/config/__tests__/env.test.ts +452 -0
- package/my-final-test/core/config/__tests__/integration.test.ts +418 -0
- package/my-final-test/core/config/__tests__/loader.test.ts +331 -0
- package/my-final-test/core/config/__tests__/schema.test.ts +129 -0
- package/my-final-test/core/config/__tests__/validator.test.ts +318 -0
- package/my-final-test/core/config/env-dynamic.ts +326 -0
- package/my-final-test/core/config/env.ts +597 -0
- package/my-final-test/core/config/index.ts +317 -0
- package/my-final-test/core/config/loader.ts +546 -0
- package/my-final-test/core/config/runtime-config.ts +322 -0
- package/my-final-test/core/config/schema.ts +694 -0
- package/my-final-test/core/config/validator.ts +540 -0
- package/my-final-test/core/framework/__tests__/server.test.ts +233 -0
- package/my-final-test/core/framework/client.ts +132 -0
- package/my-final-test/core/framework/index.ts +8 -0
- package/my-final-test/core/framework/server.ts +501 -0
- package/my-final-test/core/framework/types.ts +63 -0
- package/my-final-test/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
- package/my-final-test/core/plugins/__tests__/manager.test.ts +398 -0
- package/my-final-test/core/plugins/__tests__/monitoring.test.ts +401 -0
- package/my-final-test/core/plugins/__tests__/registry.test.ts +335 -0
- package/my-final-test/core/plugins/built-in/index.ts +142 -0
- package/my-final-test/core/plugins/built-in/logger/index.ts +180 -0
- package/my-final-test/core/plugins/built-in/monitoring/README.md +193 -0
- package/my-final-test/core/plugins/built-in/monitoring/index.ts +912 -0
- package/my-final-test/core/plugins/built-in/static/index.ts +289 -0
- package/my-final-test/core/plugins/built-in/swagger/index.ts +229 -0
- package/my-final-test/core/plugins/built-in/vite/index.ts +316 -0
- package/my-final-test/core/plugins/config.ts +348 -0
- package/my-final-test/core/plugins/discovery.ts +350 -0
- package/my-final-test/core/plugins/executor.ts +351 -0
- package/my-final-test/core/plugins/index.ts +195 -0
- package/my-final-test/core/plugins/manager.ts +583 -0
- package/my-final-test/core/plugins/registry.ts +424 -0
- package/my-final-test/core/plugins/types.ts +254 -0
- package/my-final-test/core/server/framework.ts +123 -0
- package/my-final-test/core/server/index.ts +8 -0
- package/my-final-test/core/server/plugins/database.ts +182 -0
- package/my-final-test/core/server/plugins/logger.ts +47 -0
- package/my-final-test/core/server/plugins/swagger.ts +34 -0
- package/my-final-test/core/server/standalone.ts +91 -0
- package/my-final-test/core/templates/create-project.ts +455 -0
- package/my-final-test/core/types/api.ts +169 -0
- package/my-final-test/core/types/build.ts +174 -0
- package/my-final-test/core/types/config.ts +68 -0
- package/my-final-test/core/types/index.ts +127 -0
- package/my-final-test/core/types/plugin.ts +94 -0
- package/my-final-test/core/utils/__tests__/errors.test.ts +139 -0
- package/my-final-test/core/utils/__tests__/helpers.test.ts +297 -0
- package/my-final-test/core/utils/__tests__/logger.test.ts +141 -0
- package/my-final-test/core/utils/env-runtime-v2.ts +232 -0
- package/my-final-test/core/utils/env-runtime.ts +252 -0
- package/my-final-test/core/utils/errors/codes.ts +115 -0
- package/my-final-test/core/utils/errors/handlers.ts +63 -0
- package/my-final-test/core/utils/errors/index.ts +81 -0
- package/my-final-test/core/utils/helpers.ts +180 -0
- package/my-final-test/core/utils/index.ts +18 -0
- package/my-final-test/core/utils/logger/index.ts +161 -0
- package/my-final-test/core/utils/logger.ts +106 -0
- package/my-final-test/core/utils/monitoring/index.ts +212 -0
- package/my-final-test/package.json +68 -0
- package/my-final-test/tsconfig.json +51 -0
- package/my-final-test/vite.config.ts +42 -0
- package/nginx-lb.conf +37 -0
- package/package-template.json +32 -15
- package/package.json +71 -30
- package/publish-setup.md +111 -0
- package/publish.sh +63 -0
- package/run-clean.ts +26 -0
- package/run-env-tests.ts +313 -0
- package/tailwind.config.js +34 -0
- package/teste-corrigido/README.md +44 -0
- package/teste-corrigido/app/client/README.md +69 -0
- package/teste-corrigido/app/client/frontend-only.ts +12 -0
- package/teste-corrigido/app/client/index.html +13 -0
- package/teste-corrigido/app/client/public/vite.svg +1 -0
- package/teste-corrigido/app/client/src/App.css +883 -0
- package/teste-corrigido/app/client/src/App.tsx +669 -0
- package/teste-corrigido/app/client/src/assets/react.svg +1 -0
- package/teste-corrigido/app/client/src/components/TestPage.tsx +453 -0
- package/teste-corrigido/app/client/src/index.css +51 -0
- package/teste-corrigido/app/client/src/lib/eden-api.ts +110 -0
- package/teste-corrigido/app/client/src/main.tsx +10 -0
- package/teste-corrigido/app/client/src/vite-env.d.ts +1 -0
- package/teste-corrigido/app/client/tsconfig.app.json +43 -0
- package/teste-corrigido/app/client/tsconfig.json +7 -0
- package/teste-corrigido/app/client/tsconfig.node.json +25 -0
- package/teste-corrigido/app/server/app.ts +10 -0
- package/teste-corrigido/app/server/backend-only.ts +15 -0
- package/teste-corrigido/app/server/controllers/users.controller.ts +69 -0
- package/teste-corrigido/app/server/index.ts +104 -0
- package/teste-corrigido/app/server/routes/index.ts +25 -0
- package/teste-corrigido/app/server/routes/users.routes.ts +121 -0
- package/teste-corrigido/app/server/types/index.ts +1 -0
- package/teste-corrigido/app/shared/types/index.ts +18 -0
- package/teste-corrigido/bun.lock +1053 -0
- package/teste-corrigido/core/__tests__/integration.test.ts +227 -0
- package/teste-corrigido/core/build/index.ts +186 -0
- package/teste-corrigido/core/cli/command-registry.ts +334 -0
- package/teste-corrigido/core/cli/index.ts +394 -0
- package/teste-corrigido/core/cli/plugin-discovery.ts +200 -0
- package/teste-corrigido/core/client/standalone.ts +57 -0
- package/teste-corrigido/core/config/__tests__/config-loader.test.ts +591 -0
- package/teste-corrigido/core/config/__tests__/config-merger.test.ts +657 -0
- package/teste-corrigido/core/config/__tests__/env-converter.test.ts +372 -0
- package/teste-corrigido/core/config/__tests__/env-processor.test.ts +431 -0
- package/teste-corrigido/core/config/__tests__/env.test.ts +452 -0
- package/teste-corrigido/core/config/__tests__/integration.test.ts +418 -0
- package/teste-corrigido/core/config/__tests__/loader.test.ts +331 -0
- package/teste-corrigido/core/config/__tests__/schema.test.ts +129 -0
- package/teste-corrigido/core/config/__tests__/validator.test.ts +318 -0
- package/teste-corrigido/core/config/env-dynamic.ts +326 -0
- package/teste-corrigido/core/config/env.ts +597 -0
- package/teste-corrigido/core/config/index.ts +317 -0
- package/teste-corrigido/core/config/loader.ts +546 -0
- package/teste-corrigido/core/config/runtime-config.ts +322 -0
- package/teste-corrigido/core/config/schema.ts +694 -0
- package/teste-corrigido/core/config/validator.ts +540 -0
- package/teste-corrigido/core/framework/__tests__/server.test.ts +233 -0
- package/teste-corrigido/core/framework/client.ts +132 -0
- package/teste-corrigido/core/framework/index.ts +8 -0
- package/teste-corrigido/core/framework/server.ts +501 -0
- package/teste-corrigido/core/framework/types.ts +63 -0
- package/teste-corrigido/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
- package/teste-corrigido/core/plugins/__tests__/manager.test.ts +398 -0
- package/teste-corrigido/core/plugins/__tests__/monitoring.test.ts +401 -0
- package/teste-corrigido/core/plugins/__tests__/registry.test.ts +335 -0
- package/teste-corrigido/core/plugins/built-in/index.ts +142 -0
- package/teste-corrigido/core/plugins/built-in/logger/index.ts +180 -0
- package/teste-corrigido/core/plugins/built-in/monitoring/README.md +193 -0
- package/teste-corrigido/core/plugins/built-in/monitoring/index.ts +912 -0
- package/teste-corrigido/core/plugins/built-in/static/index.ts +289 -0
- package/teste-corrigido/core/plugins/built-in/swagger/index.ts +229 -0
- package/teste-corrigido/core/plugins/built-in/vite/index.ts +316 -0
- package/teste-corrigido/core/plugins/config.ts +348 -0
- package/teste-corrigido/core/plugins/discovery.ts +350 -0
- package/teste-corrigido/core/plugins/executor.ts +351 -0
- package/teste-corrigido/core/plugins/index.ts +195 -0
- package/teste-corrigido/core/plugins/manager.ts +583 -0
- package/teste-corrigido/core/plugins/registry.ts +424 -0
- package/teste-corrigido/core/plugins/types.ts +254 -0
- package/teste-corrigido/core/server/framework.ts +123 -0
- package/teste-corrigido/core/server/index.ts +8 -0
- package/teste-corrigido/core/server/plugins/database.ts +182 -0
- package/teste-corrigido/core/server/plugins/logger.ts +47 -0
- package/teste-corrigido/core/server/plugins/swagger.ts +34 -0
- package/teste-corrigido/core/server/standalone.ts +91 -0
- package/teste-corrigido/core/templates/create-project.ts +455 -0
- package/teste-corrigido/core/types/api.ts +169 -0
- package/teste-corrigido/core/types/build.ts +174 -0
- package/teste-corrigido/core/types/config.ts +68 -0
- package/teste-corrigido/core/types/index.ts +127 -0
- package/teste-corrigido/core/types/plugin.ts +94 -0
- package/teste-corrigido/core/utils/__tests__/errors.test.ts +139 -0
- package/teste-corrigido/core/utils/__tests__/helpers.test.ts +297 -0
- package/teste-corrigido/core/utils/__tests__/logger.test.ts +141 -0
- package/teste-corrigido/core/utils/env-runtime-v2.ts +232 -0
- package/teste-corrigido/core/utils/env-runtime.ts +252 -0
- package/teste-corrigido/core/utils/errors/codes.ts +115 -0
- package/teste-corrigido/core/utils/errors/handlers.ts +63 -0
- package/teste-corrigido/core/utils/errors/index.ts +81 -0
- package/teste-corrigido/core/utils/helpers.ts +180 -0
- package/teste-corrigido/core/utils/index.ts +18 -0
- package/teste-corrigido/core/utils/logger/index.ts +161 -0
- package/teste-corrigido/core/utils/logger.ts +106 -0
- package/teste-corrigido/core/utils/monitoring/index.ts +212 -0
- package/teste-corrigido/package-template.json +51 -0
- package/teste-corrigido/package.json +51 -0
- package/teste-corrigido/tsconfig.json +51 -0
- package/teste-corrigido/vite.config.ts +42 -0
- package/teste-final-npm/README.md +44 -0
- package/teste-final-npm/app/client/README.md +69 -0
- package/teste-final-npm/app/client/frontend-only.ts +12 -0
- package/teste-final-npm/app/client/index.html +13 -0
- package/teste-final-npm/app/client/public/vite.svg +1 -0
- package/teste-final-npm/app/client/src/App.css +883 -0
- package/teste-final-npm/app/client/src/App.tsx +669 -0
- package/teste-final-npm/app/client/src/assets/react.svg +1 -0
- package/teste-final-npm/app/client/src/components/TestPage.tsx +453 -0
- package/teste-final-npm/app/client/src/index.css +51 -0
- package/teste-final-npm/app/client/src/lib/eden-api.ts +110 -0
- package/teste-final-npm/app/client/src/main.tsx +10 -0
- package/teste-final-npm/app/client/src/vite-env.d.ts +1 -0
- package/teste-final-npm/app/client/tsconfig.app.json +43 -0
- package/teste-final-npm/app/client/tsconfig.json +7 -0
- package/teste-final-npm/app/client/tsconfig.node.json +25 -0
- package/teste-final-npm/app/server/app.ts +10 -0
- package/teste-final-npm/app/server/backend-only.ts +15 -0
- package/teste-final-npm/app/server/controllers/users.controller.ts +69 -0
- package/teste-final-npm/app/server/index.ts +104 -0
- package/teste-final-npm/app/server/routes/index.ts +25 -0
- package/teste-final-npm/app/server/routes/users.routes.ts +121 -0
- package/teste-final-npm/app/server/types/index.ts +1 -0
- package/teste-final-npm/app/shared/types/index.ts +18 -0
- package/teste-final-npm/bun.lock +1053 -0
- package/teste-final-npm/core/__tests__/integration.test.ts +227 -0
- package/teste-final-npm/core/build/index.ts +186 -0
- package/teste-final-npm/core/cli/command-registry.ts +334 -0
- package/teste-final-npm/core/cli/index.ts +394 -0
- package/teste-final-npm/core/cli/plugin-discovery.ts +200 -0
- package/teste-final-npm/core/client/standalone.ts +57 -0
- package/teste-final-npm/core/config/__tests__/config-loader.test.ts +591 -0
- package/teste-final-npm/core/config/__tests__/config-merger.test.ts +657 -0
- package/teste-final-npm/core/config/__tests__/env-converter.test.ts +372 -0
- package/teste-final-npm/core/config/__tests__/env-processor.test.ts +431 -0
- package/teste-final-npm/core/config/__tests__/env.test.ts +452 -0
- package/teste-final-npm/core/config/__tests__/integration.test.ts +418 -0
- package/teste-final-npm/core/config/__tests__/loader.test.ts +331 -0
- package/teste-final-npm/core/config/__tests__/schema.test.ts +129 -0
- package/teste-final-npm/core/config/__tests__/validator.test.ts +318 -0
- package/teste-final-npm/core/config/env-dynamic.ts +326 -0
- package/teste-final-npm/core/config/env.ts +597 -0
- package/teste-final-npm/core/config/index.ts +317 -0
- package/teste-final-npm/core/config/loader.ts +546 -0
- package/teste-final-npm/core/config/runtime-config.ts +322 -0
- package/teste-final-npm/core/config/schema.ts +694 -0
- package/teste-final-npm/core/config/validator.ts +540 -0
- package/teste-final-npm/core/framework/__tests__/server.test.ts +233 -0
- package/teste-final-npm/core/framework/client.ts +132 -0
- package/teste-final-npm/core/framework/index.ts +8 -0
- package/teste-final-npm/core/framework/server.ts +501 -0
- package/teste-final-npm/core/framework/types.ts +63 -0
- package/teste-final-npm/core/plugins/__tests__/built-in.test.ts.disabled +366 -0
- package/teste-final-npm/core/plugins/__tests__/manager.test.ts +398 -0
- package/teste-final-npm/core/plugins/__tests__/monitoring.test.ts +401 -0
- package/teste-final-npm/core/plugins/__tests__/registry.test.ts +335 -0
- package/teste-final-npm/core/plugins/built-in/index.ts +142 -0
- package/teste-final-npm/core/plugins/built-in/logger/index.ts +180 -0
- package/teste-final-npm/core/plugins/built-in/monitoring/README.md +193 -0
- package/teste-final-npm/core/plugins/built-in/monitoring/index.ts +912 -0
- package/teste-final-npm/core/plugins/built-in/static/index.ts +289 -0
- package/teste-final-npm/core/plugins/built-in/swagger/index.ts +229 -0
- package/teste-final-npm/core/plugins/built-in/vite/index.ts +316 -0
- package/teste-final-npm/core/plugins/config.ts +348 -0
- package/teste-final-npm/core/plugins/discovery.ts +350 -0
- package/teste-final-npm/core/plugins/executor.ts +351 -0
- package/teste-final-npm/core/plugins/index.ts +195 -0
- package/teste-final-npm/core/plugins/manager.ts +583 -0
- package/teste-final-npm/core/plugins/registry.ts +424 -0
- package/teste-final-npm/core/plugins/types.ts +254 -0
- package/teste-final-npm/core/server/framework.ts +123 -0
- package/teste-final-npm/core/server/index.ts +8 -0
- package/teste-final-npm/core/server/plugins/database.ts +182 -0
- package/teste-final-npm/core/server/plugins/logger.ts +47 -0
- package/teste-final-npm/core/server/plugins/swagger.ts +34 -0
- package/teste-final-npm/core/server/standalone.ts +91 -0
- package/teste-final-npm/core/templates/create-project.ts +455 -0
- package/teste-final-npm/core/types/api.ts +169 -0
- package/teste-final-npm/core/types/build.ts +174 -0
- package/teste-final-npm/core/types/config.ts +68 -0
- package/teste-final-npm/core/types/index.ts +127 -0
- package/teste-final-npm/core/types/plugin.ts +94 -0
- package/teste-final-npm/core/utils/__tests__/errors.test.ts +139 -0
- package/teste-final-npm/core/utils/__tests__/helpers.test.ts +297 -0
- package/teste-final-npm/core/utils/__tests__/logger.test.ts +141 -0
- package/teste-final-npm/core/utils/env-runtime-v2.ts +232 -0
- package/teste-final-npm/core/utils/env-runtime.ts +252 -0
- package/teste-final-npm/core/utils/errors/codes.ts +115 -0
- package/teste-final-npm/core/utils/errors/handlers.ts +63 -0
- package/teste-final-npm/core/utils/errors/index.ts +81 -0
- package/teste-final-npm/core/utils/helpers.ts +180 -0
- package/teste-final-npm/core/utils/index.ts +18 -0
- package/teste-final-npm/core/utils/logger/index.ts +161 -0
- package/teste-final-npm/core/utils/logger.ts +106 -0
- package/teste-final-npm/core/utils/monitoring/index.ts +212 -0
- package/teste-final-npm/package-template.json +51 -0
- package/teste-final-npm/package.json +51 -0
- package/teste-final-npm/tsconfig.json +51 -0
- package/teste-final-npm/vite.config.ts +42 -0
- package/tests/__mocks__/api.ts +56 -0
- package/tests/fixtures/users.ts +69 -0
- package/tests/integration/api/users.routes.test.ts +221 -0
- package/tests/setup.ts +29 -0
- package/tests/unit/app/client/App-simple.test.tsx +56 -0
- package/tests/unit/app/client/App.test.tsx.skip +237 -0
- package/tests/unit/app/client/eden-api.test.ts +186 -0
- package/tests/unit/app/client/simple.test.tsx +23 -0
- package/tests/unit/app/controllers/users.controller.test.ts +150 -0
- package/tests/unit/core/create-project.test.ts.skip +95 -0
- package/tests/unit/core/framework.test.ts +144 -0
- package/tests/unit/core/plugins/logger.test.ts.skip +268 -0
- package/tests/unit/core/plugins/vite.test.ts.disabled +188 -0
- package/tests/utils/test-helpers.ts +61 -0
- package/types/global.d.ts +30 -0
- package/types/vitest.d.ts +9 -0
- package/vitest.config.ts +50 -0
- package/workspace.json +6 -0
- package/.env +0 -30
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import type { Plugin, PluginContext, RequestContext } from "../../types"
|
|
2
|
+
import { createServer, type ViteDevServer } from 'vite'
|
|
3
|
+
|
|
4
|
+
let viteServer: ViteDevServer | null = null
|
|
5
|
+
|
|
6
|
+
export const vitePlugin: Plugin = {
|
|
7
|
+
name: "vite",
|
|
8
|
+
version: "1.0.0",
|
|
9
|
+
description: "Enhanced Vite integration plugin for FluxStack with improved error handling and monitoring",
|
|
10
|
+
author: "FluxStack Team",
|
|
11
|
+
priority: "high", // Should run early to setup proxying
|
|
12
|
+
category: "development",
|
|
13
|
+
tags: ["vite", "development", "hot-reload"],
|
|
14
|
+
dependencies: [], // No dependencies
|
|
15
|
+
|
|
16
|
+
configSchema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
enabled: {
|
|
20
|
+
type: "boolean",
|
|
21
|
+
description: "Enable Vite integration"
|
|
22
|
+
},
|
|
23
|
+
port: {
|
|
24
|
+
type: "number",
|
|
25
|
+
minimum: 1,
|
|
26
|
+
maximum: 65535,
|
|
27
|
+
description: "Vite development server port"
|
|
28
|
+
},
|
|
29
|
+
host: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Vite development server host"
|
|
32
|
+
},
|
|
33
|
+
checkInterval: {
|
|
34
|
+
type: "number",
|
|
35
|
+
minimum: 100,
|
|
36
|
+
description: "Interval to check if Vite is running (ms)"
|
|
37
|
+
},
|
|
38
|
+
maxRetries: {
|
|
39
|
+
type: "number",
|
|
40
|
+
minimum: 1,
|
|
41
|
+
description: "Maximum retries to connect to Vite"
|
|
42
|
+
},
|
|
43
|
+
timeout: {
|
|
44
|
+
type: "number",
|
|
45
|
+
minimum: 100,
|
|
46
|
+
description: "Timeout for Vite requests (ms)"
|
|
47
|
+
},
|
|
48
|
+
proxyPaths: {
|
|
49
|
+
type: "array",
|
|
50
|
+
items: { type: "string" },
|
|
51
|
+
description: "Paths to proxy to Vite (defaults to all non-API paths)"
|
|
52
|
+
},
|
|
53
|
+
excludePaths: {
|
|
54
|
+
type: "array",
|
|
55
|
+
items: { type: "string" },
|
|
56
|
+
description: "Paths to exclude from Vite proxying"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
additionalProperties: false
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
defaultConfig: {
|
|
63
|
+
enabled: true,
|
|
64
|
+
port: 5173,
|
|
65
|
+
host: "localhost",
|
|
66
|
+
checkInterval: 2000,
|
|
67
|
+
maxRetries: 10,
|
|
68
|
+
timeout: 5000,
|
|
69
|
+
proxyPaths: [],
|
|
70
|
+
excludePaths: []
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
setup: async (context: PluginContext) => {
|
|
74
|
+
const config = getPluginConfig(context)
|
|
75
|
+
|
|
76
|
+
if (!config.enabled || !context.config.client) {
|
|
77
|
+
context.logger.info('Vite plugin disabled or no client configuration found')
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const vitePort = config.port || context.config.client.port || 5173
|
|
82
|
+
const viteHost = config.host || "localhost"
|
|
83
|
+
|
|
84
|
+
context.logger.info(`🎨 Starting Vite dev server programmatically on ${viteHost}:${vitePort}`)
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
// Start Vite dev server programmatically
|
|
88
|
+
viteServer = await createServer({
|
|
89
|
+
configFile: './vite.config.ts',
|
|
90
|
+
// Don't override root - let vite.config.ts handle it
|
|
91
|
+
server: {
|
|
92
|
+
port: vitePort,
|
|
93
|
+
host: viteHost
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
await viteServer.listen()
|
|
98
|
+
viteServer.printUrls()
|
|
99
|
+
|
|
100
|
+
context.logger.info(`✅ Vite server started successfully on ${viteHost}:${vitePort}`)
|
|
101
|
+
context.logger.info('🔄 Hot reload coordination active - Zero órfãos!')
|
|
102
|
+
|
|
103
|
+
// Store Vite config in context for later use
|
|
104
|
+
;(context as any).viteConfig = {
|
|
105
|
+
port: vitePort,
|
|
106
|
+
host: viteHost,
|
|
107
|
+
...config,
|
|
108
|
+
server: viteServer
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Setup cleanup on process exit
|
|
112
|
+
const cleanup = async () => {
|
|
113
|
+
if (viteServer) {
|
|
114
|
+
context.logger.info('🛑 Stopping Vite server...')
|
|
115
|
+
await viteServer.close()
|
|
116
|
+
viteServer = null
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
process.on('SIGINT', cleanup)
|
|
121
|
+
process.on('SIGTERM', cleanup)
|
|
122
|
+
process.on('exit', cleanup)
|
|
123
|
+
|
|
124
|
+
} catch (error) {
|
|
125
|
+
context.logger.error('❌ Failed to start Vite server programmatically:', error)
|
|
126
|
+
context.logger.info('⚠️ Falling back to monitoring mode...')
|
|
127
|
+
|
|
128
|
+
// Fallback to monitoring if programmatic start fails
|
|
129
|
+
;(context as any).viteConfig = {
|
|
130
|
+
port: vitePort,
|
|
131
|
+
host: viteHost,
|
|
132
|
+
...config
|
|
133
|
+
}
|
|
134
|
+
monitorVite(context, viteHost, vitePort, config)
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
onServerStart: async (context: PluginContext) => {
|
|
139
|
+
const config = getPluginConfig(context)
|
|
140
|
+
const viteConfig = (context as any).viteConfig
|
|
141
|
+
|
|
142
|
+
if (config.enabled && viteConfig) {
|
|
143
|
+
context.logger.info(`Vite integration active - monitoring ${viteConfig.host}:${viteConfig.port}`)
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
onBeforeRoute: async (requestContext: RequestContext) => {
|
|
148
|
+
// Skip API routes and swagger - let them be handled by backend
|
|
149
|
+
if (requestContext.path.startsWith("/api") || requestContext.path.startsWith("/swagger")) {
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Use fixed configuration for simplicity - Vite should be running on port 5173
|
|
154
|
+
const viteHost = "localhost"
|
|
155
|
+
const vitePort = 5173
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const url = new URL(requestContext.request.url)
|
|
159
|
+
const viteUrl = `http://${viteHost}:${vitePort}${requestContext.path}${url.search}`
|
|
160
|
+
|
|
161
|
+
// Forward request to Vite
|
|
162
|
+
const response = await fetch(viteUrl, {
|
|
163
|
+
method: requestContext.method,
|
|
164
|
+
headers: requestContext.headers,
|
|
165
|
+
body: requestContext.method !== 'GET' && requestContext.method !== 'HEAD' ? requestContext.request.body : undefined
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
// If Vite responds successfully, handle the request
|
|
169
|
+
if (response.ok || response.status < 500) {
|
|
170
|
+
// Return a proper Response object with all headers and status
|
|
171
|
+
const body = await response.arrayBuffer()
|
|
172
|
+
|
|
173
|
+
requestContext.handled = true
|
|
174
|
+
requestContext.response = new Response(body, {
|
|
175
|
+
status: response.status,
|
|
176
|
+
statusText: response.statusText,
|
|
177
|
+
headers: response.headers
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
} catch (viteError) {
|
|
182
|
+
// If Vite fails, let the request continue to normal routing (will become 404)
|
|
183
|
+
// Only log if explicitly enabled for debugging
|
|
184
|
+
if (process.env.ENABLE_VITE_PROXY_LOGS === 'true') {
|
|
185
|
+
console.warn(`Vite proxy error: ${viteError}`)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Helper function to get plugin config
|
|
192
|
+
function getPluginConfig(context: PluginContext) {
|
|
193
|
+
const pluginConfig = context.config.plugins.config?.vite || {}
|
|
194
|
+
return { ...vitePlugin.defaultConfig, ...pluginConfig }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Monitor Vite server status with automatic port detection
|
|
198
|
+
async function monitorVite(
|
|
199
|
+
context: PluginContext,
|
|
200
|
+
host: string,
|
|
201
|
+
initialPort: number,
|
|
202
|
+
config: any
|
|
203
|
+
) {
|
|
204
|
+
let retries = 0
|
|
205
|
+
let isConnected = false
|
|
206
|
+
let actualPort = initialPort
|
|
207
|
+
let portDetected = false
|
|
208
|
+
|
|
209
|
+
const checkVite = async () => {
|
|
210
|
+
try {
|
|
211
|
+
// If we haven't found the correct port yet, try to detect it
|
|
212
|
+
if (!portDetected) {
|
|
213
|
+
const detectedPort = await detectVitePort(host, initialPort)
|
|
214
|
+
if (detectedPort !== null) {
|
|
215
|
+
actualPort = detectedPort
|
|
216
|
+
portDetected = true
|
|
217
|
+
// Update the context with the detected port
|
|
218
|
+
if ((context as any).viteConfig) {
|
|
219
|
+
;(context as any).viteConfig.port = actualPort
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const isRunning = await checkViteRunning(host, actualPort, config.timeout)
|
|
225
|
+
|
|
226
|
+
if (isRunning && !isConnected) {
|
|
227
|
+
isConnected = true
|
|
228
|
+
retries = 0
|
|
229
|
+
if (actualPort !== initialPort) {
|
|
230
|
+
context.logger.info(`✓ Vite server detected on ${host}:${actualPort} (auto-detected from port ${initialPort})`)
|
|
231
|
+
} else {
|
|
232
|
+
context.logger.info(`✓ Vite server detected on ${host}:${actualPort}`)
|
|
233
|
+
}
|
|
234
|
+
context.logger.info("Hot reload coordination active")
|
|
235
|
+
} else if (!isRunning && isConnected) {
|
|
236
|
+
isConnected = false
|
|
237
|
+
context.logger.warn(`✗ Vite server disconnected from ${host}:${actualPort}`)
|
|
238
|
+
// Reset port detection when disconnected
|
|
239
|
+
portDetected = false
|
|
240
|
+
actualPort = initialPort
|
|
241
|
+
} else if (!isRunning) {
|
|
242
|
+
retries++
|
|
243
|
+
if (retries <= config.maxRetries) {
|
|
244
|
+
if (portDetected) {
|
|
245
|
+
context.logger.debug(`Waiting for Vite server on ${host}:${actualPort}... (${retries}/${config.maxRetries})`)
|
|
246
|
+
} else {
|
|
247
|
+
context.logger.debug(`Detecting Vite server port... (${retries}/${config.maxRetries})`)
|
|
248
|
+
}
|
|
249
|
+
} else if (retries === config.maxRetries + 1) {
|
|
250
|
+
context.logger.warn(`Vite server not found after ${config.maxRetries} attempts. Development features may be limited.`)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
} catch (error) {
|
|
254
|
+
if (isConnected) {
|
|
255
|
+
context.logger.error('Error checking Vite server status', { error })
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Continue monitoring
|
|
260
|
+
setTimeout(checkVite, config.checkInterval)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Start monitoring after a brief delay
|
|
264
|
+
setTimeout(checkVite, 1000)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Auto-detect Vite port by trying common ports
|
|
268
|
+
async function detectVitePort(host: string, startPort: number): Promise<number | null> {
|
|
269
|
+
// Try the initial port first, then common alternatives
|
|
270
|
+
const portsToTry = [
|
|
271
|
+
startPort,
|
|
272
|
+
startPort + 1,
|
|
273
|
+
startPort + 2,
|
|
274
|
+
startPort + 3,
|
|
275
|
+
5174, // Common Vite alternative
|
|
276
|
+
5175,
|
|
277
|
+
5176,
|
|
278
|
+
3000, // Sometimes Vite might use this
|
|
279
|
+
4173 // Another common alternative
|
|
280
|
+
]
|
|
281
|
+
|
|
282
|
+
for (const port of portsToTry) {
|
|
283
|
+
try {
|
|
284
|
+
const isRunning = await checkViteRunning(host, port, 1000)
|
|
285
|
+
if (isRunning) {
|
|
286
|
+
return port
|
|
287
|
+
}
|
|
288
|
+
} catch (error) {
|
|
289
|
+
// Continue trying other ports
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return null
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Check if Vite is running
|
|
297
|
+
async function checkViteRunning(host: string, port: number, timeout: number = 1000): Promise<boolean> {
|
|
298
|
+
try {
|
|
299
|
+
const controller = new AbortController()
|
|
300
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout)
|
|
301
|
+
|
|
302
|
+
const response = await fetch(`http://${host}:${port}`, {
|
|
303
|
+
signal: controller.signal,
|
|
304
|
+
method: 'HEAD' // Use HEAD to minimize data transfer
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
clearTimeout(timeoutId)
|
|
308
|
+
return response.status >= 200 && response.status < 500
|
|
309
|
+
} catch (error) {
|
|
310
|
+
return false
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Note: Proxy logic is now handled directly in the onBeforeRoute hook above
|
|
315
|
+
|
|
316
|
+
export default vitePlugin
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Configuration Management
|
|
3
|
+
* Handles plugin-specific configuration validation and management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Plugin, PluginConfigSchema, PluginValidationResult } from "./types"
|
|
7
|
+
import type { FluxStackConfig } from "../config/schema"
|
|
8
|
+
import type { Logger } from "../utils/logger/index"
|
|
9
|
+
|
|
10
|
+
export interface PluginConfigManager {
|
|
11
|
+
validatePluginConfig(plugin: Plugin, config: any): PluginValidationResult
|
|
12
|
+
mergePluginConfig(plugin: Plugin, userConfig: any): any
|
|
13
|
+
getPluginConfig(pluginName: string, config: FluxStackConfig): any
|
|
14
|
+
setPluginConfig(pluginName: string, pluginConfig: any, config: FluxStackConfig): void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class DefaultPluginConfigManager implements PluginConfigManager {
|
|
18
|
+
constructor(_logger?: Logger) {
|
|
19
|
+
// Logger stored but not used in current implementation
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Validate plugin configuration against its schema
|
|
24
|
+
*/
|
|
25
|
+
validatePluginConfig(plugin: Plugin, config: any): PluginValidationResult {
|
|
26
|
+
const result: PluginValidationResult = {
|
|
27
|
+
valid: true,
|
|
28
|
+
errors: [],
|
|
29
|
+
warnings: []
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!plugin.configSchema) {
|
|
33
|
+
// No schema means any config is valid
|
|
34
|
+
return result
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
this.validateAgainstSchema(config, plugin.configSchema, plugin.name, result)
|
|
39
|
+
} catch (error) {
|
|
40
|
+
result.valid = false
|
|
41
|
+
result.errors.push(`Configuration validation failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return result
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Merge user configuration with plugin defaults
|
|
49
|
+
*/
|
|
50
|
+
mergePluginConfig(plugin: Plugin, userConfig: any): any {
|
|
51
|
+
const defaultConfig = plugin.defaultConfig || {}
|
|
52
|
+
|
|
53
|
+
if (!userConfig) {
|
|
54
|
+
return defaultConfig
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return this.deepMerge(defaultConfig, userConfig)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get plugin configuration from main config
|
|
62
|
+
*/
|
|
63
|
+
getPluginConfig(pluginName: string, config: FluxStackConfig): any {
|
|
64
|
+
return config.plugins.config[pluginName] || {}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Set plugin configuration in main config
|
|
69
|
+
*/
|
|
70
|
+
setPluginConfig(pluginName: string, pluginConfig: any, config: FluxStackConfig): void {
|
|
71
|
+
if (!config.plugins.config) {
|
|
72
|
+
config.plugins.config = {}
|
|
73
|
+
}
|
|
74
|
+
config.plugins.config[pluginName] = pluginConfig
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Validate configuration against JSON schema
|
|
79
|
+
*/
|
|
80
|
+
private validateAgainstSchema(
|
|
81
|
+
data: any,
|
|
82
|
+
schema: PluginConfigSchema,
|
|
83
|
+
pluginName: string,
|
|
84
|
+
result: PluginValidationResult
|
|
85
|
+
): void {
|
|
86
|
+
if (schema.type === 'object' && typeof data !== 'object') {
|
|
87
|
+
result.valid = false
|
|
88
|
+
result.errors.push(`Plugin '${pluginName}' configuration must be an object`)
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check required properties
|
|
93
|
+
if (schema.required && Array.isArray(schema.required)) {
|
|
94
|
+
for (const requiredProp of schema.required) {
|
|
95
|
+
if (!(requiredProp in data)) {
|
|
96
|
+
result.valid = false
|
|
97
|
+
result.errors.push(`Plugin '${pluginName}' configuration missing required property: ${requiredProp}`)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Validate properties
|
|
103
|
+
if (schema.properties) {
|
|
104
|
+
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
105
|
+
if (propName in data) {
|
|
106
|
+
this.validateProperty(data[propName], propSchema, `${pluginName}.${propName}`, result)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Check for additional properties
|
|
112
|
+
if (schema.additionalProperties === false) {
|
|
113
|
+
const allowedProps = Object.keys(schema.properties || {})
|
|
114
|
+
const actualProps = Object.keys(data)
|
|
115
|
+
|
|
116
|
+
for (const prop of actualProps) {
|
|
117
|
+
if (!allowedProps.includes(prop)) {
|
|
118
|
+
result.warnings.push(`Plugin '${pluginName}' configuration has unexpected property: ${prop}`)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Validate individual property
|
|
126
|
+
*/
|
|
127
|
+
private validateProperty(value: any, schema: any, path: string, result: PluginValidationResult): void {
|
|
128
|
+
if (schema.type) {
|
|
129
|
+
const actualType = Array.isArray(value) ? 'array' : typeof value
|
|
130
|
+
if (actualType !== schema.type) {
|
|
131
|
+
result.valid = false
|
|
132
|
+
result.errors.push(`Property '${path}' must be of type ${schema.type}, got ${actualType}`)
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Type-specific validations
|
|
138
|
+
switch (schema.type) {
|
|
139
|
+
case 'string':
|
|
140
|
+
this.validateStringProperty(value, schema, path, result)
|
|
141
|
+
break
|
|
142
|
+
case 'number':
|
|
143
|
+
this.validateNumberProperty(value, schema, path, result)
|
|
144
|
+
break
|
|
145
|
+
case 'array':
|
|
146
|
+
this.validateArrayProperty(value, schema, path, result)
|
|
147
|
+
break
|
|
148
|
+
case 'object':
|
|
149
|
+
if (schema.properties) {
|
|
150
|
+
this.validateObjectProperty(value, schema, path, result)
|
|
151
|
+
}
|
|
152
|
+
break
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Enum validation
|
|
156
|
+
if (schema.enum && !schema.enum.includes(value)) {
|
|
157
|
+
result.valid = false
|
|
158
|
+
result.errors.push(`Property '${path}' must be one of: ${schema.enum.join(', ')}`)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Validate string property
|
|
164
|
+
*/
|
|
165
|
+
private validateStringProperty(value: string, schema: any, path: string, result: PluginValidationResult): void {
|
|
166
|
+
if (schema.minLength && value.length < schema.minLength) {
|
|
167
|
+
result.valid = false
|
|
168
|
+
result.errors.push(`Property '${path}' must be at least ${schema.minLength} characters long`)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (schema.maxLength && value.length > schema.maxLength) {
|
|
172
|
+
result.valid = false
|
|
173
|
+
result.errors.push(`Property '${path}' must be at most ${schema.maxLength} characters long`)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (schema.pattern) {
|
|
177
|
+
const regex = new RegExp(schema.pattern)
|
|
178
|
+
if (!regex.test(value)) {
|
|
179
|
+
result.valid = false
|
|
180
|
+
result.errors.push(`Property '${path}' does not match required pattern: ${schema.pattern}`)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Validate number property
|
|
187
|
+
*/
|
|
188
|
+
private validateNumberProperty(value: number, schema: any, path: string, result: PluginValidationResult): void {
|
|
189
|
+
if (schema.minimum !== undefined && value < schema.minimum) {
|
|
190
|
+
result.valid = false
|
|
191
|
+
result.errors.push(`Property '${path}' must be at least ${schema.minimum}`)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (schema.maximum !== undefined && value > schema.maximum) {
|
|
195
|
+
result.valid = false
|
|
196
|
+
result.errors.push(`Property '${path}' must be at most ${schema.maximum}`)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (schema.multipleOf && value % schema.multipleOf !== 0) {
|
|
200
|
+
result.valid = false
|
|
201
|
+
result.errors.push(`Property '${path}' must be a multiple of ${schema.multipleOf}`)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Validate array property
|
|
207
|
+
*/
|
|
208
|
+
private validateArrayProperty(value: any[], schema: any, path: string, result: PluginValidationResult): void {
|
|
209
|
+
if (schema.minItems && value.length < schema.minItems) {
|
|
210
|
+
result.valid = false
|
|
211
|
+
result.errors.push(`Property '${path}' must have at least ${schema.minItems} items`)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (schema.maxItems && value.length > schema.maxItems) {
|
|
215
|
+
result.valid = false
|
|
216
|
+
result.errors.push(`Property '${path}' must have at most ${schema.maxItems} items`)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (schema.items) {
|
|
220
|
+
value.forEach((item, index) => {
|
|
221
|
+
this.validateProperty(item, schema.items, `${path}[${index}]`, result)
|
|
222
|
+
})
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Validate object property
|
|
228
|
+
*/
|
|
229
|
+
private validateObjectProperty(value: any, schema: any, path: string, result: PluginValidationResult): void {
|
|
230
|
+
if (schema.required) {
|
|
231
|
+
for (const requiredProp of schema.required) {
|
|
232
|
+
if (!(requiredProp in value)) {
|
|
233
|
+
result.valid = false
|
|
234
|
+
result.errors.push(`Property '${path}' missing required property: ${requiredProp}`)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (schema.properties) {
|
|
240
|
+
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
241
|
+
if (propName in value) {
|
|
242
|
+
this.validateProperty(value[propName], propSchema, `${path}.${propName}`, result)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Deep merge two objects
|
|
250
|
+
*/
|
|
251
|
+
private deepMerge(target: any, source: any): any {
|
|
252
|
+
if (source === null || source === undefined) {
|
|
253
|
+
return target
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (target === null || target === undefined) {
|
|
257
|
+
return source
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (typeof target !== 'object' || typeof source !== 'object') {
|
|
261
|
+
return source
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (Array.isArray(source)) {
|
|
265
|
+
return [...source]
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const result = { ...target }
|
|
269
|
+
|
|
270
|
+
for (const key in source) {
|
|
271
|
+
if (source.hasOwnProperty(key)) {
|
|
272
|
+
if (typeof source[key] === 'object' && !Array.isArray(source[key]) && source[key] !== null) {
|
|
273
|
+
result[key] = this.deepMerge(target[key], source[key])
|
|
274
|
+
} else {
|
|
275
|
+
result[key] = source[key]
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return result
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Create plugin configuration utilities
|
|
286
|
+
*/
|
|
287
|
+
export function createPluginUtils(logger?: Logger): PluginUtils {
|
|
288
|
+
return {
|
|
289
|
+
createTimer: (label: string) => {
|
|
290
|
+
const start = Date.now()
|
|
291
|
+
return {
|
|
292
|
+
end: () => {
|
|
293
|
+
const duration = Date.now() - start
|
|
294
|
+
logger?.debug(`Timer '${label}' completed`, { duration })
|
|
295
|
+
return duration
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
formatBytes: (bytes: number): string => {
|
|
301
|
+
if (bytes === 0) return '0 Bytes'
|
|
302
|
+
const k = 1024
|
|
303
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
|
|
304
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
305
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
isProduction: (): boolean => {
|
|
309
|
+
return process.env.NODE_ENV === 'production'
|
|
310
|
+
},
|
|
311
|
+
|
|
312
|
+
isDevelopment: (): boolean => {
|
|
313
|
+
return process.env.NODE_ENV === 'development'
|
|
314
|
+
},
|
|
315
|
+
|
|
316
|
+
getEnvironment: (): string => {
|
|
317
|
+
return process.env.NODE_ENV || 'development'
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
createHash: (data: string): string => {
|
|
321
|
+
// Simple hash function - in production, use crypto
|
|
322
|
+
let hash = 0
|
|
323
|
+
for (let i = 0; i < data.length; i++) {
|
|
324
|
+
const char = data.charCodeAt(i)
|
|
325
|
+
hash = ((hash << 5) - hash) + char
|
|
326
|
+
hash = hash & hash // Convert to 32-bit integer
|
|
327
|
+
}
|
|
328
|
+
return hash.toString(36)
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
deepMerge: (target: any, source: any): any => {
|
|
332
|
+
const manager = new DefaultPluginConfigManager()
|
|
333
|
+
return (manager as any).deepMerge(target, source)
|
|
334
|
+
},
|
|
335
|
+
|
|
336
|
+
validateSchema: (data: any, schema: any): { valid: boolean; errors: string[] } => {
|
|
337
|
+
const manager = new DefaultPluginConfigManager()
|
|
338
|
+
const result = manager.validatePluginConfig({ name: 'temp', configSchema: schema }, data)
|
|
339
|
+
return {
|
|
340
|
+
valid: result.valid,
|
|
341
|
+
errors: result.errors
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Export types for plugin utilities
|
|
348
|
+
import type { PluginUtils } from "./types"
|