@friggframework/devtools 2.0.0-next.6 → 2.0.0-next.60
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/frigg-cli/README.md +1289 -0
- package/frigg-cli/__tests__/unit/commands/build.test.js +279 -0
- package/frigg-cli/__tests__/unit/commands/db-setup.test.js +649 -0
- package/frigg-cli/__tests__/unit/commands/deploy.test.js +320 -0
- package/frigg-cli/__tests__/unit/commands/doctor.test.js +309 -0
- package/frigg-cli/__tests__/unit/commands/install.test.js +400 -0
- package/frigg-cli/__tests__/unit/commands/ui.test.js +346 -0
- package/frigg-cli/__tests__/unit/dependencies.test.js +74 -0
- package/frigg-cli/__tests__/unit/utils/database-validator.test.js +397 -0
- package/frigg-cli/__tests__/unit/utils/error-messages.test.js +345 -0
- package/frigg-cli/__tests__/unit/version-detection.test.js +171 -0
- package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
- package/frigg-cli/__tests__/utils/prisma-mock.js +194 -0
- package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
- package/frigg-cli/__tests__/utils/test-setup.js +287 -0
- package/frigg-cli/build-command/index.js +53 -14
- package/frigg-cli/db-setup-command/index.js +246 -0
- package/frigg-cli/deploy-command/SPEC-DEPLOY-DRY-RUN.md +981 -0
- package/frigg-cli/deploy-command/index.js +295 -17
- package/frigg-cli/doctor-command/index.js +335 -0
- package/frigg-cli/generate-command/__tests__/generate-command.test.js +301 -0
- package/frigg-cli/generate-command/azure-generator.js +43 -0
- package/frigg-cli/generate-command/gcp-generator.js +47 -0
- package/frigg-cli/generate-command/index.js +332 -0
- package/frigg-cli/generate-command/terraform-generator.js +555 -0
- package/frigg-cli/generate-iam-command.js +118 -0
- package/frigg-cli/index.js +142 -1
- package/frigg-cli/index.test.js +1 -4
- package/frigg-cli/init-command/backend-first-handler.js +756 -0
- package/frigg-cli/init-command/index.js +93 -0
- package/frigg-cli/init-command/template-handler.js +143 -0
- package/frigg-cli/install-command/index.js +1 -4
- package/frigg-cli/jest.config.js +124 -0
- package/frigg-cli/package.json +63 -0
- package/frigg-cli/repair-command/index.js +564 -0
- package/frigg-cli/start-command/index.js +125 -6
- package/frigg-cli/start-command/start-command.test.js +297 -0
- package/frigg-cli/test/init-command.test.js +180 -0
- package/frigg-cli/test/npm-registry.test.js +319 -0
- package/frigg-cli/ui-command/index.js +154 -0
- package/frigg-cli/utils/app-resolver.js +319 -0
- package/frigg-cli/utils/backend-path.js +16 -17
- package/frigg-cli/utils/database-validator.js +167 -0
- package/frigg-cli/utils/error-messages.js +329 -0
- package/frigg-cli/utils/npm-registry.js +167 -0
- package/frigg-cli/utils/process-manager.js +199 -0
- package/frigg-cli/utils/repo-detection.js +405 -0
- package/infrastructure/ARCHITECTURE.md +487 -0
- package/infrastructure/CLAUDE.md +481 -0
- package/infrastructure/HEALTH.md +468 -0
- package/infrastructure/README.md +522 -0
- package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
- package/infrastructure/__tests__/helpers/test-utils.js +277 -0
- package/infrastructure/__tests__/postgres-config.test.js +914 -0
- package/infrastructure/__tests__/template-generation.test.js +687 -0
- package/infrastructure/create-frigg-infrastructure.js +129 -20
- package/infrastructure/docs/POSTGRES-CONFIGURATION.md +630 -0
- package/infrastructure/docs/PRE-DEPLOYMENT-HEALTH-CHECK-SPEC.md +1317 -0
- package/infrastructure/docs/WEBSOCKET-CONFIGURATION.md +105 -0
- package/infrastructure/docs/deployment-instructions.md +268 -0
- package/infrastructure/docs/generate-iam-command.md +278 -0
- package/infrastructure/docs/iam-policy-templates.md +193 -0
- package/infrastructure/domains/database/aurora-builder.js +809 -0
- package/infrastructure/domains/database/aurora-builder.test.js +950 -0
- package/infrastructure/domains/database/aurora-discovery.js +87 -0
- package/infrastructure/domains/database/aurora-discovery.test.js +188 -0
- package/infrastructure/domains/database/aurora-resolver.js +210 -0
- package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
- package/infrastructure/domains/database/migration-builder.js +701 -0
- package/infrastructure/domains/database/migration-builder.test.js +321 -0
- package/infrastructure/domains/database/migration-resolver.js +163 -0
- package/infrastructure/domains/database/migration-resolver.test.js +337 -0
- package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +164 -0
- package/infrastructure/domains/health/application/ports/IResourceDetector.js +129 -0
- package/infrastructure/domains/health/application/ports/IResourceImporter.js +142 -0
- package/infrastructure/domains/health/application/ports/IStackRepository.js +131 -0
- package/infrastructure/domains/health/application/ports/index.js +26 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +679 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +167 -0
- package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +1130 -0
- package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +221 -0
- package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +152 -0
- package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +343 -0
- package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +535 -0
- package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +376 -0
- package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +213 -0
- package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +441 -0
- package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +267 -0
- package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +324 -0
- package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +386 -0
- package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +1419 -0
- package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +391 -0
- package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +551 -0
- package/infrastructure/domains/health/domain/entities/issue.js +299 -0
- package/infrastructure/domains/health/domain/entities/issue.test.js +528 -0
- package/infrastructure/domains/health/domain/entities/property-mismatch.js +108 -0
- package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +275 -0
- package/infrastructure/domains/health/domain/entities/resource.js +159 -0
- package/infrastructure/domains/health/domain/entities/resource.test.js +432 -0
- package/infrastructure/domains/health/domain/entities/stack-health-report.js +306 -0
- package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +601 -0
- package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +380 -0
- package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +971 -0
- package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +1150 -0
- package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +672 -0
- package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +496 -0
- package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +419 -0
- package/infrastructure/domains/health/domain/services/health-score-calculator.js +248 -0
- package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +504 -0
- package/infrastructure/domains/health/domain/services/import-progress-monitor.js +195 -0
- package/infrastructure/domains/health/domain/services/import-template-generator.js +435 -0
- package/infrastructure/domains/health/domain/services/logical-id-mapper.js +345 -0
- package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +234 -0
- package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +431 -0
- package/infrastructure/domains/health/domain/services/property-mutability-config.js +382 -0
- package/infrastructure/domains/health/domain/services/template-parser.js +245 -0
- package/infrastructure/domains/health/domain/services/update-progress-monitor.js +192 -0
- package/infrastructure/domains/health/domain/value-objects/health-score.js +138 -0
- package/infrastructure/domains/health/domain/value-objects/health-score.test.js +267 -0
- package/infrastructure/domains/health/domain/value-objects/property-mutability.js +161 -0
- package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +198 -0
- package/infrastructure/domains/health/domain/value-objects/resource-state.js +167 -0
- package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +196 -0
- package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +192 -0
- package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +262 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +312 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +367 -0
- package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +432 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +784 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +1133 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +565 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +554 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +318 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +398 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +777 -0
- package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +580 -0
- package/infrastructure/domains/integration/integration-builder.js +404 -0
- package/infrastructure/domains/integration/integration-builder.test.js +690 -0
- package/infrastructure/domains/integration/integration-resolver.js +170 -0
- package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
- package/infrastructure/domains/integration/websocket-builder.js +69 -0
- package/infrastructure/domains/integration/websocket-builder.test.js +195 -0
- package/infrastructure/domains/networking/vpc-builder.js +2051 -0
- package/infrastructure/domains/networking/vpc-builder.test.js +1960 -0
- package/infrastructure/domains/networking/vpc-discovery.js +177 -0
- package/infrastructure/domains/networking/vpc-discovery.test.js +350 -0
- package/infrastructure/domains/networking/vpc-resolver.js +505 -0
- package/infrastructure/domains/networking/vpc-resolver.test.js +801 -0
- package/infrastructure/domains/parameters/ssm-builder.js +79 -0
- package/infrastructure/domains/parameters/ssm-builder.test.js +189 -0
- package/infrastructure/domains/parameters/ssm-discovery.js +84 -0
- package/infrastructure/domains/parameters/ssm-discovery.test.js +210 -0
- package/infrastructure/domains/security/iam-generator.js +816 -0
- package/infrastructure/domains/security/iam-generator.test.js +204 -0
- package/infrastructure/domains/security/kms-builder.js +415 -0
- package/infrastructure/domains/security/kms-builder.test.js +392 -0
- package/infrastructure/domains/security/kms-discovery.js +80 -0
- package/infrastructure/domains/security/kms-discovery.test.js +177 -0
- package/infrastructure/domains/security/kms-resolver.js +96 -0
- package/infrastructure/domains/security/kms-resolver.test.js +216 -0
- package/infrastructure/domains/security/templates/frigg-deployment-iam-stack.yaml +401 -0
- package/infrastructure/domains/security/templates/iam-policy-basic.json +218 -0
- package/infrastructure/domains/security/templates/iam-policy-full.json +288 -0
- package/infrastructure/domains/shared/base-builder.js +112 -0
- package/infrastructure/domains/shared/base-resolver.js +186 -0
- package/infrastructure/domains/shared/base-resolver.test.js +305 -0
- package/infrastructure/domains/shared/builder-orchestrator.js +212 -0
- package/infrastructure/domains/shared/builder-orchestrator.test.js +213 -0
- package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
- package/infrastructure/domains/shared/cloudformation-discovery.js +672 -0
- package/infrastructure/domains/shared/cloudformation-discovery.test.js +985 -0
- package/infrastructure/domains/shared/environment-builder.js +119 -0
- package/infrastructure/domains/shared/environment-builder.test.js +247 -0
- package/infrastructure/domains/shared/providers/aws-provider-adapter.js +579 -0
- package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +416 -0
- package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +93 -0
- package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +136 -0
- package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +82 -0
- package/infrastructure/domains/shared/providers/provider-factory.js +108 -0
- package/infrastructure/domains/shared/providers/provider-factory.test.js +170 -0
- package/infrastructure/domains/shared/resource-discovery.enhanced.test.js +306 -0
- package/infrastructure/domains/shared/resource-discovery.js +233 -0
- package/infrastructure/domains/shared/resource-discovery.test.js +588 -0
- package/infrastructure/domains/shared/types/app-definition.js +205 -0
- package/infrastructure/domains/shared/types/discovery-result.js +106 -0
- package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
- package/infrastructure/domains/shared/types/index.js +46 -0
- package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
- package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.js +394 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +338 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +291 -0
- package/infrastructure/domains/shared/utilities/handler-path-resolver.js +134 -0
- package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +268 -0
- package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +159 -0
- package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +444 -0
- package/infrastructure/domains/shared/validation/env-validator.js +78 -0
- package/infrastructure/domains/shared/validation/env-validator.test.js +173 -0
- package/infrastructure/domains/shared/validation/plugin-validator.js +187 -0
- package/infrastructure/domains/shared/validation/plugin-validator.test.js +323 -0
- package/infrastructure/esbuild.config.js +53 -0
- package/infrastructure/infrastructure-composer.js +117 -0
- package/infrastructure/infrastructure-composer.test.js +1895 -0
- package/infrastructure/integration.test.js +383 -0
- package/infrastructure/scripts/build-prisma-layer.js +701 -0
- package/infrastructure/scripts/build-prisma-layer.test.js +170 -0
- package/infrastructure/scripts/build-time-discovery.js +238 -0
- package/infrastructure/scripts/build-time-discovery.test.js +379 -0
- package/infrastructure/scripts/run-discovery.js +110 -0
- package/infrastructure/scripts/verify-prisma-layer.js +72 -0
- package/layers/prisma/.build-complete +3 -0
- package/layers/prisma/nodejs/package.json +8 -0
- package/management-ui/.eslintrc.js +22 -0
- package/management-ui/README.md +203 -0
- package/management-ui/components.json +21 -0
- package/management-ui/docs/phase2-integration-guide.md +320 -0
- package/management-ui/index.html +13 -0
- package/management-ui/package.json +76 -0
- package/management-ui/packages/devtools/frigg-cli/ui-command/index.js +302 -0
- package/management-ui/postcss.config.js +6 -0
- package/management-ui/server/api/backend.js +256 -0
- package/management-ui/server/api/cli.js +315 -0
- package/management-ui/server/api/codegen.js +663 -0
- package/management-ui/server/api/connections.js +857 -0
- package/management-ui/server/api/discovery.js +185 -0
- package/management-ui/server/api/environment/index.js +1 -0
- package/management-ui/server/api/environment/router.js +378 -0
- package/management-ui/server/api/environment.js +328 -0
- package/management-ui/server/api/integrations.js +876 -0
- package/management-ui/server/api/logs.js +248 -0
- package/management-ui/server/api/monitoring.js +282 -0
- package/management-ui/server/api/open-ide.js +31 -0
- package/management-ui/server/api/project.js +1029 -0
- package/management-ui/server/api/users/sessions.js +371 -0
- package/management-ui/server/api/users/simulation.js +254 -0
- package/management-ui/server/api/users.js +362 -0
- package/management-ui/server/api-contract.md +275 -0
- package/management-ui/server/index.js +873 -0
- package/management-ui/server/middleware/errorHandler.js +93 -0
- package/management-ui/server/middleware/security.js +32 -0
- package/management-ui/server/processManager.js +296 -0
- package/management-ui/server/server.js +346 -0
- package/management-ui/server/services/aws-monitor.js +413 -0
- package/management-ui/server/services/npm-registry.js +347 -0
- package/management-ui/server/services/template-engine.js +538 -0
- package/management-ui/server/utils/cliIntegration.js +220 -0
- package/management-ui/server/utils/environment/auditLogger.js +471 -0
- package/management-ui/server/utils/environment/awsParameterStore.js +275 -0
- package/management-ui/server/utils/environment/encryption.js +278 -0
- package/management-ui/server/utils/environment/envFileManager.js +286 -0
- package/management-ui/server/utils/import-commonjs.js +28 -0
- package/management-ui/server/utils/response.js +83 -0
- package/management-ui/server/websocket/handler.js +325 -0
- package/management-ui/src/App.jsx +25 -0
- package/management-ui/src/assets/FriggLogo.svg +1 -0
- package/management-ui/src/components/AppRouter.jsx +65 -0
- package/management-ui/src/components/Button.jsx +70 -0
- package/management-ui/src/components/Card.jsx +97 -0
- package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
- package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
- package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
- package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
- package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
- package/management-ui/src/components/ErrorBoundary.jsx +73 -0
- package/management-ui/src/components/IntegrationCard.jsx +481 -0
- package/management-ui/src/components/IntegrationCardEnhanced.jsx +770 -0
- package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
- package/management-ui/src/components/IntegrationStatus.jsx +336 -0
- package/management-ui/src/components/Layout.jsx +716 -0
- package/management-ui/src/components/LoadingSpinner.jsx +113 -0
- package/management-ui/src/components/RepositoryPicker.jsx +248 -0
- package/management-ui/src/components/SessionMonitor.jsx +350 -0
- package/management-ui/src/components/StatusBadge.jsx +208 -0
- package/management-ui/src/components/UserContextSwitcher.jsx +212 -0
- package/management-ui/src/components/UserSimulation.jsx +327 -0
- package/management-ui/src/components/Welcome.jsx +434 -0
- package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
- package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
- package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
- package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
- package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
- package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
- package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
- package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
- package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
- package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
- package/management-ui/src/components/codegen/index.js +10 -0
- package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
- package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
- package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
- package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
- package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
- package/management-ui/src/components/connections/index.js +5 -0
- package/management-ui/src/components/index.js +21 -0
- package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
- package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
- package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
- package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
- package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
- package/management-ui/src/components/monitoring/index.js +6 -0
- package/management-ui/src/components/monitoring/monitoring.css +218 -0
- package/management-ui/src/components/theme-provider.jsx +52 -0
- package/management-ui/src/components/theme-toggle.jsx +39 -0
- package/management-ui/src/components/ui/badge.tsx +36 -0
- package/management-ui/src/components/ui/button.test.jsx +56 -0
- package/management-ui/src/components/ui/button.tsx +57 -0
- package/management-ui/src/components/ui/card.tsx +76 -0
- package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
- package/management-ui/src/components/ui/select.tsx +157 -0
- package/management-ui/src/components/ui/skeleton.jsx +15 -0
- package/management-ui/src/hooks/useFrigg.jsx +387 -0
- package/management-ui/src/hooks/useSocket.jsx +58 -0
- package/management-ui/src/index.css +193 -0
- package/management-ui/src/lib/utils.ts +6 -0
- package/management-ui/src/main.jsx +10 -0
- package/management-ui/src/pages/CodeGeneration.jsx +14 -0
- package/management-ui/src/pages/Connections.jsx +252 -0
- package/management-ui/src/pages/ConnectionsEnhanced.jsx +633 -0
- package/management-ui/src/pages/Dashboard.jsx +311 -0
- package/management-ui/src/pages/Environment.jsx +314 -0
- package/management-ui/src/pages/IntegrationConfigure.jsx +669 -0
- package/management-ui/src/pages/IntegrationDiscovery.jsx +567 -0
- package/management-ui/src/pages/IntegrationTest.jsx +742 -0
- package/management-ui/src/pages/Integrations.jsx +253 -0
- package/management-ui/src/pages/Monitoring.jsx +17 -0
- package/management-ui/src/pages/Simulation.jsx +155 -0
- package/management-ui/src/pages/Users.jsx +492 -0
- package/management-ui/src/services/api.js +41 -0
- package/management-ui/src/services/apiModuleService.js +193 -0
- package/management-ui/src/services/websocket-handlers.js +120 -0
- package/management-ui/src/test/api/project.test.js +273 -0
- package/management-ui/src/test/components/Welcome.test.jsx +378 -0
- package/management-ui/src/test/mocks/server.js +178 -0
- package/management-ui/src/test/setup.js +61 -0
- package/management-ui/src/test/utils/test-utils.jsx +134 -0
- package/management-ui/src/utils/repository.js +98 -0
- package/management-ui/src/utils/repository.test.js +118 -0
- package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
- package/management-ui/tailwind.config.js +63 -0
- package/management-ui/tsconfig.json +37 -0
- package/management-ui/tsconfig.node.json +10 -0
- package/management-ui/vite.config.js +26 -0
- package/management-ui/vitest.config.js +38 -0
- package/package.json +35 -14
- package/test/index.js +2 -4
- package/test/mock-integration.js +4 -14
- package/infrastructure/app-handler-helpers.js +0 -57
- package/infrastructure/backend-utils.js +0 -87
- package/infrastructure/routers/auth.js +0 -26
- package/infrastructure/routers/integration-defined-routers.js +0 -42
- package/infrastructure/routers/middleware/loadUser.js +0 -15
- package/infrastructure/routers/middleware/requireLoggedInUser.js +0 -12
- package/infrastructure/routers/user.js +0 -41
- package/infrastructure/routers/websocket.js +0 -55
- package/infrastructure/serverless-template.js +0 -291
- package/infrastructure/workers/integration-defined-workers.js +0 -24
- package/test/auther-definition-tester.js +0 -125
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handler Path Resolver Utility
|
|
3
|
+
*
|
|
4
|
+
* Utility Layer - Hexagonal Architecture
|
|
5
|
+
*
|
|
6
|
+
* Handles Lambda handler path resolution for offline mode compatibility.
|
|
7
|
+
* In offline mode, handler paths need to be relative to the working directory
|
|
8
|
+
* rather than absolute paths to node_modules.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Find node_modules path for offline mode handler path resolution
|
|
16
|
+
*
|
|
17
|
+
* Searches upward from current directory to locate node_modules directory
|
|
18
|
+
* using multiple fallback strategies.
|
|
19
|
+
*
|
|
20
|
+
* @returns {string} Path to node_modules directory
|
|
21
|
+
*/
|
|
22
|
+
function findNodeModulesPath() {
|
|
23
|
+
try {
|
|
24
|
+
let currentDir = process.cwd();
|
|
25
|
+
let nodeModulesPath = null;
|
|
26
|
+
|
|
27
|
+
// Strategy 1: Search upward through directory tree
|
|
28
|
+
for (let i = 0; i < 5; i++) {
|
|
29
|
+
const potentialPath = path.join(currentDir, 'node_modules');
|
|
30
|
+
if (fs.existsSync(potentialPath)) {
|
|
31
|
+
nodeModulesPath = potentialPath;
|
|
32
|
+
console.log(
|
|
33
|
+
`Found node_modules at: ${nodeModulesPath} (method 1)`
|
|
34
|
+
);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
const parentDir = path.dirname(currentDir);
|
|
38
|
+
if (parentDir === currentDir) break;
|
|
39
|
+
currentDir = parentDir;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Strategy 2: Use npm root command
|
|
43
|
+
if (!nodeModulesPath) {
|
|
44
|
+
try {
|
|
45
|
+
const { execSync } = require('node:child_process');
|
|
46
|
+
const npmRoot = execSync('npm root', {
|
|
47
|
+
encoding: 'utf8',
|
|
48
|
+
}).trim();
|
|
49
|
+
if (fs.existsSync(npmRoot)) {
|
|
50
|
+
nodeModulesPath = npmRoot;
|
|
51
|
+
console.log(
|
|
52
|
+
`Found node_modules at: ${nodeModulesPath} (method 2)`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
} catch (npmError) {
|
|
56
|
+
console.error('Error executing npm root:', npmError);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Strategy 3: Search from package.json locations
|
|
61
|
+
if (!nodeModulesPath) {
|
|
62
|
+
currentDir = process.cwd();
|
|
63
|
+
for (let i = 0; i < 5; i++) {
|
|
64
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
65
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
66
|
+
const potentialNodeModules = path.join(
|
|
67
|
+
currentDir,
|
|
68
|
+
'node_modules'
|
|
69
|
+
);
|
|
70
|
+
if (fs.existsSync(potentialNodeModules)) {
|
|
71
|
+
nodeModulesPath = potentialNodeModules;
|
|
72
|
+
console.log(
|
|
73
|
+
`Found node_modules at: ${nodeModulesPath} (method 3)`
|
|
74
|
+
);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const parentDir = path.dirname(currentDir);
|
|
79
|
+
if (parentDir === currentDir) break;
|
|
80
|
+
currentDir = parentDir;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (nodeModulesPath) {
|
|
85
|
+
return nodeModulesPath;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Fallback: Assume parent directory
|
|
89
|
+
console.warn(
|
|
90
|
+
'Could not find node_modules path, falling back to default'
|
|
91
|
+
);
|
|
92
|
+
return path.resolve(process.cwd(), '../node_modules');
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('Error finding node_modules path:', error);
|
|
95
|
+
return path.resolve(process.cwd(), '../node_modules');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Modify handler paths for offline mode
|
|
101
|
+
*
|
|
102
|
+
* In serverless-offline mode, handler paths need to be relative
|
|
103
|
+
* to the current working directory rather than using absolute
|
|
104
|
+
* node_modules paths.
|
|
105
|
+
*
|
|
106
|
+
* @param {Object} functions - Serverless functions configuration
|
|
107
|
+
* @returns {Object} Functions with modified handler paths
|
|
108
|
+
*/
|
|
109
|
+
function modifyHandlerPaths(functions) {
|
|
110
|
+
const isOffline = process.argv.includes('offline');
|
|
111
|
+
console.log('isOffline', isOffline);
|
|
112
|
+
|
|
113
|
+
if (!isOffline) {
|
|
114
|
+
console.log('Not in offline mode, skipping handler path modification');
|
|
115
|
+
// Return shallow copy to prevent mutations (DDD immutability principle)
|
|
116
|
+
return { ...functions };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// In offline mode, don't modify the handler paths at all
|
|
120
|
+
// serverless-offline will resolve node_modules paths from the working directory
|
|
121
|
+
console.log('Offline mode detected - keeping original handler paths for serverless-offline');
|
|
122
|
+
|
|
123
|
+
// Return deep copy to prevent mutations (DDD immutability principle)
|
|
124
|
+
return Object.entries(functions).reduce((acc, [key, value]) => {
|
|
125
|
+
acc[key] = { ...value };
|
|
126
|
+
return acc;
|
|
127
|
+
}, {});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
module.exports = {
|
|
131
|
+
findNodeModulesPath,
|
|
132
|
+
modifyHandlerPaths,
|
|
133
|
+
};
|
|
134
|
+
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Handler Path Resolver Utility
|
|
3
|
+
*
|
|
4
|
+
* Tests offline mode handler path resolution
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const { findNodeModulesPath, modifyHandlerPaths } = require('./handler-path-resolver');
|
|
10
|
+
|
|
11
|
+
// Mock fs and child_process
|
|
12
|
+
jest.mock('fs');
|
|
13
|
+
jest.mock('node:child_process', () => ({
|
|
14
|
+
execSync: jest.fn(),
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
describe('Handler Path Resolver', () => {
|
|
18
|
+
let originalArgv;
|
|
19
|
+
let originalCwd;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
originalArgv = process.argv;
|
|
23
|
+
originalCwd = process.cwd;
|
|
24
|
+
jest.clearAllMocks();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
process.argv = originalArgv;
|
|
29
|
+
process.cwd = originalCwd;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('findNodeModulesPath()', () => {
|
|
33
|
+
it('should find node_modules in current directory (method 1)', () => {
|
|
34
|
+
const mockCwd = '/project';
|
|
35
|
+
process.cwd = jest.fn().mockReturnValue(mockCwd);
|
|
36
|
+
fs.existsSync = jest.fn().mockImplementation((p) =>
|
|
37
|
+
p === path.join(mockCwd, 'node_modules')
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const result = findNodeModulesPath();
|
|
41
|
+
|
|
42
|
+
expect(result).toBe(path.join(mockCwd, 'node_modules'));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should search parent directories if not found in current (method 1)', () => {
|
|
46
|
+
const mockCwd = '/project/nested/deep';
|
|
47
|
+
process.cwd = jest.fn().mockReturnValue(mockCwd);
|
|
48
|
+
fs.existsSync = jest.fn().mockImplementation((p) =>
|
|
49
|
+
p === '/project/node_modules'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const result = findNodeModulesPath();
|
|
53
|
+
|
|
54
|
+
expect(result).toBe('/project/node_modules');
|
|
55
|
+
expect(fs.existsSync).toHaveBeenCalledWith('/project/nested/deep/node_modules');
|
|
56
|
+
expect(fs.existsSync).toHaveBeenCalledWith('/project/nested/node_modules');
|
|
57
|
+
expect(fs.existsSync).toHaveBeenCalledWith('/project/node_modules');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should use npm root if directory search fails (method 2)', () => {
|
|
61
|
+
process.cwd = jest.fn().mockReturnValue('/some/unusual/directory');
|
|
62
|
+
|
|
63
|
+
const { execSync } = require('node:child_process');
|
|
64
|
+
// npm root returns a different path
|
|
65
|
+
execSync.mockReturnValue('/usr/local/lib/node_modules\n');
|
|
66
|
+
|
|
67
|
+
// Mock to fail directory searches but succeed for npm root result
|
|
68
|
+
fs.existsSync = jest.fn().mockImplementation((p) => {
|
|
69
|
+
// Only succeed for the npm root path (not under /some/unusual/directory)
|
|
70
|
+
return p === '/usr/local/lib/node_modules';
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const result = findNodeModulesPath();
|
|
74
|
+
|
|
75
|
+
expect(result).toBe('/usr/local/lib/node_modules');
|
|
76
|
+
expect(execSync).toHaveBeenCalledWith('npm root', { encoding: 'utf8' });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should handle npm root errors gracefully', () => {
|
|
80
|
+
process.cwd = jest.fn().mockReturnValue('/project');
|
|
81
|
+
fs.existsSync = jest.fn().mockReturnValue(false);
|
|
82
|
+
|
|
83
|
+
const { execSync } = require('node:child_process');
|
|
84
|
+
execSync.mockImplementation(() => {
|
|
85
|
+
throw new Error('npm not found');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const result = findNodeModulesPath();
|
|
89
|
+
|
|
90
|
+
// Should fall back to default
|
|
91
|
+
expect(result).toBe(path.resolve('/project', '../node_modules'));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should search from package.json locations (method 3)', () => {
|
|
95
|
+
process.cwd = jest.fn().mockReturnValue('/project/workspace');
|
|
96
|
+
|
|
97
|
+
let callCount = 0;
|
|
98
|
+
fs.existsSync = jest.fn().mockImplementation((p) => {
|
|
99
|
+
callCount++;
|
|
100
|
+
// First 5 calls fail (directory search)
|
|
101
|
+
if (callCount <= 5) return false;
|
|
102
|
+
// Package.json search
|
|
103
|
+
if (p === '/project/package.json') return true;
|
|
104
|
+
if (p === '/project/node_modules') return true;
|
|
105
|
+
return false;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const { execSync } = require('node:child_process');
|
|
109
|
+
execSync.mockImplementation(() => {
|
|
110
|
+
throw new Error('npm root failed');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const result = findNodeModulesPath();
|
|
114
|
+
|
|
115
|
+
expect(result).toBe('/project/node_modules');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should fall back to default path if all methods fail', () => {
|
|
119
|
+
process.cwd = jest.fn().mockReturnValue('/project');
|
|
120
|
+
fs.existsSync = jest.fn().mockReturnValue(false);
|
|
121
|
+
|
|
122
|
+
const { execSync } = require('node:child_process');
|
|
123
|
+
execSync.mockImplementation(() => {
|
|
124
|
+
throw new Error('npm root failed');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const result = findNodeModulesPath();
|
|
128
|
+
|
|
129
|
+
expect(result).toBe(path.resolve('/project', '../node_modules'));
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should handle errors during search', () => {
|
|
133
|
+
process.cwd = jest.fn().mockReturnValue('/project');
|
|
134
|
+
// Mock fs.existsSync to throw an error
|
|
135
|
+
fs.existsSync = jest.fn().mockImplementation(() => {
|
|
136
|
+
throw new Error('fs error');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const { execSync } = require('node:child_process');
|
|
140
|
+
execSync.mockImplementation(() => {
|
|
141
|
+
throw new Error('npm error');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const result = findNodeModulesPath();
|
|
145
|
+
|
|
146
|
+
// Should fallback to default path even when search methods fail
|
|
147
|
+
expect(result).toBe(path.resolve('/project', '../node_modules'));
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('modifyHandlerPaths()', () => {
|
|
152
|
+
it('should not modify paths when not in offline mode', () => {
|
|
153
|
+
process.argv = ['node', 'test'];
|
|
154
|
+
|
|
155
|
+
const functions = {
|
|
156
|
+
auth: {
|
|
157
|
+
handler: 'node_modules/@friggframework/core/handlers/routers/auth.handler',
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const result = modifyHandlerPaths(functions);
|
|
162
|
+
|
|
163
|
+
expect(result.auth.handler).toBe('node_modules/@friggframework/core/handlers/routers/auth.handler');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('should modify handler paths in offline mode', () => {
|
|
167
|
+
process.argv = ['node', 'test', 'offline'];
|
|
168
|
+
process.cwd = jest.fn().mockReturnValue('/project');
|
|
169
|
+
fs.existsSync = jest.fn().mockImplementation((p) =>
|
|
170
|
+
p === '/project/node_modules'
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const functions = {
|
|
174
|
+
auth: {
|
|
175
|
+
handler: 'node_modules/@friggframework/core/handlers/routers/auth.handler',
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const result = modifyHandlerPaths(functions);
|
|
180
|
+
|
|
181
|
+
expect(result.auth.handler).toBe('node_modules/@friggframework/core/handlers/routers/auth.handler');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should handle functions without handlers', () => {
|
|
185
|
+
process.argv = ['node', 'test', 'offline'];
|
|
186
|
+
|
|
187
|
+
const functions = {
|
|
188
|
+
noHandler: {
|
|
189
|
+
events: [{ http: { path: '/test' } }],
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const result = modifyHandlerPaths(functions);
|
|
194
|
+
|
|
195
|
+
expect(result.noHandler.handler).toBeUndefined();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should only modify handlers with node_modules path', () => {
|
|
199
|
+
process.argv = ['node', 'test', 'offline'];
|
|
200
|
+
process.cwd = jest.fn().mockReturnValue('/project');
|
|
201
|
+
fs.existsSync = jest.fn().mockImplementation((p) =>
|
|
202
|
+
p === '/project/node_modules'
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const functions = {
|
|
206
|
+
coreHandler: {
|
|
207
|
+
handler: 'node_modules/@friggframework/core/handlers/auth.handler',
|
|
208
|
+
},
|
|
209
|
+
customHandler: {
|
|
210
|
+
handler: 'src/handlers/custom.handler',
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const result = modifyHandlerPaths(functions);
|
|
215
|
+
|
|
216
|
+
expect(result.coreHandler.handler).toContain('node_modules');
|
|
217
|
+
expect(result.customHandler.handler).toBe('src/handlers/custom.handler');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should not mutate original functions object', () => {
|
|
221
|
+
process.argv = ['node', 'test', 'offline'];
|
|
222
|
+
process.cwd = jest.fn().mockReturnValue('/project');
|
|
223
|
+
fs.existsSync = jest.fn().mockImplementation((p) =>
|
|
224
|
+
p === '/project/node_modules'
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
const original = {
|
|
228
|
+
auth: {
|
|
229
|
+
handler: 'node_modules/@friggframework/core/handlers/auth.handler',
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const result = modifyHandlerPaths(original);
|
|
234
|
+
|
|
235
|
+
// Result should be a copy
|
|
236
|
+
expect(result).not.toBe(original);
|
|
237
|
+
expect(result.auth).not.toBe(original.auth);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('should handle multiple functions', () => {
|
|
241
|
+
process.argv = ['node', 'test', 'offline'];
|
|
242
|
+
process.cwd = jest.fn().mockReturnValue('/project');
|
|
243
|
+
fs.existsSync = jest.fn().mockImplementation((p) =>
|
|
244
|
+
p === '/project/node_modules'
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
const functions = {
|
|
248
|
+
auth: {
|
|
249
|
+
handler: 'node_modules/@friggframework/core/handlers/auth.handler',
|
|
250
|
+
},
|
|
251
|
+
user: {
|
|
252
|
+
handler: 'node_modules/@friggframework/core/handlers/user.handler',
|
|
253
|
+
},
|
|
254
|
+
health: {
|
|
255
|
+
handler: 'node_modules/@friggframework/core/handlers/health.handler',
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const result = modifyHandlerPaths(functions);
|
|
260
|
+
|
|
261
|
+
expect(Object.keys(result)).toHaveLength(3);
|
|
262
|
+
expect(result.auth.handler).toContain('node_modules');
|
|
263
|
+
expect(result.user.handler).toContain('node_modules');
|
|
264
|
+
expect(result.health.handler).toContain('node_modules');
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prisma Lambda Layer Manager
|
|
3
|
+
*
|
|
4
|
+
* Utility Layer - Hexagonal Architecture
|
|
5
|
+
*
|
|
6
|
+
* Manages Prisma Lambda Layer for serverless deployments.
|
|
7
|
+
* Ensures the layer exists and is built before deployment.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const { buildPrismaLayer } = require('../../../scripts/build-prisma-layer');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check if a process is still running
|
|
16
|
+
* @param {number} pid - Process ID to check
|
|
17
|
+
* @returns {boolean} True if process is running
|
|
18
|
+
*/
|
|
19
|
+
function isProcessRunning(pid) {
|
|
20
|
+
try {
|
|
21
|
+
// Signal 0 checks if process exists without killing it
|
|
22
|
+
process.kill(pid, 0);
|
|
23
|
+
return true;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Ensure Prisma Lambda Layer exists
|
|
31
|
+
*
|
|
32
|
+
* Automatically builds the layer if it doesn't exist.
|
|
33
|
+
* The layer contains ONLY the Prisma runtime client (minimal, ~10-15MB).
|
|
34
|
+
* Prisma CLI is bundled separately in the dbMigrate function.
|
|
35
|
+
*
|
|
36
|
+
* Domain Concept: Build Completion State & Process Locking
|
|
37
|
+
* - Uses .build-complete marker file to track successful builds
|
|
38
|
+
* - Uses .build-lock PID file to prevent concurrent builds
|
|
39
|
+
* - Waits for active builds to complete before starting new one
|
|
40
|
+
* - Cleans stale locks and incomplete builds before retry
|
|
41
|
+
*
|
|
42
|
+
* @param {Object} databaseConfig - Database configuration from app definition
|
|
43
|
+
* @returns {Promise<void>}
|
|
44
|
+
* @throws {Error} If layer build fails
|
|
45
|
+
*/
|
|
46
|
+
async function ensurePrismaLayerExists(databaseConfig = {}) {
|
|
47
|
+
const projectRoot = process.cwd();
|
|
48
|
+
const layerPath = path.join(projectRoot, 'layers/prisma');
|
|
49
|
+
const completionMarkerPath = path.join(layerPath, '.build-complete');
|
|
50
|
+
const lockFilePath = path.join(layerPath, '.build-lock');
|
|
51
|
+
|
|
52
|
+
// Check if build is complete (marker exists)
|
|
53
|
+
if (fs.existsSync(completionMarkerPath)) {
|
|
54
|
+
console.log('✓ Prisma Lambda Layer already exists at', layerPath);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Check for active build process
|
|
59
|
+
if (fs.existsSync(lockFilePath)) {
|
|
60
|
+
const lockPid = parseInt(fs.readFileSync(lockFilePath, 'utf-8').trim(), 10);
|
|
61
|
+
|
|
62
|
+
if (isProcessRunning(lockPid)) {
|
|
63
|
+
console.log(`⏳ Another build process (PID ${lockPid}) is active - waiting...`);
|
|
64
|
+
|
|
65
|
+
// Wait up to 60 seconds for the other process to complete
|
|
66
|
+
for (let i = 0; i < 60; i++) {
|
|
67
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
68
|
+
|
|
69
|
+
// Check if build completed
|
|
70
|
+
if (fs.existsSync(completionMarkerPath)) {
|
|
71
|
+
console.log('✓ Concurrent build completed successfully');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check if process died
|
|
76
|
+
if (!isProcessRunning(lockPid)) {
|
|
77
|
+
console.log(`⚠ Build process ${lockPid} terminated - cleaning up stale lock`);
|
|
78
|
+
fs.rmSync(lockFilePath, { force: true });
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Timeout - check one final time
|
|
84
|
+
if (fs.existsSync(completionMarkerPath)) {
|
|
85
|
+
console.log('✓ Concurrent build completed');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Still locked after 60s - remove stale lock
|
|
90
|
+
console.log('⚠ Build timeout - removing stale lock and rebuilding');
|
|
91
|
+
fs.rmSync(lockFilePath, { force: true });
|
|
92
|
+
} else {
|
|
93
|
+
// Stale lock file (process not running)
|
|
94
|
+
console.log(`⚠ Stale lock file detected (PID ${lockPid} not running) - cleaning up`);
|
|
95
|
+
fs.rmSync(lockFilePath, { force: true });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Check if incomplete build exists (directory without marker)
|
|
100
|
+
if (fs.existsSync(layerPath) && !fs.existsSync(completionMarkerPath)) {
|
|
101
|
+
console.log('⚠ Incomplete Prisma layer detected - will be cleaned by buildPrismaLayer()');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Build layer
|
|
105
|
+
console.log('📦 Prisma Lambda Layer not found - building automatically...');
|
|
106
|
+
console.log(' Building MINIMAL layer (runtime only, NO CLI)');
|
|
107
|
+
console.log(' CLI is packaged separately in dbMigrate function');
|
|
108
|
+
console.log(' This may take a minute on first deployment.\n');
|
|
109
|
+
|
|
110
|
+
// Create lock file with current process PID
|
|
111
|
+
try {
|
|
112
|
+
if (!fs.existsSync(layerPath)) {
|
|
113
|
+
fs.mkdirSync(layerPath, { recursive: true });
|
|
114
|
+
}
|
|
115
|
+
fs.writeFileSync(lockFilePath, process.pid.toString());
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.warn('⚠ Could not create lock file:', error.message);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
// Build layer WITHOUT CLI (runtime only for minimal size)
|
|
122
|
+
await buildPrismaLayer(databaseConfig);
|
|
123
|
+
|
|
124
|
+
// Create completion marker
|
|
125
|
+
fs.writeFileSync(
|
|
126
|
+
completionMarkerPath,
|
|
127
|
+
`Build completed: ${new Date().toISOString()}\nNode: ${process.version}\nPlatform: ${process.platform}\n`
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
console.log('✓ Prisma Lambda Layer built successfully (~10-15MB)\n');
|
|
131
|
+
} catch (error) {
|
|
132
|
+
// Clean up partial build on failure
|
|
133
|
+
if (fs.existsSync(layerPath)) {
|
|
134
|
+
try {
|
|
135
|
+
fs.rmSync(layerPath, { recursive: true, force: true });
|
|
136
|
+
} catch (cleanupError) {
|
|
137
|
+
console.warn('⚠ Could not clean failed build:', cleanupError.message);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.error('✗ Failed to build Prisma Lambda Layer:', error.message);
|
|
142
|
+
console.error(' You may need to run: npm install @friggframework/core\n');
|
|
143
|
+
throw error;
|
|
144
|
+
} finally {
|
|
145
|
+
// Always remove lock file when done (success or failure)
|
|
146
|
+
if (fs.existsSync(lockFilePath)) {
|
|
147
|
+
try {
|
|
148
|
+
fs.rmSync(lockFilePath, { force: true });
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.warn('⚠ Could not remove lock file:', error.message);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = {
|
|
157
|
+
ensurePrismaLayerExists,
|
|
158
|
+
};
|
|
159
|
+
|