dotdo 0.0.2 → 0.1.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.
Files changed (313) hide show
  1. package/cli/README.md +238 -0
  2. package/cli/agent.ts +72 -0
  3. package/cli/bin.js +44 -0
  4. package/cli/bin.ts +38 -0
  5. package/cli/build.ts +157 -0
  6. package/cli/commands/auth/login.ts +14 -0
  7. package/cli/commands/auth/logout.ts +6 -0
  8. package/cli/commands/auth/whoami.ts +16 -0
  9. package/cli/commands/deploy-multi.ts +245 -0
  10. package/cli/commands/dev/deploy.ts +100 -0
  11. package/cli/commands/dev/dev.ts +95 -0
  12. package/cli/commands/dev/logs.ts +91 -0
  13. package/cli/commands/dev-local.ts +88 -0
  14. package/cli/commands/do-ops.ts +314 -0
  15. package/cli/commands/index.ts +100 -0
  16. package/cli/commands/init.ts +247 -0
  17. package/cli/commands/introspect/emitter.ts +315 -0
  18. package/cli/commands/introspect/index.ts +193 -0
  19. package/cli/commands/link.ts +598 -0
  20. package/cli/commands/snippets.ts +415 -0
  21. package/cli/commands/tunnel.ts +239 -0
  22. package/cli/device-auth.ts +289 -0
  23. package/cli/fallback.ts +12 -0
  24. package/cli/index.ts +121 -0
  25. package/cli/main.ts +246 -0
  26. package/cli/mcp-stdio.ts +790 -0
  27. package/cli/package.json +62 -0
  28. package/cli/runtime/do-registry.ts +193 -0
  29. package/cli/runtime/embedded-db.ts +344 -0
  30. package/cli/runtime/index.ts +9 -0
  31. package/cli/runtime/miniflare-adapter.ts +162 -0
  32. package/cli/sandbox.ts +82 -0
  33. package/cli/src/args.ts +174 -0
  34. package/cli/src/auth.ts +55 -0
  35. package/cli/src/commands/call.ts +84 -0
  36. package/cli/src/commands/charge.ts +96 -0
  37. package/cli/src/commands/config.ts +115 -0
  38. package/cli/src/commands/email.ts +112 -0
  39. package/cli/src/commands/llm.ts +115 -0
  40. package/cli/src/commands/queue.ts +134 -0
  41. package/cli/src/commands/text.ts +86 -0
  42. package/cli/src/config.ts +185 -0
  43. package/cli/src/output.ts +246 -0
  44. package/cli/src/rpc.ts +192 -0
  45. package/cli/utils/config.ts +282 -0
  46. package/cli/utils/detect.ts +73 -0
  47. package/cli/utils/index.ts +15 -0
  48. package/cli/utils/logger.ts +232 -0
  49. package/dist/ai/template-literals.js +2 -2
  50. package/dist/ai/template-literals.js.map +1 -1
  51. package/dist/api/middleware/auth.js +3 -2
  52. package/dist/api/middleware/auth.js.map +1 -1
  53. package/dist/db/iceberg/inverted-index.js +1 -1
  54. package/dist/db/iceberg/inverted-index.js.map +1 -1
  55. package/dist/db/iceberg/puffin.js.map +1 -1
  56. package/dist/db/json-indexes.js.map +1 -1
  57. package/dist/db/objects.js.map +1 -1
  58. package/dist/db/primitives/dag-scheduler/index.js +1 -1
  59. package/dist/db/primitives/dag-scheduler/index.js.map +1 -1
  60. package/dist/db/primitives/observability.js.map +1 -1
  61. package/dist/db/primitives/schema-evolution.js.map +1 -1
  62. package/dist/db/primitives/temporal-store.js.map +1 -1
  63. package/dist/db/primitives/typed-column-store.js.map +1 -1
  64. package/dist/db/primitives/utils/duration.js.map +1 -1
  65. package/dist/db/primitives/utils/murmur3.js +12 -14
  66. package/dist/db/primitives/utils/murmur3.js.map +1 -1
  67. package/dist/db/primitives/window-manager.js.map +1 -1
  68. package/dist/db/stores.js.map +1 -1
  69. package/dist/db/things.js.map +1 -1
  70. package/dist/lib/DODispatcher.js +2 -2
  71. package/dist/lib/DODispatcher.js.map +1 -1
  72. package/dist/lib/auto-wiring.js.map +1 -1
  73. package/dist/lib/channels/email.js +1 -1
  74. package/dist/lib/channels/email.js.map +1 -1
  75. package/dist/lib/channels/slack-blockkit.js.map +1 -1
  76. package/dist/lib/cloudflare/ai.js +1 -1
  77. package/dist/lib/cloudflare/ai.js.map +1 -1
  78. package/dist/lib/cloudflare/kv.js +1 -1
  79. package/dist/lib/cloudflare/kv.js.map +1 -1
  80. package/dist/lib/cloudflare/r2.js +3 -3
  81. package/dist/lib/cloudflare/r2.js.map +1 -1
  82. package/dist/lib/cloudflare/vectorize.js.map +1 -1
  83. package/dist/lib/cloudflare/workflows.js.map +1 -1
  84. package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -1
  85. package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -1
  86. package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -1
  87. package/dist/lib/executors/HumanFunctionExecutor.js +1 -1
  88. package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -1
  89. package/dist/lib/executors/ParallelStepExecutor.js.map +1 -1
  90. package/dist/lib/experiments.js.map +1 -1
  91. package/dist/lib/flags/store.js.map +1 -1
  92. package/dist/lib/functions/FunctionComposition.js.map +1 -1
  93. package/dist/lib/functions/FunctionMiddleware.js.map +1 -1
  94. package/dist/lib/functions/FunctionRegistry.js.map +1 -1
  95. package/dist/lib/humans/templates.js.map +1 -1
  96. package/dist/lib/identity.js +2 -2
  97. package/dist/lib/identity.js.map +1 -1
  98. package/dist/lib/logging/index.js.map +1 -1
  99. package/dist/lib/mixins/bash.js +1 -73
  100. package/dist/lib/mixins/bash.js.map +1 -1
  101. package/dist/lib/mixins/git.js +0 -5
  102. package/dist/lib/mixins/git.js.map +1 -1
  103. package/dist/lib/mixins/npm.js.map +1 -1
  104. package/dist/lib/noun-id.js.map +1 -1
  105. package/dist/lib/rate-limit/sliding-window.js.map +1 -1
  106. package/dist/lib/rpc/bindings.js.map +1 -1
  107. package/dist/lib/safe-stringify.js.map +1 -1
  108. package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -1
  109. package/dist/lib/sqids.js.map +1 -1
  110. package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -1
  111. package/dist/lib/sql/adapters/pgsql-parser.js +19 -18
  112. package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -1
  113. package/dist/metrics/hunch.js.map +1 -1
  114. package/dist/objects/API.js +1 -1
  115. package/dist/objects/API.js.map +1 -1
  116. package/dist/objects/Agent.js.map +1 -1
  117. package/dist/objects/Browser.js.map +1 -1
  118. package/dist/objects/CLI.js.map +1 -1
  119. package/dist/objects/DOBase.js.map +1 -1
  120. package/dist/objects/DOCache.js +153 -0
  121. package/dist/objects/DOCache.js.map +1 -0
  122. package/dist/objects/DOFull.js.map +1 -1
  123. package/dist/objects/Entity.js.map +1 -1
  124. package/dist/objects/Human.js.map +1 -1
  125. package/dist/objects/IcebergMetadataDO.js.map +1 -1
  126. package/dist/objects/IntegrationsDO.js.map +1 -1
  127. package/dist/objects/ObservabilityBroadcaster.js.map +1 -1
  128. package/dist/objects/Package.js.map +1 -1
  129. package/dist/objects/Product.js +1 -1
  130. package/dist/objects/Product.js.map +1 -1
  131. package/dist/objects/SaaS.js.map +1 -1
  132. package/dist/objects/SandboxDO.js.map +1 -1
  133. package/dist/objects/Service.js.map +1 -1
  134. package/dist/objects/VectorShardDO.js +9 -7
  135. package/dist/objects/VectorShardDO.js.map +1 -1
  136. package/dist/objects/Workflow.js.map +1 -1
  137. package/dist/objects/WorkflowFactory.js.map +1 -1
  138. package/dist/objects/WorkflowRuntime.js.map +1 -1
  139. package/dist/objects/lifecycle/Branch.js.map +1 -1
  140. package/dist/objects/lifecycle/Clone.js +1 -1
  141. package/dist/objects/lifecycle/Clone.js.map +1 -1
  142. package/dist/objects/lifecycle/Compact.js.map +1 -1
  143. package/dist/objects/lifecycle/Shard.js.map +1 -1
  144. package/dist/objects/persistence/checkpoint-manager.js.map +1 -1
  145. package/dist/objects/persistence/migration-runner.js.map +1 -1
  146. package/dist/objects/persistence/replication-manager.js +2 -2
  147. package/dist/objects/persistence/replication-manager.js.map +1 -1
  148. package/dist/objects/persistence/tiered-storage-manager.js.map +1 -1
  149. package/dist/objects/persistence/wal-manager.js.map +1 -1
  150. package/dist/objects/transport/auth-layer.js.map +1 -1
  151. package/dist/objects/transport/chain.js.map +1 -1
  152. package/dist/objects/transport/mcp-server.js +7 -6
  153. package/dist/objects/transport/mcp-server.js.map +1 -1
  154. package/dist/objects/transport/rest-autowire.js +3 -2
  155. package/dist/objects/transport/rest-autowire.js.map +1 -1
  156. package/dist/objects/transport/rest-router.js.map +1 -1
  157. package/dist/objects/transport/rpc-server.js +18 -15
  158. package/dist/objects/transport/rpc-server.js.map +1 -1
  159. package/dist/objects/transport/shared.js +2 -1
  160. package/dist/objects/transport/shared.js.map +1 -1
  161. package/dist/snippets/artifacts-ingest.js.map +1 -1
  162. package/dist/snippets/artifacts-serve.js.map +1 -1
  163. package/dist/snippets/search.js.map +1 -1
  164. package/dist/workflows/ScheduleManager.js.map +1 -1
  165. package/dist/workflows/StepResultStorage.js.map +1 -1
  166. package/dist/workflows/WaitForEventManager.js.map +1 -1
  167. package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -1
  168. package/dist/workflows/compat/inngest/index.js.map +1 -1
  169. package/dist/workflows/compat/qstash/index.js.map +1 -1
  170. package/dist/workflows/compat/temporal/client.js.map +1 -1
  171. package/dist/workflows/compat/temporal/index.js.map +1 -1
  172. package/dist/workflows/compat/trigger/index.js.map +1 -1
  173. package/dist/workflows/compat/utils/index.js.map +1 -1
  174. package/dist/workflows/context/correlation.js +2 -2
  175. package/dist/workflows/context/correlation.js.map +1 -1
  176. package/dist/workflows/context/experiment.js +1 -1
  177. package/dist/workflows/context/experiment.js.map +1 -1
  178. package/dist/workflows/context/flag.js +1 -1
  179. package/dist/workflows/context/flag.js.map +1 -1
  180. package/dist/workflows/context/measure.js +1 -1
  181. package/dist/workflows/context/measure.js.map +1 -1
  182. package/dist/workflows/context/rate-limit.js.map +1 -1
  183. package/dist/workflows/data/entity-events/entity-events.js.map +1 -1
  184. package/dist/workflows/data/experiment/index.js.map +1 -1
  185. package/dist/workflows/data/goal/context.js +1 -1
  186. package/dist/workflows/data/goal/context.js.map +1 -1
  187. package/dist/workflows/data/measure/index.js +1 -1
  188. package/dist/workflows/data/measure/index.js.map +1 -1
  189. package/dist/workflows/data/stream/index.js +10 -76
  190. package/dist/workflows/data/stream/index.js.map +1 -1
  191. package/dist/workflows/data/track/context.js.map +1 -1
  192. package/dist/workflows/data/view/context.js.map +1 -1
  193. package/dist/workflows/domain.js.map +1 -1
  194. package/dist/workflows/flags.js +1 -1
  195. package/dist/workflows/flags.js.map +1 -1
  196. package/dist/workflows/hash.js.map +1 -1
  197. package/dist/workflows/on.js +1 -1
  198. package/dist/workflows/on.js.map +1 -1
  199. package/dist/workflows/schedule-builder.js.map +1 -1
  200. package/dist/workflows/visibility/index.js +0 -2
  201. package/dist/workflows/visibility/index.js.map +1 -1
  202. package/dist/workflows/visibility/query-parser.js.map +1 -1
  203. package/package.json +18 -3
  204. package/dist/api/analytics/router.js +0 -601
  205. package/dist/api/analytics/router.js.map +0 -1
  206. package/dist/api/index.js +0 -158
  207. package/dist/api/index.js.map +0 -1
  208. package/dist/api/middleware/error-handling.js +0 -176
  209. package/dist/api/middleware/error-handling.js.map +0 -1
  210. package/dist/api/middleware/request-id.js +0 -21
  211. package/dist/api/middleware/request-id.js.map +0 -1
  212. package/dist/api/pages.js +0 -1180
  213. package/dist/api/pages.js.map +0 -1
  214. package/dist/api/routes/api.js +0 -612
  215. package/dist/api/routes/api.js.map +0 -1
  216. package/dist/api/routes/browsers.js +0 -471
  217. package/dist/api/routes/browsers.js.map +0 -1
  218. package/dist/api/routes/do.js +0 -188
  219. package/dist/api/routes/do.js.map +0 -1
  220. package/dist/api/routes/mcp.js +0 -459
  221. package/dist/api/routes/mcp.js.map +0 -1
  222. package/dist/api/routes/obs.js +0 -445
  223. package/dist/api/routes/obs.js.map +0 -1
  224. package/dist/api/routes/openapi.js +0 -794
  225. package/dist/api/routes/openapi.js.map +0 -1
  226. package/dist/api/routes/rpc.js +0 -1103
  227. package/dist/api/routes/rpc.js.map +0 -1
  228. package/dist/api/routes/sandboxes.js +0 -389
  229. package/dist/api/routes/sandboxes.js.map +0 -1
  230. package/dist/api/test-do.js +0 -38
  231. package/dist/api/test-do.js.map +0 -1
  232. package/dist/api/types.js +0 -11
  233. package/dist/api/types.js.map +0 -1
  234. package/dist/cli/bin.js +0 -2
  235. package/dist/cli/main.js +0 -52342
  236. package/dist/do/bash.js +0 -35
  237. package/dist/do/bash.js.map +0 -1
  238. package/dist/do/fs.js +0 -25
  239. package/dist/do/fs.js.map +0 -1
  240. package/dist/do/full.js +0 -61
  241. package/dist/do/full.js.map +0 -1
  242. package/dist/do/git.js +0 -28
  243. package/dist/do/git.js.map +0 -1
  244. package/dist/do/index.js +0 -52
  245. package/dist/do/index.js.map +0 -1
  246. package/dist/lib/agent/tools/bash.js +0 -336
  247. package/dist/lib/agent/tools/bash.js.map +0 -1
  248. package/dist/lib/agent/tools/edit.js +0 -157
  249. package/dist/lib/agent/tools/edit.js.map +0 -1
  250. package/dist/lib/agent/tools/glob.js +0 -137
  251. package/dist/lib/agent/tools/glob.js.map +0 -1
  252. package/dist/lib/agent/tools/grep.js +0 -315
  253. package/dist/lib/agent/tools/grep.js.map +0 -1
  254. package/dist/lib/agent/tools/index.js +0 -71
  255. package/dist/lib/agent/tools/index.js.map +0 -1
  256. package/dist/lib/agent/tools/read.js +0 -212
  257. package/dist/lib/agent/tools/read.js.map +0 -1
  258. package/dist/lib/agent/tools/types.js +0 -197
  259. package/dist/lib/agent/tools/types.js.map +0 -1
  260. package/dist/lib/agent/tools/write.js +0 -159
  261. package/dist/lib/agent/tools/write.js.map +0 -1
  262. package/dist/lib/mixins/index.js +0 -29
  263. package/dist/lib/mixins/index.js.map +0 -1
  264. package/dist/primitives/bashx/src/ast/analyze.js +0 -1472
  265. package/dist/primitives/bashx/src/ast/analyze.js.map +0 -1
  266. package/dist/primitives/bashx/src/ast/parser.js +0 -1488
  267. package/dist/primitives/bashx/src/ast/parser.js.map +0 -1
  268. package/dist/primitives/bashx/src/do/commands/crypto.js +0 -1954
  269. package/dist/primitives/bashx/src/do/commands/crypto.js.map +0 -1
  270. package/dist/primitives/bashx/src/do/commands/data-processing.js +0 -1812
  271. package/dist/primitives/bashx/src/do/commands/data-processing.js.map +0 -1
  272. package/dist/primitives/bashx/src/do/commands/extended-utils.js +0 -804
  273. package/dist/primitives/bashx/src/do/commands/extended-utils.js.map +0 -1
  274. package/dist/primitives/bashx/src/do/commands/math-control.js +0 -1122
  275. package/dist/primitives/bashx/src/do/commands/math-control.js.map +0 -1
  276. package/dist/primitives/bashx/src/do/commands/posix-utils.js +0 -1015
  277. package/dist/primitives/bashx/src/do/commands/posix-utils.js.map +0 -1
  278. package/dist/primitives/bashx/src/do/commands/system-utils.js +0 -687
  279. package/dist/primitives/bashx/src/do/commands/system-utils.js.map +0 -1
  280. package/dist/primitives/bashx/src/do/commands/test-command.js +0 -523
  281. package/dist/primitives/bashx/src/do/commands/test-command.js.map +0 -1
  282. package/dist/primitives/bashx/src/do/commands/text-processing.js +0 -1550
  283. package/dist/primitives/bashx/src/do/commands/text-processing.js.map +0 -1
  284. package/dist/primitives/bashx/src/do/container-executor.js +0 -429
  285. package/dist/primitives/bashx/src/do/container-executor.js.map +0 -1
  286. package/dist/primitives/bashx/src/do/index.js +0 -668
  287. package/dist/primitives/bashx/src/do/index.js.map +0 -1
  288. package/dist/primitives/bashx/src/do/tiered-executor.js +0 -2647
  289. package/dist/primitives/bashx/src/do/tiered-executor.js.map +0 -1
  290. package/dist/primitives/bashx/src/do/worker.js +0 -352
  291. package/dist/primitives/bashx/src/do/worker.js.map +0 -1
  292. package/dist/primitives/bashx/src/types.js +0 -10
  293. package/dist/primitives/bashx/src/types.js.map +0 -1
  294. package/dist/primitives/fsx/core/backend.js +0 -480
  295. package/dist/primitives/fsx/core/backend.js.map +0 -1
  296. package/dist/primitives/fsx/core/constants.js +0 -140
  297. package/dist/primitives/fsx/core/constants.js.map +0 -1
  298. package/dist/primitives/fsx/core/fsx.js +0 -1184
  299. package/dist/primitives/fsx/core/fsx.js.map +0 -1
  300. package/dist/primitives/fsx/core/glob/glob.js +0 -438
  301. package/dist/primitives/fsx/core/glob/glob.js.map +0 -1
  302. package/dist/primitives/fsx/core/glob/index.js +0 -8
  303. package/dist/primitives/fsx/core/glob/index.js.map +0 -1
  304. package/dist/primitives/fsx/core/glob/match.js +0 -392
  305. package/dist/primitives/fsx/core/glob/match.js.map +0 -1
  306. package/dist/primitives/fsx/core/types.js +0 -307
  307. package/dist/primitives/fsx/core/types.js.map +0 -1
  308. package/dist/sdk/capnweb-compat.js +0 -42
  309. package/dist/sdk/capnweb-compat.js.map +0 -1
  310. package/dist/sdk/client.js +0 -20
  311. package/dist/sdk/client.js.map +0 -1
  312. package/dist/sdk/index.js +0 -17
  313. package/dist/sdk/index.js.map +0 -1
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Deploy Command
3
+ *
4
+ * Deploys to multiple targets:
5
+ * - Cloudflare Workers (default)
6
+ * - Vercel Edge Functions
7
+ * - Fly.io
8
+ */
9
+
10
+ import { Command } from 'commander'
11
+ import { createLogger } from '../utils/logger'
12
+ import { loadConfigAsync, findProjectRoot } from '../utils/config'
13
+ import { spawn } from 'child_process'
14
+ import * as fs from 'fs'
15
+ import * as path from 'path'
16
+
17
+ const logger = createLogger('deploy')
18
+
19
+ type DeployTarget = 'cloudflare' | 'vercel' | 'fly'
20
+
21
+ interface DeployResult {
22
+ success: boolean
23
+ url?: string
24
+ error?: string
25
+ }
26
+
27
+ /**
28
+ * Deploy to Cloudflare Workers
29
+ */
30
+ async function deployCloudflare(): Promise<DeployResult> {
31
+ logger.info('Deploying to Cloudflare Workers...')
32
+
33
+ return new Promise((resolve) => {
34
+ const proc = spawn('bunx', ['wrangler', 'deploy'], {
35
+ stdio: 'inherit',
36
+ env: process.env,
37
+ })
38
+
39
+ proc.on('exit', (code) => {
40
+ if (code === 0) {
41
+ resolve({ success: true })
42
+ } else {
43
+ resolve({ success: false, error: `wrangler exited with code ${code}` })
44
+ }
45
+ })
46
+
47
+ proc.on('error', (error) => {
48
+ resolve({ success: false, error: error.message })
49
+ })
50
+ })
51
+ }
52
+
53
+ /**
54
+ * Generate Vercel configuration
55
+ */
56
+ function generateVercelConfig(projectRoot: string): void {
57
+ const vercelConfig = {
58
+ buildCommand: 'bun run build',
59
+ outputDirectory: 'dist',
60
+ framework: null,
61
+ functions: {
62
+ 'api/**/*.ts': {
63
+ runtime: 'edge',
64
+ },
65
+ },
66
+ }
67
+
68
+ const configPath = path.join(projectRoot, 'vercel.json')
69
+ if (!fs.existsSync(configPath)) {
70
+ fs.writeFileSync(configPath, JSON.stringify(vercelConfig, null, 2))
71
+ logger.info('Created vercel.json')
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Deploy to Vercel
77
+ */
78
+ async function deployVercel(): Promise<DeployResult> {
79
+ logger.info('Deploying to Vercel...')
80
+
81
+ const projectRoot = findProjectRoot()
82
+ generateVercelConfig(projectRoot)
83
+
84
+ return new Promise((resolve) => {
85
+ const proc = spawn('bunx', ['vercel', '--prod'], {
86
+ stdio: 'inherit',
87
+ env: process.env,
88
+ })
89
+
90
+ proc.on('exit', (code) => {
91
+ if (code === 0) {
92
+ resolve({ success: true })
93
+ } else {
94
+ resolve({ success: false, error: `vercel exited with code ${code}` })
95
+ }
96
+ })
97
+
98
+ proc.on('error', (error) => {
99
+ resolve({ success: false, error: error.message })
100
+ })
101
+ })
102
+ }
103
+
104
+ /**
105
+ * Generate Fly.io configuration
106
+ */
107
+ function generateFlyConfig(projectRoot: string, appName: string): void {
108
+ const flyConfig = `
109
+ # fly.toml - Fly.io configuration
110
+ # Generated by dotdo CLI
111
+
112
+ app = "${appName}"
113
+ primary_region = "iad"
114
+
115
+ [build]
116
+ builder = "paketobuildpacks/builder:base"
117
+
118
+ [env]
119
+ NODE_ENV = "production"
120
+
121
+ [http_service]
122
+ internal_port = 8080
123
+ force_https = true
124
+ auto_stop_machines = true
125
+ auto_start_machines = true
126
+ min_machines_running = 0
127
+
128
+ [[vm]]
129
+ cpu_kind = "shared"
130
+ cpus = 1
131
+ memory_mb = 256
132
+ `.trim()
133
+
134
+ const configPath = path.join(projectRoot, 'fly.toml')
135
+ if (!fs.existsSync(configPath)) {
136
+ fs.writeFileSync(configPath, flyConfig)
137
+ logger.info('Created fly.toml')
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Deploy to Fly.io
143
+ */
144
+ async function deployFly(appName?: string): Promise<DeployResult> {
145
+ logger.info('Deploying to Fly.io...')
146
+
147
+ const projectRoot = findProjectRoot()
148
+ const name = appName ?? path.basename(projectRoot)
149
+ generateFlyConfig(projectRoot, name)
150
+
151
+ return new Promise((resolve) => {
152
+ const proc = spawn('flyctl', ['deploy'], {
153
+ stdio: 'inherit',
154
+ env: process.env,
155
+ })
156
+
157
+ proc.on('exit', (code) => {
158
+ if (code === 0) {
159
+ resolve({ success: true })
160
+ } else {
161
+ resolve({ success: false, error: `flyctl exited with code ${code}` })
162
+ }
163
+ })
164
+
165
+ proc.on('error', (error) => {
166
+ resolve({ success: false, error: error.message })
167
+ })
168
+ })
169
+ }
170
+
171
+ export const deployCommand = new Command('deploy')
172
+ .description('Deploy to production')
173
+ .option('-t, --target <target>', 'Deploy target (cloudflare, vercel, fly)', 'cloudflare')
174
+ .option('--all', 'Deploy to all configured targets')
175
+ .option('--dry-run', 'Show what would be deployed')
176
+ .option('-n, --name <name>', 'App name (for fly.io)')
177
+ .action(async (options) => {
178
+ const config = await loadConfigAsync()
179
+
180
+ // Determine targets
181
+ let targets: DeployTarget[] = []
182
+
183
+ if (options.all) {
184
+ // Deploy to all configured targets
185
+ if (config.deploy?.cloudflare !== false) targets.push('cloudflare')
186
+ if (config.deploy?.vercel) targets.push('vercel')
187
+ if (config.deploy?.fly) targets.push('fly')
188
+ } else {
189
+ targets = [options.target as DeployTarget]
190
+ }
191
+
192
+ if (targets.length === 0) {
193
+ targets = ['cloudflare'] // Default
194
+ }
195
+
196
+ logger.info(`Deploying to: ${targets.join(', ')}`)
197
+
198
+ if (options.dryRun) {
199
+ logger.info('Dry run - no actual deployment')
200
+ return
201
+ }
202
+
203
+ const results: Record<DeployTarget, DeployResult> = {} as Record<DeployTarget, DeployResult>
204
+
205
+ for (const target of targets) {
206
+ switch (target) {
207
+ case 'cloudflare':
208
+ results[target] = await deployCloudflare()
209
+ break
210
+ case 'vercel':
211
+ results[target] = await deployVercel()
212
+ break
213
+ case 'fly':
214
+ results[target] = await deployFly(options.name)
215
+ break
216
+ default:
217
+ logger.error(`Unknown target: ${target}`)
218
+ results[target] = { success: false, error: `Unknown target: ${target}` }
219
+ }
220
+ }
221
+
222
+ // Summary
223
+ console.log()
224
+ console.log('Deployment Summary')
225
+ console.log('─'.repeat(40))
226
+
227
+ let allSuccess = true
228
+ for (const [target, result] of Object.entries(results)) {
229
+ if (result.success) {
230
+ logger.success(`${target}: Deployed successfully`)
231
+ if (result.url) {
232
+ console.log(` URL: ${result.url}`)
233
+ }
234
+ } else {
235
+ logger.error(`${target}: Failed - ${result.error}`)
236
+ allSuccess = false
237
+ }
238
+ }
239
+
240
+ if (!allSuccess) {
241
+ process.exit(1)
242
+ }
243
+ })
244
+
245
+ export default deployCommand
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Deploy Command
3
+ *
4
+ * Deploys to Cloudflare Workers using wrangler deploy.
5
+ * Authenticates via oauth.do and passes DO_TOKEN to the spawned process.
6
+ */
7
+
8
+ import { ensureLoggedIn } from 'oauth.do/node'
9
+
10
+ export const name = 'deploy'
11
+ export const description = 'Deploy to Cloudflare Workers'
12
+
13
+ interface SpawnOptions {
14
+ env?: Record<string, string | undefined>
15
+ stdio?: ['inherit' | 'pipe', 'inherit' | 'pipe', 'inherit' | 'pipe'] | 'inherit'
16
+ cwd?: string
17
+ }
18
+
19
+ interface SpawnedProcess {
20
+ pid: number
21
+ exited: Promise<number>
22
+ kill: (signal?: number) => void
23
+ stdout?: ReadableStream<Uint8Array>
24
+ stderr?: ReadableStream<Uint8Array>
25
+ }
26
+
27
+ type SpawnFn = (command: string[], options?: SpawnOptions) => SpawnedProcess
28
+
29
+ interface RunOptions {
30
+ spawn?: SpawnFn
31
+ apiUrl?: string
32
+ }
33
+
34
+ interface RunResult {
35
+ exitCode: number
36
+ success: boolean
37
+ }
38
+
39
+ export async function run(args: string[], options: RunOptions = {}): Promise<RunResult> {
40
+ const spawnFn = options.spawn ?? defaultSpawn
41
+
42
+ // Authenticate first
43
+ let token: string
44
+ try {
45
+ const result = await ensureLoggedIn({
46
+ openBrowser: true,
47
+ print: console.log,
48
+ })
49
+ token = result.token
50
+
51
+ if (result.isNewLogin) {
52
+ console.log('Logged in successfully')
53
+ }
54
+ } catch (error) {
55
+ const message = error instanceof Error ? error.message : String(error)
56
+ console.error('Authentication error:', message)
57
+ throw new Error(`Authentication failed: ${message}`)
58
+ }
59
+
60
+ console.log('Deploying...')
61
+
62
+ // Build environment with token
63
+ const env: Record<string, string | undefined> = {
64
+ ...process.env,
65
+ DO_TOKEN: token,
66
+ }
67
+
68
+ if (options.apiUrl) {
69
+ env.DO_API_URL = options.apiUrl
70
+ }
71
+
72
+ // Spawn wrangler deploy
73
+ let proc: SpawnedProcess
74
+ try {
75
+ proc = spawnFn(['bunx', 'wrangler', 'deploy', ...args], {
76
+ env,
77
+ stdio: ['inherit', 'inherit', 'inherit'],
78
+ })
79
+ } catch (error) {
80
+ const message = error instanceof Error ? error.message : String(error)
81
+ console.error('Failed to start wrangler. Please ensure wrangler is installed.')
82
+ throw error
83
+ }
84
+
85
+ const exitCode = await proc.exited
86
+ const success = exitCode === 0
87
+
88
+ if (success) {
89
+ console.log('Deployment completed successfully')
90
+ } else {
91
+ console.error('Deployment failed with exit code:', exitCode)
92
+ }
93
+
94
+ return { exitCode, success }
95
+ }
96
+
97
+ function defaultSpawn(command: string[], options?: SpawnOptions): SpawnedProcess {
98
+ // This will be replaced by Bun.spawn in production
99
+ throw new Error('No spawn function provided')
100
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Dev Command
3
+ *
4
+ * Starts local development server using wrangler dev.
5
+ * Authenticates via oauth.do and passes DO_TOKEN to the spawned process.
6
+ */
7
+
8
+ import { ensureLoggedIn } from 'oauth.do/node'
9
+
10
+ export const name = 'dev'
11
+ export const description = 'Start local development server'
12
+
13
+ interface SpawnOptions {
14
+ env?: Record<string, string | undefined>
15
+ stdio?: ['inherit' | 'pipe', 'inherit' | 'pipe', 'inherit' | 'pipe'] | 'inherit'
16
+ cwd?: string
17
+ }
18
+
19
+ interface SpawnedProcess {
20
+ pid: number
21
+ exited: Promise<number>
22
+ kill: (signal?: number) => void
23
+ stdout?: ReadableStream<Uint8Array>
24
+ stderr?: ReadableStream<Uint8Array>
25
+ }
26
+
27
+ type SpawnFn = (command: string[], options?: SpawnOptions) => SpawnedProcess
28
+
29
+ interface RunOptions {
30
+ spawn?: SpawnFn
31
+ apiUrl?: string
32
+ }
33
+
34
+ interface RunResult {
35
+ exitCode: number
36
+ }
37
+
38
+ export async function run(args: string[], options: RunOptions = {}): Promise<RunResult> {
39
+ const spawnFn = options.spawn ?? defaultSpawn
40
+
41
+ // Authenticate first
42
+ let token: string
43
+ try {
44
+ const result = await ensureLoggedIn({
45
+ openBrowser: true,
46
+ print: console.log,
47
+ })
48
+ token = result.token
49
+
50
+ if (result.isNewLogin) {
51
+ console.log('Logged in successfully')
52
+ }
53
+ } catch (error) {
54
+ const message = error instanceof Error ? error.message : String(error)
55
+ if (message.toLowerCase().includes('network')) {
56
+ console.error('Network connection error. Please check your internet connection.')
57
+ } else {
58
+ console.error('Authentication error:', message)
59
+ }
60
+ throw new Error(`Authentication failed: ${message}`)
61
+ }
62
+
63
+ console.log('Starting dev server...')
64
+
65
+ // Build environment with token
66
+ const env: Record<string, string | undefined> = {
67
+ ...process.env,
68
+ DO_TOKEN: token,
69
+ }
70
+
71
+ if (options.apiUrl) {
72
+ env.DO_API_URL = options.apiUrl
73
+ }
74
+
75
+ // Spawn wrangler dev
76
+ let proc: SpawnedProcess
77
+ try {
78
+ proc = spawnFn(['bunx', 'wrangler', 'dev', ...args], {
79
+ env,
80
+ stdio: ['inherit', 'inherit', 'inherit'],
81
+ })
82
+ } catch (error) {
83
+ const message = error instanceof Error ? error.message : String(error)
84
+ console.error('Failed to start wrangler. Please ensure wrangler is installed.')
85
+ throw error
86
+ }
87
+
88
+ const exitCode = await proc.exited
89
+ return { exitCode }
90
+ }
91
+
92
+ function defaultSpawn(command: string[], options?: SpawnOptions): SpawnedProcess {
93
+ // This will be replaced by Bun.spawn in production
94
+ throw new Error('No spawn function provided')
95
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Logs Command
3
+ *
4
+ * Streams live logs from Cloudflare Workers using wrangler tail.
5
+ * Authenticates via oauth.do and passes DO_TOKEN to the spawned process.
6
+ */
7
+
8
+ import { ensureLoggedIn } from 'oauth.do/node'
9
+
10
+ export const name = 'logs'
11
+ export const description = 'Stream live logs from Cloudflare Workers'
12
+
13
+ interface SpawnOptions {
14
+ env?: Record<string, string | undefined>
15
+ stdio?: ['inherit' | 'pipe', 'inherit' | 'pipe', 'inherit' | 'pipe'] | 'inherit'
16
+ cwd?: string
17
+ }
18
+
19
+ interface SpawnedProcess {
20
+ pid: number
21
+ exited: Promise<number>
22
+ kill: (signal?: number) => void
23
+ stdout?: ReadableStream<Uint8Array>
24
+ stderr?: ReadableStream<Uint8Array>
25
+ }
26
+
27
+ type SpawnFn = (command: string[], options?: SpawnOptions) => SpawnedProcess
28
+
29
+ interface RunOptions {
30
+ spawn?: SpawnFn
31
+ apiUrl?: string
32
+ }
33
+
34
+ interface RunResult {
35
+ exitCode: number
36
+ }
37
+
38
+ export async function run(args: string[], options: RunOptions = {}): Promise<RunResult> {
39
+ const spawnFn = options.spawn ?? defaultSpawn
40
+
41
+ // Authenticate first
42
+ let token: string
43
+ try {
44
+ const result = await ensureLoggedIn({
45
+ openBrowser: true,
46
+ print: console.log,
47
+ })
48
+ token = result.token
49
+
50
+ if (result.isNewLogin) {
51
+ console.log('Logged in successfully')
52
+ }
53
+ } catch (error) {
54
+ const message = error instanceof Error ? error.message : String(error)
55
+ console.error('Authentication error:', message)
56
+ throw new Error(`Authentication failed: ${message}`)
57
+ }
58
+
59
+ console.log('Connecting to logs stream...')
60
+
61
+ // Build environment with token
62
+ const env: Record<string, string | undefined> = {
63
+ ...process.env,
64
+ DO_TOKEN: token,
65
+ }
66
+
67
+ if (options.apiUrl) {
68
+ env.DO_API_URL = options.apiUrl
69
+ }
70
+
71
+ // Spawn wrangler tail
72
+ let proc: SpawnedProcess
73
+ try {
74
+ proc = spawnFn(['bunx', 'wrangler', 'tail', ...args], {
75
+ env,
76
+ stdio: ['inherit', 'inherit', 'inherit'],
77
+ })
78
+ } catch (error) {
79
+ const message = error instanceof Error ? error.message : String(error)
80
+ console.error('Failed to start wrangler. Please ensure wrangler is installed.')
81
+ throw error
82
+ }
83
+
84
+ const exitCode = await proc.exited
85
+ return { exitCode }
86
+ }
87
+
88
+ function defaultSpawn(command: string[], options?: SpawnOptions): SpawnedProcess {
89
+ // This will be replaced by Bun.spawn in production
90
+ throw new Error('No spawn function provided')
91
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Dev Command
3
+ *
4
+ * Starts local development server with embedded DO runtime.
5
+ * Uses Miniflare for full Durable Object support locally.
6
+ */
7
+
8
+ import { Command } from 'commander'
9
+ import { createAdapter } from '../runtime/miniflare-adapter'
10
+ import { createLogger } from '../utils/logger'
11
+ import { loadConfigAsync } from '../utils/config'
12
+ import { startTunnel } from './tunnel'
13
+
14
+ const logger = createLogger('dev')
15
+
16
+ export const devCommand = new Command('dev')
17
+ .description('Start local development runtime')
18
+ .option('-p, --port <port>', 'Port to listen on', '8787')
19
+ .option('--host <host>', 'Host to bind to', 'localhost')
20
+ .option('--tunnel', 'Expose via Cloudflare Tunnel')
21
+ .option('--tunnel-name <name>', 'Custom tunnel name')
22
+ .option('--no-persist', 'Disable state persistence')
23
+ .option('--persist <path>', 'Custom persistence path')
24
+ .option('--inspect', 'Enable V8 inspector')
25
+ .option('--live-reload', 'Enable live reload on file changes', true)
26
+ .option('-c, --config <path>', 'Path to config file')
27
+ .action(async (options) => {
28
+ const config = await loadConfigAsync()
29
+
30
+ const port = parseInt(options.port, 10)
31
+ const host = options.host
32
+
33
+ logger.info(`Starting development server...`)
34
+ logger.debug('Options:', { port, host, tunnel: options.tunnel, persist: options.persist })
35
+
36
+ // Create Miniflare adapter
37
+ const adapter = createAdapter({
38
+ logger,
39
+ config,
40
+ persist: options.persist === false ? false : options.persist ?? config.persist,
41
+ })
42
+
43
+ try {
44
+ // Start the runtime
45
+ const instance = await adapter.start({
46
+ port,
47
+ host,
48
+ live: options.liveReload,
49
+ })
50
+
51
+ console.log()
52
+ console.log(` Local: ${instance.url}`)
53
+
54
+ // Start tunnel if requested
55
+ if (options.tunnel) {
56
+ const tunnelUrl = await startTunnel({
57
+ port,
58
+ name: options.tunnelName,
59
+ logger,
60
+ })
61
+ console.log(` Tunnel: ${tunnelUrl}`)
62
+ }
63
+
64
+ console.log()
65
+ console.log(' Press Ctrl+C to stop')
66
+ console.log()
67
+
68
+ // Handle shutdown
69
+ const shutdown = async () => {
70
+ console.log('\nShutting down...')
71
+ await instance.stop()
72
+ process.exit(0)
73
+ }
74
+
75
+ process.on('SIGINT', shutdown)
76
+ process.on('SIGTERM', shutdown)
77
+
78
+ // Keep process alive
79
+ await new Promise(() => {})
80
+ } catch (error) {
81
+ logger.error('Failed to start dev server', {
82
+ error: error instanceof Error ? error.message : String(error),
83
+ })
84
+ process.exit(1)
85
+ }
86
+ })
87
+
88
+ export default devCommand