@mesh-tech/mesh-cli 0.1.1 → 0.12.1
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 +20878 -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 +28 -0
- package/dist/src/commands/install-shim.d.ts.map +1 -0
- package/dist/src/commands/install-shim.js +191 -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
|
@@ -0,0 +1,739 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assembly: turn the discovered doc roots into a plain content tree plus a
|
|
3
|
+
* navigation manifest, ready for a docs renderer (Zudoku today) to build.
|
|
4
|
+
*
|
|
5
|
+
* The seam of the whole design is here: assembly's output is a directory of
|
|
6
|
+
* markdown files, a generated `zudoku.config.ts`, and a publish manifest.
|
|
7
|
+
* Nothing downstream knows about Mesh; nothing upstream knows about Zudoku.
|
|
8
|
+
*
|
|
9
|
+
* What assembly does, per page:
|
|
10
|
+
* - derives the title (front-matter `title:` → first `#` heading → filename)
|
|
11
|
+
* and writes it into the assembled front-matter, so nav labels and page
|
|
12
|
+
* titles can never drift apart
|
|
13
|
+
* - rewrites links: a relative link between two published files is correct
|
|
14
|
+
* *on disk* but meaningless at a route, so published targets become
|
|
15
|
+
* routes, unpublished-but-real files become repo blob links (reported as
|
|
16
|
+
* `external`), and links that resolve to nothing are reported `broken`
|
|
17
|
+
* - footers the page with the exact repo file it came from, so a reader who
|
|
18
|
+
* spots a mistake knows where to fix it
|
|
19
|
+
*
|
|
20
|
+
* It also emits the publish manifest — every source path that made it into
|
|
21
|
+
* the site — which the CI gate uploads and diffs so growing the public
|
|
22
|
+
* surface is a thing a reviewer sees.
|
|
23
|
+
*/
|
|
24
|
+
import { execFileSync } from "node:child_process";
|
|
25
|
+
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
import { parse as parseYaml } from "yaml";
|
|
28
|
+
import { pathKind } from "./discover.js";
|
|
29
|
+
import { hasReservedSegment } from "./schema.js";
|
|
30
|
+
const DEFAULT_REPO_URL = "https://github.com/mesh-tech/mesh-platform";
|
|
31
|
+
const DEFAULT_IGNORE_LINK_PREFIXES = ["node_modules/"];
|
|
32
|
+
/**
|
|
33
|
+
* Split a markdown document into front-matter and body. Only a `---` fence on
|
|
34
|
+
* the very first line counts — a horizontal rule later in the prose is not
|
|
35
|
+
* front-matter. A YAML parse failure is not fatal: the document is treated as
|
|
36
|
+
* having no front-matter (the heading/filename title fallbacks still apply),
|
|
37
|
+
* because one bad page must not take the whole site down at assemble time.
|
|
38
|
+
*/
|
|
39
|
+
export function splitFrontMatter(markdown) {
|
|
40
|
+
const normalized = markdown.replace(/^\uFEFF/, "");
|
|
41
|
+
if (!normalized.startsWith("---\n") && !normalized.startsWith("---\r\n")) {
|
|
42
|
+
return { data: {}, body: markdown, hasFrontMatter: false };
|
|
43
|
+
}
|
|
44
|
+
const end = normalized.indexOf("\n---", 4);
|
|
45
|
+
if (end === -1)
|
|
46
|
+
return { data: {}, body: markdown, hasFrontMatter: false };
|
|
47
|
+
const rawBlock = normalized.slice(4, end);
|
|
48
|
+
const bodyStart = normalized.indexOf("\n", end + 1);
|
|
49
|
+
const body = (bodyStart === -1 ? "" : normalized.slice(bodyStart + 1)).replace(/^\r?\n/, "");
|
|
50
|
+
try {
|
|
51
|
+
const data = parseYaml(rawBlock);
|
|
52
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
53
|
+
return {
|
|
54
|
+
data: data,
|
|
55
|
+
body,
|
|
56
|
+
hasFrontMatter: true,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// fall through to the no-front-matter shape
|
|
62
|
+
}
|
|
63
|
+
return { data: {}, body, hasFrontMatter: true };
|
|
64
|
+
}
|
|
65
|
+
/** Serialize front-matter data + body back into a markdown document. */
|
|
66
|
+
function joinFrontMatter(data, body) {
|
|
67
|
+
const lines = Object.entries(data).map(([key, value]) => {
|
|
68
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
69
|
+
return `${key}: ${value}`;
|
|
70
|
+
const text = String(value);
|
|
71
|
+
// Quote only when YAML would misread the bare form.
|
|
72
|
+
return /^[\w .,'’()/-]+$/.test(text)
|
|
73
|
+
? `${key}: ${text}`
|
|
74
|
+
: `${key}: ${JSON.stringify(text)}`;
|
|
75
|
+
});
|
|
76
|
+
return `---\n${lines.join("\n")}\n---\n\n${body.replace(/^\s*\n/, "")}`;
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Title derivation
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
/** First `#` heading text, or undefined. Headings inside code fences don't count. */
|
|
82
|
+
function firstHeading(body) {
|
|
83
|
+
let inFence = false;
|
|
84
|
+
for (const line of body.split("\n")) {
|
|
85
|
+
if (/^\s*(```|~~~)/.test(line)) {
|
|
86
|
+
inFence = !inFence;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (inFence)
|
|
90
|
+
continue;
|
|
91
|
+
const match = /^#\s+(.+?)\s*#*\s*$/.exec(line);
|
|
92
|
+
if (match)
|
|
93
|
+
return match[1].trim();
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
/** Titleize a filename stem for the filename-fallback case: `hub-dev-local` → "Hub dev local". */
|
|
98
|
+
function titleizeStem(stem) {
|
|
99
|
+
const words = stem.replace(/[-_]+/g, " ").trim();
|
|
100
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The title derivation order, fixed by the design: front-matter `title:` →
|
|
104
|
+
* first `#` heading → filename. `sidebar_label` wins for the nav when present
|
|
105
|
+
* (Zudoku honours it), but the document still gets its real title.
|
|
106
|
+
*/
|
|
107
|
+
export function deriveTitle(frontMatter, body, source) {
|
|
108
|
+
const fmTitle = frontMatter.title;
|
|
109
|
+
if (typeof fmTitle === "string" && fmTitle.trim())
|
|
110
|
+
return fmTitle.trim();
|
|
111
|
+
const heading = firstHeading(body);
|
|
112
|
+
if (heading)
|
|
113
|
+
return heading;
|
|
114
|
+
const stem = path.posix.basename(source).replace(/\.md$/i, "");
|
|
115
|
+
return titleizeStem(stem);
|
|
116
|
+
}
|
|
117
|
+
function scanLinks(markdown) {
|
|
118
|
+
const hits = [];
|
|
119
|
+
const lines = markdown.split("\n");
|
|
120
|
+
let offset = 0;
|
|
121
|
+
let inFence = null;
|
|
122
|
+
for (const line of lines) {
|
|
123
|
+
const fenceMatch = /^(\s{0,3})(`{3,}|~{3,})/.exec(line);
|
|
124
|
+
if (fenceMatch) {
|
|
125
|
+
if (!inFence) {
|
|
126
|
+
inFence = { marker: fenceMatch[2][0] };
|
|
127
|
+
}
|
|
128
|
+
else if (fenceMatch[2].startsWith(inFence.marker)) {
|
|
129
|
+
inFence = null;
|
|
130
|
+
}
|
|
131
|
+
offset += line.length + 1;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (inFence) {
|
|
135
|
+
offset += line.length + 1;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// Reference definitions: [id]: href — the href runs to end of line
|
|
139
|
+
// (optionally followed by a title). Rewrite in place.
|
|
140
|
+
const refDef = /^ {0,3}\[[^\]]+\]:\s*(\S+)/.exec(line);
|
|
141
|
+
if (refDef) {
|
|
142
|
+
const href = refDef[1];
|
|
143
|
+
const start = offset + line.indexOf(href);
|
|
144
|
+
hits.push({ start, end: start + href.length, href });
|
|
145
|
+
offset += line.length + 1;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
// Inline links/images, skipping inline code spans.
|
|
149
|
+
let i = 0;
|
|
150
|
+
while (i < line.length) {
|
|
151
|
+
const ch = line[i];
|
|
152
|
+
if (ch === "`") {
|
|
153
|
+
const run = /^`+/.exec(line.slice(i))[0];
|
|
154
|
+
const close = line.indexOf(run, i + run.length);
|
|
155
|
+
i = close === -1 ? line.length : close + run.length;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (ch === "<") {
|
|
159
|
+
const close = line.indexOf(">", i);
|
|
160
|
+
i = close === -1 ? line.length : close + 1;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (ch === "!" && line[i + 1] === "[") {
|
|
164
|
+
i = scanBracketLink(line, i + 1, offset, hits);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (ch === "[") {
|
|
168
|
+
i = scanBracketLink(line, i, offset, hits);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
i++;
|
|
172
|
+
}
|
|
173
|
+
offset += line.length + 1;
|
|
174
|
+
}
|
|
175
|
+
return hits;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* At `line[i] === "["`, try to read `[...](href …)` or `[...][id]`. Only the
|
|
179
|
+
* `(...)` form carries an inline href we can rewrite; reference uses are
|
|
180
|
+
* covered by rewriting their definitions.
|
|
181
|
+
*/
|
|
182
|
+
function scanBracketLink(line, open, lineOffset, hits) {
|
|
183
|
+
const closeBracket = line.indexOf("]", open);
|
|
184
|
+
if (closeBracket === -1)
|
|
185
|
+
return line.length;
|
|
186
|
+
if (line[closeBracket + 1] !== "(")
|
|
187
|
+
return closeBracket + 1;
|
|
188
|
+
let j = closeBracket + 2;
|
|
189
|
+
while (j < line.length && /\s/.test(line[j]))
|
|
190
|
+
j++;
|
|
191
|
+
if (line[j] === "<") {
|
|
192
|
+
const end = line.indexOf(">", j);
|
|
193
|
+
if (end === -1)
|
|
194
|
+
return line.length;
|
|
195
|
+
hits.push({
|
|
196
|
+
start: lineOffset + j + 1,
|
|
197
|
+
end: lineOffset + end,
|
|
198
|
+
href: line.slice(j + 1, end),
|
|
199
|
+
});
|
|
200
|
+
return end + 1;
|
|
201
|
+
}
|
|
202
|
+
const closeParen = line.indexOf(")", j);
|
|
203
|
+
if (closeParen === -1)
|
|
204
|
+
return line.length;
|
|
205
|
+
const inner = line.slice(j, closeParen).trim();
|
|
206
|
+
// href may be followed by a "title" — split on the first space.
|
|
207
|
+
const space = inner.search(/\s/);
|
|
208
|
+
const href = space === -1 ? inner : inner.slice(0, space);
|
|
209
|
+
if (href) {
|
|
210
|
+
const start = lineOffset + line.indexOf(href, j);
|
|
211
|
+
hits.push({ start, end: start + href.length, href });
|
|
212
|
+
}
|
|
213
|
+
return closeParen + 1;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Remove HTML comments (`<!-- … -->`, single- or multi-line) from a page body.
|
|
217
|
+
* They are invisible in any rendered output by definition — the source file
|
|
218
|
+
* keeps them — and multi-line comments currently crash Zudoku's MDX plugin
|
|
219
|
+
* (`chunks[startIndex].slice is not a function`), which turns one authored
|
|
220
|
+
* comment into a failed site build. Fenced code blocks are left alone: a doc
|
|
221
|
+
* *teaching* HTML comments shows them as code, and that code must survive.
|
|
222
|
+
*/
|
|
223
|
+
export function stripHtmlComments(body) {
|
|
224
|
+
const lines = body.split("\n");
|
|
225
|
+
const out = [];
|
|
226
|
+
let inFence = false;
|
|
227
|
+
let inComment = false;
|
|
228
|
+
for (const line of lines) {
|
|
229
|
+
if (/^\s*(```|~~~)/.test(line)) {
|
|
230
|
+
if (!inComment)
|
|
231
|
+
inFence = !inFence;
|
|
232
|
+
if (!inComment)
|
|
233
|
+
out.push(line);
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (inFence) {
|
|
237
|
+
out.push(line);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
let rest = line;
|
|
241
|
+
let rebuilt = "";
|
|
242
|
+
while (rest.length > 0) {
|
|
243
|
+
if (inComment) {
|
|
244
|
+
const end = rest.indexOf("-->");
|
|
245
|
+
if (end === -1) {
|
|
246
|
+
rest = "";
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
inComment = false;
|
|
250
|
+
rest = rest.slice(end + 3);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const start = rest.indexOf("<!--");
|
|
254
|
+
if (start === -1) {
|
|
255
|
+
rebuilt += rest;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
rebuilt += rest.slice(0, start);
|
|
259
|
+
inComment = true;
|
|
260
|
+
rest = rest.slice(start + 4);
|
|
261
|
+
}
|
|
262
|
+
// A line that held only a comment collapses to nothing; a line with prose
|
|
263
|
+
// around a comment keeps its prose.
|
|
264
|
+
if (rebuilt.trim() !== "" || !inComment)
|
|
265
|
+
out.push(rebuilt.replace(/\s+$/, ""));
|
|
266
|
+
}
|
|
267
|
+
return out.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
268
|
+
}
|
|
269
|
+
function isAbsoluteHref(href) {
|
|
270
|
+
return /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(href);
|
|
271
|
+
}
|
|
272
|
+
function normalizeRepoPath(value) {
|
|
273
|
+
return path.posix
|
|
274
|
+
.normalize(value.replace(/\\/g, "/"))
|
|
275
|
+
.replace(/^\.\//, "")
|
|
276
|
+
.replace(/\/+$/, "");
|
|
277
|
+
}
|
|
278
|
+
function splitHash(href) {
|
|
279
|
+
const index = href.indexOf("#");
|
|
280
|
+
return index === -1
|
|
281
|
+
? [href, ""]
|
|
282
|
+
: [href.slice(0, index), href.slice(index + 1)];
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Resolve one link, exactly the #3503 semantics with routes instead of slugs:
|
|
286
|
+
*
|
|
287
|
+
* - anchors, absolute URLs, mailto: → untouched
|
|
288
|
+
* - an `ignoreLinkPrefixes` match → untouched (declared deliberately
|
|
289
|
+
* unresolvable — the app-kit README's `node_modules/…` guidance exists in
|
|
290
|
+
* a tenant's install, never in this repo)
|
|
291
|
+
* - a file the portal publishes → that page's route
|
|
292
|
+
* - a directory whose index/README the portal publishes → that route
|
|
293
|
+
* - a real repo file the portal does not publish → a repo blob link
|
|
294
|
+
* (reported `external`)
|
|
295
|
+
* - nothing → reported `broken`
|
|
296
|
+
* - a site-rooted path (`/guides/x`) → validated against the route set, so a
|
|
297
|
+
* typo'd route fails the gate instead of shipping as a 404
|
|
298
|
+
*/
|
|
299
|
+
export function resolveLink(args) {
|
|
300
|
+
const { href, pageRoute, sourceDir, sourceIndex, routes, repoUrl } = args;
|
|
301
|
+
if (href.startsWith("#") || isAbsoluteHref(href))
|
|
302
|
+
return { href };
|
|
303
|
+
if (args.ignoreLinkPrefixes.some((prefix) => href.startsWith(prefix)))
|
|
304
|
+
return { href };
|
|
305
|
+
const [rawTarget, rawHash] = splitHash(href);
|
|
306
|
+
const hash = rawHash ? `#${rawHash}` : "";
|
|
307
|
+
if (rawTarget === "")
|
|
308
|
+
return { href };
|
|
309
|
+
// Site-rooted route reference.
|
|
310
|
+
if (rawTarget.startsWith("/")) {
|
|
311
|
+
const route = rawTarget.replace(/\/$/, "") || "/";
|
|
312
|
+
return routes.has(route)
|
|
313
|
+
? { href: `${route}${hash}` }
|
|
314
|
+
: { href, issue: { kind: "broken", page: pageRoute, href } };
|
|
315
|
+
}
|
|
316
|
+
const repoPath = normalizeRepoPath(path.posix.join(sourceDir, rawTarget));
|
|
317
|
+
const page = sourceIndex.get(repoPath);
|
|
318
|
+
if (page)
|
|
319
|
+
return { href: `${page.route}${hash}` };
|
|
320
|
+
// A link to a directory conventionally means its index page.
|
|
321
|
+
for (const candidate of [`${repoPath}/index.md`]) {
|
|
322
|
+
const indexPage = sourceIndex.get(normalizeRepoPath(candidate));
|
|
323
|
+
if (indexPage)
|
|
324
|
+
return { href: `${indexPage.route}${hash}` };
|
|
325
|
+
}
|
|
326
|
+
const kind = args.pathKind(repoPath);
|
|
327
|
+
if (kind !== null) {
|
|
328
|
+
const base = repoUrl.replace(/\/$/, "").replace(/\/(blob|tree)$/, "");
|
|
329
|
+
return {
|
|
330
|
+
href: `${base}/${kind === "dir" ? "tree" : "blob"}/main/${repoPath}${hash}`,
|
|
331
|
+
issue: { kind: "external", page: pageRoute, href },
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return { href, issue: { kind: "broken", page: pageRoute, href } };
|
|
335
|
+
}
|
|
336
|
+
/** Rewrite every link in a page body, collecting issues. */
|
|
337
|
+
export function rewriteLinks(args) {
|
|
338
|
+
const issues = [];
|
|
339
|
+
const hits = scanLinks(args.body);
|
|
340
|
+
if (hits.length === 0)
|
|
341
|
+
return { body: args.body, issues };
|
|
342
|
+
const sourceDir = path.posix.dirname(args.page.source);
|
|
343
|
+
let out = "";
|
|
344
|
+
let cursor = 0;
|
|
345
|
+
for (const hit of hits) {
|
|
346
|
+
const resolution = resolveLink({
|
|
347
|
+
href: hit.href,
|
|
348
|
+
pageRoute: args.page.route,
|
|
349
|
+
sourceDir,
|
|
350
|
+
sourceIndex: args.sourceIndex,
|
|
351
|
+
routes: args.routes,
|
|
352
|
+
ignoreLinkPrefixes: args.ignoreLinkPrefixes,
|
|
353
|
+
pathKind: args.pathKind,
|
|
354
|
+
repoUrl: args.repoUrl,
|
|
355
|
+
});
|
|
356
|
+
out += args.body.slice(cursor, hit.start) + resolution.href;
|
|
357
|
+
cursor = hit.end;
|
|
358
|
+
if (resolution.issue)
|
|
359
|
+
issues.push(resolution.issue);
|
|
360
|
+
}
|
|
361
|
+
out += args.body.slice(cursor);
|
|
362
|
+
return { body: out, issues };
|
|
363
|
+
}
|
|
364
|
+
/** A page's full route: section slug + route path. "/" for the site home. */
|
|
365
|
+
export function pageRoute(page) {
|
|
366
|
+
const joined = [page.root.slug, page.routePath].filter(Boolean).join("/");
|
|
367
|
+
return `/${joined}`.replace(/\/$/, "") || "/";
|
|
368
|
+
}
|
|
369
|
+
/** The assembled file path (no leading slash, with extension). */
|
|
370
|
+
export function pageFilePath(route) {
|
|
371
|
+
return route === "/" ? "index.md" : `${route.slice(1)}.md`;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Assemble the discovered pages into `outDir`. Pure function of the repo tree
|
|
375
|
+
* — the same inputs always produce the same tree, manifest, and navigation.
|
|
376
|
+
*/
|
|
377
|
+
export function assemblePortal(options) {
|
|
378
|
+
const { repoRoot, discovery, outDir } = options;
|
|
379
|
+
const repoUrl = options.repoUrl ?? DEFAULT_REPO_URL;
|
|
380
|
+
const ignoreLinkPrefixes = options.ignoreLinkPrefixes ?? DEFAULT_IGNORE_LINK_PREFIXES;
|
|
381
|
+
// Build the page model first: routes must all exist before any link can be
|
|
382
|
+
// rewritten against them.
|
|
383
|
+
const pages = discovery.pages.map((page) => {
|
|
384
|
+
const route = pageRoute(page);
|
|
385
|
+
return {
|
|
386
|
+
source: page.source,
|
|
387
|
+
route,
|
|
388
|
+
filePath: pageFilePath(route),
|
|
389
|
+
title: "",
|
|
390
|
+
sectionTitle: page.root.config.title,
|
|
391
|
+
sectionOrder: page.root.config.order,
|
|
392
|
+
sectionSlug: page.root.slug,
|
|
393
|
+
};
|
|
394
|
+
});
|
|
395
|
+
const sourceIndex = new Map(pages.map((p) => [normalizeRepoPath(p.source), p]));
|
|
396
|
+
const routes = new Set(pages.map((p) => p.route));
|
|
397
|
+
const brokenLinks = [];
|
|
398
|
+
const externalLinks = [];
|
|
399
|
+
rmSync(outDir, { recursive: true, force: true });
|
|
400
|
+
mkdirSync(outDir, { recursive: true });
|
|
401
|
+
for (const page of pages) {
|
|
402
|
+
const raw = readFileSync(path.join(repoRoot, page.source), "utf-8");
|
|
403
|
+
const frontMatter = splitFrontMatter(raw);
|
|
404
|
+
const title = deriveTitle(frontMatter.data, frontMatter.body, page.source);
|
|
405
|
+
page.title = title;
|
|
406
|
+
const order = frontMatter.data.order;
|
|
407
|
+
if (typeof order === "number" && Number.isFinite(order))
|
|
408
|
+
page.order = order;
|
|
409
|
+
const rewritten = rewriteLinks({
|
|
410
|
+
body: stripHtmlComments(frontMatter.body),
|
|
411
|
+
page,
|
|
412
|
+
sourceIndex,
|
|
413
|
+
routes,
|
|
414
|
+
ignoreLinkPrefixes,
|
|
415
|
+
pathKind: (rel) => pathKind(path.join(repoRoot, rel)),
|
|
416
|
+
repoUrl,
|
|
417
|
+
});
|
|
418
|
+
for (const issue of rewritten.issues) {
|
|
419
|
+
(issue.kind === "broken" ? brokenLinks : externalLinks).push(issue);
|
|
420
|
+
}
|
|
421
|
+
// Front-matter: keep the author's, guarantee `title`. `showLastModified`
|
|
422
|
+
// is off — the assembled tree is rebuilt every run, so git-mtime-derived
|
|
423
|
+
// dates would say "today" on every page.
|
|
424
|
+
const outData = { ...frontMatter.data, title };
|
|
425
|
+
const blobBase = repoUrl.replace(/\/$/, "").replace(/\/(blob|tree)$/, "");
|
|
426
|
+
const sourceNote = `\n\n---\n\n<sub>Source: [\`${page.source}\`](${blobBase}/blob/main/${page.source}) — edit that file, not this page.</sub>\n`;
|
|
427
|
+
const outFile = path.join(outDir, page.filePath);
|
|
428
|
+
mkdirSync(path.dirname(outFile), { recursive: true });
|
|
429
|
+
writeFileSync(outFile, joinFrontMatter(outData, rewritten.body.trimEnd() + sourceNote));
|
|
430
|
+
}
|
|
431
|
+
const navigation = buildNavigation(pages);
|
|
432
|
+
// Fail-closed: no assembled output path may contain a reserved segment. The
|
|
433
|
+
// walk already skips reserved directories, so a violation here means the
|
|
434
|
+
// exclusion itself broke — exactly what the gate exists to catch.
|
|
435
|
+
const reservedViolations = pages
|
|
436
|
+
.map((p) => p.filePath)
|
|
437
|
+
.filter((filePath) => hasReservedSegment(filePath));
|
|
438
|
+
const publishManifest = {
|
|
439
|
+
version: 1,
|
|
440
|
+
count: pages.length,
|
|
441
|
+
sources: pages.map((p) => p.source).sort(),
|
|
442
|
+
};
|
|
443
|
+
return {
|
|
444
|
+
outDir,
|
|
445
|
+
pages,
|
|
446
|
+
navigation,
|
|
447
|
+
brokenLinks,
|
|
448
|
+
externalLinks,
|
|
449
|
+
publishManifest,
|
|
450
|
+
reservedViolations,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function titleizeDir(name) {
|
|
454
|
+
return titleizeStem(name);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Build the Zudoku navigation array from the assembled pages.
|
|
458
|
+
*
|
|
459
|
+
* Shape: one root category ("Documentation", clicking it lands on the home
|
|
460
|
+
* page) whose items are one non-collapsible category per doc root — the
|
|
461
|
+
* sidebar's section headers — each holding the section's tree: pages as doc
|
|
462
|
+
* items, directories as nested categories. A directory with an index page
|
|
463
|
+
* becomes a clickable category (its link); the section's own index page
|
|
464
|
+
* becomes the section category's link. Order is front-matter `order:` first,
|
|
465
|
+
* then filename — never declared anywhere but the files themselves.
|
|
466
|
+
*/
|
|
467
|
+
export function buildNavigation(pages) {
|
|
468
|
+
const sections = new Map();
|
|
469
|
+
for (const page of pages) {
|
|
470
|
+
const key = page.sectionSlug;
|
|
471
|
+
if (!sections.has(key)) {
|
|
472
|
+
sections.set(key, {
|
|
473
|
+
title: page.sectionTitle,
|
|
474
|
+
order: page.sectionOrder,
|
|
475
|
+
slug: page.sectionSlug,
|
|
476
|
+
pages: [],
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
sections.get(key).pages.push(page);
|
|
480
|
+
}
|
|
481
|
+
const sortedSections = [...sections.values()].sort((a, b) => a.order - b.order || a.title.localeCompare(b.title));
|
|
482
|
+
const sortPages = (list) => [...list].sort((a, b) => (a.order ?? Number.MAX_SAFE_INTEGER) -
|
|
483
|
+
(b.order ?? Number.MAX_SAFE_INTEGER) ||
|
|
484
|
+
a.filePath.localeCompare(b.filePath));
|
|
485
|
+
// A nav doc reference (item or category link — same shape in both places).
|
|
486
|
+
// A `path` is a CUSTOM path in Zudoku: when it equals the file-derived
|
|
487
|
+
// route, the build moves the file's entry onto itself and deletes it
|
|
488
|
+
// (resolveCustomNavigationPaths compares `path === file` without the
|
|
489
|
+
// leading slash). The assembler already names files so the file route IS
|
|
490
|
+
// the desired route — so `path` is only emitted for the one genuinely
|
|
491
|
+
// custom mapping: the home page (file "index" → "/").
|
|
492
|
+
const docRef = (page) => {
|
|
493
|
+
const file = page.filePath.replace(/\.md$/, "");
|
|
494
|
+
return page.route === `/${file}`
|
|
495
|
+
? file
|
|
496
|
+
: { type: "doc", file, path: page.route };
|
|
497
|
+
};
|
|
498
|
+
const items = [];
|
|
499
|
+
for (const section of sortedSections) {
|
|
500
|
+
const indexPage = section.pages.find((p) => p.route === `/${section.slug}` ||
|
|
501
|
+
(section.slug === "" && p.route === "/"));
|
|
502
|
+
const rest = section.pages.filter((p) => p !== indexPage);
|
|
503
|
+
// Group remaining pages by their section-relative directory.
|
|
504
|
+
const rootPages = [];
|
|
505
|
+
const dirs = new Map();
|
|
506
|
+
for (const page of rest) {
|
|
507
|
+
const rel = page.route.replace(/^\//, "");
|
|
508
|
+
const sectionPrefix = section.slug ? `${section.slug}/` : "";
|
|
509
|
+
const relParts = (sectionPrefix && rel.startsWith(sectionPrefix)
|
|
510
|
+
? rel.slice(sectionPrefix.length)
|
|
511
|
+
: rel)
|
|
512
|
+
.split("/")
|
|
513
|
+
.filter(Boolean);
|
|
514
|
+
if (relParts.length <= 1) {
|
|
515
|
+
rootPages.push(page);
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const dirKey = relParts.slice(0, -1).join("/");
|
|
519
|
+
if (!dirs.has(dirKey)) {
|
|
520
|
+
dirs.set(dirKey, {
|
|
521
|
+
label: titleizeDir(relParts[relParts.length - 2]),
|
|
522
|
+
routePath: relParts.slice(0, -1).join("/"),
|
|
523
|
+
pages: [],
|
|
524
|
+
dirs: new Map(),
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
dirs.get(dirKey).pages.push(page);
|
|
528
|
+
}
|
|
529
|
+
const byRoute = new Map(section.pages.map((p) => [p.route, p]));
|
|
530
|
+
const childItems = sortPages(rootPages).map(docRef);
|
|
531
|
+
for (const dir of [...dirs.values()].sort((a, b) => a.routePath.localeCompare(b.routePath))) {
|
|
532
|
+
const dirRoute = `/${[section.slug, dir.routePath].filter(Boolean).join("/")}`.replace(/\/$/, "") || "/";
|
|
533
|
+
const dirIndex = byRoute.get(dirRoute);
|
|
534
|
+
const grandchildren = sortPages(dir.pages.filter((p) => p !== dirIndex)).map(docRef);
|
|
535
|
+
if (grandchildren.length === 0 && dirIndex) {
|
|
536
|
+
childItems.push(docRef(dirIndex));
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
childItems.push({
|
|
540
|
+
type: "category",
|
|
541
|
+
label: dir.label,
|
|
542
|
+
...(dirIndex ? { link: docRef(dirIndex) } : {}),
|
|
543
|
+
items: grandchildren,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
items.push({
|
|
547
|
+
type: "category",
|
|
548
|
+
label: section.title,
|
|
549
|
+
collapsible: false,
|
|
550
|
+
...(indexPage ? { link: docRef(indexPage) } : {}),
|
|
551
|
+
items: childItems,
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
return [
|
|
555
|
+
{
|
|
556
|
+
type: "category",
|
|
557
|
+
label: "Documentation",
|
|
558
|
+
link: { type: "doc", file: "index", path: "/" },
|
|
559
|
+
items,
|
|
560
|
+
},
|
|
561
|
+
];
|
|
562
|
+
}
|
|
563
|
+
// ---------------------------------------------------------------------------
|
|
564
|
+
// Generated config + manifests
|
|
565
|
+
// ---------------------------------------------------------------------------
|
|
566
|
+
/**
|
|
567
|
+
* Render the generated `zudoku.config.ts`. It is regenerated on every
|
|
568
|
+
* assemble and gitignored — the navigation manifest is derived state, and
|
|
569
|
+
* committed derived state is how the old manifest rotted.
|
|
570
|
+
*/
|
|
571
|
+
export function renderZudokuConfig(args) {
|
|
572
|
+
const versionLine = args.baseline
|
|
573
|
+
? `Documents @mesh-tech/* ${args.baseline} · built from ${args.commit ?? "unknown"}`
|
|
574
|
+
: `Local build · ${args.commit ?? "unknown"}`;
|
|
575
|
+
const config = {
|
|
576
|
+
metadata: {
|
|
577
|
+
title: args.title,
|
|
578
|
+
description: args.description,
|
|
579
|
+
},
|
|
580
|
+
site: {
|
|
581
|
+
title: args.title,
|
|
582
|
+
logoUrl: "/",
|
|
583
|
+
footer: {
|
|
584
|
+
copyright: `${versionLine} · /version.json`,
|
|
585
|
+
},
|
|
586
|
+
},
|
|
587
|
+
theme: "THEME_IMPORT",
|
|
588
|
+
navigation: args.navigation,
|
|
589
|
+
docs: {
|
|
590
|
+
files: ["/content/**/*.{md,mdx}"],
|
|
591
|
+
defaultOptions: {
|
|
592
|
+
toc: true,
|
|
593
|
+
showLastModified: false,
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
redirects: [],
|
|
597
|
+
// Search is Zudoku's built-in Pagefind index — no config needed.
|
|
598
|
+
};
|
|
599
|
+
const json = JSON.stringify(config, null, 2).replace(`"THEME_IMPORT"`, "portalTheme");
|
|
600
|
+
return `/**
|
|
601
|
+
* GENERATED by \`mesh docs portal\` — do not edit.
|
|
602
|
+
*
|
|
603
|
+
* The navigation array is derived from the repo's docs.json roots and the
|
|
604
|
+
* markdown tree beneath them. To change what the site publishes, change the
|
|
605
|
+
* tree; to change section labels or order, change the root's docs.json.
|
|
606
|
+
* Regenerate: pnpm exec mesh docs portal --assemble-only
|
|
607
|
+
*/
|
|
608
|
+
import type { ZudokuConfig } from "zudoku";
|
|
609
|
+
import { portalTheme } from "./theme.js";
|
|
610
|
+
|
|
611
|
+
const config: ZudokuConfig = ${json};
|
|
612
|
+
|
|
613
|
+
export default config;
|
|
614
|
+
`;
|
|
615
|
+
}
|
|
616
|
+
/** version.json — the version-parity contract the parity monitor asserts. */
|
|
617
|
+
export function renderVersionJson(args) {
|
|
618
|
+
return `${JSON.stringify({
|
|
619
|
+
meshBaseline: args.baseline ?? null,
|
|
620
|
+
commit: args.commit,
|
|
621
|
+
builtAt: args.builtAt,
|
|
622
|
+
}, null, 2)}\n`;
|
|
623
|
+
}
|
|
624
|
+
/** Best-effort short commit of the repo being assembled. */
|
|
625
|
+
export function currentCommit(repoRoot) {
|
|
626
|
+
try {
|
|
627
|
+
return execFileSync("git", ["rev-parse", "--short", "HEAD"], {
|
|
628
|
+
cwd: repoRoot,
|
|
629
|
+
encoding: "utf-8",
|
|
630
|
+
}).trim();
|
|
631
|
+
}
|
|
632
|
+
catch {
|
|
633
|
+
return "unknown";
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
/** The fixed lockstep group's version, read from app-kit's package.json. */
|
|
637
|
+
export function currentBaseline(repoRoot) {
|
|
638
|
+
try {
|
|
639
|
+
const pkg = JSON.parse(readFileSync(path.join(repoRoot, "libs/app-kit/package.json"), "utf-8"));
|
|
640
|
+
return pkg.version;
|
|
641
|
+
}
|
|
642
|
+
catch {
|
|
643
|
+
return undefined;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Compute the publish set of another git ref WITHOUT checking it out — the
|
|
648
|
+
* docs.json files and tree listing are read via `git show`/`git ls-tree`, and
|
|
649
|
+
* the same discovery rules (reserved segments, README exclusion, include[])
|
|
650
|
+
* are applied to that listing. Lets a PR diff its publish set against its
|
|
651
|
+
* merge base in a CI job that has no second worktree and no installed deps
|
|
652
|
+
* for the base.
|
|
653
|
+
*
|
|
654
|
+
* APPROXIMATION, base side only: this reimplementation skips schema
|
|
655
|
+
* validation (an invalid docs.json publishes nothing in real discovery but
|
|
656
|
+
* is walked here), nested-root rejection, and route-collision detection, so
|
|
657
|
+
* it can OVER-report the base's publish set (a spurious "removed" row in the
|
|
658
|
+
* summary) — never under-report the head's. The head side is always real
|
|
659
|
+
* discovery; the gate's assertions never read this function.
|
|
660
|
+
*/
|
|
661
|
+
export function publishSetAtRef(repoRoot, ref) {
|
|
662
|
+
const git = (gitArgs) => execFileSync("git", gitArgs, {
|
|
663
|
+
cwd: repoRoot,
|
|
664
|
+
encoding: "utf-8",
|
|
665
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
666
|
+
});
|
|
667
|
+
const allFiles = git(["ls-tree", "-r", "--name-only", ref])
|
|
668
|
+
.split("\n")
|
|
669
|
+
.filter(Boolean);
|
|
670
|
+
const docsJsonPaths = allFiles.filter((file) => file === "docs.json" || file.endsWith("/docs.json"));
|
|
671
|
+
const published = new Set();
|
|
672
|
+
for (const docsJsonPath of docsJsonPaths) {
|
|
673
|
+
const rootDir = docsJsonPath === "docs.json"
|
|
674
|
+
? ""
|
|
675
|
+
: docsJsonPath.slice(0, -"/docs.json".length);
|
|
676
|
+
if (rootDir && hasReservedSegment(rootDir))
|
|
677
|
+
continue;
|
|
678
|
+
let config;
|
|
679
|
+
try {
|
|
680
|
+
config = JSON.parse(git(["show", `${ref}:${docsJsonPath}`]));
|
|
681
|
+
}
|
|
682
|
+
catch {
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
const prefix = rootDir ? `${rootDir}/` : "";
|
|
686
|
+
for (const file of allFiles) {
|
|
687
|
+
if (!file.startsWith(prefix) || !file.toLowerCase().endsWith(".md"))
|
|
688
|
+
continue;
|
|
689
|
+
const rel = file.slice(prefix.length);
|
|
690
|
+
if (hasReservedSegment(rel))
|
|
691
|
+
continue;
|
|
692
|
+
if (path.posix.basename(file).toLowerCase() === "readme.md")
|
|
693
|
+
continue;
|
|
694
|
+
published.add(file);
|
|
695
|
+
}
|
|
696
|
+
for (const include of config.include ?? []) {
|
|
697
|
+
const normalized = include.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
698
|
+
if (hasReservedSegment(normalized))
|
|
699
|
+
continue;
|
|
700
|
+
if (allFiles.includes(normalized))
|
|
701
|
+
published.add(normalized);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return [...published].sort();
|
|
705
|
+
}
|
|
706
|
+
export function diffPublishSets(base, head) {
|
|
707
|
+
const baseSet = new Set(base);
|
|
708
|
+
const headSet = new Set(head);
|
|
709
|
+
return {
|
|
710
|
+
added: head.filter((source) => !baseSet.has(source)),
|
|
711
|
+
removed: base.filter((source) => !headSet.has(source)),
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
/** Render the publish-set diff as a GitHub job-summary markdown block. */
|
|
715
|
+
export function renderPublishSetSummary(manifest, diff) {
|
|
716
|
+
const lines = [
|
|
717
|
+
`## Docs portal publish set`,
|
|
718
|
+
``,
|
|
719
|
+
`**${manifest.count} pages publish** from this tree.`,
|
|
720
|
+
``,
|
|
721
|
+
];
|
|
722
|
+
if (diff && (diff.added.length > 0 || diff.removed.length > 0)) {
|
|
723
|
+
lines.push(`### Changes vs the merge base`, ``);
|
|
724
|
+
for (const source of diff.added)
|
|
725
|
+
lines.push(`- ➕ \`${source}\``);
|
|
726
|
+
for (const source of diff.removed)
|
|
727
|
+
lines.push(`- ➖ \`${source}\``);
|
|
728
|
+
lines.push(``, `Growing the public surface is a deliberate act — a reviewer should see this list.`);
|
|
729
|
+
}
|
|
730
|
+
else if (diff) {
|
|
731
|
+
lines.push(`No change vs the merge base.`);
|
|
732
|
+
}
|
|
733
|
+
lines.push(``, `<details><summary>Full publish set</summary>`, ``);
|
|
734
|
+
for (const source of manifest.sources)
|
|
735
|
+
lines.push(`- \`${source}\``);
|
|
736
|
+
lines.push(``, `</details>`);
|
|
737
|
+
return `${lines.join("\n")}\n`;
|
|
738
|
+
}
|
|
739
|
+
//# sourceMappingURL=assemble.js.map
|