@celljs/cli 3.9.0 → 4.0.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/README.md +442 -1
- package/agent/guide.md +39 -0
- package/bin/cell.js +2 -0
- package/lib/agent/agent-guide.d.ts +39 -0
- package/lib/agent/agent-guide.d.ts.map +1 -0
- package/lib/agent/agent-guide.js +67 -0
- package/lib/agent/agent-guide.js.map +1 -0
- package/lib/build/executable-compiler.d.ts +44 -0
- package/lib/build/executable-compiler.d.ts.map +1 -0
- package/lib/build/executable-compiler.js +145 -0
- package/lib/build/executable-compiler.js.map +1 -0
- package/lib/build/executable-compiler.spec.d.ts +2 -0
- package/lib/build/executable-compiler.spec.d.ts.map +1 -0
- package/lib/build/executable-compiler.spec.js +71 -0
- package/lib/build/executable-compiler.spec.js.map +1 -0
- package/lib/build/single-compile.spec.d.ts +2 -0
- package/lib/build/single-compile.spec.d.ts.map +1 -0
- package/lib/build/single-compile.spec.js +135 -0
- package/lib/build/single-compile.spec.js.map +1 -0
- package/lib/check/project-checker.d.ts +85 -0
- package/lib/check/project-checker.d.ts.map +1 -0
- package/lib/check/project-checker.js +332 -0
- package/lib/check/project-checker.js.map +1 -0
- package/lib/check/project-checker.spec.d.ts +2 -0
- package/lib/check/project-checker.spec.d.ts.map +1 -0
- package/lib/check/project-checker.spec.js +147 -0
- package/lib/check/project-checker.spec.js.map +1 -0
- package/lib/cli/agent-command.d.ts +15 -0
- package/lib/cli/agent-command.d.ts.map +1 -0
- package/lib/cli/agent-command.js +42 -0
- package/lib/cli/agent-command.js.map +1 -0
- package/lib/cli/build-command.d.ts +84 -0
- package/lib/cli/build-command.d.ts.map +1 -0
- package/lib/cli/build-command.js +170 -0
- package/lib/cli/build-command.js.map +1 -0
- package/lib/cli/cell-cli.d.ts +35 -0
- package/lib/cli/cell-cli.d.ts.map +1 -0
- package/lib/cli/cell-cli.js +159 -0
- package/lib/cli/cell-cli.js.map +1 -0
- package/lib/cli/cell-cli.spec.d.ts +2 -0
- package/lib/cli/cell-cli.spec.d.ts.map +1 -0
- package/lib/cli/cell-cli.spec.js +195 -0
- package/lib/cli/cell-cli.spec.js.map +1 -0
- package/lib/cli/check-command.d.ts +31 -0
- package/lib/cli/check-command.d.ts.map +1 -0
- package/lib/cli/check-command.js +67 -0
- package/lib/cli/check-command.js.map +1 -0
- package/lib/cli/command.d.ts +24 -0
- package/lib/cli/command.d.ts.map +1 -0
- package/lib/cli/command.js +10 -0
- package/lib/cli/command.js.map +1 -0
- package/lib/cli/config-command.d.ts +29 -0
- package/lib/cli/config-command.d.ts.map +1 -0
- package/lib/cli/config-command.js +71 -0
- package/lib/cli/config-command.js.map +1 -0
- package/lib/cli/config-command.spec.d.ts +2 -0
- package/lib/cli/config-command.spec.d.ts.map +1 -0
- package/lib/cli/config-command.spec.js +79 -0
- package/lib/cli/config-command.spec.js.map +1 -0
- package/lib/cli/deploy-command.d.ts +41 -0
- package/lib/cli/deploy-command.d.ts.map +1 -0
- package/lib/cli/deploy-command.js +114 -0
- package/lib/cli/deploy-command.js.map +1 -0
- package/lib/cli/dev-command.d.ts +47 -0
- package/lib/cli/dev-command.d.ts.map +1 -0
- package/lib/cli/dev-command.js +219 -0
- package/lib/cli/dev-command.js.map +1 -0
- package/lib/cli/dev-command.spec.d.ts +2 -0
- package/lib/cli/dev-command.spec.d.ts.map +1 -0
- package/lib/cli/dev-command.spec.js +149 -0
- package/lib/cli/dev-command.spec.js.map +1 -0
- package/lib/cli/docs-command.d.ts +19 -0
- package/lib/cli/docs-command.d.ts.map +1 -0
- package/lib/cli/docs-command.js +47 -0
- package/lib/cli/docs-command.js.map +1 -0
- package/lib/cli/info-command.d.ts +44 -0
- package/lib/cli/info-command.d.ts.map +1 -0
- package/lib/cli/info-command.js +39 -0
- package/lib/cli/info-command.js.map +1 -0
- package/lib/cli/info-command.spec.d.ts +2 -0
- package/lib/cli/info-command.spec.d.ts.map +1 -0
- package/lib/cli/info-command.spec.js +236 -0
- package/lib/cli/info-command.spec.js.map +1 -0
- package/lib/cli/init-command.d.ts +20 -0
- package/lib/cli/init-command.d.ts.map +1 -0
- package/lib/cli/init-command.js +43 -0
- package/lib/cli/init-command.js.map +1 -0
- package/lib/cli/main.d.ts +2 -0
- package/lib/cli/main.d.ts.map +1 -0
- package/lib/cli/main.js +3 -0
- package/lib/cli/main.js.map +1 -0
- package/lib/cli/mcp-command.d.ts +34 -0
- package/lib/cli/mcp-command.d.ts.map +1 -0
- package/lib/cli/mcp-command.js +85 -0
- package/lib/cli/mcp-command.js.map +1 -0
- package/lib/cli/mcp-command.spec.d.ts +2 -0
- package/lib/cli/mcp-command.spec.d.ts.map +1 -0
- package/lib/cli/mcp-command.spec.js +132 -0
- package/lib/cli/mcp-command.spec.js.map +1 -0
- package/lib/cli/preview-command.d.ts +24 -0
- package/lib/cli/preview-command.d.ts.map +1 -0
- package/lib/cli/preview-command.js +91 -0
- package/lib/cli/preview-command.js.map +1 -0
- package/lib/cli/reporter.d.ts +26 -0
- package/lib/cli/reporter.d.ts.map +1 -0
- package/lib/cli/reporter.js +58 -0
- package/lib/cli/reporter.js.map +1 -0
- package/lib/config/config-build.spec.d.ts +2 -0
- package/lib/config/config-build.spec.d.ts.map +1 -0
- package/lib/config/config-build.spec.js +111 -0
- package/lib/config/config-build.spec.js.map +1 -0
- package/lib/config/config-explainer.d.ts +48 -0
- package/lib/config/config-explainer.d.ts.map +1 -0
- package/lib/config/config-explainer.js +130 -0
- package/lib/config/config-explainer.js.map +1 -0
- package/lib/config/config-file-loader.d.ts +22 -0
- package/lib/config/config-file-loader.d.ts.map +1 -0
- package/lib/config/config-file-loader.js +63 -0
- package/lib/config/config-file-loader.js.map +1 -0
- package/lib/config/config-resolver.d.ts +111 -0
- package/lib/config/config-resolver.d.ts.map +1 -0
- package/lib/config/config-resolver.js +215 -0
- package/lib/config/config-resolver.js.map +1 -0
- package/lib/config/config-resolver.spec.d.ts +2 -0
- package/lib/config/config-resolver.spec.d.ts.map +1 -0
- package/lib/config/config-resolver.spec.js +159 -0
- package/lib/config/config-resolver.spec.js.map +1 -0
- package/lib/config/config-validator.d.ts +35 -0
- package/lib/config/config-validator.d.ts.map +1 -0
- package/lib/config/config-validator.js +160 -0
- package/lib/config/config-validator.js.map +1 -0
- package/lib/config/config-validator.spec.d.ts +2 -0
- package/lib/config/config-validator.spec.d.ts.map +1 -0
- package/lib/config/config-validator.spec.js +77 -0
- package/lib/config/config-validator.spec.js.map +1 -0
- package/lib/config/define-config.d.ts +4 -0
- package/lib/config/define-config.d.ts.map +1 -0
- package/lib/config/define-config.js +5 -0
- package/lib/config/define-config.js.map +1 -0
- package/lib/config/types.d.ts +53 -0
- package/lib/config/types.d.ts.map +1 -0
- package/lib/config/types.js +2 -0
- package/lib/config/types.js.map +1 -0
- package/lib/deploy/cloud-api.d.ts +58 -0
- package/lib/deploy/cloud-api.d.ts.map +1 -0
- package/lib/deploy/cloud-api.js +189 -0
- package/lib/deploy/cloud-api.js.map +1 -0
- package/lib/deploy/code-package.d.ts +15 -0
- package/lib/deploy/code-package.d.ts.map +1 -0
- package/lib/deploy/code-package.js +40 -0
- package/lib/deploy/code-package.js.map +1 -0
- package/lib/deploy/deploy-utils.spec.d.ts +2 -0
- package/lib/deploy/deploy-utils.spec.d.ts.map +1 -0
- package/lib/deploy/deploy-utils.spec.js +56 -0
- package/lib/deploy/deploy-utils.spec.js.map +1 -0
- package/lib/deploy/deployer-registry.d.ts +11 -0
- package/lib/deploy/deployer-registry.d.ts.map +1 -0
- package/lib/deploy/deployer-registry.js +40 -0
- package/lib/deploy/deployer-registry.js.map +1 -0
- package/lib/deploy/request-signer.d.ts +51 -0
- package/lib/deploy/request-signer.d.ts.map +1 -0
- package/lib/deploy/request-signer.js +109 -0
- package/lib/deploy/request-signer.js.map +1 -0
- package/lib/deploy/zip-writer.d.ts +32 -0
- package/lib/deploy/zip-writer.d.ts.map +1 -0
- package/lib/deploy/zip-writer.js +114 -0
- package/lib/deploy/zip-writer.js.map +1 -0
- package/lib/docs/docs-index.d.ts +54 -0
- package/lib/docs/docs-index.d.ts.map +1 -0
- package/lib/docs/docs-index.js +140 -0
- package/lib/docs/docs-index.js.map +1 -0
- package/lib/docs/docs-index.spec.d.ts +2 -0
- package/lib/docs/docs-index.spec.d.ts.map +1 -0
- package/lib/docs/docs-index.spec.js +52 -0
- package/lib/docs/docs-index.spec.js.map +1 -0
- package/lib/events/event-bus.d.ts +30 -0
- package/lib/events/event-bus.d.ts.map +1 -0
- package/lib/events/event-bus.js +81 -0
- package/lib/events/event-bus.js.map +1 -0
- package/lib/events/event-bus.spec.d.ts +2 -0
- package/lib/events/event-bus.spec.d.ts.map +1 -0
- package/lib/events/event-bus.spec.js +69 -0
- package/lib/events/event-bus.spec.js.map +1 -0
- package/lib/events/hook-runner.d.ts +27 -0
- package/lib/events/hook-runner.d.ts.map +1 -0
- package/lib/events/hook-runner.js +65 -0
- package/lib/events/hook-runner.js.map +1 -0
- package/lib/events/hook-runner.spec.d.ts +2 -0
- package/lib/events/hook-runner.spec.d.ts.map +1 -0
- package/lib/events/hook-runner.spec.js +36 -0
- package/lib/events/hook-runner.spec.js.map +1 -0
- package/lib/index.d.ts +57 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +57 -2
- package/lib/index.js.map +1 -1
- package/lib/info/project-inspector.d.ts +143 -0
- package/lib/info/project-inspector.d.ts.map +1 -0
- package/lib/info/project-inspector.js +244 -0
- package/lib/info/project-inspector.js.map +1 -0
- package/lib/init/project-initializer.d.ts +44 -0
- package/lib/init/project-initializer.d.ts.map +1 -0
- package/lib/init/project-initializer.js +90 -0
- package/lib/init/project-initializer.js.map +1 -0
- package/lib/init/project-initializer.spec.d.ts +2 -0
- package/lib/init/project-initializer.spec.d.ts.map +1 -0
- package/lib/init/project-initializer.spec.js +88 -0
- package/lib/init/project-initializer.spec.js.map +1 -0
- package/lib/mcp/dev-activity.d.ts +34 -0
- package/lib/mcp/dev-activity.d.ts.map +1 -0
- package/lib/mcp/dev-activity.js +46 -0
- package/lib/mcp/dev-activity.js.map +1 -0
- package/lib/mcp/dev-mcp-endpoint.d.ts +62 -0
- package/lib/mcp/dev-mcp-endpoint.d.ts.map +1 -0
- package/lib/mcp/dev-mcp-endpoint.js +280 -0
- package/lib/mcp/dev-mcp-endpoint.js.map +1 -0
- package/lib/mcp/dev-mcp-endpoint.spec.d.ts +2 -0
- package/lib/mcp/dev-mcp-endpoint.spec.d.ts.map +1 -0
- package/lib/mcp/dev-mcp-endpoint.spec.js +143 -0
- package/lib/mcp/dev-mcp-endpoint.spec.js.map +1 -0
- package/lib/mcp/mcp-server.d.ts +64 -0
- package/lib/mcp/mcp-server.d.ts.map +1 -0
- package/lib/mcp/mcp-server.js +201 -0
- package/lib/mcp/mcp-server.js.map +1 -0
- package/lib/mcp/mcp-server.spec.d.ts +2 -0
- package/lib/mcp/mcp-server.spec.d.ts.map +1 -0
- package/lib/mcp/mcp-server.spec.js +136 -0
- package/lib/mcp/mcp-server.spec.js.map +1 -0
- package/lib/mcp/project-mcp-tools.d.ts +35 -0
- package/lib/mcp/project-mcp-tools.d.ts.map +1 -0
- package/lib/mcp/project-mcp-tools.js +199 -0
- package/lib/mcp/project-mcp-tools.js.map +1 -0
- package/lib/modules/module-host.d.ts +118 -0
- package/lib/modules/module-host.d.ts.map +1 -0
- package/lib/modules/module-host.js +405 -0
- package/lib/modules/module-host.js.map +1 -0
- package/lib/modules/module-host.spec.d.ts +2 -0
- package/lib/modules/module-host.spec.d.ts.map +1 -0
- package/lib/modules/module-host.spec.js +220 -0
- package/lib/modules/module-host.spec.js.map +1 -0
- package/lib/preset/builtin-presets.d.ts +9 -0
- package/lib/preset/builtin-presets.d.ts.map +1 -0
- package/lib/preset/builtin-presets.js +24 -0
- package/lib/preset/builtin-presets.js.map +1 -0
- package/lib/preset/cloudflare/cloudflare-deployer.d.ts +26 -0
- package/lib/preset/cloudflare/cloudflare-deployer.d.ts.map +1 -0
- package/lib/preset/cloudflare/cloudflare-deployer.js +116 -0
- package/lib/preset/cloudflare/cloudflare-deployer.js.map +1 -0
- package/lib/preset/cloudflare/cloudflare-preset.d.ts +16 -0
- package/lib/preset/cloudflare/cloudflare-preset.d.ts.map +1 -0
- package/lib/preset/cloudflare/cloudflare-preset.js +97 -0
- package/lib/preset/cloudflare/cloudflare-preset.js.map +1 -0
- package/lib/preset/cloudflare/cloudflare.spec.d.ts +2 -0
- package/lib/preset/cloudflare/cloudflare.spec.d.ts.map +1 -0
- package/lib/preset/cloudflare/cloudflare.spec.js +212 -0
- package/lib/preset/cloudflare/cloudflare.spec.js.map +1 -0
- package/lib/preset/cloudflare/wrangler-config.d.ts +50 -0
- package/lib/preset/cloudflare/wrangler-config.d.ts.map +1 -0
- package/lib/preset/cloudflare/wrangler-config.js +160 -0
- package/lib/preset/cloudflare/wrangler-config.js.map +1 -0
- package/lib/preset/cloudflare/wrangler-config.spec.d.ts +2 -0
- package/lib/preset/cloudflare/wrangler-config.spec.d.ts.map +1 -0
- package/lib/preset/cloudflare/wrangler-config.spec.js +112 -0
- package/lib/preset/cloudflare/wrangler-config.spec.js.map +1 -0
- package/lib/preset/cloudflare/wrangler.d.ts +38 -0
- package/lib/preset/cloudflare/wrangler.d.ts.map +1 -0
- package/lib/preset/cloudflare/wrangler.js +90 -0
- package/lib/preset/cloudflare/wrangler.js.map +1 -0
- package/lib/preset/cloudflare/wrangler.spec.d.ts +2 -0
- package/lib/preset/cloudflare/wrangler.spec.d.ts.map +1 -0
- package/lib/preset/cloudflare/wrangler.spec.js +64 -0
- package/lib/preset/cloudflare/wrangler.spec.js.map +1 -0
- package/lib/preset/fc/fc-deployer.d.ts +50 -0
- package/lib/preset/fc/fc-deployer.d.ts.map +1 -0
- package/lib/preset/fc/fc-deployer.js +209 -0
- package/lib/preset/fc/fc-deployer.js.map +1 -0
- package/lib/preset/fc/fc-preset.d.ts +20 -0
- package/lib/preset/fc/fc-preset.d.ts.map +1 -0
- package/lib/preset/fc/fc-preset.js +46 -0
- package/lib/preset/fc/fc-preset.js.map +1 -0
- package/lib/preset/lambda/lambda-deployer.d.ts +50 -0
- package/lib/preset/lambda/lambda-deployer.d.ts.map +1 -0
- package/lib/preset/lambda/lambda-deployer.js +274 -0
- package/lib/preset/lambda/lambda-deployer.js.map +1 -0
- package/lib/preset/lambda/lambda-preset.d.ts +14 -0
- package/lib/preset/lambda/lambda-preset.d.ts.map +1 -0
- package/lib/preset/lambda/lambda-preset.js +44 -0
- package/lib/preset/lambda/lambda-preset.js.map +1 -0
- package/lib/preset/preset-output.d.ts +19 -0
- package/lib/preset/preset-output.d.ts.map +1 -0
- package/lib/preset/preset-output.js +45 -0
- package/lib/preset/preset-output.js.map +1 -0
- package/lib/preset/preset-registry.d.ts +16 -0
- package/lib/preset/preset-registry.d.ts.map +1 -0
- package/lib/preset/preset-registry.js +58 -0
- package/lib/preset/preset-registry.js.map +1 -0
- package/lib/preset/preset-registry.spec.d.ts +2 -0
- package/lib/preset/preset-registry.spec.d.ts.map +1 -0
- package/lib/preset/preset-registry.spec.js +28 -0
- package/lib/preset/preset-registry.spec.js.map +1 -0
- package/lib/preset/scf/scf-deployer.d.ts +54 -0
- package/lib/preset/scf/scf-deployer.d.ts.map +1 -0
- package/lib/preset/scf/scf-deployer.js +202 -0
- package/lib/preset/scf/scf-deployer.js.map +1 -0
- package/lib/preset/scf/scf-preset.d.ts +19 -0
- package/lib/preset/scf/scf-preset.d.ts.map +1 -0
- package/lib/preset/scf/scf-preset.js +43 -0
- package/lib/preset/scf/scf-preset.js.map +1 -0
- package/lib/preset/serverless-deployers.spec.d.ts +2 -0
- package/lib/preset/serverless-deployers.spec.d.ts.map +1 -0
- package/lib/preset/serverless-deployers.spec.js +307 -0
- package/lib/preset/serverless-deployers.spec.js.map +1 -0
- package/lib/preset/serverless-presets.spec.d.ts +2 -0
- package/lib/preset/serverless-presets.spec.d.ts.map +1 -0
- package/lib/preset/serverless-presets.spec.js +280 -0
- package/lib/preset/serverless-presets.spec.js.map +1 -0
- package/lib/preset/serverless-scripts.d.ts +29 -0
- package/lib/preset/serverless-scripts.d.ts.map +1 -0
- package/lib/preset/serverless-scripts.js +120 -0
- package/lib/preset/serverless-scripts.js.map +1 -0
- package/lib/preset/vercel/vercel-deployer.d.ts +38 -0
- package/lib/preset/vercel/vercel-deployer.d.ts.map +1 -0
- package/lib/preset/vercel/vercel-deployer.js +160 -0
- package/lib/preset/vercel/vercel-deployer.js.map +1 -0
- package/lib/preset/vercel/vercel-preset.d.ts +19 -0
- package/lib/preset/vercel/vercel-preset.d.ts.map +1 -0
- package/lib/preset/vercel/vercel-preset.js +102 -0
- package/lib/preset/vercel/vercel-preset.js.map +1 -0
- package/lib/test/fixture-project.d.ts +17 -0
- package/lib/test/fixture-project.d.ts.map +1 -0
- package/lib/test/fixture-project.js +43 -0
- package/lib/test/fixture-project.js.map +1 -0
- package/lib/testing/create-test-app.d.ts +27 -0
- package/lib/testing/create-test-app.d.ts.map +1 -0
- package/lib/testing/create-test-app.js +54 -0
- package/lib/testing/create-test-app.js.map +1 -0
- package/lib/testing/create-test-app.spec.d.ts +2 -0
- package/lib/testing/create-test-app.spec.d.ts.map +1 -0
- package/lib/testing/create-test-app.spec.js +66 -0
- package/lib/testing/create-test-app.spec.js.map +1 -0
- package/lib/toolchain/toolchain.d.ts +49 -0
- package/lib/toolchain/toolchain.d.ts.map +1 -0
- package/lib/toolchain/toolchain.js +100 -0
- package/lib/toolchain/toolchain.js.map +1 -0
- package/lib/utils/json-util.d.ts +11 -0
- package/lib/utils/json-util.d.ts.map +1 -0
- package/lib/utils/json-util.js +73 -0
- package/lib/utils/json-util.js.map +1 -0
- package/lib/utils/json-util.spec.d.ts +2 -0
- package/lib/utils/json-util.spec.d.ts.map +1 -0
- package/lib/utils/json-util.spec.js +18 -0
- package/lib/utils/json-util.spec.js.map +1 -0
- package/lib/utils/text-util.d.ts +19 -0
- package/lib/utils/text-util.d.ts.map +1 -0
- package/lib/utils/text-util.js +66 -0
- package/lib/utils/text-util.js.map +1 -0
- package/lib/utils/text-util.spec.d.ts +2 -0
- package/lib/utils/text-util.spec.d.ts.map +1 -0
- package/lib/utils/text-util.spec.js +22 -0
- package/lib/utils/text-util.spec.js.map +1 -0
- package/package.json +28 -30
- package/src/agent/agent-guide.ts +90 -0
- package/src/build/executable-compiler.ts +179 -0
- package/src/check/project-checker.ts +365 -0
- package/src/cli/agent-command.ts +46 -0
- package/src/cli/build-command.ts +189 -0
- package/src/cli/cell-cli.ts +174 -0
- package/src/cli/check-command.ts +74 -0
- package/src/cli/command.ts +29 -0
- package/src/cli/config-command.ts +73 -0
- package/src/cli/deploy-command.ts +122 -0
- package/src/cli/dev-command.ts +232 -0
- package/src/cli/docs-command.ts +53 -0
- package/src/cli/info-command.ts +40 -0
- package/src/cli/init-command.ts +53 -0
- package/src/cli/main.ts +3 -0
- package/src/cli/mcp-command.ts +98 -0
- package/src/cli/preview-command.ts +98 -0
- package/src/cli/reporter.ts +67 -0
- package/src/config/config-explainer.ts +158 -0
- package/src/config/config-file-loader.ts +76 -0
- package/src/config/config-resolver.ts +300 -0
- package/src/config/config-validator.ts +208 -0
- package/src/config/define-config.ts +6 -0
- package/src/config/types.ts +57 -0
- package/src/deploy/cloud-api.ts +194 -0
- package/src/deploy/code-package.ts +44 -0
- package/src/deploy/deployer-registry.ts +44 -0
- package/src/deploy/request-signer.ts +155 -0
- package/src/deploy/zip-writer.ts +132 -0
- package/src/docs/docs-index.ts +174 -0
- package/src/events/event-bus.ts +94 -0
- package/src/events/hook-runner.ts +78 -0
- package/src/index.ts +57 -0
- package/src/info/project-inspector.ts +352 -0
- package/src/init/project-initializer.ts +111 -0
- package/src/mcp/dev-activity.ts +71 -0
- package/src/mcp/dev-mcp-endpoint.ts +323 -0
- package/src/mcp/mcp-server.ts +251 -0
- package/src/mcp/project-mcp-tools.ts +216 -0
- package/src/modules/module-host.ts +489 -0
- package/src/preset/builtin-presets.ts +26 -0
- package/src/preset/cloudflare/cloudflare-deployer.ts +126 -0
- package/src/preset/cloudflare/cloudflare-preset.ts +97 -0
- package/src/preset/cloudflare/wrangler-config.ts +173 -0
- package/src/preset/cloudflare/wrangler.ts +113 -0
- package/src/preset/fc/fc-deployer.ts +237 -0
- package/src/preset/fc/fc-preset.ts +51 -0
- package/src/preset/lambda/lambda-deployer.ts +317 -0
- package/src/preset/lambda/lambda-preset.ts +45 -0
- package/src/preset/preset-output.ts +55 -0
- package/src/preset/preset-registry.ts +65 -0
- package/src/preset/scf/scf-deployer.ts +232 -0
- package/src/preset/scf/scf-preset.ts +45 -0
- package/src/preset/serverless-scripts.ts +132 -0
- package/src/preset/vercel/vercel-deployer.ts +168 -0
- package/src/preset/vercel/vercel-preset.ts +111 -0
- package/src/test/fixture-project.ts +50 -0
- package/src/testing/create-test-app.ts +73 -0
- package/src/toolchain/toolchain.ts +121 -0
- package/src/utils/json-util.ts +67 -0
- package/src/utils/text-util.ts +68 -0
- package/templates/backend/README.md +13 -0
- package/templates/backend/_gitignore +5 -0
- package/templates/backend/cell.yml +3 -0
- package/templates/backend/package.json +23 -0
- package/templates/{file-service/src → backend/src/node}/home-controller.ts +5 -2
- package/templates/{file-service/src → backend/src/node}/module.ts +0 -1
- package/templates/backend/template.json +3 -0
- package/templates/backend/test/app.spec.ts +19 -0
- package/templates/backend/tsconfig.json +25 -0
- package/templates/fullstack/README.md +13 -0
- package/templates/fullstack/_gitignore +5 -0
- package/templates/fullstack/cell.yml +6 -0
- package/templates/fullstack/package.json +27 -0
- package/templates/fullstack/src/browser/home.view.tsx +19 -0
- package/templates/{cell-component/src → fullstack/src/browser}/module.ts +1 -1
- package/templates/fullstack/src/common/greeting-protocol.ts +5 -0
- package/templates/fullstack/src/node/greeting-server.ts +13 -0
- package/templates/{admin-app/src/browser → fullstack/src/node}/module.ts +2 -1
- package/templates/fullstack/template.json +3 -0
- package/templates/fullstack/test/app.spec.ts +18 -0
- package/templates/fullstack/tsconfig.json +27 -0
- package/bin/cell +0 -2
- package/lib/build/build-manager.d.ts +0 -9
- package/lib/build/build-manager.d.ts.map +0 -1
- package/lib/build/build-manager.js +0 -41
- package/lib/build/build-manager.js.map +0 -1
- package/lib/build/build.d.ts +0 -6
- package/lib/build/build.d.ts.map +0 -1
- package/lib/build/build.js +0 -16
- package/lib/build/build.js.map +0 -1
- package/lib/cell-main.d.ts +0 -2
- package/lib/cell-main.d.ts.map +0 -1
- package/lib/cell-main.js +0 -110
- package/lib/cell-main.js.map +0 -1
- package/lib/cell.d.ts +0 -2
- package/lib/cell.d.ts.map +0 -1
- package/lib/cell.js +0 -194
- package/lib/cell.js.map +0 -1
- package/lib/config/config.d.ts +0 -12
- package/lib/config/config.d.ts.map +0 -1
- package/lib/config/config.js +0 -48
- package/lib/config/config.js.map +0 -1
- package/lib/deploy/deploy.d.ts +0 -7
- package/lib/deploy/deploy.d.ts.map +0 -1
- package/lib/deploy/deploy.js +0 -30
- package/lib/deploy/deploy.js.map +0 -1
- package/lib/info/info.d.ts +0 -6
- package/lib/info/info.d.ts.map +0 -1
- package/lib/info/info.js +0 -21
- package/lib/info/info.js.map +0 -1
- package/lib/init/init-manager.d.ts +0 -33
- package/lib/init/init-manager.d.ts.map +0 -1
- package/lib/init/init-manager.js +0 -141
- package/lib/init/init-manager.js.map +0 -1
- package/lib/init/init.d.ts +0 -4
- package/lib/init/init.d.ts.map +0 -1
- package/lib/init/init.js +0 -17
- package/lib/init/init.js.map +0 -1
- package/lib/init/templates.d.ts +0 -2
- package/lib/init/templates.d.ts.map +0 -1
- package/lib/init/templates.js +0 -23
- package/lib/init/templates.js.map +0 -1
- package/lib/package.spec.d.ts +0 -2
- package/lib/package.spec.d.ts.map +0 -1
- package/lib/package.spec.js +0 -7
- package/lib/package.spec.js.map +0 -1
- package/lib/props/props.d.ts +0 -9
- package/lib/props/props.d.ts.map +0 -1
- package/lib/props/props.js +0 -49
- package/lib/props/props.js.map +0 -1
- package/lib/serve/serve-manager.d.ts +0 -8
- package/lib/serve/serve-manager.d.ts.map +0 -1
- package/lib/serve/serve-manager.js +0 -44
- package/lib/serve/serve-manager.js.map +0 -1
- package/lib/serve/serve.d.ts +0 -8
- package/lib/serve/serve.d.ts.map +0 -1
- package/lib/serve/serve.js +0 -25
- package/lib/serve/serve.js.map +0 -1
- package/lib/update/update.d.ts +0 -9
- package/lib/update/update.d.ts.map +0 -1
- package/lib/update/update.js +0 -56
- package/lib/update/update.js.map +0 -1
- package/lib/utils/banner-util.d.ts +0 -6
- package/lib/utils/banner-util.d.ts.map +0 -1
- package/lib/utils/banner-util.js +0 -44
- package/lib/utils/banner-util.js.map +0 -1
- package/lib/utils/index.d.ts +0 -2
- package/lib/utils/index.d.ts.map +0 -1
- package/lib/utils/index.js +0 -18
- package/lib/utils/index.js.map +0 -1
- package/src/build/build-manager.ts +0 -50
- package/src/build/build.ts +0 -17
- package/src/cell-main.ts +0 -125
- package/src/cell.ts +0 -215
- package/src/config/config.ts +0 -56
- package/src/deploy/deploy.ts +0 -31
- package/src/info/info.ts +0 -23
- package/src/init/init-manager.ts +0 -163
- package/src/init/init.ts +0 -15
- package/src/init/templates.ts +0 -19
- package/src/package.spec.ts +0 -5
- package/src/props/props.ts +0 -48
- package/src/serve/serve-manager.ts +0 -51
- package/src/serve/serve.ts +0 -29
- package/src/update/update.ts +0 -61
- package/src/utils/banner-util.ts +0 -41
- package/src/utils/index.ts +0 -1
- package/templates/accounts/README.md +0 -76
- package/templates/accounts/cell-database.yml +0 -17
- package/templates/accounts/cell-locale.yml +0 -17
- package/templates/accounts/cell-oauth2.0.yml +0 -8
- package/templates/accounts/cell-theme.yml +0 -9
- package/templates/accounts/cell.yml +0 -10
- package/templates/accounts/favicon.ico +0 -0
- package/templates/accounts/package.json +0 -48
- package/templates/accounts/src/browser/home.view.tsx +0 -86
- package/templates/accounts/src/browser/index.ts +0 -3
- package/templates/accounts/src/browser/login.view.tsx +0 -78
- package/templates/accounts/src/browser/module.ts +0 -3
- package/templates/accounts/src/common/entity-protocol.ts +0 -7
- package/templates/accounts/src/common/index.ts +0 -1
- package/templates/accounts/src/node/authentication/authentication-success-handler.ts +0 -69
- package/templates/accounts/src/node/authentication/index.ts +0 -1
- package/templates/accounts/src/node/entity/base-entity.ts +0 -13
- package/templates/accounts/src/node/entity/connection.ts +0 -52
- package/templates/accounts/src/node/entity/index.ts +0 -1
- package/templates/accounts/src/node/entity/user.ts +0 -73
- package/templates/accounts/src/node/error/error.ts +0 -14
- package/templates/accounts/src/node/error/index.ts +0 -1
- package/templates/accounts/src/node/index.ts +0 -2
- package/templates/accounts/src/node/module.ts +0 -9
- package/templates/accounts/src/node/user/index.ts +0 -4
- package/templates/accounts/src/node/user/user-protocol.ts +0 -19
- package/templates/accounts/src/node/user/user-repository.ts +0 -72
- package/templates/accounts/src/node/user/user-service.ts +0 -36
- package/templates/accounts/tsconfig.json +0 -32
- package/templates/admin-app/.github/workflows/deploy.yml +0 -25
- package/templates/admin-app/.vscode/launch.json +0 -23
- package/templates/admin-app/README.md +0 -76
- package/templates/admin-app/cell-database.yml +0 -7
- package/templates/admin-app/cell.yml +0 -93
- package/templates/admin-app/package.json +0 -37
- package/templates/admin-app/src/browser/user.view.tsx +0 -40
- package/templates/admin-app/src/common/index.ts +0 -1
- package/templates/admin-app/src/common/user-protocol.ts +0 -23
- package/templates/admin-app/src/node/entity/index.ts +0 -1
- package/templates/admin-app/src/node/entity/user.ts +0 -15
- package/templates/admin-app/src/node/module.ts +0 -8
- package/templates/admin-app/src/node/user-service.ts +0 -41
- package/templates/admin-app/tsconfig.json +0 -32
- package/templates/backend-app/.github/workflows/deploy.yml +0 -25
- package/templates/backend-app/.vscode/launch.json +0 -23
- package/templates/backend-app/README.md +0 -76
- package/templates/backend-app/cell.yml +0 -0
- package/templates/backend-app/package.json +0 -33
- package/templates/backend-app/src/home-controller.ts +0 -11
- package/templates/backend-app/src/module.ts +0 -4
- package/templates/backend-app/src/user-controller.ts +0 -48
- package/templates/backend-app/test/home-controller.spec.ts +0 -19
- package/templates/backend-app/tsconfig.json +0 -32
- package/templates/cell-component/README.md +0 -27
- package/templates/cell-component/cell.yml +0 -0
- package/templates/cell-component/package.json +0 -29
- package/templates/cell-component/src/echo-service.ts +0 -16
- package/templates/cell-component/src/index.ts +0 -1
- package/templates/cell-component/src/package.spec.ts +0 -5
- package/templates/cell-component/tsconfig.json +0 -37
- package/templates/database-app/.github/workflows/deploy.yml +0 -25
- package/templates/database-app/.vscode/launch.json +0 -23
- package/templates/database-app/README.md +0 -76
- package/templates/database-app/cell.yml +0 -17
- package/templates/database-app/package.json +0 -31
- package/templates/database-app/src/entity/index.ts +0 -1
- package/templates/database-app/src/entity/user.ts +0 -13
- package/templates/database-app/src/home-controller.ts +0 -11
- package/templates/database-app/src/module.ts +0 -8
- package/templates/database-app/src/user-controller.ts +0 -43
- package/templates/database-app/tsconfig.json +0 -32
- package/templates/docker-app/.github/workflows/deploy.yml +0 -25
- package/templates/docker-app/.vscode/launch.json +0 -23
- package/templates/docker-app/Dockerfile +0 -27
- package/templates/docker-app/README.md +0 -77
- package/templates/docker-app/cell.yml +0 -0
- package/templates/docker-app/package.json +0 -31
- package/templates/docker-app/src/browser/assets/logo.png +0 -0
- package/templates/docker-app/src/browser/css-shims.d.ts +0 -30
- package/templates/docker-app/src/browser/hello.view.tsx +0 -31
- package/templates/docker-app/src/browser/module.ts +0 -3
- package/templates/docker-app/src/browser/style/hello.module.scss +0 -4
- package/templates/docker-app/src/common/welcome-protocol.ts +0 -5
- package/templates/docker-app/src/node/module.ts +0 -3
- package/templates/docker-app/src/node/welcome-server.ts +0 -9
- package/templates/docker-app/tsconfig.json +0 -33
- package/templates/file-service/.github/workflows/deploy.yml +0 -25
- package/templates/file-service/.vscode/launch.json +0 -23
- package/templates/file-service/README.md +0 -76
- package/templates/file-service/cell.yml +0 -12
- package/templates/file-service/package.json +0 -34
- package/templates/file-service/src/file-controller.ts +0 -47
- package/templates/file-service/tsconfig.json +0 -32
- package/templates/jwt-app/.github/workflows/deploy.yml +0 -25
- package/templates/jwt-app/.vscode/launch.json +0 -23
- package/templates/jwt-app/README.md +0 -76
- package/templates/jwt-app/cell.yml +0 -4
- package/templates/jwt-app/package.json +0 -36
- package/templates/jwt-app/src/context.ts +0 -16
- package/templates/jwt-app/src/error-handler.ts +0 -30
- package/templates/jwt-app/src/error.ts +0 -4
- package/templates/jwt-app/src/home-controller.ts +0 -23
- package/templates/jwt-app/src/index.ts +0 -5
- package/templates/jwt-app/src/jwt-middleware.ts +0 -36
- package/templates/jwt-app/src/module.ts +0 -3
- package/templates/jwt-app/test/home-controller.spec.ts +0 -19
- package/templates/jwt-app/tsconfig.json +0 -32
- package/templates/koa-app/app.js +0 -8
- package/templates/koa-app/package.json +0 -9
- package/templates/microservice/.github/workflows/deploy.yml +0 -28
- package/templates/microservice/.vscode/launch.json +0 -24
- package/templates/microservice/README.md +0 -76
- package/templates/microservice/examples/backend-app/README.md +0 -76
- package/templates/microservice/examples/backend-app/cell-remote.yml +0 -4
- package/templates/microservice/examples/backend-app/cell.yml +0 -3
- package/templates/microservice/examples/backend-app/package.json +0 -32
- package/templates/microservice/examples/backend-app/src/api-controller.ts +0 -31
- package/templates/microservice/examples/backend-app/src/module.ts +0 -3
- package/templates/microservice/examples/backend-app/tsconfig.json +0 -32
- package/templates/microservice/package.json +0 -20
- package/templates/microservice/packages/api/README.md +0 -76
- package/templates/microservice/packages/api/cell.yml +0 -0
- package/templates/microservice/packages/api/package.json +0 -25
- package/templates/microservice/packages/api/src/common/api-protocol.ts +0 -10
- package/templates/microservice/packages/api/src/common/index.ts +0 -1
- package/templates/microservice/packages/api/tsconfig.json +0 -30
- package/templates/microservice/packages/serviceA/.vscode/launch.json +0 -23
- package/templates/microservice/packages/serviceA/README.md +0 -76
- package/templates/microservice/packages/serviceA/cell.yml +0 -6
- package/templates/microservice/packages/serviceA/package.json +0 -29
- package/templates/microservice/packages/serviceA/src/node/module.ts +0 -3
- package/templates/microservice/packages/serviceA/src/node/service-a.ts +0 -9
- package/templates/microservice/packages/serviceA/tsconfig.json +0 -30
- package/templates/microservice/packages/serviceB/README.md +0 -76
- package/templates/microservice/packages/serviceB/cell.yml +0 -5
- package/templates/microservice/packages/serviceB/package.json +0 -29
- package/templates/microservice/packages/serviceB/src/node/module.ts +0 -3
- package/templates/microservice/packages/serviceB/src/node/service-b.ts +0 -9
- package/templates/microservice/packages/serviceB/tsconfig.json +0 -30
- package/templates/microservice/tsconfig.json +0 -32
- package/templates/mycli/.vscode/launch.json +0 -33
- package/templates/mycli/bin/mycli +0 -2
- package/templates/mycli/bin/mycli-deploy +0 -2
- package/templates/mycli/bin/mycli-init +0 -2
- package/templates/mycli/package.json +0 -33
- package/templates/mycli/src/bootstrap.ts +0 -7
- package/templates/mycli/src/constants.ts +0 -1
- package/templates/mycli/src/deploy/deploy-manager.ts +0 -12
- package/templates/mycli/src/deploy/deploy.ts +0 -16
- package/templates/mycli/src/deploy/index.ts +0 -1
- package/templates/mycli/src/index.ts +0 -2
- package/templates/mycli/src/init/index.ts +0 -1
- package/templates/mycli/src/init/init-manager.ts +0 -85
- package/templates/mycli/src/init/init.ts +0 -25
- package/templates/mycli/src/init/templates.ts +0 -3
- package/templates/mycli/src/module.ts +0 -3
- package/templates/mycli/src/mycli.ts +0 -13
- package/templates/mycli/templates/application-template/README.md +0 -0
- package/templates/mycli/tsconfig.json +0 -32
- package/templates/nest-app/.eslintrc.js +0 -25
- package/templates/nest-app/.prettierrc +0 -4
- package/templates/nest-app/README.md +0 -73
- package/templates/nest-app/nest-cli.json +0 -8
- package/templates/nest-app/package.json +0 -69
- package/templates/nest-app/src/app.controller.spec.ts +0 -22
- package/templates/nest-app/src/app.controller.ts +0 -12
- package/templates/nest-app/src/app.module.ts +0 -10
- package/templates/nest-app/src/app.service.ts +0 -8
- package/templates/nest-app/src/main.ts +0 -8
- package/templates/nest-app/test/app.e2e-spec.ts +0 -24
- package/templates/nest-app/test/jest-e2e.json +0 -9
- package/templates/nest-app/tsconfig.build.json +0 -12
- package/templates/nest-app/tsconfig.json +0 -25
- package/templates/nextjs-app/.eslintrc.json +0 -3
- package/templates/nextjs-app/README.md +0 -34
- package/templates/nextjs-app/next.config.js +0 -6
- package/templates/nextjs-app/package.json +0 -20
- package/templates/nextjs-app/pages/_app.js +0 -7
- package/templates/nextjs-app/pages/api/hello.js +0 -5
- package/templates/nextjs-app/pages/index.js +0 -69
- package/templates/nextjs-app/public/favicon.ico +0 -0
- package/templates/nextjs-app/public/vercel.svg +0 -4
- package/templates/nextjs-app/styles/Home.module.css +0 -116
- package/templates/nextjs-app/styles/globals.css +0 -16
- package/templates/sample-app/.github/workflows/deploy.yml +0 -25
- package/templates/sample-app/.vscode/launch.json +0 -23
- package/templates/sample-app/README.md +0 -76
- package/templates/sample-app/cell.yml +0 -0
- package/templates/sample-app/package.json +0 -31
- package/templates/sample-app/src/browser/assets/logo.png +0 -0
- package/templates/sample-app/src/browser/css-shims.d.ts +0 -30
- package/templates/sample-app/src/browser/hello.view.tsx +0 -31
- package/templates/sample-app/src/browser/module.ts +0 -3
- package/templates/sample-app/src/browser/style/hello.module.scss +0 -4
- package/templates/sample-app/src/common/welcome-protocol.ts +0 -5
- package/templates/sample-app/src/node/module.ts +0 -3
- package/templates/sample-app/src/node/welcome-server.ts +0 -9
- package/templates/sample-app/tsconfig.json +0 -32
- package/templates/schedule/.github/workflows/deploy.yml +0 -25
- package/templates/schedule/.vscode/launch.json +0 -23
- package/templates/schedule/README.md +0 -76
- package/templates/schedule/cell.yml +0 -1
- package/templates/schedule/package.json +0 -29
- package/templates/schedule/src/module.ts +0 -3
- package/templates/schedule/src/scheduler.ts +0 -10
- package/templates/schedule/tsconfig.json +0 -32
- package/templates/standalone-app/package.json +0 -17
- package/templates/standalone-app/src/app.service.ts +0 -10
- package/templates/standalone-app/src/main.ts +0 -14
- package/templates/standalone-app/src/module.ts +0 -3
- package/templates/standalone-app/tsconfig.json +0 -30
- package/templates/vue-app/.github/workflows/deploy.yml +0 -25
- package/templates/vue-app/.vscode/launch.json +0 -23
- package/templates/vue-app/README.md +0 -76
- package/templates/vue-app/cell.yml +0 -0
- package/templates/vue-app/package.json +0 -32
- package/templates/vue-app/src/browser/App.vue +0 -32
- package/templates/vue-app/src/browser/app.ts +0 -7
- package/templates/vue-app/src/browser/components/HelloWorld.vue +0 -42
- package/templates/vue-app/src/browser/declare.d.ts +0 -7
- package/templates/vue-app/src/browser/images/logo.png +0 -0
- package/templates/vue-app/src/browser/module.ts +0 -3
- package/templates/vue-app/src/browser/router.ts +0 -13
- package/templates/vue-app/src/browser/shims-vue.d.ts +0 -5
- package/templates/vue-app/src/browser/views/About.vue +0 -5
- package/templates/vue-app/src/browser/views/Root.vue +0 -37
- package/templates/vue-app/src/common/welcome-protocol.ts +0 -5
- package/templates/vue-app/src/node/module.ts +0 -3
- package/templates/vue-app/src/node/welcome-server.ts +0 -9
- package/templates/vue-app/tsconfig.json +0 -32
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { definePreset, type PresetOutputContext, type PresetPreviewContext, type PreviewProcess } from '@celljs/kit';
|
|
4
|
+
import { Wrangler } from './wrangler.js';
|
|
5
|
+
import { WranglerConfig } from './wrangler-config.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Cloudflare Workers with Node.js compatibility. The Cell server (Express on the node:http server of
|
|
9
|
+
* Workers) is the worker; the frontend is served by Cloudflare as static assets, so only requests
|
|
10
|
+
* that match no asset reach the worker.
|
|
11
|
+
*/
|
|
12
|
+
export namespace CloudflarePreset {
|
|
13
|
+
/** `server/worker.mjs`: the worker module around the server bundle. */
|
|
14
|
+
export const WORKER = [
|
|
15
|
+
'// Generated by the Cell cloudflare preset. Do not edit.',
|
|
16
|
+
"import { createServer } from 'node:http';",
|
|
17
|
+
"import { httpServerHandler } from 'cloudflare:node';",
|
|
18
|
+
'',
|
|
19
|
+
'// Workers allow code generation (new Function) only while modules load and I/O only while a request is',
|
|
20
|
+
'// handled: the modules of the application load now, the application starts on the first request.',
|
|
21
|
+
'const server = createServer((req, res) => {',
|
|
22
|
+
' firstRequest();',
|
|
23
|
+
' application',
|
|
24
|
+
' .then(handler => {',
|
|
25
|
+
' if (!handler) {',
|
|
26
|
+
" throw new Error('The application has no HTTP entry: add @celljs/express-adapter to the dependencies.');",
|
|
27
|
+
' }',
|
|
28
|
+
' handler(req, res);',
|
|
29
|
+
' })',
|
|
30
|
+
' .catch(error => {',
|
|
31
|
+
' console.error(error);',
|
|
32
|
+
' res.statusCode = 500;',
|
|
33
|
+
" res.end('Internal Server Error');",
|
|
34
|
+
' });',
|
|
35
|
+
'});',
|
|
36
|
+
'let firstRequest;',
|
|
37
|
+
'const requested = new Promise(resolve => (firstRequest = resolve));',
|
|
38
|
+
'let modulesLoaded;',
|
|
39
|
+
'const loaded = new Promise(resolve => (modulesLoaded = resolve));',
|
|
40
|
+
'const application = new Promise((resolve, reject) => {',
|
|
41
|
+
" globalThis[Symbol.for('@celljs/core/application-host')] = {",
|
|
42
|
+
' server,',
|
|
43
|
+
' beforeStart: () => {',
|
|
44
|
+
' modulesLoaded();',
|
|
45
|
+
' return requested;',
|
|
46
|
+
' },',
|
|
47
|
+
' started: app => resolve(app.handler),',
|
|
48
|
+
' failed: reject,',
|
|
49
|
+
' };',
|
|
50
|
+
'});',
|
|
51
|
+
'',
|
|
52
|
+
"await import('./index.mjs');",
|
|
53
|
+
'// A module that fails to load fails the worker at startup, so wrangler dev and wrangler deploy report it.',
|
|
54
|
+
'await Promise.race([loaded, application]);',
|
|
55
|
+
'',
|
|
56
|
+
'export default httpServerHandler(server);',
|
|
57
|
+
'',
|
|
58
|
+
].join('\n');
|
|
59
|
+
|
|
60
|
+
export function output(context: PresetOutputContext): void {
|
|
61
|
+
const { manifest, outDir, root } = context;
|
|
62
|
+
if (manifest.server) {
|
|
63
|
+
context.write(WranglerConfig.MAIN, WORKER);
|
|
64
|
+
}
|
|
65
|
+
const { config, warnings } = new WranglerConfig(root).generate(manifest, outDir, packageName(root));
|
|
66
|
+
for (const warning of warnings) {
|
|
67
|
+
context.warn(warning);
|
|
68
|
+
}
|
|
69
|
+
context.write(WranglerConfig.OUTPUT_FILE, `${JSON.stringify(config, null, 2)}\n`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** `wrangler dev` on the output: the worker runs in workerd, the runtime of Cloudflare, on this machine. */
|
|
73
|
+
export function preview({ root, outDir, port, env }: PresetPreviewContext): PreviewProcess {
|
|
74
|
+
const args = ['dev', '--config', join(outDir, WranglerConfig.OUTPUT_FILE), ...(port === undefined ? [] : ['--port', String(port)])];
|
|
75
|
+
const { command, args: commandArgs } = new Wrangler(root, env).command(args);
|
|
76
|
+
return { command, args: commandArgs };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function packageName(root: string): string | undefined {
|
|
80
|
+
const file = join(root, 'package.json');
|
|
81
|
+
return existsSync(file) ? (JSON.parse(readFileSync(file, 'utf8')) as { name?: string }).name : undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const cloudflarePreset = definePreset({
|
|
86
|
+
name: 'cloudflare',
|
|
87
|
+
description: 'Cloudflare Workers; the frontend is served as static assets',
|
|
88
|
+
entry: 'http',
|
|
89
|
+
format: 'esm',
|
|
90
|
+
runtime: 'workerd',
|
|
91
|
+
staticHosting: true,
|
|
92
|
+
// Workers Builds (Cloudflare's CI) sets WORKERS_CI=1.
|
|
93
|
+
detect: env => env.WORKERS_CI === '1',
|
|
94
|
+
output: context => CloudflarePreset.output(context),
|
|
95
|
+
preview: context => CloudflarePreset.preview(context),
|
|
96
|
+
deployer: 'cloudflare',
|
|
97
|
+
});
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { basename, join, relative, resolve } from 'node:path';
|
|
3
|
+
import { CellError, type OutputManifest } from '@celljs/kit';
|
|
4
|
+
import { ConfigUtil } from '@celljs/vite';
|
|
5
|
+
import { JsonUtil } from '../../utils/json-util.js';
|
|
6
|
+
|
|
7
|
+
export type WranglerJson = Record<string, unknown>;
|
|
8
|
+
|
|
9
|
+
export interface GeneratedWranglerConfig {
|
|
10
|
+
config: WranglerJson;
|
|
11
|
+
/** The project's configuration file the output is based on. */
|
|
12
|
+
source?: string;
|
|
13
|
+
warnings: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The Wrangler configuration of the output (`<outDir>/wrangler.json`). Cloudflare settings (name,
|
|
18
|
+
* bindings, vars, routes, compatibility date) stay where Cloudflare documents them, in the project's
|
|
19
|
+
* `wrangler.json` or `wrangler.jsonc`; Cell adds what the build decides: the worker entry, the
|
|
20
|
+
* frontend as static assets and Node.js compatibility.
|
|
21
|
+
*/
|
|
22
|
+
export class WranglerConfig {
|
|
23
|
+
/** Project files, in Wrangler's order of precedence. */
|
|
24
|
+
static readonly FILES = ['wrangler.json', 'wrangler.jsonc', 'wrangler.toml'];
|
|
25
|
+
static readonly OUTPUT_FILE = 'wrangler.json';
|
|
26
|
+
/** The worker module, relative to the output directory. */
|
|
27
|
+
static readonly MAIN = 'server/worker.mjs';
|
|
28
|
+
/**
|
|
29
|
+
* From this date on `nodejs_compat` includes every Node.js module the Cell server needs: the
|
|
30
|
+
* node:http server Express runs on (2025-09-01) and node:tty (2026-03-17, used by `debug`).
|
|
31
|
+
*/
|
|
32
|
+
static readonly MIN_COMPATIBILITY_DATE = '2026-03-17';
|
|
33
|
+
static readonly NODEJS_COMPAT = 'nodejs_compat';
|
|
34
|
+
static readonly DEFAULT_NAME = 'cell-app';
|
|
35
|
+
|
|
36
|
+
constructor(protected readonly root: string) {}
|
|
37
|
+
|
|
38
|
+
/** The project's Wrangler configuration file, if it has one. */
|
|
39
|
+
get file(): string | undefined {
|
|
40
|
+
return WranglerConfig.FILES.map(name => join(this.root, name)).find(file => existsSync(file));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The project's configuration, `{}` without a file. */
|
|
44
|
+
readProject(): WranglerJson {
|
|
45
|
+
const file = this.file;
|
|
46
|
+
if (!file) {
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
if (file.endsWith('.toml')) {
|
|
50
|
+
throw new CellError({
|
|
51
|
+
code: 'CELL_CLOUDFLARE_CONFIG_UNSUPPORTED',
|
|
52
|
+
message: 'The cloudflare preset reads wrangler.json or wrangler.jsonc; wrangler.toml is not supported.',
|
|
53
|
+
file,
|
|
54
|
+
hint: 'Rewrite wrangler.toml as wrangler.jsonc (the same keys in JSON syntax) and delete it.',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
let config: unknown;
|
|
58
|
+
try {
|
|
59
|
+
config = JsonUtil.parseJsonc(readFileSync(file, 'utf8'));
|
|
60
|
+
} catch (cause) {
|
|
61
|
+
throw new CellError({
|
|
62
|
+
code: 'CELL_CLOUDFLARE_CONFIG_INVALID',
|
|
63
|
+
message: `${basename(file)} is not valid JSON: ${(cause as Error).message}`,
|
|
64
|
+
file,
|
|
65
|
+
hint: 'Fix the syntax; comments and trailing commas are allowed.',
|
|
66
|
+
cause,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (!ConfigUtil.isPlainObject(config)) {
|
|
70
|
+
throw new CellError({
|
|
71
|
+
code: 'CELL_CLOUDFLARE_CONFIG_INVALID',
|
|
72
|
+
message: `${basename(file)} must contain an object.`,
|
|
73
|
+
file,
|
|
74
|
+
hint: 'Write the configuration as one JSON object, e.g. { "name": "my-app" }.',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return config;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The configuration of a build output whose manifest is `manifest`, written to `outDir`. */
|
|
81
|
+
generate(manifest: OutputManifest, outDir: string, packageName?: string): GeneratedWranglerConfig {
|
|
82
|
+
const project = this.readProject();
|
|
83
|
+
const source = this.file;
|
|
84
|
+
const where = source ? relative(this.root, source) : 'wrangler.json';
|
|
85
|
+
const warnings: string[] = [];
|
|
86
|
+
const { $schema: _schema, main, ...rest } = project;
|
|
87
|
+
if (main !== undefined && manifest.server) {
|
|
88
|
+
warnings.push(`${where}: \`main\` is ignored; the worker is the Cell application (${WranglerConfig.MAIN}).`);
|
|
89
|
+
}
|
|
90
|
+
const config: WranglerJson = {
|
|
91
|
+
name: WranglerConfig.workerName(packageName),
|
|
92
|
+
...rest,
|
|
93
|
+
...(manifest.server ? { main: WranglerConfig.MAIN } : {}),
|
|
94
|
+
compatibility_date: this.compatibilityDate(project.compatibility_date, source),
|
|
95
|
+
compatibility_flags: this.compatibilityFlags(project.compatibility_flags, source),
|
|
96
|
+
};
|
|
97
|
+
const assets = this.assets(project.assets, manifest, outDir, where, warnings);
|
|
98
|
+
if (assets) {
|
|
99
|
+
config.assets = assets;
|
|
100
|
+
}
|
|
101
|
+
return { config, source, warnings };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** A valid worker name from a package name: `@scope/my-app` → `scope-my-app`. */
|
|
105
|
+
static workerName(packageName?: string): string {
|
|
106
|
+
const name = (packageName ?? '')
|
|
107
|
+
.toLowerCase()
|
|
108
|
+
.replace(/[^a-z0-9-]+/g, '-')
|
|
109
|
+
.replace(/-+/g, '-')
|
|
110
|
+
.replace(/^-|-$/g, '')
|
|
111
|
+
.slice(0, 63)
|
|
112
|
+
.replace(/-$/, '');
|
|
113
|
+
return name || WranglerConfig.DEFAULT_NAME;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
protected compatibilityDate(value: unknown, file?: string): string {
|
|
117
|
+
if (value === undefined) {
|
|
118
|
+
return WranglerConfig.MIN_COMPATIBILITY_DATE;
|
|
119
|
+
}
|
|
120
|
+
if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
121
|
+
throw new CellError({
|
|
122
|
+
code: 'CELL_CLOUDFLARE_CONFIG_INVALID',
|
|
123
|
+
message: `compatibility_date must be a date like "${WranglerConfig.MIN_COMPATIBILITY_DATE}", got ${JSON.stringify(value)}.`,
|
|
124
|
+
file,
|
|
125
|
+
hint: `Set "compatibility_date": "${WranglerConfig.MIN_COMPATIBILITY_DATE}" or a later date.`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if (value < WranglerConfig.MIN_COMPATIBILITY_DATE) {
|
|
129
|
+
throw new CellError({
|
|
130
|
+
code: 'CELL_CLOUDFLARE_COMPATIBILITY_DATE',
|
|
131
|
+
message: `compatibility_date ${value} is too old: the Node.js modules the Cell server needs (node:http server, node:tty) are available from ${WranglerConfig.MIN_COMPATIBILITY_DATE}.`,
|
|
132
|
+
file,
|
|
133
|
+
hint: `Set "compatibility_date" to "${WranglerConfig.MIN_COMPATIBILITY_DATE}" or later.`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
protected compatibilityFlags(value: unknown, file?: string): string[] {
|
|
140
|
+
if (value !== undefined && !(Array.isArray(value) && value.every(flag => typeof flag === 'string'))) {
|
|
141
|
+
throw new CellError({
|
|
142
|
+
code: 'CELL_CLOUDFLARE_CONFIG_INVALID',
|
|
143
|
+
message: `compatibility_flags must be an array of strings, got ${JSON.stringify(value)}.`,
|
|
144
|
+
file,
|
|
145
|
+
hint: `Write "compatibility_flags": ["${WranglerConfig.NODEJS_COMPAT}"].`,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
const flags = (value as string[] | undefined) ?? [];
|
|
149
|
+
return flags.includes(WranglerConfig.NODEJS_COMPAT) ? flags : [WranglerConfig.NODEJS_COMPAT, ...flags];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The frontend becomes the static assets of the worker; the project's other asset settings
|
|
154
|
+
* (`binding`, `not_found_handling`, ...) are kept. Cell frontends are single-page applications
|
|
155
|
+
* (`@celljs/serve-static` answers unknown paths with index.html on Node.js), so navigation to a
|
|
156
|
+
* path that is not a file gets index.html from Cloudflare unless the project sets
|
|
157
|
+
* `not_found_handling`; other requests, such as API calls, still reach the worker. Without a frontend, the project's own asset
|
|
158
|
+
* directory is kept, relative to the output directory now.
|
|
159
|
+
*/
|
|
160
|
+
protected assets(value: unknown, manifest: OutputManifest, outDir: string, where: string, warnings: string[]): WranglerJson | undefined {
|
|
161
|
+
const assets = ConfigUtil.isPlainObject(value) ? (value as WranglerJson) : undefined;
|
|
162
|
+
if (manifest.public) {
|
|
163
|
+
if (typeof assets?.directory === 'string') {
|
|
164
|
+
warnings.push(`${where}: \`assets.directory\` is ignored; the assets are the Cell frontend (${manifest.public}).`);
|
|
165
|
+
}
|
|
166
|
+
return { not_found_handling: 'single-page-application', ...assets, directory: manifest.public };
|
|
167
|
+
}
|
|
168
|
+
if (typeof assets?.directory === 'string') {
|
|
169
|
+
return { ...assets, directory: relative(outDir, resolve(this.root, assets.directory)) || '.' };
|
|
170
|
+
}
|
|
171
|
+
return assets;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
5
|
+
|
|
6
|
+
/** How to start Wrangler, and whether it is the project's own. */
|
|
7
|
+
export interface WranglerCommand {
|
|
8
|
+
command: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
/** `project`: installed in the project; `npx`: {@link Wrangler.PACKAGE}, downloaded once by npm and cached. */
|
|
11
|
+
source: 'project' | 'npx';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface WranglerResult {
|
|
15
|
+
code: number;
|
|
16
|
+
/** stdout and stderr together, without terminal colours. */
|
|
17
|
+
output: string;
|
|
18
|
+
source: WranglerCommand['source'];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Runs Wrangler, Cloudflare's CLI, which bundles, previews and uploads workers and owns the
|
|
23
|
+
* Cloudflare credentials (`CLOUDFLARE_API_TOKEN` or `wrangler login`). It is not a dependency of
|
|
24
|
+
* Cell: the project's wrangler is used when it has one, otherwise npx installs it on first use.
|
|
25
|
+
*/
|
|
26
|
+
export class Wrangler {
|
|
27
|
+
static readonly PACKAGE = 'wrangler@4';
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
protected readonly root: string,
|
|
31
|
+
protected readonly env: NodeJS.ProcessEnv = process.env,
|
|
32
|
+
) {}
|
|
33
|
+
|
|
34
|
+
/** Node.js, also when the CLI itself runs on Bun (Wrangler supports Node.js only). */
|
|
35
|
+
static get node(): string {
|
|
36
|
+
return process.execPath.includes('bun') ? 'node' : process.execPath;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
command(args: string[]): WranglerCommand {
|
|
40
|
+
const bin = this.projectBin();
|
|
41
|
+
if (bin) {
|
|
42
|
+
return { command: Wrangler.node, args: [bin, ...args], source: 'project' };
|
|
43
|
+
}
|
|
44
|
+
return { command: process.platform === 'win32' ? 'npx.cmd' : 'npx', args: ['--yes', Wrangler.PACKAGE, ...args], source: 'npx' };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The wrangler executable installed for the project, looked up like Node.js resolves packages. */
|
|
48
|
+
projectBin(): string | undefined {
|
|
49
|
+
for (let dir = this.root; ; dir = dirname(dir)) {
|
|
50
|
+
const manifest = join(dir, 'node_modules', 'wrangler', 'package.json');
|
|
51
|
+
if (existsSync(manifest)) {
|
|
52
|
+
const { bin } = JSON.parse(readFileSync(manifest, 'utf8')) as { bin?: string | Record<string, string> };
|
|
53
|
+
const path = typeof bin === 'string' ? bin : bin?.wrangler;
|
|
54
|
+
return path ? join(dirname(manifest), path) : undefined;
|
|
55
|
+
}
|
|
56
|
+
if (dirname(dir) === dir) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Runs Wrangler in the project root without standard input; `relay` receives its output as it comes. */
|
|
63
|
+
run(args: string[], relay: (chunk: string, stream: 'stdout' | 'stderr') => void): Promise<WranglerResult> {
|
|
64
|
+
const { command, args: commandArgs, source } = this.command(args);
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
let output = '';
|
|
67
|
+
const child = spawn(command, commandArgs, { cwd: this.root, env: this.env, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
68
|
+
for (const stream of ['stdout', 'stderr'] as const) {
|
|
69
|
+
child[stream].setEncoding('utf8');
|
|
70
|
+
child[stream].on('data', (chunk: string) => {
|
|
71
|
+
output += chunk;
|
|
72
|
+
relay(chunk, stream);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
child.on('error', reject);
|
|
76
|
+
child.on('close', code => resolve({ code: code ?? 1, output: stripVTControlCharacters(output), source }));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The first error Wrangler reported (`✘ [ERROR] ...` and its indented continuation, e.g. a link), else its last line of output. */
|
|
81
|
+
static errorOf(output: string): string {
|
|
82
|
+
const lines = output.split('\n');
|
|
83
|
+
const start = lines.findIndex(line => line.trim().startsWith('✘ [ERROR]'));
|
|
84
|
+
if (start < 0) {
|
|
85
|
+
return (
|
|
86
|
+
lines
|
|
87
|
+
.map(line => line.trim())
|
|
88
|
+
.filter(Boolean)
|
|
89
|
+
.pop() ?? 'Wrangler failed without output.'
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
const message = [lines[start].trim().replace(/^✘ \[ERROR\]\s*/, '')];
|
|
93
|
+
for (const line of lines.slice(start + 1)) {
|
|
94
|
+
if (line.trim() && !/^\s/.test(line)) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
if (line.trim()) {
|
|
98
|
+
message.push(line.trim());
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return message.join(' ');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Whether the account has no workers.dev subdomain yet, so a worker without `routes` has nowhere to go. */
|
|
105
|
+
static isSubdomainError(output: string): boolean {
|
|
106
|
+
return /register a workers\.dev subdomain/i.test(output);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Whether the failure is about missing or wrong Cloudflare credentials. */
|
|
110
|
+
static isAuthError(output: string): boolean {
|
|
111
|
+
return /CLOUDFLARE_API_TOKEN|wrangler login|not authenticated|Authentication error|Invalid access token|\[code: 10000\]|\[code: 9109\]/i.test(output);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { CellError, type DeployContext, type Deployment, type DeployPlan, type DeployResource, defineDeployer } from '@celljs/kit';
|
|
2
|
+
import { CloudApi, CloudApiError, CloudCredentials, type CloudIo, CloudNames, DEFAULT_IO } from '../../deploy/cloud-api.js';
|
|
3
|
+
import { CodePackage } from '../../deploy/code-package.js';
|
|
4
|
+
import { RequestSigner } from '../../deploy/request-signer.js';
|
|
5
|
+
import { FcPreset } from './fc-preset.js';
|
|
6
|
+
|
|
7
|
+
type Credentials = NonNullable<ReturnType<typeof CloudCredentials.alibaba>>;
|
|
8
|
+
|
|
9
|
+
/** The calls of the Function Compute 3.0 API (2023-03-30, ROA) that the deployer makes. */
|
|
10
|
+
export class FcClient {
|
|
11
|
+
static readonly VERSION = '2023-03-30';
|
|
12
|
+
readonly host: string;
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
readonly region: string,
|
|
16
|
+
protected readonly credentials: Credentials,
|
|
17
|
+
protected readonly io: CloudIo = DEFAULT_IO,
|
|
18
|
+
) {
|
|
19
|
+
this.host = `fcv3.${region}.aliyuncs.com`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async call<T = Record<string, any>>(action: string, method: string, path: string, body?: unknown): Promise<T> {
|
|
23
|
+
const text = body === undefined ? '' : JSON.stringify(body);
|
|
24
|
+
const headers = RequestSigner.acs3(
|
|
25
|
+
{ method, host: this.host, path, action, version: FcClient.VERSION, body: text, headers: text ? { 'content-type': 'application/json' } : {} },
|
|
26
|
+
this.credentials,
|
|
27
|
+
this.io.now(),
|
|
28
|
+
);
|
|
29
|
+
const response = await CloudApi.send(this.io, `https://${this.host}${path}`, { method, headers, body: text || undefined }, 'Alibaba Cloud FC');
|
|
30
|
+
const raw = await response.text();
|
|
31
|
+
const json = raw ? (JSON.parse(raw) as Record<string, any>) : {};
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
throw new CloudApiError(
|
|
34
|
+
response.status,
|
|
35
|
+
json.Code ?? json.code ?? String(response.status),
|
|
36
|
+
json.Message ?? json.message ?? raw,
|
|
37
|
+
json.RequestId ?? json.requestId,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return json as T;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The function, or undefined when there is none of that name. */
|
|
44
|
+
async getFunction(name: string): Promise<Record<string, any> | undefined> {
|
|
45
|
+
return this.orUndefined(() => this.call('GetFunction', 'GET', `/${FcClient.VERSION}/functions/${name}`));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async getTrigger(name: string, trigger: string): Promise<Record<string, any> | undefined> {
|
|
49
|
+
return this.orUndefined(() => this.call('GetTrigger', 'GET', `/${FcClient.VERSION}/functions/${name}/triggers/${trigger}`));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected async orUndefined<T>(call: () => Promise<T>): Promise<T | undefined> {
|
|
53
|
+
try {
|
|
54
|
+
return await call();
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (error instanceof CloudApiError && error.status === 404) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Deploys the output of the fc preset with the Function Compute 3.0 API: the output directory as
|
|
66
|
+
* the code of a custom runtime function, and an anonymous HTTP trigger. Credentials:
|
|
67
|
+
* ALIBABA_CLOUD_ACCESS_KEY_ID / ALIBABA_CLOUD_ACCESS_KEY_SECRET (/ ALIBABA_CLOUD_SECURITY_TOKEN).
|
|
68
|
+
*/
|
|
69
|
+
export class FcDeployment {
|
|
70
|
+
static readonly TRIGGER = 'http';
|
|
71
|
+
/** Code of a direct upload, base64 in the request body. */
|
|
72
|
+
static readonly MAX_PACKAGE = 100 * 1024 * 1024;
|
|
73
|
+
static readonly CREDENTIALS = 'ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET';
|
|
74
|
+
|
|
75
|
+
readonly name: string;
|
|
76
|
+
readonly region: string;
|
|
77
|
+
protected readonly credentials?: Credentials;
|
|
78
|
+
|
|
79
|
+
constructor(
|
|
80
|
+
protected readonly context: DeployContext,
|
|
81
|
+
protected readonly io: CloudIo = DEFAULT_IO,
|
|
82
|
+
) {
|
|
83
|
+
const { options, env, root } = context;
|
|
84
|
+
this.name = CloudNames.functionName(root, options.name, 64);
|
|
85
|
+
this.region = (options.region as string | undefined) ?? env.ALIBABA_CLOUD_REGION_ID ?? 'cn-hangzhou';
|
|
86
|
+
this.credentials = CloudCredentials.alibaba(env);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Memory in MB and vCPUs: FC wants memory (GB) between 1 and 4 times the vCPUs, cpu in steps of 0.05. */
|
|
90
|
+
get resources(): { memorySize: number; cpu: number; timeout: number; instanceConcurrency: number } {
|
|
91
|
+
const { options } = this.context;
|
|
92
|
+
const memorySize = Math.ceil(((options.memory as number | undefined) ?? 1024) / 64) * 64;
|
|
93
|
+
const cpu = (options.cpu as number | undefined) ?? Math.max(0.05, Math.round(memorySize / 2048 / 0.05) * 0.05);
|
|
94
|
+
return {
|
|
95
|
+
memorySize,
|
|
96
|
+
cpu: Number(cpu.toFixed(2)),
|
|
97
|
+
timeout: (options.timeout as number | undefined) ?? 60,
|
|
98
|
+
instanceConcurrency: (options.concurrency as number | undefined) ?? 20,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
functionConfig(code: CodePackage): Record<string, unknown> {
|
|
103
|
+
return {
|
|
104
|
+
description: 'Deployed by Cell (cell deploy --preset fc)',
|
|
105
|
+
runtime: FcPreset.RUNTIME,
|
|
106
|
+
handler: 'index.handler',
|
|
107
|
+
code: { zipFile: code.base64 },
|
|
108
|
+
customRuntimeConfig: { command: [`/code/${FcPreset.BOOTSTRAP}`], port: FcPreset.PORT },
|
|
109
|
+
...this.resources,
|
|
110
|
+
diskSize: 512,
|
|
111
|
+
internetAccess: true,
|
|
112
|
+
environmentVariables: { NODE_ENV: 'production', ...((this.context.options.env as Record<string, string> | undefined) ?? {}) },
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async plan(): Promise<DeployPlan> {
|
|
117
|
+
this.checkOutput();
|
|
118
|
+
const code = CodePackage.of(this.context.outDir);
|
|
119
|
+
let exists: { fn?: boolean; trigger?: boolean } = {};
|
|
120
|
+
if (this.credentials) {
|
|
121
|
+
const client = new FcClient(this.region, this.credentials, this.io);
|
|
122
|
+
const fn = await this.step('GetFunction', () => client.getFunction(this.name));
|
|
123
|
+
exists = { fn: Boolean(fn), trigger: Boolean(fn && (await this.step('GetTrigger', () => client.getTrigger(this.name, FcDeployment.TRIGGER)))) };
|
|
124
|
+
} else {
|
|
125
|
+
this.context.warn(`No Alibaba Cloud credentials (${FcDeployment.CREDENTIALS}): the plan does not say whether the function exists.`);
|
|
126
|
+
}
|
|
127
|
+
const action = (found?: boolean): DeployResource['action'] => (found === undefined ? 'deploy' : found ? 'update' : 'create');
|
|
128
|
+
return {
|
|
129
|
+
deployer: 'fc',
|
|
130
|
+
resources: [
|
|
131
|
+
{
|
|
132
|
+
type: 'function',
|
|
133
|
+
name: this.name,
|
|
134
|
+
action: action(exists.fn),
|
|
135
|
+
details: {
|
|
136
|
+
region: this.region,
|
|
137
|
+
runtime: `${FcPreset.RUNTIME} (Node.js ${this.context.options.node ?? '20'})`,
|
|
138
|
+
...this.resources,
|
|
139
|
+
package: code.describe(),
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
// An existing trigger is kept as it is (its settings may have been changed in the console).
|
|
143
|
+
...(exists.trigger
|
|
144
|
+
? []
|
|
145
|
+
: [
|
|
146
|
+
{
|
|
147
|
+
type: 'http-trigger',
|
|
148
|
+
name: FcDeployment.TRIGGER,
|
|
149
|
+
action: action(exists.trigger),
|
|
150
|
+
details: { authType: 'anonymous' },
|
|
151
|
+
} satisfies DeployResource,
|
|
152
|
+
]),
|
|
153
|
+
],
|
|
154
|
+
details: {
|
|
155
|
+
region: this.region,
|
|
156
|
+
credentials: this.credentials ? 'ALIBABA_CLOUD_ACCESS_KEY_ID' : 'missing',
|
|
157
|
+
note: 'The default fcapp.run URL makes browsers download HTML pages; bind a custom domain to serve web pages.',
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async apply(): Promise<Deployment> {
|
|
163
|
+
this.checkOutput();
|
|
164
|
+
if (!this.credentials) {
|
|
165
|
+
throw CloudCredentials.missing('Alibaba Cloud', FcDeployment.CREDENTIALS, ' (an AccessKey of a RAM user with AliyunFCFullAccess)');
|
|
166
|
+
}
|
|
167
|
+
const client = new FcClient(this.region, this.credentials, this.io);
|
|
168
|
+
const code = CodePackage.of(this.context.outDir);
|
|
169
|
+
code.checkSize(FcDeployment.MAX_PACKAGE, 'Function Compute', 'Keep large packages out of the server bundle (build.external) and the output directory.');
|
|
170
|
+
const config = this.functionConfig(code);
|
|
171
|
+
const path = `/${FcClient.VERSION}/functions/${this.name}`;
|
|
172
|
+
if (await this.step('GetFunction', () => client.getFunction(this.name))) {
|
|
173
|
+
this.context.info(`Updating function ${this.name} in ${this.region} (${code.describe()})…`);
|
|
174
|
+
await this.step('UpdateFunction', () => client.call('UpdateFunction', 'PUT', path, config));
|
|
175
|
+
} else {
|
|
176
|
+
this.context.info(`Creating function ${this.name} in ${this.region} (${code.describe()})…`);
|
|
177
|
+
await this.step('CreateFunction', () =>
|
|
178
|
+
client.call('CreateFunction', 'POST', `/${FcClient.VERSION}/functions`, { functionName: this.name, ...config }),
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
const fn = await CloudApi.poll(
|
|
182
|
+
this.io,
|
|
183
|
+
() => this.step('GetFunction', async () => (await client.getFunction(this.name)) ?? {}),
|
|
184
|
+
f => f.state !== 'Pending' && f.lastUpdateStatus !== 'InProgress',
|
|
185
|
+
`function ${this.name} to become active`,
|
|
186
|
+
);
|
|
187
|
+
if (fn.state === 'Failed' || fn.lastUpdateStatus === 'Failed') {
|
|
188
|
+
throw new CellError({
|
|
189
|
+
code: 'CELL_DEPLOY_FAILED',
|
|
190
|
+
message: `Function ${this.name} failed to become active: ${fn.stateReason ?? fn.lastUpdateStatusReason ?? 'no reason given'}`,
|
|
191
|
+
hint: 'Look at the function in the Function Compute console; fix the reported problem and deploy again.',
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
let trigger = await this.step('GetTrigger', () => client.getTrigger(this.name, FcDeployment.TRIGGER));
|
|
195
|
+
if (!trigger) {
|
|
196
|
+
this.context.info(`Creating HTTP trigger ${FcDeployment.TRIGGER}…`);
|
|
197
|
+
trigger = await this.step('CreateTrigger', () =>
|
|
198
|
+
client.call('CreateTrigger', 'POST', `${path}/triggers`, {
|
|
199
|
+
triggerName: FcDeployment.TRIGGER,
|
|
200
|
+
triggerType: 'http',
|
|
201
|
+
qualifier: 'LATEST',
|
|
202
|
+
triggerConfig: JSON.stringify({
|
|
203
|
+
authType: 'anonymous',
|
|
204
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],
|
|
205
|
+
disableURLInternet: false,
|
|
206
|
+
}),
|
|
207
|
+
}),
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
return { url: trigger?.httpTrigger?.urlInternet, details: { region: this.region, function: this.name } };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
protected checkOutput(): void {
|
|
214
|
+
if (this.context.manifest.preset !== 'fc') {
|
|
215
|
+
throw new CellError({
|
|
216
|
+
code: 'CELL_DEPLOY_OUTPUT_MISMATCH',
|
|
217
|
+
message: `${this.context.outDir} has no output of the fc preset (built with: ${this.context.manifest.preset ?? 'no preset'}).`,
|
|
218
|
+
hint: 'Run cell deploy --preset fc without --skip-build, or cell build --preset fc first.',
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
protected async step<T>(name: string, call: () => Promise<T>): Promise<T> {
|
|
224
|
+
try {
|
|
225
|
+
return await call();
|
|
226
|
+
} catch (error) {
|
|
227
|
+
throw error instanceof CloudApiError ? CloudApi.failure('Function Compute', name, error) : error;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export const fcDeployer = defineDeployer({
|
|
233
|
+
name: 'fc',
|
|
234
|
+
description: 'Alibaba Cloud Function Compute 3.0 through its API (ALIBABA_CLOUD_ACCESS_KEY_ID / _SECRET)',
|
|
235
|
+
plan: context => new FcDeployment(context).plan(),
|
|
236
|
+
apply: context => new FcDeployment(context).apply(),
|
|
237
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { definePreset, type PresetOutputContext } from '@celljs/kit';
|
|
2
|
+
import { PresetOptionsSchema } from '../../deploy/cloud-api.js';
|
|
3
|
+
import { ServerlessScripts } from '../serverless-scripts.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Alibaba Cloud Function Compute 3.0, custom runtime: `bootstrap` starts the Cell server with the
|
|
7
|
+
* Node.js of the image on port 9000, and an HTTP trigger sends requests to it. The frontend, if
|
|
8
|
+
* any, is served by the server from `public/` like on Node.js.
|
|
9
|
+
*/
|
|
10
|
+
export namespace FcPreset {
|
|
11
|
+
export const BOOTSTRAP = 'bootstrap';
|
|
12
|
+
export const RUNTIME = 'custom.debian10';
|
|
13
|
+
export const PORT = 9000;
|
|
14
|
+
/** Node.js versions built into the custom.debian10 runtime. */
|
|
15
|
+
export const NODE = { '20': '/var/fc/lang/nodejs20/bin/node', '18': '/var/fc/lang/nodejs18/bin/node' } as const;
|
|
16
|
+
|
|
17
|
+
export const OPTIONS = PresetOptionsSchema.of({
|
|
18
|
+
name: 'string',
|
|
19
|
+
region: 'string',
|
|
20
|
+
node: ['20', '18'],
|
|
21
|
+
memory: 'number',
|
|
22
|
+
cpu: 'number',
|
|
23
|
+
timeout: 'number',
|
|
24
|
+
concurrency: 'number',
|
|
25
|
+
env: 'env',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export function output(context: PresetOutputContext): void {
|
|
29
|
+
const { manifest, options } = context;
|
|
30
|
+
if (!manifest.server) {
|
|
31
|
+
context.warn('The fc preset deploys a server, but the project builds no backend.');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const node = NODE[(options.node as keyof typeof NODE | undefined) ?? '20'];
|
|
35
|
+
context.write(
|
|
36
|
+
BOOTSTRAP,
|
|
37
|
+
ServerlessScripts.bootstrap({ preset: 'fc', node, port: PORT, portVariable: 'FC_SERVER_PORT', server: manifest.server }),
|
|
38
|
+
0o755,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const fcPreset = definePreset({
|
|
44
|
+
name: 'fc',
|
|
45
|
+
description: 'Alibaba Cloud Function Compute 3.0 (custom runtime, HTTP trigger)',
|
|
46
|
+
entry: 'http',
|
|
47
|
+
format: 'esm',
|
|
48
|
+
options: FcPreset.OPTIONS,
|
|
49
|
+
output: context => FcPreset.output(context),
|
|
50
|
+
deployer: 'fc',
|
|
51
|
+
});
|