forgeos 0.1.0-alpha.4 → 0.1.0-alpha.41
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/.npmignore +10 -0
- package/AGENTS.md +142 -90
- package/CHANGELOG.md +433 -0
- package/LICENSE +21 -0
- package/README.md +67 -8
- package/adapters/go/README.md +23 -0
- package/adapters/go/go.mod +3 -0
- package/adapters/go/http.go +149 -0
- package/adapters/go/registry.go +234 -0
- package/adapters/go/types.go +136 -0
- package/adapters/java/README.md +68 -0
- package/adapters/java/pom.xml +34 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Auth.java +20 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Diagnostic.java +16 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Entry.java +38 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/EntryKind.java +16 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ErrorInfo.java +4 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Forge.java +94 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeCall.java +12 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeContext.java +11 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHandler.java +8 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeHttpHandler.java +179 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ForgeRegistry.java +121 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Json.java +14 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Manifest.java +14 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/RequestEnvelope.java +6 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/ResponseEnvelope.java +25 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Risk.java +18 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Schemas.java +36 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/Service.java +65 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/TransactionMode.java +18 -0
- package/adapters/java/src/main/java/dev/forgeos/adapter/TypedForgeHandler.java +6 -0
- package/adapters/java-spring-boot-starter/README.md +32 -0
- package/adapters/java-spring-boot-starter/pom.xml +36 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeCommand.java +22 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeExternalService.java +15 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeQuery.java +16 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeServiceBeanCondition.java +18 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringAutoConfiguration.java +16 -0
- package/adapters/java-spring-boot-starter/src/main/java/dev/forgeos/adapter/spring/ForgeSpringRuntime.java +104 -0
- package/adapters/java-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +1 -0
- package/bin/forge.mjs +18 -0
- package/docs/cair-protocol.md +103 -0
- package/docs/changelog.md +548 -0
- package/docs/forge-protocol.md +189 -0
- package/examples/go-billing/go.mod +7 -0
- package/examples/go-billing/main.go +120 -0
- package/examples/java-billing/pom.xml +52 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/CreateInvoiceInput.java +4 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Invoice.java +11 -0
- package/examples/java-billing/src/main/java/dev/forgeos/examples/billing/Main.java +127 -0
- package/package.json +31 -3
- package/schemas/forge-manifest.schema.json +57 -0
- package/src/forge/_generated/releaseManifest.json +1 -2
- package/src/forge/_generated/releaseManifest.ts +3 -3
- package/src/forge/agent-adapters/index.ts +1584 -125
- package/src/forge/agent-adapters/types.ts +224 -1
- package/src/forge/agent-memory/bridge.ts +1333 -0
- package/src/forge/agent-memory/context-pack.ts +277 -0
- package/src/forge/agent-memory/hook-runner.ts +312 -0
- package/src/forge/agent-memory/mcp.ts +224 -0
- package/src/forge/agent-memory/normalize.ts +498 -0
- package/src/forge/agent-memory/redaction.ts +103 -0
- package/src/forge/agent-memory/sources/claude-code.ts +51 -0
- package/src/forge/agent-memory/sources/codex-hook-runner.mjs +273 -0
- package/src/forge/agent-memory/sources/codex.ts +119 -0
- package/src/forge/agent-memory/sources/cursor.ts +35 -0
- package/src/forge/agent-memory/types.ts +204 -0
- package/src/forge/bench.ts +248 -0
- package/src/forge/brownfield-import/index.ts +801 -0
- package/src/forge/brownfield-import/types.ts +127 -0
- package/src/forge/cair/action-journal.ts +61 -0
- package/src/forge/cair/action-parser.ts +314 -0
- package/src/forge/cair/action-validator.ts +40 -0
- package/src/forge/cair/actions.ts +1818 -0
- package/src/forge/cair/format.ts +77 -0
- package/src/forge/cair/index.ts +106 -0
- package/src/forge/cair/query.ts +478 -0
- package/src/forge/cair/snapshot.ts +315 -0
- package/src/forge/cair/types.ts +248 -0
- package/src/forge/cli/ai.ts +339 -21
- package/src/forge/cli/auth.ts +348 -10
- package/src/forge/cli/authmd.ts +441 -0
- package/src/forge/cli/baseline.ts +112 -0
- package/src/forge/cli/build.ts +20 -4
- package/src/forge/cli/changed.ts +437 -0
- package/src/forge/cli/codex-app-server.ts +877 -0
- package/src/forge/cli/commands.ts +1620 -20
- package/src/forge/cli/db.ts +209 -2
- package/src/forge/cli/deploy.ts +887 -0
- package/src/forge/cli/deps.ts +82 -13
- package/src/forge/cli/dev.ts +961 -46
- package/src/forge/cli/docs.ts +265 -0
- package/src/forge/cli/doctor.ts +297 -0
- package/src/forge/cli/field-test.ts +329 -0
- package/src/forge/cli/handoff.ts +336 -0
- package/src/forge/cli/index.ts +1 -0
- package/src/forge/cli/last-run.ts +84 -0
- package/src/forge/cli/main.ts +107 -3
- package/src/forge/cli/new.ts +152 -13
- package/src/forge/cli/next-actions.ts +23 -0
- package/src/forge/cli/output.ts +389 -6
- package/src/forge/cli/parse.ts +1050 -34
- package/src/forge/cli/progress.ts +51 -0
- package/src/forge/cli/query.ts +32 -0
- package/src/forge/cli/release.ts +35 -11
- package/src/forge/cli/rls.ts +43 -4
- package/src/forge/cli/run.ts +41 -0
- package/src/forge/cli/security.ts +112 -0
- package/src/forge/cli/self-host.ts +56 -14
- package/src/forge/cli/studio.ts +2218 -0
- package/src/forge/cli/verify.ts +1455 -32
- package/src/forge/cli/windows.ts +23 -0
- package/src/forge/cli/workos.ts +1020 -0
- package/src/forge/compiler/agent-contract/build.ts +670 -64
- package/src/forge/compiler/agent-contract/types.ts +45 -2
- package/src/forge/compiler/ai-registry/parse.ts +71 -2
- package/src/forge/compiler/api-surface/build.ts +47 -0
- package/src/forge/compiler/app-graph/build.ts +112 -9
- package/src/forge/compiler/app-graph/extract.ts +107 -0
- package/src/forge/compiler/app-graph/module-graph.ts +73 -78
- package/src/forge/compiler/app-graph/parser.ts +24 -24
- package/src/forge/compiler/app-graph/profile.ts +26 -0
- package/src/forge/compiler/app-graph/versions.ts +1 -1
- package/src/forge/compiler/classifier/capabilities.ts +3 -2
- package/src/forge/compiler/classifier/classify.ts +32 -8
- package/src/forge/compiler/classifier/secrets.ts +3 -2
- package/src/forge/compiler/classifier/signals.ts +91 -1
- package/src/forge/compiler/client-sdk/build-manifest.ts +59 -0
- package/src/forge/compiler/client-sdk/render-client.ts +295 -13
- package/src/forge/compiler/data-graph/parse.ts +20 -4
- package/src/forge/compiler/data-graph/sql/ddl.ts +144 -31
- package/src/forge/compiler/data-graph/sql/serialize.ts +4 -0
- package/src/forge/compiler/data-graph/sql/types.ts +1 -0
- package/src/forge/compiler/diagnostics/codes.ts +30 -0
- package/src/forge/compiler/diagnostics/create.ts +21 -2
- package/src/forge/compiler/diagnostics/index.ts +2 -0
- package/src/forge/compiler/emitter/barrel.ts +3 -0
- package/src/forge/compiler/emitter/render.ts +9 -0
- package/src/forge/compiler/external-manifest/registry.ts +205 -0
- package/src/forge/compiler/external-manifest/types.ts +91 -0
- package/src/forge/compiler/external-manifest/validate.ts +373 -0
- package/src/forge/compiler/frontend-graph/build.ts +142 -14
- package/src/forge/compiler/integration/add.ts +618 -24
- package/src/forge/compiler/integration/plan.ts +43 -12
- package/src/forge/compiler/integration/render.ts +29 -0
- package/src/forge/compiler/integration/snapshot.ts +2 -0
- package/src/forge/compiler/integration/templates/convex.ts +70 -0
- package/src/forge/compiler/integration/templates/index.ts +1 -0
- package/src/forge/compiler/integration/templates/render.ts +38 -0
- package/src/forge/compiler/integration/templates/types.ts +3 -0
- package/src/forge/compiler/integration/templates/workos.ts +1219 -0
- package/src/forge/compiler/make-registry/build.ts +8 -9
- package/src/forge/compiler/orchestrator/fast-check.ts +4 -0
- package/src/forge/compiler/orchestrator/generate-lock.ts +14 -3
- package/src/forge/compiler/orchestrator/manifest.ts +1 -1
- package/src/forge/compiler/orchestrator/plan-profile.ts +23 -0
- package/src/forge/compiler/orchestrator/plan.ts +247 -10
- package/src/forge/compiler/orchestrator/profile.ts +65 -0
- package/src/forge/compiler/orchestrator/run.ts +97 -31
- package/src/forge/compiler/orchestrator/serialize.ts +33 -8
- package/src/forge/compiler/orchestrator/types.ts +1 -1
- package/src/forge/compiler/package-graph/compiler.ts +3 -1
- package/src/forge/compiler/package-graph/constants.ts +1 -1
- package/src/forge/compiler/package-manager/adapter.ts +4 -1
- package/src/forge/compiler/package-manager/commands.ts +4 -0
- package/src/forge/compiler/package-manager/executor.ts +30 -1
- package/src/forge/compiler/package-manager/version.ts +36 -12
- package/src/forge/compiler/package-upgrades/planner.ts +155 -18
- package/src/forge/compiler/package-upgrades/types.ts +2 -0
- package/src/forge/compiler/policy-registry/build.ts +47 -2
- package/src/forge/compiler/policy-registry/parse.ts +32 -2
- package/src/forge/compiler/recipes/definitions.ts +63 -0
- package/src/forge/compiler/recipes/index.ts +2 -0
- package/src/forge/compiler/recipes/registry.ts +6 -0
- package/src/forge/compiler/test-graph/build.ts +11 -3
- package/src/forge/compiler/types/app-graph.ts +8 -2
- package/src/forge/compiler/types/cli.ts +75 -1
- package/src/forge/compiler/types/dev-manifest.ts +4 -0
- package/src/forge/compiler/types/emit.ts +2 -0
- package/src/forge/compiler/types/frontend-graph.ts +2 -2
- package/src/forge/compiler/types/integration.ts +1 -0
- package/src/forge/compiler/types/package-graph.ts +6 -0
- package/src/forge/compiler/types/policy-registry.ts +3 -1
- package/src/forge/delta/classifier.ts +52 -0
- package/src/forge/delta/explain.ts +238 -0
- package/src/forge/delta/git-observer.ts +43 -0
- package/src/forge/delta/ids.ts +44 -0
- package/src/forge/delta/index.ts +25 -0
- package/src/forge/delta/recorder.ts +540 -0
- package/src/forge/delta/redaction.ts +50 -0
- package/src/forge/delta/schema.ts +240 -0
- package/src/forge/delta/session.ts +142 -0
- package/src/forge/delta/status.ts +1202 -0
- package/src/forge/delta/store.ts +3284 -0
- package/src/forge/delta/timeline.ts +178 -0
- package/src/forge/dev/server.ts +808 -17
- package/src/forge/dev/types.ts +15 -1
- package/src/forge/dev/watch.ts +17 -7
- package/src/forge/dev-console/cycle.ts +280 -33
- package/src/forge/dev-console/types.ts +47 -1
- package/src/forge/impact/index.ts +204 -9
- package/src/forge/impact/types.ts +33 -1
- package/src/forge/intent/index.ts +35 -16
- package/src/forge/make/fields.ts +26 -0
- package/src/forge/make/index.ts +40 -6
- package/src/forge/make/templates.ts +155 -2
- package/src/forge/make/types.ts +2 -1
- package/src/forge/policy.ts +1 -1
- package/src/forge/react/index.ts +160 -2
- package/src/forge/refactor/index.ts +1 -0
- package/src/forge/repair/rules/index.ts +2 -2
- package/src/forge/review/index.ts +158 -12
- package/src/forge/review/types.ts +15 -0
- package/src/forge/runtime/auth/config.ts +17 -0
- package/src/forge/runtime/auth/evaluate.ts +15 -2
- package/src/forge/runtime/auth/resolve.ts +61 -6
- package/src/forge/runtime/auth/types.ts +1 -0
- package/src/forge/runtime/db/factory.ts +1 -3
- package/src/forge/runtime/db/generated-client.ts +13 -2
- package/src/forge/runtime/db/memory-adapter.ts +139 -32
- package/src/forge/runtime/db/pglite-adapter.ts +263 -2
- package/src/forge/runtime/db/postgres-adapter.ts +6 -3
- package/src/forge/runtime/executor.ts +129 -16
- package/src/forge/runtime/external/bridge.ts +649 -0
- package/src/forge/runtime/runner/run-entry.ts +16 -7
- package/src/forge/runtime/telemetry/buffer.ts +4 -1
- package/src/forge/runtime/telemetry/scrubber.ts +35 -5
- package/src/forge/runtime/webhooks/security.ts +12 -7
- package/src/forge/server.ts +17 -3
- package/src/forge/ui/index.ts +209 -0
- package/src/forge/ui/types.ts +1 -0
- package/src/forge/version.ts +1 -1
- package/src/forge/vue/index.ts +422 -0
- package/src/forge/workspace/baseline.ts +112 -0
- package/src/forge/workspace/change-summary.ts +250 -0
- package/src/forge/workspace/forge-cli.ts +42 -0
- package/src/forge/workspace/git-summary.ts +391 -0
- package/templates/agent-workroom/AGENTS.md +29 -0
- package/templates/agent-workroom/README.md +34 -0
- package/templates/agent-workroom/forge.config.ts +3 -0
- package/templates/agent-workroom/package.json +33 -0
- package/templates/agent-workroom/src/actions/indexAgentSignal.ts +10 -0
- package/templates/agent-workroom/src/commands/openWorkroom.ts +61 -0
- package/templates/agent-workroom/src/commands/recordAgentSignal.ts +119 -0
- package/templates/agent-workroom/src/commands/recordCheckRun.ts +52 -0
- package/templates/agent-workroom/src/forge/schema.ts +54 -0
- package/templates/agent-workroom/src/policies.ts +6 -0
- package/templates/agent-workroom/src/queries/listWorkrooms.ts +11 -0
- package/templates/agent-workroom/src/queries/liveWorkroom.ts +63 -0
- package/templates/agent-workroom/tsconfig.json +16 -0
- package/templates/agent-workroom/web/index.html +12 -0
- package/templates/agent-workroom/web/package.json +21 -0
- package/templates/agent-workroom/web/src/App.tsx +345 -0
- package/templates/agent-workroom/web/src/lib/forge.ts +13 -0
- package/templates/agent-workroom/web/src/main.tsx +13 -0
- package/templates/agent-workroom/web/src/styles.css +545 -0
- package/templates/agent-workroom/web/tsconfig.json +27 -0
- package/templates/b2b-support-web/package.json +1 -0
- package/templates/b2b-support-web/web/package.json +1 -1
- package/templates/minimal-web/package.json +1 -1
- package/templates/minimal-web/web/package.json +2 -2
- package/templates/nuxt-web/.vscode/settings.json +14 -0
- package/templates/nuxt-web/README.md +30 -0
- package/templates/nuxt-web/forge.config.ts +3 -0
- package/templates/nuxt-web/package.json +33 -0
- package/templates/nuxt-web/src/actions/logNoteCreated.ts +11 -0
- package/templates/nuxt-web/src/commands/createNote.ts +26 -0
- package/templates/nuxt-web/src/forge/schema.ts +12 -0
- package/templates/nuxt-web/src/policies.ts +6 -0
- package/templates/nuxt-web/src/queries/listNotes.ts +8 -0
- package/templates/nuxt-web/src/queries/liveNotes.ts +8 -0
- package/templates/nuxt-web/tsconfig.json +17 -0
- package/templates/nuxt-web/web/app.vue +67 -0
- package/templates/nuxt-web/web/components/LiveNotes.vue +89 -0
- package/templates/nuxt-web/web/components/NoteComposer.vue +100 -0
- package/templates/nuxt-web/web/composables/forge.ts +13 -0
- package/templates/nuxt-web/web/composables/useNotes.ts +24 -0
- package/templates/nuxt-web/web/nuxt.config.ts +11 -0
- package/templates/nuxt-web/web/package.json +18 -0
- package/templates/nuxt-web/web/plugins/forge.client.ts +10 -0
- package/templates/nuxt-web/web/plugins/forge.server.ts +10 -0
- package/templates/nuxt-web/web/server/api/forge-health.get.ts +7 -0
- package/templates/nuxt-web/web/tsconfig.json +6 -0
- package/src/forge/_generated/actionSubscriptions.json +0 -2
- package/src/forge/_generated/actionSubscriptions.ts +0 -10
- package/src/forge/_generated/agentAdapterManifest.json +0 -2
- package/src/forge/_generated/agentAdapterManifest.ts +0 -73
- package/src/forge/_generated/agentContract.json +0 -2
- package/src/forge/_generated/agentContract.ts +0 -7829
- package/src/forge/_generated/agentQuickstart.md +0 -34
- package/src/forge/_generated/agentTools.json +0 -2
- package/src/forge/_generated/agentTools.md +0 -16
- package/src/forge/_generated/agentTools.ts +0 -12
- package/src/forge/_generated/aiContext.ts +0 -125
- package/src/forge/_generated/aiModels.json +0 -2
- package/src/forge/_generated/aiModels.ts +0 -51
- package/src/forge/_generated/aiProviders.json +0 -2
- package/src/forge/_generated/aiProviders.ts +0 -23
- package/src/forge/_generated/aiRegistry.json +0 -2
- package/src/forge/_generated/aiRegistry.ts +0 -31
- package/src/forge/_generated/api.json +0 -2
- package/src/forge/_generated/api.ts +0 -8
- package/src/forge/_generated/appGraph.json +0 -2
- package/src/forge/_generated/appGraph.ts +0 -14919
- package/src/forge/_generated/appMap.md +0 -55
- package/src/forge/_generated/artifactManifest.json +0 -2
- package/src/forge/_generated/artifactManifest.ts +0 -7
- package/src/forge/_generated/authClaims.json +0 -2
- package/src/forge/_generated/authClaims.ts +0 -13
- package/src/forge/_generated/authConfig.json +0 -2
- package/src/forge/_generated/authConfig.ts +0 -17
- package/src/forge/_generated/authContext.ts +0 -23
- package/src/forge/_generated/authRegistry.json +0 -2
- package/src/forge/_generated/authRegistry.ts +0 -25
- package/src/forge/_generated/buildInfo.json +0 -2
- package/src/forge/_generated/buildInfo.ts +0 -9
- package/src/forge/_generated/capabilityMap.json +0 -2
- package/src/forge/_generated/capabilityMap.md +0 -15
- package/src/forge/_generated/capabilityMap.ts +0 -17
- package/src/forge/_generated/client.ts +0 -282
- package/src/forge/_generated/clientApi.ts +0 -9
- package/src/forge/_generated/clientManifest.json +0 -2
- package/src/forge/_generated/clientManifest.ts +0 -39
- package/src/forge/_generated/clientTypes.ts +0 -78
- package/src/forge/_generated/configRegistry.json +0 -2
- package/src/forge/_generated/configRegistry.ts +0 -4
- package/src/forge/_generated/dataGraph.json +0 -2
- package/src/forge/_generated/dataGraph.ts +0 -8
- package/src/forge/_generated/db.json +0 -2
- package/src/forge/_generated/db.ts +0 -2
- package/src/forge/_generated/dbSecurityManifest.json +0 -2
- package/src/forge/_generated/dbSecurityManifest.ts +0 -15
- package/src/forge/_generated/dbSessionContext.json +0 -2
- package/src/forge/_generated/dbSessionContext.ts +0 -39
- package/src/forge/_generated/deployManifest.json +0 -2
- package/src/forge/_generated/deployManifest.ts +0 -14
- package/src/forge/_generated/devManifest.json +0 -2
- package/src/forge/_generated/devManifest.ts +0 -62
- package/src/forge/_generated/envSchema.json +0 -2
- package/src/forge/_generated/envSchema.ts +0 -59
- package/src/forge/_generated/frontendGraph.json +0 -2
- package/src/forge/_generated/frontendGraph.ts +0 -27
- package/src/forge/_generated/importGuards.json +0 -2
- package/src/forge/_generated/importGuards.ts +0 -686
- package/src/forge/_generated/index.ts +0 -68
- package/src/forge/_generated/liveProductionManifest.json +0 -2
- package/src/forge/_generated/liveProductionManifest.ts +0 -23
- package/src/forge/_generated/liveProtocol.json +0 -2
- package/src/forge/_generated/liveProtocol.ts +0 -21
- package/src/forge/_generated/liveQueryRegistry.json +0 -2
- package/src/forge/_generated/liveQueryRegistry.ts +0 -9
- package/src/forge/_generated/liveTransportConfig.json +0 -2
- package/src/forge/_generated/liveTransportConfig.ts +0 -19
- package/src/forge/_generated/makeRegistry.json +0 -2
- package/src/forge/_generated/makeRegistry.ts +0 -177
- package/src/forge/_generated/makeTemplates.json +0 -2
- package/src/forge/_generated/makeTemplates.ts +0 -66
- package/src/forge/_generated/mockMap.json +0 -2
- package/src/forge/_generated/mockMap.ts +0 -7
- package/src/forge/_generated/operationPlaybooks.md +0 -167
- package/src/forge/_generated/packageGraph.json +0 -2
- package/src/forge/_generated/packageGraph.ts +0 -249334
- package/src/forge/_generated/packageUpgradeRegistry.json +0 -2
- package/src/forge/_generated/packageUpgradeRegistry.ts +0 -15
- package/src/forge/_generated/permissionMatrix.json +0 -2
- package/src/forge/_generated/permissionMatrix.ts +0 -7
- package/src/forge/_generated/policyRegistry.json +0 -2
- package/src/forge/_generated/policyRegistry.ts +0 -11
- package/src/forge/_generated/queryRegistry.json +0 -2
- package/src/forge/_generated/queryRegistry.ts +0 -9
- package/src/forge/_generated/react.d.ts +0 -22
- package/src/forge/_generated/react.ts +0 -29
- package/src/forge/_generated/reactManifest.json +0 -2
- package/src/forge/_generated/reactManifest.ts +0 -19
- package/src/forge/_generated/rlsPolicies.json +0 -2
- package/src/forge/_generated/rlsPolicies.sql +0 -34
- package/src/forge/_generated/rlsPolicies.ts +0 -6
- package/src/forge/_generated/runtimeGraph.json +0 -2
- package/src/forge/_generated/runtimeGraph.ts +0 -8
- package/src/forge/_generated/runtimeMatrix.json +0 -2
- package/src/forge/_generated/runtimeMatrix.ts +0 -334130
- package/src/forge/_generated/runtimeRegistry.ts +0 -2
- package/src/forge/_generated/runtimeRules.md +0 -91
- package/src/forge/_generated/secretRegistry.json +0 -2
- package/src/forge/_generated/secretRegistry.ts +0 -50
- package/src/forge/_generated/secretsContext.ts +0 -11
- package/src/forge/_generated/serverApi.ts +0 -10
- package/src/forge/_generated/sourceMapManifest.json +0 -2
- package/src/forge/_generated/sourceMapManifest.ts +0 -7
- package/src/forge/_generated/sqlPlan.json +0 -2
- package/src/forge/_generated/sqlPlan.ts +0 -88
- package/src/forge/_generated/subscriptionManifest.json +0 -2
- package/src/forge/_generated/subscriptionManifest.ts +0 -7
- package/src/forge/_generated/symbolicationManifest.json +0 -2
- package/src/forge/_generated/symbolicationManifest.ts +0 -17
- package/src/forge/_generated/telemetryRegistry.json +0 -2
- package/src/forge/_generated/telemetryRegistry.ts +0 -9
- package/src/forge/_generated/telemetrySinks.json +0 -2
- package/src/forge/_generated/telemetrySinks.ts +0 -11
- package/src/forge/_generated/tenantScope.json +0 -2
- package/src/forge/_generated/tenantScope.ts +0 -8
- package/src/forge/_generated/testGraph.json +0 -2
- package/src/forge/_generated/testGraph.ts +0 -3430
- package/src/forge/_generated/testPlanRegistry.json +0 -2
- package/src/forge/_generated/testPlanRegistry.ts +0 -33
- package/src/forge/_generated/uiRoutes.json +0 -2
- package/src/forge/_generated/uiRoutes.ts +0 -16
- package/src/forge/_generated/uiScenarios.json +0 -2
- package/src/forge/_generated/uiScenarios.ts +0 -30
- package/src/forge/_generated/uiTestManifest.json +0 -2
- package/src/forge/_generated/uiTestManifest.ts +0 -27
- package/src/forge/_generated/workflowRegistry.json +0 -2
- package/src/forge/_generated/workflowRegistry.ts +0 -9
- package/src/forge/_generated/workflowSubscriptions.json +0 -2
- package/src/forge/_generated/workflowSubscriptions.ts +0 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
1
|
+
import { join, relative, resolve } from "node:path";
|
|
2
2
|
import { nodeFileSystem } from "../fs/index.ts";
|
|
3
3
|
import type { AddOptions } from "../types/cli.ts";
|
|
4
4
|
import type { Diagnostic } from "../types/diagnostic.ts";
|
|
@@ -16,11 +16,14 @@ import { PACKAGE_ANALYZER_VERSION } from "../package-graph/constants.ts";
|
|
|
16
16
|
import { renderBody } from "../emitter/render.ts";
|
|
17
17
|
import { hashStable } from "../primitives/hash.ts";
|
|
18
18
|
import { PackageGraphCompiler } from "../package-graph/compiler.ts";
|
|
19
|
+
import { run as runGenerate } from "../orchestrator/run.ts";
|
|
19
20
|
import {
|
|
21
|
+
buildAddCommand,
|
|
20
22
|
detectAndCreatePackageManagerAdapter,
|
|
21
23
|
dryRunRecipeFallbackMessage,
|
|
22
24
|
type PackageManagerAdapter,
|
|
23
25
|
} from "../package-manager/adapter.ts";
|
|
26
|
+
import { parsePackageName } from "../package-manager/parse-spec.ts";
|
|
24
27
|
import { PackageManagerCommandError } from "../package-manager/executor.ts";
|
|
25
28
|
import {
|
|
26
29
|
isReferenceAlias,
|
|
@@ -50,6 +53,24 @@ export interface ForgeAddOptions extends AddOptions {
|
|
|
50
53
|
|
|
51
54
|
export interface ForgeAddResult {
|
|
52
55
|
alias: string;
|
|
56
|
+
mode?: "integration" | "package";
|
|
57
|
+
targetKind?: "forge-integration" | "npm-package";
|
|
58
|
+
target?: string;
|
|
59
|
+
packageTarget?: "root" | "frontend" | "backend" | "workspace";
|
|
60
|
+
packageTargetReason?: string;
|
|
61
|
+
explanation?: string;
|
|
62
|
+
recipeVersion?: string;
|
|
63
|
+
recipePackages?: string[];
|
|
64
|
+
requiredSecrets?: string[];
|
|
65
|
+
optionalSecrets?: string[];
|
|
66
|
+
packageSpec?: string;
|
|
67
|
+
packageName?: string;
|
|
68
|
+
packageManager?: string;
|
|
69
|
+
installCommand?: string[];
|
|
70
|
+
nativeInstallCommand?: string[];
|
|
71
|
+
avoidedManualCommand?: string;
|
|
72
|
+
installCwd?: string;
|
|
73
|
+
installWorkspace?: string;
|
|
53
74
|
changed: string[];
|
|
54
75
|
unchanged: string[];
|
|
55
76
|
warnings: Diagnostic[];
|
|
@@ -58,6 +79,210 @@ export interface ForgeAddResult {
|
|
|
58
79
|
failureKind?: string;
|
|
59
80
|
}
|
|
60
81
|
|
|
82
|
+
function recipeResultMetadata(recipe: NonNullable<ReturnType<typeof resolveRecipe>>): Pick<
|
|
83
|
+
ForgeAddResult,
|
|
84
|
+
"recipeVersion" | "recipePackages" | "requiredSecrets" | "optionalSecrets"
|
|
85
|
+
> {
|
|
86
|
+
return {
|
|
87
|
+
recipeVersion: recipe.recipeVersion,
|
|
88
|
+
recipePackages: recipe.packages.map((pkg) => pkg.packageName),
|
|
89
|
+
requiredSecrets: recipe.secrets.filter((secret) => secret.required !== false).map((secret) => secret.envVar),
|
|
90
|
+
optionalSecrets: recipe.secrets.filter((secret) => secret.required === false).map((secret) => secret.envVar),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function addExplanation(result: ForgeAddResult): string {
|
|
95
|
+
if (result.mode === "package") {
|
|
96
|
+
const location = result.target && result.target !== "root" ? `${result.target}/package.json` : "package.json";
|
|
97
|
+
const command = result.installCommand?.join(" ") ?? `package manager add ${result.packageSpec ?? result.alias}`;
|
|
98
|
+
const target = result.packageTarget && result.packageTarget !== "root" ? ` (${result.packageTarget})` : "";
|
|
99
|
+
return `Adds npm package '${result.packageSpec ?? result.alias}' to ${location}${target}, then refreshes Forge package evidence. Forge runs the native install command for you: ${command}.`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (result.failureKind === "unknown_alias") {
|
|
103
|
+
return `No Forge integration recipe exists for '${result.alias}'. Use 'forge add ${result.alias}' or 'forge add package ${result.alias}' for a normal npm package, or choose a supported integration alias.`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return `Applies the Forge integration recipe '${result.alias}', including package install, generated adapters, secret-name metadata, runtime guards, and Forge lock evidence.`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function finalizeAddResult(result: Omit<ForgeAddResult, "targetKind" | "explanation">): ForgeAddResult {
|
|
110
|
+
const mode = result.mode ?? "integration";
|
|
111
|
+
const withMode: ForgeAddResult = {
|
|
112
|
+
...result,
|
|
113
|
+
mode,
|
|
114
|
+
targetKind: mode === "package" ? "npm-package" : "forge-integration",
|
|
115
|
+
};
|
|
116
|
+
return {
|
|
117
|
+
...withMode,
|
|
118
|
+
explanation: addExplanation(withMode),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function packageJsonRelativeFor(workspace?: string): string {
|
|
123
|
+
return workspace ? `${workspace.replace(/\\/g, "/")}/package.json` : "package.json";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
type PackageAddScope = "root" | "frontend" | "backend" | "workspace";
|
|
127
|
+
|
|
128
|
+
interface NormalizedPackageRequest {
|
|
129
|
+
spec: string;
|
|
130
|
+
packageTarget: PackageAddScope;
|
|
131
|
+
packageTargetReason: string;
|
|
132
|
+
installWorkspace?: string;
|
|
133
|
+
forcePackageMode: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function parseScopedPackageSpec(spec: string): {
|
|
137
|
+
spec: string;
|
|
138
|
+
target?: "frontend" | "backend";
|
|
139
|
+
forcePackageMode: boolean;
|
|
140
|
+
} {
|
|
141
|
+
const trimmed = spec.trim();
|
|
142
|
+
const match = /^(frontend|front|web|client|backend|back|server|api|root):(.+)$/i.exec(trimmed);
|
|
143
|
+
if (!match) {
|
|
144
|
+
return { spec: trimmed, forcePackageMode: false };
|
|
145
|
+
}
|
|
146
|
+
const scope = match[1]!.toLowerCase();
|
|
147
|
+
return {
|
|
148
|
+
spec: match[2]!.trim(),
|
|
149
|
+
target: scope === "frontend" || scope === "front" || scope === "web" || scope === "client"
|
|
150
|
+
? "frontend"
|
|
151
|
+
: "backend",
|
|
152
|
+
forcePackageMode: true,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function findFrontendWorkspace(workspaceRoot: string): string | undefined {
|
|
157
|
+
for (const candidate of ["web", "frontend", "client", "apps/web", "packages/web"]) {
|
|
158
|
+
if (nodeFileSystem.exists(join(workspaceRoot, candidate, "package.json"))) {
|
|
159
|
+
return candidate;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function normalizePackageRequest(
|
|
166
|
+
spec: string,
|
|
167
|
+
options: ForgeAddOptions,
|
|
168
|
+
): { request: NormalizedPackageRequest; error?: Diagnostic } {
|
|
169
|
+
const scoped = parseScopedPackageSpec(spec);
|
|
170
|
+
const requestedTarget = options.packageTarget ?? scoped.target;
|
|
171
|
+
if (options.installWorkspace?.trim()) {
|
|
172
|
+
return {
|
|
173
|
+
request: {
|
|
174
|
+
spec: scoped.spec,
|
|
175
|
+
packageTarget: "workspace",
|
|
176
|
+
packageTargetReason: `explicit --workspace ${options.installWorkspace.trim()}`,
|
|
177
|
+
installWorkspace: options.installWorkspace.trim(),
|
|
178
|
+
forcePackageMode: scoped.forcePackageMode,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (requestedTarget === "frontend") {
|
|
183
|
+
const workspace = findFrontendWorkspace(options.workspaceRoot);
|
|
184
|
+
if (!workspace) {
|
|
185
|
+
return {
|
|
186
|
+
request: {
|
|
187
|
+
spec: scoped.spec,
|
|
188
|
+
packageTarget: "frontend",
|
|
189
|
+
packageTargetReason: "frontend target requested, but no frontend package.json was detected",
|
|
190
|
+
forcePackageMode: true,
|
|
191
|
+
},
|
|
192
|
+
error: createDiagnostic({
|
|
193
|
+
severity: "error",
|
|
194
|
+
code: "FORGE_ADD_FRONTEND_WORKSPACE_MISSING",
|
|
195
|
+
message: "frontend package target requested, but no frontend package.json was found under web, frontend, client, apps/web, or packages/web",
|
|
196
|
+
fixHint: "Create a frontend with forge make ui, pass --workspace <path>, or install as a backend/root package.",
|
|
197
|
+
suggestedCommands: [
|
|
198
|
+
"forge make ui --framework vite --dry-run --json",
|
|
199
|
+
`forge add ${scoped.spec} --workspace web --dry-run --json`,
|
|
200
|
+
`forge add backend:${scoped.spec} --dry-run --json`,
|
|
201
|
+
],
|
|
202
|
+
}),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
request: {
|
|
207
|
+
spec: scoped.spec,
|
|
208
|
+
packageTarget: "frontend",
|
|
209
|
+
packageTargetReason: `frontend target resolved to ${workspace}/package.json`,
|
|
210
|
+
installWorkspace: workspace,
|
|
211
|
+
forcePackageMode: true,
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
if (requestedTarget === "backend") {
|
|
216
|
+
return {
|
|
217
|
+
request: {
|
|
218
|
+
spec: scoped.spec,
|
|
219
|
+
packageTarget: "backend",
|
|
220
|
+
packageTargetReason: "backend target resolves to the Forge app root package.json",
|
|
221
|
+
forcePackageMode: true,
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
request: {
|
|
227
|
+
spec: scoped.spec,
|
|
228
|
+
packageTarget: "root",
|
|
229
|
+
packageTargetReason: "default package target resolves to the Forge app root package.json",
|
|
230
|
+
forcePackageMode: scoped.forcePackageMode,
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function resolveInstallRoot(options: ForgeAddOptions): {
|
|
236
|
+
installRoot: string;
|
|
237
|
+
target: string;
|
|
238
|
+
extraSnapshotPaths: string[];
|
|
239
|
+
error?: Diagnostic;
|
|
240
|
+
} {
|
|
241
|
+
const workspace = options.installWorkspace?.trim();
|
|
242
|
+
if (!workspace) {
|
|
243
|
+
return {
|
|
244
|
+
installRoot: options.workspaceRoot,
|
|
245
|
+
target: "root",
|
|
246
|
+
extraSnapshotPaths: [],
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const workspaceRoot = resolve(options.workspaceRoot);
|
|
251
|
+
const installRoot = resolve(workspaceRoot, workspace);
|
|
252
|
+
const rel = relative(workspaceRoot, installRoot).replace(/\\/g, "/");
|
|
253
|
+
if (rel.startsWith("..") || rel === "") {
|
|
254
|
+
return {
|
|
255
|
+
installRoot,
|
|
256
|
+
target: workspace,
|
|
257
|
+
extraSnapshotPaths: [],
|
|
258
|
+
error: createDiagnostic({
|
|
259
|
+
severity: "error",
|
|
260
|
+
code: "FORGE_ADD_INVALID_WORKSPACE",
|
|
261
|
+
message: `workspace '${workspace}' must resolve inside the Forge app`,
|
|
262
|
+
}),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (!nodeFileSystem.exists(join(installRoot, "package.json"))) {
|
|
267
|
+
return {
|
|
268
|
+
installRoot,
|
|
269
|
+
target: rel,
|
|
270
|
+
extraSnapshotPaths: [],
|
|
271
|
+
error: createDiagnostic({
|
|
272
|
+
severity: "error",
|
|
273
|
+
code: "FORGE_ADD_INVALID_WORKSPACE",
|
|
274
|
+
message: `workspace '${workspace}' does not contain a package.json`,
|
|
275
|
+
}),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
installRoot,
|
|
281
|
+
target: rel,
|
|
282
|
+
extraSnapshotPaths: [packageJsonRelativeFor(rel)],
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
61
286
|
function failureKind(errors: Diagnostic[]): string | undefined {
|
|
62
287
|
if (errors.length === 0) {
|
|
63
288
|
return undefined;
|
|
@@ -119,6 +344,104 @@ function dependencyFromInstall(
|
|
|
119
344
|
};
|
|
120
345
|
}
|
|
121
346
|
|
|
347
|
+
function fileHashOrNull(path: string): string | null {
|
|
348
|
+
if (!nodeFileSystem.exists(path)) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
return hashStable(nodeFileSystem.readText(path) ?? "");
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function snapshotPackageManagerFiles(
|
|
355
|
+
workspaceRoot: string,
|
|
356
|
+
pm: PackageManagerAdapter,
|
|
357
|
+
extraPaths: string[] = [],
|
|
358
|
+
): Map<string, string | null> {
|
|
359
|
+
const paths = [...new Set(["package.json", pm.lockfile, ...extraPaths])];
|
|
360
|
+
return new Map(
|
|
361
|
+
paths.map((path) => [
|
|
362
|
+
path,
|
|
363
|
+
fileHashOrNull(join(workspaceRoot, path)),
|
|
364
|
+
]),
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function changedPackageManagerFiles(
|
|
369
|
+
workspaceRoot: string,
|
|
370
|
+
before: Map<string, string | null>,
|
|
371
|
+
): string[] {
|
|
372
|
+
const changed: string[] = [];
|
|
373
|
+
for (const [path, previousHash] of before) {
|
|
374
|
+
if (fileHashOrNull(join(workspaceRoot, path)) !== previousHash) {
|
|
375
|
+
changed.push(path);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return changed.sort();
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function workosFrontendWorkspace(workspaceRoot: string): string | undefined {
|
|
382
|
+
return findFrontendWorkspace(workspaceRoot);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function connectWorkOSReactRoot(workspaceRoot: string, frontendWorkspace: string): {
|
|
386
|
+
changed: string[];
|
|
387
|
+
warnings: Diagnostic[];
|
|
388
|
+
} {
|
|
389
|
+
const mainRel = `${frontendWorkspace}/src/main.tsx`;
|
|
390
|
+
const mainPath = join(workspaceRoot, mainRel);
|
|
391
|
+
const current = nodeFileSystem.readText(mainPath);
|
|
392
|
+
if (current === null) {
|
|
393
|
+
return {
|
|
394
|
+
changed: [],
|
|
395
|
+
warnings: [
|
|
396
|
+
createDiagnostic({
|
|
397
|
+
severity: "warning",
|
|
398
|
+
code: "FORGE_WORKOS_AUTHKIT_ROOT_NOT_FOUND",
|
|
399
|
+
message: `generated WorkOS AuthKit bridge, but ${mainRel} was not found`,
|
|
400
|
+
fixHint: "Wrap the web app root with ForgeWorkOSAuthProvider from ./lib/workos-auth.",
|
|
401
|
+
suggestedCommands: ["forge workos doctor --json", "forge inspect ui --json"],
|
|
402
|
+
}),
|
|
403
|
+
],
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
if (current.includes("ForgeWorkOSAuthProvider")) {
|
|
407
|
+
return { changed: [], warnings: [] };
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const canRewriteDefaultViteRoot =
|
|
411
|
+
current.includes('import { ForgeProvider, forgeUrl } from "./lib/forge";') &&
|
|
412
|
+
current.includes("<ForgeProvider url={forgeUrl} devAuth>") &&
|
|
413
|
+
current.includes("</ForgeProvider>");
|
|
414
|
+
|
|
415
|
+
if (!canRewriteDefaultViteRoot) {
|
|
416
|
+
return {
|
|
417
|
+
changed: [],
|
|
418
|
+
warnings: [
|
|
419
|
+
createDiagnostic({
|
|
420
|
+
severity: "warning",
|
|
421
|
+
code: "FORGE_WORKOS_AUTHKIT_ROOT_CUSTOM",
|
|
422
|
+
message: `generated WorkOS AuthKit bridge, but ${mainRel} is custom and was not rewritten automatically`,
|
|
423
|
+
fixHint: "Import ForgeWorkOSAuthProvider from ./lib/workos-auth and wrap the app root with it so AuthKit tokens are passed to ForgeProvider.",
|
|
424
|
+
suggestedCommands: ["forge workos doctor --json", "forge inspect ui --json"],
|
|
425
|
+
}),
|
|
426
|
+
],
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const next = current
|
|
431
|
+
.replace(
|
|
432
|
+
'import { ForgeProvider, forgeUrl } from "./lib/forge";',
|
|
433
|
+
'import { ForgeWorkOSAuthProvider } from "./lib/workos-auth";',
|
|
434
|
+
)
|
|
435
|
+
.replace("<ForgeProvider url={forgeUrl} devAuth>", "<ForgeWorkOSAuthProvider>")
|
|
436
|
+
.replace("</ForgeProvider>", "</ForgeWorkOSAuthProvider>");
|
|
437
|
+
|
|
438
|
+
if (next !== current) {
|
|
439
|
+
nodeFileSystem.writeText(mainPath, next);
|
|
440
|
+
return { changed: [mainRel], warnings: [] };
|
|
441
|
+
}
|
|
442
|
+
return { changed: [], warnings: [] };
|
|
443
|
+
}
|
|
444
|
+
|
|
122
445
|
async function analyzeRecipePackages(
|
|
123
446
|
recipe: NonNullable<ReturnType<typeof resolveRecipe>>,
|
|
124
447
|
ctx: ReturnType<typeof discover>,
|
|
@@ -258,24 +581,85 @@ export async function forgeAdd(
|
|
|
258
581
|
alias: string,
|
|
259
582
|
options: ForgeAddOptions,
|
|
260
583
|
): Promise<ForgeAddResult> {
|
|
261
|
-
const
|
|
584
|
+
const packageRequestResult = normalizePackageRequest(alias, options);
|
|
585
|
+
const packageRequest = packageRequestResult.request;
|
|
586
|
+
const effectiveOptions: ForgeAddOptions = {
|
|
587
|
+
...options,
|
|
588
|
+
installWorkspace: packageRequest.installWorkspace,
|
|
589
|
+
};
|
|
590
|
+
const packageModeRequested =
|
|
591
|
+
options.mode === "package" ||
|
|
592
|
+
packageRequest.forcePackageMode ||
|
|
593
|
+
options.packageTarget !== undefined;
|
|
594
|
+
if (packageRequestResult.error && packageModeRequested) {
|
|
595
|
+
return finalizeAddResult({
|
|
596
|
+
alias: packageRequest.spec,
|
|
597
|
+
mode: "package",
|
|
598
|
+
target: packageRequest.installWorkspace ?? packageRequest.packageTarget,
|
|
599
|
+
packageTarget: packageRequest.packageTarget,
|
|
600
|
+
packageTargetReason: packageRequest.packageTargetReason,
|
|
601
|
+
packageSpec: packageRequest.spec,
|
|
602
|
+
packageName: parsePackageName(packageRequest.spec),
|
|
603
|
+
changed: [],
|
|
604
|
+
unchanged: [],
|
|
605
|
+
warnings: [],
|
|
606
|
+
errors: [packageRequestResult.error],
|
|
607
|
+
exitCode: 1,
|
|
608
|
+
failureKind: "invalid_workspace",
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
if (options.mode === "integration" && (packageRequest.forcePackageMode || options.packageTarget)) {
|
|
612
|
+
const error = createDiagnostic({
|
|
613
|
+
severity: "error",
|
|
614
|
+
code: "FORGE_ADD_SCOPED_INTEGRATION",
|
|
615
|
+
message: "frontend/backend package targets only apply to normal npm package installs, not explicit integration recipes",
|
|
616
|
+
fixHint: "Use forge add package <spec> --frontend, forge add frontend:<spec>, or remove the frontend/backend target for an integration recipe.",
|
|
617
|
+
suggestedCommands: [
|
|
618
|
+
`forge add package ${packageRequest.spec} --frontend --dry-run --json`,
|
|
619
|
+
`forge add integration ${packageRequest.spec} --dry-run --json`,
|
|
620
|
+
],
|
|
621
|
+
});
|
|
622
|
+
return finalizeAddResult({
|
|
623
|
+
alias: packageRequest.spec,
|
|
624
|
+
mode: "integration",
|
|
625
|
+
changed: [],
|
|
626
|
+
unchanged: [],
|
|
627
|
+
warnings: [],
|
|
628
|
+
errors: [error],
|
|
629
|
+
exitCode: 1,
|
|
630
|
+
failureKind: "invalid_target",
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
const normalized = packageRequest.spec.trim().toLowerCase();
|
|
262
635
|
const recipe = resolveRecipe(normalized);
|
|
636
|
+
const mode = options.mode ?? "auto";
|
|
637
|
+
|
|
638
|
+
if (packageModeRequested) {
|
|
639
|
+
return forgeAddPackage(packageRequest.spec, effectiveOptions, packageRequest);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
if (mode === "auto" && (!isReferenceAlias(normalized) || recipe === null)) {
|
|
643
|
+
return forgeAddPackage(packageRequest.spec, effectiveOptions, packageRequest);
|
|
644
|
+
}
|
|
263
645
|
|
|
264
646
|
if (!isReferenceAlias(normalized) || recipe === null) {
|
|
265
647
|
const error = createDiagnostic({
|
|
266
648
|
severity: "error",
|
|
267
649
|
code: "FORGE_UNKNOWN_ALIAS",
|
|
268
|
-
message: `unknown integration alias '${alias}'; supported: stripe, posthog, sentry, zod, ai
|
|
650
|
+
message: `unknown integration alias '${alias}'; supported: stripe, posthog, sentry, zod, convex, workos, ai. For npm packages, use 'forge add package ${alias}' or 'forge add ${alias}'.`,
|
|
651
|
+
suggestedCommands: [`forge add package ${alias} --dry-run --json`, "forge add --help"],
|
|
269
652
|
});
|
|
270
|
-
return {
|
|
653
|
+
return finalizeAddResult({
|
|
271
654
|
alias: normalized,
|
|
655
|
+
mode: "integration",
|
|
272
656
|
changed: [],
|
|
273
657
|
unchanged: [],
|
|
274
658
|
warnings: [],
|
|
275
659
|
errors: [error],
|
|
276
660
|
exitCode: 1,
|
|
277
661
|
failureKind: "unknown_alias",
|
|
278
|
-
};
|
|
662
|
+
});
|
|
279
663
|
}
|
|
280
664
|
|
|
281
665
|
const pm =
|
|
@@ -283,7 +667,7 @@ export async function forgeAdd(
|
|
|
283
667
|
detectAndCreatePackageManagerAdapter(options.workspaceRoot);
|
|
284
668
|
|
|
285
669
|
if (options.dryRun) {
|
|
286
|
-
const ctx = discover({ workspaceRoot:
|
|
670
|
+
const ctx = discover({ workspaceRoot: effectiveOptions.workspaceRoot });
|
|
287
671
|
let installRoot = options.workspaceRoot;
|
|
288
672
|
|
|
289
673
|
try {
|
|
@@ -302,7 +686,7 @@ export async function forgeAdd(
|
|
|
302
686
|
recipe,
|
|
303
687
|
ctx,
|
|
304
688
|
installRoot,
|
|
305
|
-
|
|
689
|
+
effectiveOptions,
|
|
306
690
|
);
|
|
307
691
|
warnings.push(
|
|
308
692
|
createDiagnostic({
|
|
@@ -312,15 +696,17 @@ export async function forgeAdd(
|
|
|
312
696
|
}),
|
|
313
697
|
);
|
|
314
698
|
|
|
315
|
-
return {
|
|
699
|
+
return finalizeAddResult({
|
|
316
700
|
alias: normalized,
|
|
701
|
+
mode: "integration",
|
|
702
|
+
...recipeResultMetadata(recipe),
|
|
317
703
|
changed: [...emitPlan.files.map((file) => file.path), "forge.lock"],
|
|
318
704
|
unchanged: [],
|
|
319
705
|
warnings,
|
|
320
706
|
errors,
|
|
321
707
|
exitCode: errors.length > 0 ? 1 : 0,
|
|
322
708
|
failureKind: failureKind(errors),
|
|
323
|
-
};
|
|
709
|
+
});
|
|
324
710
|
}
|
|
325
711
|
|
|
326
712
|
const { emitPlan, warnings, errors } = await buildAddPlan(
|
|
@@ -328,29 +714,43 @@ export async function forgeAdd(
|
|
|
328
714
|
recipe,
|
|
329
715
|
ctx,
|
|
330
716
|
installRoot,
|
|
331
|
-
|
|
717
|
+
effectiveOptions,
|
|
332
718
|
);
|
|
333
719
|
|
|
334
|
-
return {
|
|
720
|
+
return finalizeAddResult({
|
|
335
721
|
alias: normalized,
|
|
722
|
+
mode: "integration",
|
|
723
|
+
...recipeResultMetadata(recipe),
|
|
336
724
|
changed: [...emitPlan.files.map((file) => file.path), "forge.lock"],
|
|
337
725
|
unchanged: [],
|
|
338
726
|
warnings,
|
|
339
727
|
errors,
|
|
340
728
|
exitCode: errors.length > 0 ? 1 : 0,
|
|
341
729
|
failureKind: failureKind(errors),
|
|
342
|
-
};
|
|
730
|
+
});
|
|
343
731
|
}
|
|
344
732
|
|
|
345
733
|
const snapshot = snapshotVersionControlled(options.workspaceRoot);
|
|
346
734
|
|
|
347
735
|
try {
|
|
736
|
+
const frontendWorkspace = normalized === "workos" ? workosFrontendWorkspace(options.workspaceRoot) : undefined;
|
|
737
|
+
const packageManagerBefore = snapshotPackageManagerFiles(
|
|
738
|
+
options.workspaceRoot,
|
|
739
|
+
pm,
|
|
740
|
+
frontendWorkspace ? [packageJsonRelativeFor(frontendWorkspace)] : [],
|
|
741
|
+
);
|
|
348
742
|
for (const pkg of recipe.packages) {
|
|
349
743
|
await pm.add(pkg.packageName, {
|
|
350
744
|
cwd: options.workspaceRoot,
|
|
351
745
|
ignoreScripts: !options.allowScripts,
|
|
352
746
|
});
|
|
353
747
|
}
|
|
748
|
+
if (frontendWorkspace) {
|
|
749
|
+
await pm.add("@workos-inc/authkit-react", {
|
|
750
|
+
cwd: join(options.workspaceRoot, frontendWorkspace),
|
|
751
|
+
ignoreScripts: !options.allowScripts,
|
|
752
|
+
});
|
|
753
|
+
}
|
|
354
754
|
|
|
355
755
|
const ctx = discover({ workspaceRoot: options.workspaceRoot });
|
|
356
756
|
const { emitPlan, warnings, errors: analyzeErrors } = await buildAddPlan(
|
|
@@ -363,15 +763,17 @@ export async function forgeAdd(
|
|
|
363
763
|
|
|
364
764
|
if (analyzeErrors.length > 0) {
|
|
365
765
|
restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
|
|
366
|
-
return {
|
|
766
|
+
return finalizeAddResult({
|
|
367
767
|
alias: normalized,
|
|
768
|
+
mode: "integration",
|
|
769
|
+
...recipeResultMetadata(recipe),
|
|
368
770
|
changed: [],
|
|
369
771
|
unchanged: [],
|
|
370
772
|
warnings,
|
|
371
773
|
errors: analyzeErrors,
|
|
372
774
|
exitCode: 1,
|
|
373
775
|
failureKind: failureKind(analyzeErrors),
|
|
374
|
-
};
|
|
776
|
+
});
|
|
375
777
|
}
|
|
376
778
|
|
|
377
779
|
const emitResult = await emit(emitPlan, {
|
|
@@ -379,20 +781,26 @@ export async function forgeAdd(
|
|
|
379
781
|
mode: "write",
|
|
380
782
|
});
|
|
381
783
|
|
|
382
|
-
const
|
|
784
|
+
const workosWeb = normalized === "workos" && frontendWorkspace
|
|
785
|
+
? connectWorkOSReactRoot(options.workspaceRoot, frontendWorkspace)
|
|
786
|
+
: { changed: [] as string[], warnings: [] as Diagnostic[] };
|
|
787
|
+
|
|
788
|
+
const warningsCombined = [...warnings, ...emitResult.warnings, ...workosWeb.warnings];
|
|
383
789
|
const errors = [...analyzeErrors, ...emitResult.errors];
|
|
384
790
|
|
|
385
791
|
if (errors.length > 0) {
|
|
386
792
|
restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
|
|
387
|
-
return {
|
|
793
|
+
return finalizeAddResult({
|
|
388
794
|
alias: normalized,
|
|
795
|
+
mode: "integration",
|
|
796
|
+
...recipeResultMetadata(recipe),
|
|
389
797
|
changed: [],
|
|
390
798
|
unchanged: [],
|
|
391
799
|
warnings: warningsCombined,
|
|
392
800
|
errors,
|
|
393
801
|
exitCode: 1,
|
|
394
802
|
failureKind: failureKind(errors),
|
|
395
|
-
};
|
|
803
|
+
});
|
|
396
804
|
}
|
|
397
805
|
|
|
398
806
|
const integrityErrors = verifyLockIntegrity(
|
|
@@ -401,15 +809,17 @@ export async function forgeAdd(
|
|
|
401
809
|
);
|
|
402
810
|
if (integrityErrors.length > 0) {
|
|
403
811
|
restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
|
|
404
|
-
return {
|
|
812
|
+
return finalizeAddResult({
|
|
405
813
|
alias: normalized,
|
|
814
|
+
mode: "integration",
|
|
815
|
+
...recipeResultMetadata(recipe),
|
|
406
816
|
changed: [],
|
|
407
817
|
unchanged: [],
|
|
408
818
|
warnings: warningsCombined,
|
|
409
819
|
errors: integrityErrors,
|
|
410
820
|
exitCode: 1,
|
|
411
821
|
failureKind: "lock_integrity",
|
|
412
|
-
};
|
|
822
|
+
});
|
|
413
823
|
}
|
|
414
824
|
|
|
415
825
|
const manifest = loadManifest(ctx.cacheDir);
|
|
@@ -435,14 +845,20 @@ export async function forgeAdd(
|
|
|
435
845
|
),
|
|
436
846
|
);
|
|
437
847
|
|
|
438
|
-
return {
|
|
848
|
+
return finalizeAddResult({
|
|
439
849
|
alias: normalized,
|
|
440
|
-
|
|
850
|
+
mode: "integration",
|
|
851
|
+
...recipeResultMetadata(recipe),
|
|
852
|
+
changed: [
|
|
853
|
+
...changedPackageManagerFiles(options.workspaceRoot, packageManagerBefore),
|
|
854
|
+
...emitResult.changed,
|
|
855
|
+
...workosWeb.changed,
|
|
856
|
+
],
|
|
441
857
|
unchanged: emitResult.unchanged,
|
|
442
858
|
warnings: warningsCombined,
|
|
443
859
|
errors: [],
|
|
444
860
|
exitCode: 0,
|
|
445
|
-
};
|
|
861
|
+
});
|
|
446
862
|
} catch (error) {
|
|
447
863
|
restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
|
|
448
864
|
|
|
@@ -459,15 +875,193 @@ export async function forgeAdd(
|
|
|
459
875
|
message: `forge add failed: ${message}`,
|
|
460
876
|
});
|
|
461
877
|
|
|
462
|
-
return {
|
|
878
|
+
return finalizeAddResult({
|
|
463
879
|
alias: normalized,
|
|
880
|
+
mode: "integration",
|
|
881
|
+
...recipeResultMetadata(recipe),
|
|
464
882
|
changed: [],
|
|
465
883
|
unchanged: [],
|
|
466
884
|
warnings: [],
|
|
467
885
|
errors: [diagnostic],
|
|
468
886
|
exitCode: 1,
|
|
469
887
|
failureKind: "install_failed",
|
|
470
|
-
};
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
async function forgeAddPackage(
|
|
893
|
+
spec: string,
|
|
894
|
+
options: ForgeAddOptions,
|
|
895
|
+
request = normalizePackageRequest(spec, options).request,
|
|
896
|
+
): Promise<ForgeAddResult> {
|
|
897
|
+
const normalized = request.spec.trim();
|
|
898
|
+
const packageName = parsePackageName(normalized);
|
|
899
|
+
const target = resolveInstallRoot(options);
|
|
900
|
+
if (target.error) {
|
|
901
|
+
return finalizeAddResult({
|
|
902
|
+
alias: normalized,
|
|
903
|
+
mode: "package",
|
|
904
|
+
target: target.target,
|
|
905
|
+
packageTarget: request.packageTarget,
|
|
906
|
+
packageTargetReason: request.packageTargetReason,
|
|
907
|
+
changed: [],
|
|
908
|
+
unchanged: [],
|
|
909
|
+
warnings: [],
|
|
910
|
+
errors: [target.error],
|
|
911
|
+
exitCode: 1,
|
|
912
|
+
failureKind: "invalid_workspace",
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const pm =
|
|
917
|
+
options.pmAdapter ??
|
|
918
|
+
detectAndCreatePackageManagerAdapter(options.workspaceRoot);
|
|
919
|
+
const packageManagerCwd = target.installRoot;
|
|
920
|
+
const semanticInstallWorkspace = target.target === "root" ? undefined : target.target;
|
|
921
|
+
const installCommand = buildAddCommand(pm.name, normalized, {
|
|
922
|
+
ignoreScripts: !options.allowScripts,
|
|
923
|
+
workspace: undefined,
|
|
924
|
+
});
|
|
925
|
+
const avoidedManualCommand = installCommand.join(" ");
|
|
926
|
+
const installPlan = {
|
|
927
|
+
packageSpec: normalized,
|
|
928
|
+
packageName,
|
|
929
|
+
packageManager: pm.name,
|
|
930
|
+
installCommand,
|
|
931
|
+
nativeInstallCommand: installCommand,
|
|
932
|
+
avoidedManualCommand,
|
|
933
|
+
installCwd: packageManagerCwd.replace(/\\/g, "/"),
|
|
934
|
+
packageTarget: request.packageTarget,
|
|
935
|
+
packageTargetReason: request.packageTargetReason,
|
|
936
|
+
...(semanticInstallWorkspace ? { installWorkspace: semanticInstallWorkspace } : {}),
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
if (options.dryRun) {
|
|
940
|
+
try {
|
|
941
|
+
await pm.dryRunAdd(normalized, {
|
|
942
|
+
cwd: packageManagerCwd,
|
|
943
|
+
ignoreScripts: !options.allowScripts,
|
|
944
|
+
workspace: undefined,
|
|
945
|
+
});
|
|
946
|
+
} catch (error) {
|
|
947
|
+
const message =
|
|
948
|
+
error instanceof PackageManagerCommandError
|
|
949
|
+
? error.message
|
|
950
|
+
: error instanceof Error
|
|
951
|
+
? error.message
|
|
952
|
+
: String(error);
|
|
953
|
+
const diagnostic = createDiagnostic({
|
|
954
|
+
severity: "error",
|
|
955
|
+
code: "FORGE_ADD_INSTALL_FAILED",
|
|
956
|
+
message: `forge add package dry-run failed: ${message}`,
|
|
957
|
+
});
|
|
958
|
+
return finalizeAddResult({
|
|
959
|
+
alias: normalized,
|
|
960
|
+
mode: "package",
|
|
961
|
+
target: target.target,
|
|
962
|
+
...installPlan,
|
|
963
|
+
changed: [],
|
|
964
|
+
unchanged: [],
|
|
965
|
+
warnings: [],
|
|
966
|
+
errors: [diagnostic],
|
|
967
|
+
exitCode: 1,
|
|
968
|
+
failureKind: "install_failed",
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
return finalizeAddResult({
|
|
973
|
+
alias: normalized,
|
|
974
|
+
mode: "package",
|
|
975
|
+
target: target.target,
|
|
976
|
+
...installPlan,
|
|
977
|
+
changed: [
|
|
978
|
+
packageJsonRelativeFor(target.target === "root" ? undefined : target.target),
|
|
979
|
+
],
|
|
980
|
+
unchanged: [],
|
|
981
|
+
warnings: [],
|
|
982
|
+
errors: [],
|
|
983
|
+
exitCode: 0,
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
const snapshot = snapshotVersionControlled(
|
|
988
|
+
options.workspaceRoot,
|
|
989
|
+
target.extraSnapshotPaths,
|
|
990
|
+
);
|
|
991
|
+
|
|
992
|
+
try {
|
|
993
|
+
await pm.add(normalized, {
|
|
994
|
+
cwd: packageManagerCwd,
|
|
995
|
+
ignoreScripts: !options.allowScripts,
|
|
996
|
+
workspace: undefined,
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
const generated = await runGenerate({
|
|
1000
|
+
workspaceRoot: options.workspaceRoot,
|
|
1001
|
+
check: false,
|
|
1002
|
+
dryRun: false,
|
|
1003
|
+
json: options.json,
|
|
1004
|
+
concurrency: 4,
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
if (generated.exitCode !== 0) {
|
|
1008
|
+
restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
|
|
1009
|
+
return finalizeAddResult({
|
|
1010
|
+
alias: normalized,
|
|
1011
|
+
mode: "package",
|
|
1012
|
+
target: target.target,
|
|
1013
|
+
...installPlan,
|
|
1014
|
+
changed: [],
|
|
1015
|
+
unchanged: [],
|
|
1016
|
+
warnings: generated.warnings,
|
|
1017
|
+
errors: generated.errors,
|
|
1018
|
+
exitCode: 1,
|
|
1019
|
+
failureKind: generated.failureKind,
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
return finalizeAddResult({
|
|
1024
|
+
alias: normalized,
|
|
1025
|
+
mode: "package",
|
|
1026
|
+
target: target.target,
|
|
1027
|
+
...installPlan,
|
|
1028
|
+
changed: [
|
|
1029
|
+
packageJsonRelativeFor(target.target === "root" ? undefined : target.target),
|
|
1030
|
+
...generated.changed,
|
|
1031
|
+
],
|
|
1032
|
+
unchanged: generated.unchanged,
|
|
1033
|
+
warnings: generated.warnings,
|
|
1034
|
+
errors: generated.errors,
|
|
1035
|
+
exitCode: 0,
|
|
1036
|
+
});
|
|
1037
|
+
} catch (error) {
|
|
1038
|
+
restoreVersionControlledSnapshot(options.workspaceRoot, snapshot);
|
|
1039
|
+
|
|
1040
|
+
const message =
|
|
1041
|
+
error instanceof PackageManagerCommandError
|
|
1042
|
+
? error.message
|
|
1043
|
+
: error instanceof Error
|
|
1044
|
+
? error.message
|
|
1045
|
+
: String(error);
|
|
1046
|
+
|
|
1047
|
+
const diagnostic = createDiagnostic({
|
|
1048
|
+
severity: "error",
|
|
1049
|
+
code: "FORGE_ADD_INSTALL_FAILED",
|
|
1050
|
+
message: `forge add package failed: ${message}`,
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
return finalizeAddResult({
|
|
1054
|
+
alias: normalized,
|
|
1055
|
+
mode: "package",
|
|
1056
|
+
target: target.target,
|
|
1057
|
+
...installPlan,
|
|
1058
|
+
changed: [],
|
|
1059
|
+
unchanged: [],
|
|
1060
|
+
warnings: [],
|
|
1061
|
+
errors: [diagnostic],
|
|
1062
|
+
exitCode: 1,
|
|
1063
|
+
failureKind: "install_failed",
|
|
1064
|
+
});
|
|
471
1065
|
}
|
|
472
1066
|
}
|
|
473
1067
|
|