@mesh-tech/mesh-cli 0.1.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/intent/agents-fence.md +10 -0
- package/assets/intent/intent-claude-gate.mjs +255 -0
- package/assets/log-shipper.mjs +94 -0
- package/bin/mesh.mjs +80 -0
- package/dist/bin/mesh.d.ts +7 -9
- package/dist/bin/mesh.d.ts.map +1 -1
- package/dist/bin/mesh.js +20826 -37
- package/dist/bin/mesh.js.map +7 -1
- package/dist/build-info.json +4 -0
- package/dist/src/commands/agent-api-client.d.ts +79 -0
- package/dist/src/commands/agent-api-client.d.ts.map +1 -0
- package/dist/src/commands/agent-api-client.js +170 -0
- package/dist/src/commands/agent-api-client.js.map +1 -0
- package/dist/src/commands/artifacts.d.ts +13 -0
- package/dist/src/commands/artifacts.d.ts.map +1 -0
- package/dist/src/commands/artifacts.js +140 -0
- package/dist/src/commands/artifacts.js.map +1 -0
- package/dist/src/commands/cluster.d.ts +45 -0
- package/dist/src/commands/cluster.d.ts.map +1 -0
- package/dist/src/commands/cluster.js +259 -0
- package/dist/src/commands/cluster.js.map +1 -0
- package/dist/src/commands/conversations.d.ts +61 -0
- package/dist/src/commands/conversations.d.ts.map +1 -0
- package/dist/src/commands/conversations.js +239 -0
- package/dist/src/commands/conversations.js.map +1 -0
- package/dist/src/commands/create-app.d.ts +26 -3
- package/dist/src/commands/create-app.d.ts.map +1 -1
- package/dist/src/commands/create-app.js +465 -107
- package/dist/src/commands/create-app.js.map +1 -1
- package/dist/src/commands/deploy.d.ts +19 -0
- package/dist/src/commands/deploy.d.ts.map +1 -1
- package/dist/src/commands/deploy.js +83 -142
- package/dist/src/commands/deploy.js.map +1 -1
- package/dist/src/commands/dev-doctor.d.ts +137 -0
- package/dist/src/commands/dev-doctor.d.ts.map +1 -0
- package/dist/src/commands/dev-doctor.js +671 -0
- package/dist/src/commands/dev-doctor.js.map +1 -0
- package/dist/src/commands/dev-launch.d.ts +59 -0
- package/dist/src/commands/dev-launch.d.ts.map +1 -0
- package/dist/src/commands/dev-launch.js +118 -0
- package/dist/src/commands/dev-launch.js.map +1 -0
- package/dist/src/commands/dev-token-server.d.ts +32 -0
- package/dist/src/commands/dev-token-server.d.ts.map +1 -0
- package/dist/src/commands/dev-token-server.js +68 -0
- package/dist/src/commands/dev-token-server.js.map +1 -0
- package/dist/src/commands/dev.d.ts +289 -2
- package/dist/src/commands/dev.d.ts.map +1 -1
- package/dist/src/commands/dev.js +2501 -574
- package/dist/src/commands/dev.js.map +1 -1
- package/dist/src/commands/docs.d.ts +3 -0
- package/dist/src/commands/docs.d.ts.map +1 -0
- package/dist/src/commands/docs.js +262 -0
- package/dist/src/commands/docs.js.map +1 -0
- package/dist/src/commands/hub/index.d.ts +99 -0
- package/dist/src/commands/hub/index.d.ts.map +1 -0
- package/dist/src/commands/hub/index.js +452 -0
- package/dist/src/commands/hub/index.js.map +1 -0
- package/dist/src/commands/init.d.ts +65 -0
- package/dist/src/commands/init.d.ts.map +1 -0
- package/dist/src/commands/init.js +370 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/install-shim.d.ts +21 -0
- package/dist/src/commands/install-shim.d.ts.map +1 -0
- package/dist/src/commands/install-shim.js +132 -0
- package/dist/src/commands/install-shim.js.map +1 -0
- package/dist/src/commands/local/auth-provision.d.ts +71 -0
- package/dist/src/commands/local/auth-provision.d.ts.map +1 -0
- package/dist/src/commands/local/auth-provision.js +286 -0
- package/dist/src/commands/local/auth-provision.js.map +1 -0
- package/dist/src/commands/local/dev-local.d.ts +97 -0
- package/dist/src/commands/local/dev-local.d.ts.map +1 -0
- package/dist/src/commands/local/dev-local.js +306 -0
- package/dist/src/commands/local/dev-local.js.map +1 -0
- package/dist/src/commands/local/docker-runner.d.ts +37 -0
- package/dist/src/commands/local/docker-runner.d.ts.map +1 -0
- package/dist/src/commands/local/docker-runner.js +104 -0
- package/dist/src/commands/local/docker-runner.js.map +1 -0
- package/dist/src/commands/local/helpers.d.ts +22 -0
- package/dist/src/commands/local/helpers.d.ts.map +1 -0
- package/dist/src/commands/local/helpers.js +46 -0
- package/dist/src/commands/local/helpers.js.map +1 -0
- package/dist/src/commands/local/hub-local.d.ts +51 -0
- package/dist/src/commands/local/hub-local.d.ts.map +1 -0
- package/dist/src/commands/local/hub-local.js +197 -0
- package/dist/src/commands/local/hub-local.js.map +1 -0
- package/dist/src/commands/local/index.d.ts +23 -0
- package/dist/src/commands/local/index.d.ts.map +1 -0
- package/dist/src/commands/local/index.js +386 -0
- package/dist/src/commands/local/index.js.map +1 -0
- package/dist/src/commands/local/mocks.d.ts +361 -0
- package/dist/src/commands/local/mocks.d.ts.map +1 -0
- package/dist/src/commands/local/mocks.js +756 -0
- package/dist/src/commands/local/mocks.js.map +1 -0
- package/dist/src/commands/local/seed-zitadel.d.ts +151 -0
- package/dist/src/commands/local/seed-zitadel.d.ts.map +1 -0
- package/dist/src/commands/local/seed-zitadel.js +408 -0
- package/dist/src/commands/local/seed-zitadel.js.map +1 -0
- package/dist/src/commands/local/seed.d.ts +106 -0
- package/dist/src/commands/local/seed.d.ts.map +1 -0
- package/dist/src/commands/local/seed.js +252 -0
- package/dist/src/commands/local/seed.js.map +1 -0
- package/dist/src/commands/local/stack.d.ts +173 -0
- package/dist/src/commands/local/stack.d.ts.map +1 -0
- package/dist/src/commands/local/stack.js +499 -0
- package/dist/src/commands/local/stack.js.map +1 -0
- package/dist/src/commands/login.d.ts +256 -12
- package/dist/src/commands/login.d.ts.map +1 -1
- package/dist/src/commands/login.js +978 -50
- package/dist/src/commands/login.js.map +1 -1
- package/dist/src/commands/peer-addressing.d.ts +51 -0
- package/dist/src/commands/peer-addressing.d.ts.map +1 -0
- package/dist/src/commands/peer-addressing.js +64 -0
- package/dist/src/commands/peer-addressing.js.map +1 -0
- package/dist/src/commands/port-ownership.d.ts +69 -0
- package/dist/src/commands/port-ownership.d.ts.map +1 -0
- package/dist/src/commands/port-ownership.js +161 -0
- package/dist/src/commands/port-ownership.js.map +1 -0
- package/dist/src/commands/registry-publish.d.ts +3 -0
- package/dist/src/commands/registry-publish.d.ts.map +1 -0
- package/dist/src/commands/registry-publish.js +161 -0
- package/dist/src/commands/registry-publish.js.map +1 -0
- package/dist/src/commands/registry.d.ts +146 -2
- package/dist/src/commands/registry.d.ts.map +1 -1
- package/dist/src/commands/registry.js +541 -85
- package/dist/src/commands/registry.js.map +1 -1
- package/dist/src/commands/secrets/index.d.ts.map +1 -1
- package/dist/src/commands/secrets/index.js +15 -1
- package/dist/src/commands/secrets/index.js.map +1 -1
- package/dist/src/commands/secrets/migrate-config.d.ts +24 -0
- package/dist/src/commands/secrets/migrate-config.d.ts.map +1 -0
- package/dist/src/commands/secrets/migrate-config.js +277 -0
- package/dist/src/commands/secrets/migrate-config.js.map +1 -0
- package/dist/src/commands/secrets/set.d.ts +1 -0
- package/dist/src/commands/secrets/set.d.ts.map +1 -1
- package/dist/src/commands/secrets/set.js +96 -2
- package/dist/src/commands/secrets/set.js.map +1 -1
- package/dist/src/commands/skills.d.ts +34 -0
- package/dist/src/commands/skills.d.ts.map +1 -0
- package/dist/src/commands/skills.js +207 -0
- package/dist/src/commands/skills.js.map +1 -0
- package/dist/src/commands/stack.d.ts.map +1 -1
- package/dist/src/commands/stack.js +361 -23
- package/dist/src/commands/stack.js.map +1 -1
- package/dist/src/commands/temporal.d.ts +15 -0
- package/dist/src/commands/temporal.d.ts.map +1 -0
- package/dist/src/commands/temporal.js +781 -0
- package/dist/src/commands/temporal.js.map +1 -0
- package/dist/src/commands/tenant.d.ts +56 -0
- package/dist/src/commands/tenant.d.ts.map +1 -0
- package/dist/src/commands/tenant.js +233 -0
- package/dist/src/commands/tenant.js.map +1 -0
- package/dist/src/commands/tunnel/index.d.ts +49 -3
- package/dist/src/commands/tunnel/index.d.ts.map +1 -1
- package/dist/src/commands/tunnel/index.js +331 -8
- package/dist/src/commands/tunnel/index.js.map +1 -1
- package/dist/src/commands/vcs/clone.d.ts +3 -0
- package/dist/src/commands/vcs/clone.d.ts.map +1 -0
- package/dist/src/commands/vcs/clone.js +20 -0
- package/dist/src/commands/vcs/clone.js.map +1 -0
- package/dist/src/commands/vcs/common.d.ts +21 -0
- package/dist/src/commands/vcs/common.d.ts.map +1 -0
- package/dist/src/commands/vcs/common.js +62 -0
- package/dist/src/commands/vcs/common.js.map +1 -0
- package/dist/src/commands/vcs/drafts.d.ts +13 -0
- package/dist/src/commands/vcs/drafts.d.ts.map +1 -0
- package/dist/src/commands/vcs/drafts.js +45 -0
- package/dist/src/commands/vcs/drafts.js.map +1 -0
- package/dist/src/commands/vcs/get.d.ts +8 -0
- package/dist/src/commands/vcs/get.d.ts.map +1 -0
- package/dist/src/commands/vcs/get.js +61 -0
- package/dist/src/commands/vcs/get.js.map +1 -0
- package/dist/src/commands/vcs/index.d.ts +3 -0
- package/dist/src/commands/vcs/index.d.ts.map +1 -0
- package/dist/src/commands/vcs/index.js +58 -0
- package/dist/src/commands/vcs/index.js.map +1 -0
- package/dist/src/commands/vcs/propose.d.ts +23 -0
- package/dist/src/commands/vcs/propose.d.ts.map +1 -0
- package/dist/src/commands/vcs/propose.js +94 -0
- package/dist/src/commands/vcs/propose.js.map +1 -0
- package/dist/src/commands/vcs/review.d.ts +15 -0
- package/dist/src/commands/vcs/review.d.ts.map +1 -0
- package/dist/src/commands/vcs/review.js +35 -0
- package/dist/src/commands/vcs/review.js.map +1 -0
- package/dist/src/commands/vcs-enrich.d.ts +15 -0
- package/dist/src/commands/vcs-enrich.d.ts.map +1 -0
- package/dist/src/commands/vcs-enrich.js +28 -0
- package/dist/src/commands/vcs-enrich.js.map +1 -0
- package/dist/src/commands/vpn/index.d.ts +24 -0
- package/dist/src/commands/vpn/index.d.ts.map +1 -0
- package/dist/src/commands/vpn/index.js +543 -0
- package/dist/src/commands/vpn/index.js.map +1 -0
- package/dist/src/commands/vpn/tunnel.d.ts +11 -0
- package/dist/src/commands/vpn/tunnel.d.ts.map +1 -0
- package/dist/src/commands/vpn/tunnel.js +188 -0
- package/dist/src/commands/vpn/tunnel.js.map +1 -0
- package/dist/src/commands/workflow.d.ts +24 -0
- package/dist/src/commands/workflow.d.ts.map +1 -0
- package/dist/src/commands/workflow.js +577 -0
- package/dist/src/commands/workflow.js.map +1 -0
- package/dist/src/docs/assemble.d.ts +217 -0
- package/dist/src/docs/assemble.d.ts.map +1 -0
- package/dist/src/docs/assemble.js +739 -0
- package/dist/src/docs/assemble.js.map +1 -0
- package/dist/src/docs/cli-reference.d.ts +93 -0
- package/dist/src/docs/cli-reference.d.ts.map +1 -0
- package/dist/src/docs/cli-reference.js +256 -0
- package/dist/src/docs/cli-reference.js.map +1 -0
- package/dist/src/docs/discover.d.ts +60 -0
- package/dist/src/docs/discover.d.ts.map +1 -0
- package/dist/src/docs/discover.js +233 -0
- package/dist/src/docs/discover.js.map +1 -0
- package/dist/src/docs/portal.d.ts +79 -0
- package/dist/src/docs/portal.d.ts.map +1 -0
- package/dist/src/docs/portal.js +242 -0
- package/dist/src/docs/portal.js.map +1 -0
- package/dist/src/docs/registry-docs.d.ts +43 -0
- package/dist/src/docs/registry-docs.d.ts.map +1 -0
- package/dist/src/docs/registry-docs.js +138 -0
- package/dist/src/docs/registry-docs.js.map +1 -0
- package/dist/src/docs/schema.d.ts +48 -0
- package/dist/src/docs/schema.d.ts.map +1 -0
- package/dist/src/docs/schema.js +96 -0
- package/dist/src/docs/schema.js.map +1 -0
- package/dist/src/docs/serve.d.ts +27 -0
- package/dist/src/docs/serve.d.ts.map +1 -0
- package/dist/src/docs/serve.js +102 -0
- package/dist/src/docs/serve.js.map +1 -0
- package/dist/src/docs/start.d.ts +80 -0
- package/dist/src/docs/start.d.ts.map +1 -0
- package/dist/src/docs/start.js +313 -0
- package/dist/src/docs/start.js.map +1 -0
- package/dist/src/eval/agent-eval.d.mts +14 -0
- package/dist/src/eval/agent-eval.d.mts.map +1 -0
- package/dist/src/eval/agent-eval.mjs +273 -0
- package/dist/src/eval/agent-eval.mjs.map +1 -0
- package/dist/src/index.js +624 -7
- package/dist/src/index.js.map +7 -1
- package/dist/src/program.d.ts +26 -0
- package/dist/src/program.d.ts.map +1 -0
- package/dist/src/program.js +76 -0
- package/dist/src/program.js.map +1 -0
- package/dist/src/utils/auth-preflight.d.ts +159 -0
- package/dist/src/utils/auth-preflight.d.ts.map +1 -0
- package/dist/src/utils/auth-preflight.js +298 -0
- package/dist/src/utils/auth-preflight.js.map +1 -0
- package/dist/src/utils/aws-auth.d.ts +181 -0
- package/dist/src/utils/aws-auth.d.ts.map +1 -0
- package/dist/src/utils/aws-auth.js +527 -0
- package/dist/src/utils/aws-auth.js.map +1 -0
- package/dist/src/utils/bastion.d.ts +1 -1
- package/dist/src/utils/bastion.d.ts.map +1 -1
- package/dist/src/utils/bastion.js +29 -8
- package/dist/src/utils/bastion.js.map +1 -1
- package/dist/src/utils/build-info.d.ts +33 -0
- package/dist/src/utils/build-info.d.ts.map +1 -0
- package/dist/src/utils/build-info.js +102 -0
- package/dist/src/utils/build-info.js.map +1 -0
- package/dist/src/utils/capture-history.d.ts +62 -0
- package/dist/src/utils/capture-history.d.ts.map +1 -0
- package/dist/src/utils/capture-history.js +94 -0
- package/dist/src/utils/capture-history.js.map +1 -0
- package/dist/src/utils/deploy-preflight.d.ts +52 -0
- package/dist/src/utils/deploy-preflight.d.ts.map +1 -0
- package/dist/src/utils/deploy-preflight.js +183 -0
- package/dist/src/utils/deploy-preflight.js.map +1 -0
- package/dist/src/utils/errors.d.ts +75 -0
- package/dist/src/utils/errors.d.ts.map +1 -0
- package/dist/src/utils/errors.js +106 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/first-party-contexts.d.ts +40 -0
- package/dist/src/utils/first-party-contexts.d.ts.map +1 -0
- package/dist/src/utils/first-party-contexts.js +53 -0
- package/dist/src/utils/first-party-contexts.js.map +1 -0
- package/dist/src/utils/index.d.ts +2 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +2 -0
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/kubeconfig.d.ts +62 -0
- package/dist/src/utils/kubeconfig.d.ts.map +1 -0
- package/dist/src/utils/kubeconfig.js +118 -0
- package/dist/src/utils/kubeconfig.js.map +1 -0
- package/dist/src/utils/log.d.ts +27 -1
- package/dist/src/utils/log.d.ts.map +1 -1
- package/dist/src/utils/log.js +59 -5
- package/dist/src/utils/log.js.map +1 -1
- package/dist/src/utils/pid.d.ts +47 -0
- package/dist/src/utils/pid.d.ts.map +1 -0
- package/dist/src/utils/pid.js +83 -0
- package/dist/src/utils/pid.js.map +1 -0
- package/dist/src/utils/pulumi-run.d.ts +23 -0
- package/dist/src/utils/pulumi-run.d.ts.map +1 -0
- package/dist/src/utils/pulumi-run.js +112 -0
- package/dist/src/utils/pulumi-run.js.map +1 -0
- package/dist/src/utils/pulumi.d.ts +15 -0
- package/dist/src/utils/pulumi.d.ts.map +1 -1
- package/dist/src/utils/pulumi.js +35 -0
- package/dist/src/utils/pulumi.js.map +1 -1
- package/dist/src/utils/reachability.d.ts +29 -0
- package/dist/src/utils/reachability.d.ts.map +1 -0
- package/dist/src/utils/reachability.js +81 -0
- package/dist/src/utils/reachability.js.map +1 -0
- package/dist/src/utils/recover-conversation.d.ts +154 -0
- package/dist/src/utils/recover-conversation.d.ts.map +1 -0
- package/dist/src/utils/recover-conversation.js +314 -0
- package/dist/src/utils/recover-conversation.js.map +1 -0
- package/dist/src/utils/registry-broker.d.ts +148 -0
- package/dist/src/utils/registry-broker.d.ts.map +1 -0
- package/dist/src/utils/registry-broker.js +180 -0
- package/dist/src/utils/registry-broker.js.map +1 -0
- package/dist/src/utils/socks-forward.d.ts +40 -0
- package/dist/src/utils/socks-forward.d.ts.map +1 -0
- package/dist/src/utils/socks-forward.js +97 -0
- package/dist/src/utils/socks-forward.js.map +1 -0
- package/dist/src/utils/stack-flag.d.ts +23 -0
- package/dist/src/utils/stack-flag.d.ts.map +1 -0
- package/dist/src/utils/stack-flag.js +41 -0
- package/dist/src/utils/stack-flag.js.map +1 -0
- package/dist/src/utils/tailscale-targets.d.ts +52 -0
- package/dist/src/utils/tailscale-targets.d.ts.map +1 -0
- package/dist/src/utils/tailscale-targets.js +93 -0
- package/dist/src/utils/tailscale-targets.js.map +1 -0
- package/dist/src/utils/tailscale.d.ts +277 -0
- package/dist/src/utils/tailscale.d.ts.map +1 -0
- package/dist/src/utils/tailscale.js +1007 -0
- package/dist/src/utils/tailscale.js.map +1 -0
- package/dist/src/utils/temporal-auth.d.ts +43 -0
- package/dist/src/utils/temporal-auth.d.ts.map +1 -0
- package/dist/src/utils/temporal-auth.js +176 -0
- package/dist/src/utils/temporal-auth.js.map +1 -0
- package/dist/src/utils/temporal-codec.d.ts +101 -0
- package/dist/src/utils/temporal-codec.d.ts.map +1 -0
- package/dist/src/utils/temporal-codec.js +319 -0
- package/dist/src/utils/temporal-codec.js.map +1 -0
- package/dist/src/utils/tunnel-ownership.d.ts +130 -0
- package/dist/src/utils/tunnel-ownership.d.ts.map +1 -0
- package/dist/src/utils/tunnel-ownership.js +274 -0
- package/dist/src/utils/tunnel-ownership.js.map +1 -0
- package/dist/src/utils/vpn-join.d.ts +32 -0
- package/dist/src/utils/vpn-join.d.ts.map +1 -0
- package/dist/src/utils/vpn-join.js +62 -0
- package/dist/src/utils/vpn-join.js.map +1 -0
- package/dist/src/utils/vpn.d.ts +62 -0
- package/dist/src/utils/vpn.d.ts.map +1 -0
- package/dist/src/utils/vpn.js +183 -0
- package/dist/src/utils/vpn.js.map +1 -0
- package/dist/src/utils/workflow-fingerprint.d.ts +49 -0
- package/dist/src/utils/workflow-fingerprint.d.ts.map +1 -0
- package/dist/src/utils/workflow-fingerprint.js +135 -0
- package/dist/src/utils/workflow-fingerprint.js.map +1 -0
- package/dist/src/utils/worktree-identity.d.ts +86 -0
- package/dist/src/utils/worktree-identity.d.ts.map +1 -0
- package/dist/src/utils/worktree-identity.js +164 -0
- package/dist/src/utils/worktree-identity.js.map +1 -0
- package/fragments/agents/AGENTS.md.hbs +92 -0
- package/fragments/agents/CLAUDE.md.hbs +8 -0
- package/fragments/base/Pulumi.dev.yaml.hbs +10 -0
- package/fragments/base/Pulumi.yaml.hbs +9 -0
- package/fragments/base/index.ts.hbs +107 -0
- package/fragments/base/package.json.hbs +22 -0
- package/{templates/api-web-db/api → fragments/base}/tsconfig.json +3 -4
- package/fragments/bucket/api/src/storage.ts.hbs +81 -0
- package/fragments/database/api/src/db.ts.hbs +23 -0
- package/fragments/database/prisma/schema.prisma.hbs +18 -0
- package/{templates/api-web-db → fragments/service}/api/.dockerignore +2 -0
- package/fragments/service/api/package.json.hbs +40 -0
- package/fragments/service/api/src/index.ts.hbs +58 -0
- package/{templates/api-web-db → fragments/service/api}/tsconfig.json +5 -3
- package/fragments/temporal/worker/.dockerignore +4 -0
- package/fragments/temporal/worker/Dockerfile +15 -0
- package/{templates/temporal-api-worker → fragments/temporal}/worker/package.json.hbs +3 -2
- package/fragments/temporal/worker/src/activities.ts.hbs +14 -0
- package/fragments/temporal/worker/src/worker.ts.hbs +27 -0
- package/fragments/temporal/worker/src/workflows.ts.hbs +24 -0
- package/fragments/temporal/worker/tsconfig.json +13 -0
- package/package.json +36 -22
- package/skills/core/SKILL.md +365 -0
- package/skills/pull-remote-agent-context/SKILL.md +194 -0
- package/stack/docker-compose.hub.yml +134 -0
- package/stack/docker-compose.yml +447 -0
- package/stack/hub/Dockerfile.api +18 -0
- package/stack/hub/Dockerfile.auth +10 -0
- package/stack/hub/Dockerfile.ui +10 -0
- package/stack/init/01-databases.sql +12 -0
- package/stack/observability/blackbox.yml +20 -0
- package/stack/observability/otel-collector.yaml +73 -0
- package/stack/observability/prometheus.yml +36 -0
- package/stack/observability/tempo.yaml +25 -0
- package/stack/temporal/local.yaml +44 -0
- package/templates/api-auth/AGENTS.md.hbs +16 -0
- package/templates/api-auth/Pulumi.dev.yaml.hbs +8 -0
- package/templates/api-auth/Pulumi.yaml.hbs +8 -0
- package/templates/api-auth/README.md.hbs +67 -0
- package/templates/api-auth/api/package.json.hbs +28 -0
- package/templates/api-auth/api/src/index.ts.hbs +96 -0
- package/templates/api-auth/api/src/schema.ts.hbs +35 -0
- package/templates/api-auth/api/src/seed-authz.ts.hbs +48 -0
- package/templates/api-auth/api/src/spicedb-http-provider.ts.hbs +89 -0
- package/templates/api-auth/index.ts.hbs +65 -0
- package/templates/api-auth/package.json.hbs +20 -0
- package/templates/api-auth/skills/develop/SKILL.md.hbs +32 -0
- package/templates/api-role-gating/AGENTS.md.hbs +20 -0
- package/templates/api-role-gating/Pulumi.dev.yaml.hbs +8 -0
- package/templates/api-role-gating/Pulumi.yaml.hbs +8 -0
- package/templates/api-role-gating/README.md.hbs +64 -0
- package/templates/api-role-gating/api/Dockerfile +17 -0
- package/templates/api-role-gating/api/package.json.hbs +28 -0
- package/templates/api-role-gating/api/src/authn.ts.hbs +29 -0
- package/templates/api-role-gating/api/src/authz.ts.hbs +12 -0
- package/templates/api-role-gating/api/src/main.ts.hbs +58 -0
- package/templates/api-role-gating/api/src/schema.ts.hbs +22 -0
- package/templates/api-role-gating/api/tsconfig.json +13 -0
- package/templates/api-role-gating/index.ts.hbs +107 -0
- package/templates/api-role-gating/package.json.hbs +21 -0
- package/templates/api-role-gating/skills/develop/SKILL.md.hbs +60 -0
- package/templates/api-role-gating/tsconfig.json +10 -0
- package/templates/apps-repo/README.md.hbs +24 -0
- package/templates/apps-repo/gitignore +41 -0
- package/templates/apps-repo/npmrc.hbs +7 -0
- package/templates/apps-repo/package.json.hbs +15 -0
- package/templates/apps-repo/pnpm-workspace.yaml +3 -0
- package/templates/apps-repo/tsconfig.json +18 -0
- package/templates/external-service/AGENTS.md.hbs +20 -0
- package/templates/external-service/Pulumi.dev.yaml.hbs +8 -0
- package/templates/external-service/Pulumi.yaml.hbs +8 -0
- package/templates/external-service/README.md.hbs +56 -0
- package/templates/external-service/api/Dockerfile +15 -0
- package/templates/external-service/api/package.json.hbs +25 -0
- package/templates/external-service/api/src/index.ts.hbs +81 -0
- package/templates/external-service/index.ts.hbs +82 -0
- package/templates/external-service/mocks/vendorpay/package.json.hbs +9 -0
- package/templates/external-service/mocks/vendorpay/server.mjs.hbs +61 -0
- package/templates/external-service/package.json.hbs +34 -0
- package/templates/external-service/skills/develop/SKILL.md.hbs +55 -0
- package/templates/external-service/tsconfig.json +10 -0
- package/templates/platform-repo/AGENTS.md.hbs +18 -0
- package/templates/platform-repo/README.md.hbs +38 -0
- package/templates/platform-repo/core/Pulumi.yaml.hbs +12 -0
- package/templates/platform-repo/core/Pulumi.{{tenant}}-{{env}}.yaml.hbs +57 -0
- package/templates/platform-repo/core/index.ts +62 -0
- package/templates/platform-repo/core/package.json.hbs +22 -0
- package/templates/platform-repo/core/tsconfig.json +8 -0
- package/templates/platform-repo/package.json.hbs +15 -0
- package/templates/platform-repo/platform/Pulumi.yaml.hbs +12 -0
- package/templates/platform-repo/platform/Pulumi.{{tenant}}-{{env}}.yaml.hbs +59 -0
- package/templates/platform-repo/platform/index.ts +95 -0
- package/templates/platform-repo/platform/package.json.hbs +26 -0
- package/templates/platform-repo/platform/tsconfig.json +8 -0
- package/templates/platform-repo/pnpm-workspace.yaml +3 -0
- package/templates/workflow/AGENTS.md.hbs +15 -0
- package/templates/workflow/Pulumi.dev.yaml.hbs +8 -0
- package/templates/workflow/Pulumi.yaml.hbs +8 -0
- package/templates/workflow/README.md.hbs +45 -0
- package/templates/workflow/api/.dockerignore +4 -0
- package/templates/workflow/api/Dockerfile +15 -0
- package/templates/{temporal-api-worker → workflow}/api/package.json.hbs +8 -6
- package/templates/workflow/api/src/index.ts.hbs +130 -0
- package/templates/workflow/api/tsconfig.json +14 -0
- package/templates/workflow/index.ts.hbs +67 -0
- package/templates/workflow/package.json.hbs +20 -0
- package/templates/workflow/skills/develop/SKILL.md.hbs +32 -0
- package/templates/workflow/tsconfig.json +10 -0
- package/templates/workflow/worker/.dockerignore +4 -0
- package/templates/workflow/worker/Dockerfile +13 -0
- package/templates/workflow/worker/package.json.hbs +25 -0
- package/templates/workflow/worker/src/worker.ts.hbs +24 -0
- package/templates/workflow/worker/tsconfig.json +14 -0
- package/dist/src/commands/devbox.d.ts +0 -22
- package/dist/src/commands/devbox.d.ts.map +0 -1
- package/dist/src/commands/devbox.js +0 -463
- package/dist/src/commands/devbox.js.map +0 -1
- package/templates/api-web-db/api/Dockerfile +0 -16
- package/templates/api-web-db/api/package.json.hbs +0 -21
- package/templates/api-web-db/api/src/index.ts.hbs +0 -123
- package/templates/api-web-db/package.json.hbs +0 -27
- package/templates/api-web-db/sst.config.ts.hbs +0 -151
- package/templates/api-web-db/web/.dockerignore +0 -3
- package/templates/api-web-db/web/Dockerfile +0 -17
- package/templates/api-web-db/web/app/lib/db.server.ts +0 -36
- package/templates/api-web-db/web/app/root.tsx +0 -29
- package/templates/api-web-db/web/app/routes/home.tsx.hbs +0 -114
- package/templates/api-web-db/web/app/routes.ts +0 -3
- package/templates/api-web-db/web/package.json.hbs +0 -30
- package/templates/api-web-db/web/prisma/schema.prisma +0 -25
- package/templates/api-web-db/web/prisma.config.ts +0 -18
- package/templates/api-web-db/web/react-router.config.ts +0 -5
- package/templates/api-web-db/web/tsconfig.json +0 -19
- package/templates/api-web-db/web/vite.config.ts +0 -9
- package/templates/temporal-api-worker/README.md.hbs +0 -133
- package/templates/temporal-api-worker/api/src/index.ts.hbs +0 -145
- package/templates/temporal-api-worker/package.json.hbs +0 -29
- package/templates/temporal-api-worker/sst.config.ts.hbs +0 -161
- package/templates/temporal-api-worker/worker/Dockerfile +0 -11
- package/templates/temporal-api-worker/worker/src/bundle-workflows.ts +0 -38
- package/templates/temporal-api-worker/worker/src/worker.ts.hbs +0 -93
- /package/templates/{temporal-api-worker → api-auth}/api/.dockerignore +0 -0
- /package/templates/{temporal-api-worker → api-auth}/api/Dockerfile +0 -0
- /package/templates/{temporal-api-worker → api-auth}/api/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker → api-auth}/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker/worker → api-role-gating/api}/.dockerignore +0 -0
- /package/templates/{temporal-api-worker/worker → external-service/api}/tsconfig.json +0 -0
- /package/templates/{temporal-api-worker → workflow}/api/src/encryption-codec.ts +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/activities.ts.hbs +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/encryption-codec.ts +0 -0
- /package/templates/{temporal-api-worker → workflow}/worker/src/workflows.ts.hbs +0 -0
|
@@ -1,25 +1,149 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* mesh create-app - Scaffold a new tenant application
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Three modes:
|
|
5
|
+
* 1. Legacy: `mesh create-app --template workflow --tenant x --name y`
|
|
6
|
+
* 2. Composable (flags): `mesh create-app --tenant x --name y --primitives service,database`
|
|
7
|
+
* 3. Interactive: `mesh create-app` (prompts when TTY detected and flags missing)
|
|
8
|
+
*
|
|
9
|
+
* All options can be passed as flags for agent/CI usage (no TTY required).
|
|
7
10
|
*/
|
|
8
11
|
import * as fs from "fs";
|
|
12
|
+
import * as os from "os";
|
|
9
13
|
import * as path from "path";
|
|
10
14
|
import { fileURLToPath } from "url";
|
|
11
15
|
import Handlebars from "handlebars";
|
|
12
16
|
import { logInfo, logSuccess, logError, logWarn } from "../utils/index.js";
|
|
13
|
-
|
|
17
|
+
import { resolveTargetRoot, syncSkills } from "./skills.js";
|
|
18
|
+
import { findPackageRoot } from "./local/stack.js";
|
|
19
|
+
// Get package root by walking up until we find package.json with our package name.
|
|
20
|
+
// Works from both src/commands/ (tsx) and dist/src/commands/ (compiled).
|
|
14
21
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
22
|
const __dirname = path.dirname(__filename);
|
|
16
|
-
|
|
17
|
-
const packageRoot = path.resolve(__dirname, "..", "..", "..");
|
|
23
|
+
const packageRoot = findPackageRoot(__dirname);
|
|
18
24
|
// Available templates
|
|
19
25
|
const TEMPLATES = {
|
|
20
|
-
|
|
21
|
-
"
|
|
26
|
+
workflow: "Hono API + Temporal worker + hello workflow (Pulumi/app-kit)",
|
|
27
|
+
"api-auth": "Hono API with platform auth: authn (Zitadel JWT) + authz (SpiceDB)",
|
|
28
|
+
"api-role-gating": "Hono API with role-gating authz: authn (Zitadel JWT) + coarse-role checks on Zitadel project roles, in-process (no SpiceDB)",
|
|
29
|
+
"external-service": "Hono API calling a third-party vendor via platform-managed credentials (ExternalService + mock for `mesh dev --externals`)",
|
|
30
|
+
};
|
|
31
|
+
/** Removed templates → what replaced them (named in the unknown-template error). */
|
|
32
|
+
const REMOVED_TEMPLATES = {
|
|
33
|
+
"temporal-api-worker": "renamed to 'workflow'",
|
|
34
|
+
"api-web-db": "removed (SST-based) — use --primitives service,database",
|
|
35
|
+
};
|
|
36
|
+
// Available primitives for composable mode
|
|
37
|
+
const PRIMITIVES = {
|
|
38
|
+
service: "HTTP Service (API with Hono)",
|
|
39
|
+
database: "Database (PostgreSQL via Prisma)",
|
|
40
|
+
temporal: "Temporal (workflow orchestration)",
|
|
41
|
+
bucket: "S3 Bucket (file storage)",
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Hub platform account IDs — the AWS account hosting a shared tenant's
|
|
45
|
+
* `{tenant}-{env}-apps-deployer` role. Shared tenants (acme, …) deploy into the
|
|
46
|
+
* hub account, so the generated `mesh:deployerRole` ARN resolves against this map.
|
|
47
|
+
* `mesh` is the only hub today; add entries as new hubs come online.
|
|
48
|
+
*/
|
|
49
|
+
const HUB_ACCOUNTS = {
|
|
50
|
+
mesh: "159923586610",
|
|
22
51
|
};
|
|
52
|
+
/**
|
|
53
|
+
* Walk up from `dir` looking for a `pnpm-workspace.yaml` — the app lives inside a
|
|
54
|
+
* pnpm monorepo, so `@mesh-tech/*` deps should be `workspace:*` (link local source)
|
|
55
|
+
* rather than pinned registry versions the local workspace doesn't publish.
|
|
56
|
+
*/
|
|
57
|
+
function isInsideMonorepo(dir) {
|
|
58
|
+
let cur = path.resolve(dir);
|
|
59
|
+
while (cur !== path.dirname(cur)) {
|
|
60
|
+
if (fs.existsSync(path.join(cur, "pnpm-workspace.yaml")))
|
|
61
|
+
return true;
|
|
62
|
+
cur = path.dirname(cur);
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Deployer-role ARN for a shared tenant on a known hub, or a clearly-marked
|
|
68
|
+
* `ACCOUNT_ID` placeholder when the hub account is unknown (the generated config
|
|
69
|
+
* comments the fill-in step in that case).
|
|
70
|
+
*/
|
|
71
|
+
function resolveDeployerRoleArn(tenant, platformName, env) {
|
|
72
|
+
const account = HUB_ACCOUNTS[platformName] ?? "ACCOUNT_ID";
|
|
73
|
+
return `arn:aws:iam::${account}:role/${tenant}-${env}-apps-deployer`;
|
|
74
|
+
}
|
|
75
|
+
const VALID_PRIMITIVES = Object.keys(PRIMITIVES);
|
|
76
|
+
// =============================================================================
|
|
77
|
+
// Standalone apps-repo bootstrap
|
|
78
|
+
// =============================================================================
|
|
79
|
+
/**
|
|
80
|
+
* A fresh standalone tenant-apps repo (empty clone of {tenant}-mesh-apps) is
|
|
81
|
+
* bootstrappable when the cwd is a git repo root that has none of the layouts
|
|
82
|
+
* `resolveAppDir` looks for. Previously create-app exited with "Tenant
|
|
83
|
+
* directory not found: tenants/<t>/" here — even though the app-tenant
|
|
84
|
+
* doctor's Repo-shape check names create-app as the fix ("workspace files
|
|
85
|
+
* included"), so the command must actually deliver them.
|
|
86
|
+
*/
|
|
87
|
+
export function shouldBootstrapAppsRepo(cwd) {
|
|
88
|
+
return (fs.existsSync(path.join(cwd, ".git")) &&
|
|
89
|
+
!isInsideMonorepo(cwd) &&
|
|
90
|
+
!fs.existsSync(path.join(cwd, "package.json")) &&
|
|
91
|
+
!fs.existsSync(path.join(cwd, "tenants")) &&
|
|
92
|
+
!fs.existsSync(path.join(cwd, "apps")));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Generate the repo-level files of a standalone tenant-apps repo (the
|
|
96
|
+
* trabian-mesh-apps shape): pnpm workspace over apps/*, private root
|
|
97
|
+
* package.json, scoped CodeArtifact .npmrc, base tsconfig, .gitignore, README.
|
|
98
|
+
* Only writes files that don't already exist; returns what it created.
|
|
99
|
+
*/
|
|
100
|
+
export function bootstrapAppsRepo(cwd, tenant) {
|
|
101
|
+
const templateDir = path.join(packageRoot, "templates", "apps-repo");
|
|
102
|
+
const registryAccount = HUB_ACCOUNTS.mesh;
|
|
103
|
+
const context = {
|
|
104
|
+
repoName: path.basename(cwd),
|
|
105
|
+
tenant,
|
|
106
|
+
tenantTitle: tenant
|
|
107
|
+
.split("-")
|
|
108
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
109
|
+
.join(" "),
|
|
110
|
+
registryUrl: `https://mesh-platform-${registryAccount}.d.codeartifact.us-east-2.amazonaws.com/npm/mesh-packages/`,
|
|
111
|
+
};
|
|
112
|
+
const staging = fs.mkdtempSync(path.join(os.tmpdir(), "mesh-apps-repo-"));
|
|
113
|
+
try {
|
|
114
|
+
copyTemplate(templateDir, staging, context);
|
|
115
|
+
// npm strips dotfiles from published tarballs, so the template ships
|
|
116
|
+
// `gitignore`/`npmrc` and the bootstrap restores the real names.
|
|
117
|
+
for (const [from, to] of [
|
|
118
|
+
["gitignore", ".gitignore"],
|
|
119
|
+
["npmrc", ".npmrc"],
|
|
120
|
+
]) {
|
|
121
|
+
const p = path.join(staging, from);
|
|
122
|
+
if (fs.existsSync(p))
|
|
123
|
+
fs.renameSync(p, path.join(staging, to));
|
|
124
|
+
}
|
|
125
|
+
const created = [];
|
|
126
|
+
for (const entry of fs.readdirSync(staging)) {
|
|
127
|
+
const dest = path.join(cwd, entry);
|
|
128
|
+
if (fs.existsSync(dest))
|
|
129
|
+
continue;
|
|
130
|
+
fs.cpSync(path.join(staging, entry), dest, { recursive: true });
|
|
131
|
+
created.push(entry);
|
|
132
|
+
}
|
|
133
|
+
fs.mkdirSync(path.join(cwd, "apps"), { recursive: true });
|
|
134
|
+
created.push("apps/");
|
|
135
|
+
return created;
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function maybeBootstrapAppsRepo(cwd, tenant, test) {
|
|
142
|
+
if (test || !shouldBootstrapAppsRepo(cwd))
|
|
143
|
+
return;
|
|
144
|
+
const created = bootstrapAppsRepo(cwd, tenant);
|
|
145
|
+
logInfo(`Standalone apps repo detected — bootstrapped workspace files: ${created.join(", ")}`);
|
|
146
|
+
}
|
|
23
147
|
// Register Handlebars helpers
|
|
24
148
|
Handlebars.registerHelper("titleCase", (str) => {
|
|
25
149
|
return str
|
|
@@ -27,10 +151,62 @@ Handlebars.registerHelper("titleCase", (str) => {
|
|
|
27
151
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
28
152
|
.join(" ");
|
|
29
153
|
});
|
|
154
|
+
/**
|
|
155
|
+
* Check if we're in an interactive terminal
|
|
156
|
+
*/
|
|
157
|
+
function isInteractive() {
|
|
158
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Run interactive prompts to gather missing options.
|
|
162
|
+
* Only called when TTY is available and required options are missing.
|
|
163
|
+
*/
|
|
164
|
+
async function promptForOptions(options) {
|
|
165
|
+
// Dynamic imports so non-interactive usage doesn't load inquirer
|
|
166
|
+
const { default: input } = await import("@inquirer/input");
|
|
167
|
+
const { default: checkbox } = await import("@inquirer/checkbox");
|
|
168
|
+
const tenant = options.tenant ??
|
|
169
|
+
(await input({
|
|
170
|
+
message: "Tenant name",
|
|
171
|
+
validate: (v) => (v.length > 0 ? true : "Tenant name is required"),
|
|
172
|
+
}));
|
|
173
|
+
const name = options.name ??
|
|
174
|
+
(await input({
|
|
175
|
+
message: "App name",
|
|
176
|
+
validate: (v) => (v.length > 0 ? true : "App name is required"),
|
|
177
|
+
}));
|
|
178
|
+
let primitives;
|
|
179
|
+
if (options.primitives) {
|
|
180
|
+
primitives = parsePrimitives(options.primitives);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
primitives = await checkbox({
|
|
184
|
+
message: "Select primitives",
|
|
185
|
+
choices: VALID_PRIMITIVES.map((p) => ({
|
|
186
|
+
name: PRIMITIVES[p],
|
|
187
|
+
value: p,
|
|
188
|
+
checked: p === "service", // service checked by default
|
|
189
|
+
})),
|
|
190
|
+
});
|
|
191
|
+
if (primitives.length === 0) {
|
|
192
|
+
primitives = ["service"];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Database and bucket place files in api/ — ensure service is included
|
|
196
|
+
if (primitives.includes("database") && !primitives.includes("service")) {
|
|
197
|
+
primitives.push("service");
|
|
198
|
+
logInfo("Added 'service' — database files live in the api/ directory.");
|
|
199
|
+
}
|
|
200
|
+
if (primitives.includes("bucket") && !primitives.includes("service")) {
|
|
201
|
+
primitives.push("service");
|
|
202
|
+
logInfo("Added 'service' — bucket requires an API service for S3 helpers.");
|
|
203
|
+
}
|
|
204
|
+
return { tenant, name, primitives };
|
|
205
|
+
}
|
|
30
206
|
/**
|
|
31
207
|
* Recursively copy a directory, processing .hbs templates
|
|
32
208
|
*/
|
|
33
|
-
function copyTemplate(srcDir, destDir, context) {
|
|
209
|
+
export function copyTemplate(srcDir, destDir, context) {
|
|
34
210
|
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
35
211
|
for (const entry of entries) {
|
|
36
212
|
const srcPath = path.join(srcDir, entry.name);
|
|
@@ -39,6 +215,10 @@ function copyTemplate(srcDir, destDir, context) {
|
|
|
39
215
|
if (destName.endsWith(".hbs")) {
|
|
40
216
|
destName = destName.slice(0, -4);
|
|
41
217
|
}
|
|
218
|
+
// File names can be templated too (e.g. Pulumi.{{tenant}}-{{env}}.yaml.hbs)
|
|
219
|
+
if (destName.includes("{{")) {
|
|
220
|
+
destName = Handlebars.compile(destName)(context);
|
|
221
|
+
}
|
|
42
222
|
const destPath = path.join(destDir, destName);
|
|
43
223
|
if (entry.isDirectory()) {
|
|
44
224
|
fs.mkdirSync(destPath, { recursive: true });
|
|
@@ -57,120 +237,298 @@ function copyTemplate(srcDir, destDir, context) {
|
|
|
57
237
|
}
|
|
58
238
|
}
|
|
59
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Parse and validate primitive selections from comma-separated string
|
|
242
|
+
*/
|
|
243
|
+
function parsePrimitives(input) {
|
|
244
|
+
const selected = input.split(",").map((s) => s.trim().toLowerCase());
|
|
245
|
+
const invalid = selected.filter((s) => !VALID_PRIMITIVES.includes(s));
|
|
246
|
+
if (invalid.length > 0) {
|
|
247
|
+
logError(`Unknown primitives: ${invalid.join(", ")}`);
|
|
248
|
+
logInfo(`Available primitives: ${VALID_PRIMITIVES.join(", ")}`);
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
return selected;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Resolve output directory for the app
|
|
255
|
+
*/
|
|
256
|
+
function resolveAppDir(cwd, tenant, name, test) {
|
|
257
|
+
const baseDir = test ? "tests/tenants" : "tenants";
|
|
258
|
+
const possiblePaths = [
|
|
259
|
+
path.join(cwd, baseDir, tenant, "apps"),
|
|
260
|
+
path.join(cwd, "..", tenant, "apps"),
|
|
261
|
+
path.join(cwd, "apps"),
|
|
262
|
+
];
|
|
263
|
+
let appsDir = possiblePaths.find((p) => fs.existsSync(p));
|
|
264
|
+
if (!appsDir) {
|
|
265
|
+
appsDir = path.join(cwd, baseDir, tenant, "apps");
|
|
266
|
+
if (!fs.existsSync(path.join(cwd, baseDir, tenant))) {
|
|
267
|
+
logError(`Tenant directory not found: ${baseDir}/${tenant}/`);
|
|
268
|
+
logInfo("Create the tenant directory first, or run from within it.");
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
271
|
+
if (!fs.existsSync(appsDir)) {
|
|
272
|
+
logInfo(`Creating apps directory: ${appsDir}`);
|
|
273
|
+
fs.mkdirSync(appsDir, { recursive: true });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return path.join(appsDir, name);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Generate a composable app from fragments
|
|
280
|
+
*/
|
|
281
|
+
function generateComposableApp(appDir, context) {
|
|
282
|
+
const fragmentsDir = path.join(packageRoot, "fragments");
|
|
283
|
+
// 1. Always copy base fragment
|
|
284
|
+
const baseDir = path.join(fragmentsDir, "base");
|
|
285
|
+
if (!fs.existsSync(baseDir)) {
|
|
286
|
+
logError(`Fragments directory not found: ${baseDir}`);
|
|
287
|
+
logInfo("Make sure the mesh-cli package is installed correctly.");
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
copyTemplate(baseDir, appDir, context);
|
|
291
|
+
// 2. Copy primitive-specific fragments
|
|
292
|
+
if (context.service) {
|
|
293
|
+
const serviceDir = path.join(fragmentsDir, "service");
|
|
294
|
+
if (!fs.existsSync(serviceDir)) {
|
|
295
|
+
throw new Error(`Fragment directory not found: ${serviceDir}`);
|
|
296
|
+
}
|
|
297
|
+
copyTemplate(serviceDir, appDir, context);
|
|
298
|
+
}
|
|
299
|
+
if (context.database) {
|
|
300
|
+
const dbDir = path.join(fragmentsDir, "database");
|
|
301
|
+
if (!fs.existsSync(dbDir)) {
|
|
302
|
+
throw new Error(`Fragment directory not found: ${dbDir}`);
|
|
303
|
+
}
|
|
304
|
+
copyTemplate(dbDir, appDir, context);
|
|
305
|
+
}
|
|
306
|
+
if (context.temporal) {
|
|
307
|
+
const temporalDir = path.join(fragmentsDir, "temporal");
|
|
308
|
+
if (!fs.existsSync(temporalDir)) {
|
|
309
|
+
throw new Error(`Fragment directory not found: ${temporalDir}`);
|
|
310
|
+
}
|
|
311
|
+
copyTemplate(temporalDir, appDir, context);
|
|
312
|
+
}
|
|
313
|
+
if (context.bucket) {
|
|
314
|
+
const bucketDir = path.join(fragmentsDir, "bucket");
|
|
315
|
+
if (!fs.existsSync(bucketDir)) {
|
|
316
|
+
throw new Error(`Fragment directory not found: ${bucketDir}`);
|
|
317
|
+
}
|
|
318
|
+
copyTemplate(bucketDir, appDir, context);
|
|
319
|
+
}
|
|
320
|
+
// 3. Always generate AGENTS.md
|
|
321
|
+
const agentsDir = path.join(fragmentsDir, "agents");
|
|
322
|
+
if (fs.existsSync(agentsDir)) {
|
|
323
|
+
copyTemplate(agentsDir, appDir, context);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
60
326
|
export function registerCreateAppCommand(program) {
|
|
61
327
|
program
|
|
62
328
|
.command("create-app")
|
|
63
329
|
.description("Scaffold a new tenant application")
|
|
64
|
-
.
|
|
65
|
-
.
|
|
66
|
-
.option("--template <template>", `
|
|
330
|
+
.option("--tenant <tenant>", "Tenant name (e.g., acme)")
|
|
331
|
+
.option("--name <name>", "Application name (e.g., billing)")
|
|
332
|
+
.option("--template <template>", `Legacy template: ${Object.keys(TEMPLATES).join(", ")}`)
|
|
333
|
+
.option("--primitives <primitives>", `Comma-separated primitives: ${VALID_PRIMITIVES.join(", ")} (default: service)`)
|
|
67
334
|
.option("--test", "Create in tests/tenants/ directory", false)
|
|
68
335
|
.action(async (options) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
for (const [name, desc] of Object.entries(TEMPLATES)) {
|
|
75
|
-
console.log(` ${name.padEnd(20)} - ${desc}`);
|
|
336
|
+
// Legacy template mode — requires all flags
|
|
337
|
+
if (options.template) {
|
|
338
|
+
if (!options.tenant || !options.name) {
|
|
339
|
+
logError("--tenant and --name are required with --template");
|
|
340
|
+
process.exit(1);
|
|
76
341
|
}
|
|
77
|
-
|
|
342
|
+
await runLegacyTemplate(options.tenant, options.name, options.template, options.test);
|
|
343
|
+
return;
|
|
78
344
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const possiblePaths = [
|
|
91
|
-
path.join(cwd, baseDir, tenant, "apps"),
|
|
92
|
-
path.join(cwd, "..", tenant, "apps"),
|
|
93
|
-
path.join(cwd, "apps"),
|
|
94
|
-
];
|
|
95
|
-
const foundPath = possiblePaths.find((p) => fs.existsSync(p));
|
|
96
|
-
if (foundPath) {
|
|
97
|
-
appsDir = foundPath;
|
|
345
|
+
// Composable mode — interactive or flag-based
|
|
346
|
+
let tenant;
|
|
347
|
+
let name;
|
|
348
|
+
let primitives;
|
|
349
|
+
const needsPrompt = !options.tenant || !options.name || !options.primitives;
|
|
350
|
+
if (needsPrompt && isInteractive()) {
|
|
351
|
+
// Interactive: prompt for missing values
|
|
352
|
+
const prompted = await promptForOptions(options);
|
|
353
|
+
tenant = prompted.tenant;
|
|
354
|
+
name = prompted.name;
|
|
355
|
+
primitives = prompted.primitives;
|
|
98
356
|
}
|
|
99
|
-
else {
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
logError(`Tenant directory not found: ${baseDir}/${tenant}/`);
|
|
104
|
-
logInfo("Create the tenant directory first, or run from within it.");
|
|
357
|
+
else if (needsPrompt) {
|
|
358
|
+
// Non-interactive but missing flags
|
|
359
|
+
if (!options.tenant) {
|
|
360
|
+
logError("--tenant is required (no TTY for interactive mode)");
|
|
105
361
|
process.exit(1);
|
|
106
362
|
}
|
|
107
|
-
if (!
|
|
108
|
-
|
|
109
|
-
|
|
363
|
+
if (!options.name) {
|
|
364
|
+
logError("--name is required (no TTY for interactive mode)");
|
|
365
|
+
process.exit(1);
|
|
110
366
|
}
|
|
367
|
+
tenant = options.tenant;
|
|
368
|
+
name = options.name;
|
|
369
|
+
primitives = options.primitives
|
|
370
|
+
? parsePrimitives(options.primitives)
|
|
371
|
+
: ["service"];
|
|
111
372
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
logInfo("Choose a different name or remove the existing directory.");
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
// Find template directory (at package root, not in dist)
|
|
120
|
-
const templateDir = path.join(packageRoot, "templates", template);
|
|
121
|
-
if (!fs.existsSync(templateDir)) {
|
|
122
|
-
logError(`Template not found: ${templateDir}`);
|
|
123
|
-
logInfo("Make sure the mesh-cli package is installed correctly.");
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
// Create context for templates
|
|
127
|
-
const context = {
|
|
128
|
-
name,
|
|
129
|
-
tenant,
|
|
130
|
-
};
|
|
131
|
-
// Create app directory
|
|
132
|
-
logInfo(`Creating app at ${appDir}...`);
|
|
133
|
-
fs.mkdirSync(appDir, { recursive: true });
|
|
134
|
-
// Copy and process templates
|
|
135
|
-
try {
|
|
136
|
-
copyTemplate(templateDir, appDir, context);
|
|
137
|
-
logSuccess(`Created app structure at ${appDir}`);
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
logError(`Failed to create app: ${error}`);
|
|
141
|
-
// Clean up on failure
|
|
142
|
-
fs.rmSync(appDir, { recursive: true, force: true });
|
|
143
|
-
process.exit(1);
|
|
373
|
+
else {
|
|
374
|
+
tenant = options.tenant;
|
|
375
|
+
name = options.name;
|
|
376
|
+
primitives = parsePrimitives(options.primitives);
|
|
144
377
|
}
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
logInfo("You may need to create a shared config.ts for tenant apps.");
|
|
150
|
-
logInfo("See existing apps for an example.");
|
|
151
|
-
}
|
|
152
|
-
// Print next steps
|
|
153
|
-
console.log("");
|
|
154
|
-
logSuccess("App created successfully!");
|
|
155
|
-
console.log("");
|
|
156
|
-
console.log("Next steps:");
|
|
157
|
-
console.log(` cd ${appDir}`);
|
|
158
|
-
console.log(" pnpm install");
|
|
159
|
-
if (template === "temporal-api-worker") {
|
|
160
|
-
console.log("");
|
|
161
|
-
console.log("For development:");
|
|
162
|
-
console.log(" 1. Start dev server: pnpm mesh dev");
|
|
163
|
-
console.log(" (auto-starts tunnel to Temporal + DB)");
|
|
164
|
-
console.log(" 2. Start worker manually in SST dev UI");
|
|
165
|
-
console.log(" 3. Open Temporal Web UI: http://localhost:8080");
|
|
378
|
+
// Database and bucket place files in api/ — ensure service is included
|
|
379
|
+
if (primitives.includes("database") && !primitives.includes("service")) {
|
|
380
|
+
primitives.push("service");
|
|
381
|
+
logInfo("Added 'service' — database files live in the api/ directory.");
|
|
166
382
|
}
|
|
167
|
-
|
|
168
|
-
|
|
383
|
+
if (primitives.includes("bucket") && !primitives.includes("service")) {
|
|
384
|
+
primitives.push("service");
|
|
385
|
+
logInfo("Added 'service' — bucket requires an API service for S3 helpers.");
|
|
169
386
|
}
|
|
170
|
-
|
|
171
|
-
console.log("To deploy:");
|
|
172
|
-
console.log(" pnpm deploy --stage dev");
|
|
173
|
-
console.log("");
|
|
387
|
+
await runComposable(tenant, name, primitives, options.test);
|
|
174
388
|
});
|
|
175
389
|
}
|
|
390
|
+
async function runLegacyTemplate(tenant, name, template, test) {
|
|
391
|
+
if (!Object.keys(TEMPLATES).includes(template)) {
|
|
392
|
+
const removed = REMOVED_TEMPLATES[template];
|
|
393
|
+
logError(`Unknown template: ${template}${removed ? ` (${removed})` : ""}`);
|
|
394
|
+
logInfo(`Available templates:`);
|
|
395
|
+
for (const [tplName, desc] of Object.entries(TEMPLATES)) {
|
|
396
|
+
console.log(` ${tplName.padEnd(20)} - ${desc}`);
|
|
397
|
+
}
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
logInfo(`Creating app '${name}' for tenant '${tenant}'...`);
|
|
401
|
+
logInfo(`Template: ${template} (${TEMPLATES[template]})`);
|
|
402
|
+
if (test) {
|
|
403
|
+
logInfo("Creating in tests/ directory");
|
|
404
|
+
}
|
|
405
|
+
maybeBootstrapAppsRepo(process.cwd(), tenant, test);
|
|
406
|
+
const appDir = resolveAppDir(process.cwd(), tenant, name, test);
|
|
407
|
+
if (fs.existsSync(appDir)) {
|
|
408
|
+
logError(`App directory already exists: ${appDir}`);
|
|
409
|
+
process.exit(1);
|
|
410
|
+
}
|
|
411
|
+
const templateDir = path.join(packageRoot, "templates", template);
|
|
412
|
+
if (!fs.existsSync(templateDir)) {
|
|
413
|
+
logError(`Template not found: ${templateDir}`);
|
|
414
|
+
process.exit(1);
|
|
415
|
+
}
|
|
416
|
+
fs.mkdirSync(appDir, { recursive: true });
|
|
417
|
+
try {
|
|
418
|
+
copyTemplate(templateDir, appDir, { name, tenant });
|
|
419
|
+
logSuccess(`Created app at ${appDir}`);
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
logError(`Failed to create app: ${error}`);
|
|
423
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
424
|
+
process.exit(1);
|
|
425
|
+
}
|
|
426
|
+
autoSyncSkills(appDir);
|
|
427
|
+
printLegacyNextSteps(appDir, template);
|
|
428
|
+
}
|
|
429
|
+
/** Best-effort skills sync after scaffolding (design D1): a fresh Claude
|
|
430
|
+
* session in the repo sees the base skills + Intent discovery immediately. */
|
|
431
|
+
function autoSyncSkills(appDir) {
|
|
432
|
+
try {
|
|
433
|
+
syncSkills(resolveTargetRoot(appDir));
|
|
434
|
+
}
|
|
435
|
+
catch (err) {
|
|
436
|
+
logWarn(`Agent-skill sync skipped: ${err instanceof Error ? err.message : err} — run: mesh skills sync`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
async function runComposable(tenant, name, primitives, test) {
|
|
440
|
+
logInfo(`Creating app '${name}' for tenant '${tenant}'...`);
|
|
441
|
+
logInfo(`Primitives: ${primitives.join(", ")}`);
|
|
442
|
+
if (test) {
|
|
443
|
+
logInfo("Creating in tests/ directory");
|
|
444
|
+
}
|
|
445
|
+
maybeBootstrapAppsRepo(process.cwd(), tenant, test);
|
|
446
|
+
const appDir = resolveAppDir(process.cwd(), tenant, name, test);
|
|
447
|
+
if (fs.existsSync(appDir)) {
|
|
448
|
+
logError(`App directory already exists: ${appDir}`);
|
|
449
|
+
process.exit(1);
|
|
450
|
+
}
|
|
451
|
+
// Platform defaults (the generated Pulumi config targets the mesh hub / dev).
|
|
452
|
+
const region = "us-east-2";
|
|
453
|
+
const platformName = "mesh";
|
|
454
|
+
const platformEnv = "dev";
|
|
455
|
+
const context = {
|
|
456
|
+
name,
|
|
457
|
+
tenant,
|
|
458
|
+
service: primitives.includes("service"),
|
|
459
|
+
database: primitives.includes("database"),
|
|
460
|
+
temporal: primitives.includes("temporal"),
|
|
461
|
+
bucket: primitives.includes("bucket"),
|
|
462
|
+
region,
|
|
463
|
+
// Link local source when generating inside this monorepo; pin only for
|
|
464
|
+
// out-of-repo tenant repos that install `@mesh-tech/*` from the registry.
|
|
465
|
+
workspaceDeps: isInsideMonorepo(appDir),
|
|
466
|
+
deployerRoleArn: resolveDeployerRoleArn(tenant, platformName, platformEnv),
|
|
467
|
+
};
|
|
468
|
+
fs.mkdirSync(appDir, { recursive: true });
|
|
469
|
+
try {
|
|
470
|
+
generateComposableApp(appDir, context);
|
|
471
|
+
logSuccess(`Created app at ${appDir}`);
|
|
472
|
+
}
|
|
473
|
+
catch (error) {
|
|
474
|
+
logError(`Failed to create app: ${error}`);
|
|
475
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
476
|
+
process.exit(1);
|
|
477
|
+
}
|
|
478
|
+
// Check for config.ts
|
|
479
|
+
const configPath = path.join(path.dirname(appDir), "config.ts");
|
|
480
|
+
if (!fs.existsSync(configPath)) {
|
|
481
|
+
logWarn(`No config.ts found at ${configPath}`);
|
|
482
|
+
logInfo("You may need to create a shared config.ts for tenant apps.");
|
|
483
|
+
}
|
|
484
|
+
autoSyncSkills(appDir);
|
|
485
|
+
printComposableNextSteps(appDir, context);
|
|
486
|
+
}
|
|
487
|
+
function printLegacyNextSteps(appDir, _template) {
|
|
488
|
+
const configPath = path.join(path.dirname(appDir), "config.ts");
|
|
489
|
+
if (!fs.existsSync(configPath)) {
|
|
490
|
+
logWarn(`No config.ts found at ${configPath}`);
|
|
491
|
+
logInfo("You may need to create a shared config.ts for tenant apps.");
|
|
492
|
+
}
|
|
493
|
+
console.log("");
|
|
494
|
+
logSuccess("App created successfully!");
|
|
495
|
+
console.log("");
|
|
496
|
+
console.log("Next steps:");
|
|
497
|
+
console.log(` cd ${appDir}`);
|
|
498
|
+
console.log(" pnpm install");
|
|
499
|
+
console.log(" pnpm mesh dev");
|
|
500
|
+
console.log("");
|
|
501
|
+
console.log("To deploy:");
|
|
502
|
+
console.log(" pnpm mesh deploy up");
|
|
503
|
+
console.log("");
|
|
504
|
+
}
|
|
505
|
+
function printComposableNextSteps(appDir, context) {
|
|
506
|
+
console.log("");
|
|
507
|
+
logSuccess("App created successfully!");
|
|
508
|
+
console.log("");
|
|
509
|
+
console.log("Generated:");
|
|
510
|
+
console.log(" index.ts Pulumi app definition");
|
|
511
|
+
console.log(" AGENTS.md AI agent instructions");
|
|
512
|
+
console.log(" CLAUDE.md Bridges AGENTS.md into Claude Code (@AGENTS.md)");
|
|
513
|
+
if (context.service) {
|
|
514
|
+
console.log(" api/ HTTP service (Hono)");
|
|
515
|
+
}
|
|
516
|
+
if (context.temporal) {
|
|
517
|
+
console.log(" worker/ Temporal worker");
|
|
518
|
+
}
|
|
519
|
+
if (context.database) {
|
|
520
|
+
console.log(" prisma/ Database schema");
|
|
521
|
+
}
|
|
522
|
+
if (context.bucket) {
|
|
523
|
+
console.log(" api/src/storage.ts S3 helpers");
|
|
524
|
+
}
|
|
525
|
+
console.log("");
|
|
526
|
+
console.log("Next steps:");
|
|
527
|
+
console.log(` cd ${appDir}`);
|
|
528
|
+
console.log(" pnpm install");
|
|
529
|
+
console.log(" mesh stack init # personal dev stack (deploy: false)");
|
|
530
|
+
console.log(" mesh deploy up --yes # deploy via the stack's deployer role");
|
|
531
|
+
console.log(" mesh dev # run locally");
|
|
532
|
+
console.log("");
|
|
533
|
+
}
|
|
176
534
|
//# sourceMappingURL=create-app.js.map
|