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,314 @@
1
+ /**
2
+ * DO Command
3
+ *
4
+ * Operations for managing Durable Objects:
5
+ * - list: List all DO instances
6
+ * - show: Show DO state
7
+ * - save: Create snapshot
8
+ * - restore: Restore from snapshot
9
+ * - clone: Clone DO instance
10
+ * - delete: Delete DO instance
11
+ */
12
+
13
+ import { Command } from 'commander'
14
+ import { createDB } from '../runtime/embedded-db'
15
+ import { createLogger } from '../utils/logger'
16
+
17
+ const logger = createLogger('do')
18
+
19
+ /**
20
+ * Format timestamp for display
21
+ */
22
+ function formatTime(ts: number): string {
23
+ return new Date(ts * 1000).toLocaleString()
24
+ }
25
+
26
+ /**
27
+ * Format state for display
28
+ */
29
+ function formatState(state: Record<string, unknown>, indent = 2): string {
30
+ return JSON.stringify(state, null, indent)
31
+ }
32
+
33
+ export const doCommand = new Command('do')
34
+ .description('Durable Object operations')
35
+
36
+ /**
37
+ * do:list - List all DO instances
38
+ */
39
+ doCommand
40
+ .command('list')
41
+ .alias('ls')
42
+ .description('List all Durable Object instances')
43
+ .option('-c, --class <name>', 'Filter by class name')
44
+ .option('--json', 'Output as JSON')
45
+ .action(async (options) => {
46
+ const db = createDB()
47
+ await db.init()
48
+
49
+ try {
50
+ const instances = await db.list(options.class)
51
+
52
+ if (options.json) {
53
+ console.log(JSON.stringify(instances, null, 2))
54
+ return
55
+ }
56
+
57
+ if (instances.length === 0) {
58
+ logger.info('No Durable Objects found')
59
+ return
60
+ }
61
+
62
+ console.log()
63
+ console.log(`Found ${instances.length} Durable Object(s):`)
64
+ console.log()
65
+
66
+ for (const instance of instances) {
67
+ console.log(` ${instance.id}`)
68
+ console.log(` Class: ${instance.className}`)
69
+ console.log(` Created: ${formatTime(instance.createdAt)}`)
70
+ console.log(` Updated: ${formatTime(instance.updatedAt)}`)
71
+ console.log()
72
+ }
73
+ } finally {
74
+ db.close()
75
+ }
76
+ })
77
+
78
+ /**
79
+ * do:show - Show DO state
80
+ */
81
+ doCommand
82
+ .command('show <id>')
83
+ .description('Show Durable Object state')
84
+ .option('--json', 'Output as JSON')
85
+ .option('--storage', 'Include storage data')
86
+ .action(async (id, options) => {
87
+ const db = createDB()
88
+ await db.init()
89
+
90
+ try {
91
+ const instance = await db.get(id)
92
+
93
+ if (!instance) {
94
+ logger.error(`Durable Object not found: ${id}`)
95
+ process.exit(1)
96
+ }
97
+
98
+ if (options.json) {
99
+ console.log(JSON.stringify(instance, null, 2))
100
+ return
101
+ }
102
+
103
+ console.log()
104
+ console.log(`Durable Object: ${instance.id}`)
105
+ console.log('─'.repeat(40))
106
+ console.log(` Class: ${instance.className}`)
107
+ console.log(` Created: ${formatTime(instance.createdAt)}`)
108
+ console.log(` Updated: ${formatTime(instance.updatedAt)}`)
109
+ console.log()
110
+ console.log('State:')
111
+ console.log(formatState(instance.state))
112
+
113
+ if (options.storage) {
114
+ console.log()
115
+ console.log('Storage:')
116
+ console.log(formatState(instance.storage))
117
+ }
118
+ console.log()
119
+ } finally {
120
+ db.close()
121
+ }
122
+ })
123
+
124
+ /**
125
+ * do:save - Create snapshot
126
+ */
127
+ doCommand
128
+ .command('save <id>')
129
+ .description('Create a snapshot of a Durable Object')
130
+ .option('-l, --label <label>', 'Label for the snapshot')
131
+ .action(async (id, options) => {
132
+ const db = createDB()
133
+ await db.init()
134
+
135
+ try {
136
+ const instance = await db.get(id)
137
+
138
+ if (!instance) {
139
+ logger.error(`Durable Object not found: ${id}`)
140
+ process.exit(1)
141
+ }
142
+
143
+ const snapshotId = await db.snapshot(id, options.label)
144
+ logger.success(`Snapshot created: ${snapshotId}`)
145
+
146
+ if (options.label) {
147
+ console.log(` Label: ${options.label}`)
148
+ }
149
+ } finally {
150
+ db.close()
151
+ }
152
+ })
153
+
154
+ /**
155
+ * do:restore - Restore from snapshot
156
+ */
157
+ doCommand
158
+ .command('restore <id> <snapshot>')
159
+ .description('Restore a Durable Object from a snapshot')
160
+ .option('-f, --force', 'Force restore without confirmation')
161
+ .action(async (id, snapshotId, options) => {
162
+ const db = createDB()
163
+ await db.init()
164
+
165
+ try {
166
+ const instance = await db.get(id)
167
+
168
+ if (!instance) {
169
+ logger.error(`Durable Object not found: ${id}`)
170
+ process.exit(1)
171
+ }
172
+
173
+ // List snapshots if snapshot ID is 'list'
174
+ if (snapshotId === 'list') {
175
+ const snapshots = await db.listSnapshots(id)
176
+
177
+ if (snapshots.length === 0) {
178
+ logger.info('No snapshots found')
179
+ return
180
+ }
181
+
182
+ console.log()
183
+ console.log(`Snapshots for ${id}:`)
184
+ console.log()
185
+
186
+ for (const snap of snapshots) {
187
+ console.log(` ${snap.id}`)
188
+ console.log(` Created: ${formatTime(snap.createdAt)}`)
189
+ if (snap.label) {
190
+ console.log(` Label: ${snap.label}`)
191
+ }
192
+ console.log()
193
+ }
194
+ return
195
+ }
196
+
197
+ if (!options.force) {
198
+ logger.warn('This will overwrite current state.')
199
+ logger.info('Use --force to confirm')
200
+ process.exit(1)
201
+ }
202
+
203
+ await db.restore(id, snapshotId)
204
+ logger.success(`Restored ${id} from snapshot ${snapshotId}`)
205
+ } finally {
206
+ db.close()
207
+ }
208
+ })
209
+
210
+ /**
211
+ * do:clone - Clone DO instance
212
+ */
213
+ doCommand
214
+ .command('clone <source> <target>')
215
+ .description('Clone a Durable Object instance')
216
+ .action(async (sourceId, targetId) => {
217
+ const db = createDB()
218
+ await db.init()
219
+
220
+ try {
221
+ const source = await db.get(sourceId)
222
+
223
+ if (!source) {
224
+ logger.error(`Source Durable Object not found: ${sourceId}`)
225
+ process.exit(1)
226
+ }
227
+
228
+ const existing = await db.get(targetId)
229
+ if (existing) {
230
+ logger.error(`Target already exists: ${targetId}`)
231
+ logger.info('Delete it first or choose a different ID')
232
+ process.exit(1)
233
+ }
234
+
235
+ await db.clone(sourceId, targetId)
236
+ logger.success(`Cloned ${sourceId} to ${targetId}`)
237
+ } finally {
238
+ db.close()
239
+ }
240
+ })
241
+
242
+ /**
243
+ * do:delete - Delete DO instance
244
+ */
245
+ doCommand
246
+ .command('delete <id>')
247
+ .alias('rm')
248
+ .description('Delete a Durable Object instance')
249
+ .option('-f, --force', 'Force delete without confirmation')
250
+ .action(async (id, options) => {
251
+ const db = createDB()
252
+ await db.init()
253
+
254
+ try {
255
+ const instance = await db.get(id)
256
+
257
+ if (!instance) {
258
+ logger.error(`Durable Object not found: ${id}`)
259
+ process.exit(1)
260
+ }
261
+
262
+ if (!options.force) {
263
+ logger.warn(`This will permanently delete ${id} and all its snapshots.`)
264
+ logger.info('Use --force to confirm')
265
+ process.exit(1)
266
+ }
267
+
268
+ await db.delete(id)
269
+ logger.success(`Deleted ${id}`)
270
+ } finally {
271
+ db.close()
272
+ }
273
+ })
274
+
275
+ /**
276
+ * do:snapshots - List snapshots
277
+ */
278
+ doCommand
279
+ .command('snapshots <id>')
280
+ .description('List snapshots for a Durable Object')
281
+ .option('--json', 'Output as JSON')
282
+ .action(async (id, options) => {
283
+ const db = createDB()
284
+ await db.init()
285
+
286
+ try {
287
+ const snapshots = await db.listSnapshots(id)
288
+
289
+ if (options.json) {
290
+ console.log(JSON.stringify(snapshots, null, 2))
291
+ return
292
+ }
293
+
294
+ if (snapshots.length === 0) {
295
+ logger.info(`No snapshots found for ${id}`)
296
+ return
297
+ }
298
+
299
+ console.log()
300
+ console.log(`Snapshots for ${id} (${snapshots.length}):`)
301
+ console.log()
302
+
303
+ for (const snap of snapshots) {
304
+ const label = snap.label ? ` (${snap.label})` : ''
305
+ console.log(` ${snap.id}${label}`)
306
+ console.log(` Created: ${formatTime(snap.createdAt)}`)
307
+ console.log()
308
+ }
309
+ } finally {
310
+ db.close()
311
+ }
312
+ })
313
+
314
+ export default doCommand
@@ -0,0 +1,100 @@
1
+ /**
2
+ * CLI Command Registry
3
+ *
4
+ * Exports all available CLI commands.
5
+ */
6
+
7
+ import { run as introspectRun } from './introspect'
8
+
9
+ // Service commands (cli.do)
10
+ import { run as callRun } from '../src/commands/call'
11
+ import { run as textRun } from '../src/commands/text'
12
+ import { run as emailRun } from '../src/commands/email'
13
+ import { run as chargeRun } from '../src/commands/charge'
14
+ import { run as queueRun } from '../src/commands/queue'
15
+ import { run as llmRun } from '../src/commands/llm'
16
+ import { run as configRun } from '../src/commands/config'
17
+
18
+ export type CommandHandler = (args: string[]) => Promise<void> | void
19
+
20
+ export interface Command {
21
+ run: CommandHandler
22
+ description?: string
23
+ }
24
+
25
+ /** Command registry object */
26
+ export const commands: Record<string, Command> = {
27
+ // Auth commands
28
+ login: {
29
+ run: async (_args: string[]) => {
30
+ // Placeholder - will be implemented
31
+ },
32
+ description: 'Log in to your account',
33
+ },
34
+ logout: {
35
+ run: async (_args: string[]) => {
36
+ // Placeholder - will be implemented
37
+ },
38
+ description: 'Log out of your account',
39
+ },
40
+
41
+ // Dev commands
42
+ dev: {
43
+ run: async (_args: string[]) => {
44
+ // Placeholder - will be implemented
45
+ },
46
+ description: 'Start development server',
47
+ },
48
+ build: {
49
+ run: async (_args: string[]) => {
50
+ // Placeholder - will be implemented
51
+ },
52
+ description: 'Build the project',
53
+ },
54
+ deploy: {
55
+ run: async (_args: string[]) => {
56
+ // Placeholder - will be implemented
57
+ },
58
+ description: 'Deploy to production',
59
+ },
60
+ init: {
61
+ run: async (_args: string[]) => {
62
+ // Placeholder - will be implemented
63
+ },
64
+ description: 'Initialize a new project',
65
+ },
66
+ introspect: {
67
+ run: introspectRun,
68
+ description: 'Generate .do/types.d.ts from DB.mdx schemas',
69
+ },
70
+
71
+ // Service commands (cli.do)
72
+ call: {
73
+ run: callRun,
74
+ description: 'Make voice calls via calls.do',
75
+ },
76
+ text: {
77
+ run: textRun,
78
+ description: 'Send SMS/MMS via texts.do',
79
+ },
80
+ email: {
81
+ run: emailRun,
82
+ description: 'Send emails via emails.do',
83
+ },
84
+ charge: {
85
+ run: chargeRun,
86
+ description: 'Create charges via payments.do',
87
+ },
88
+ queue: {
89
+ run: queueRun,
90
+ description: 'Queue operations via queue.do',
91
+ },
92
+ llm: {
93
+ run: llmRun,
94
+ description: 'LLM requests via llm.do',
95
+ },
96
+ config: {
97
+ run: configRun,
98
+ description: 'Manage CLI configuration',
99
+ },
100
+ }
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Init Command
3
+ *
4
+ * Scaffolds a new dotdo project with the proper structure.
5
+ *
6
+ * Usage:
7
+ * npx dotdo init my-startup # Create new project directory
8
+ * npx dotdo init . # Initialize in current directory
9
+ */
10
+
11
+ import * as fs from 'node:fs'
12
+ import * as path from 'node:path'
13
+
14
+ // ============================================================================
15
+ // Command Metadata
16
+ // ============================================================================
17
+
18
+ export const name = 'init'
19
+ export const description = 'Initialize a new dotdo project'
20
+
21
+ // ============================================================================
22
+ // Types
23
+ // ============================================================================
24
+
25
+ export interface InitOptions {
26
+ /** Working directory (defaults to process.cwd()) */
27
+ cwd?: string
28
+ }
29
+
30
+ // ============================================================================
31
+ // Helpers
32
+ // ============================================================================
33
+
34
+ /**
35
+ * Convert kebab-case or snake_case to PascalCase
36
+ */
37
+ function toPascalCase(str: string): string {
38
+ return str
39
+ .split(/[-_]/)
40
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
41
+ .join('')
42
+ }
43
+
44
+ /**
45
+ * Validate project name
46
+ */
47
+ function validateProjectName(name: string): void {
48
+ // Allow "." for current directory
49
+ if (name === '.') return
50
+
51
+ // Check for valid npm package name (simplified)
52
+ const validNamePattern = /^[a-z][a-z0-9-]*$/
53
+
54
+ if (!validNamePattern.test(name)) {
55
+ throw new Error(`Invalid project name: "${name}". Must start with a letter and contain only lowercase letters, numbers, and hyphens.`)
56
+ }
57
+ }
58
+
59
+ // ============================================================================
60
+ // Templates
61
+ // ============================================================================
62
+
63
+ /**
64
+ * Generate src/index.ts content
65
+ */
66
+ function generateIndexTs(className: string): string {
67
+ return `/**
68
+ * ${className} - A dotdo Startup
69
+ *
70
+ * Build your 1-Person Unicorn.
71
+ */
72
+
73
+ import { DO } from 'dotdo'
74
+
75
+ export class ${className} extends DO {
76
+ static readonly $type = '${className}'
77
+ }
78
+
79
+ // Re-export the simple worker as default
80
+ export { default } from 'dotdo/workers/simple'
81
+ `
82
+ }
83
+
84
+ /**
85
+ * Generate wrangler.jsonc content
86
+ */
87
+ function generateWranglerJsonc(projectName: string, className: string): string {
88
+ return `{
89
+ "$schema": "https://raw.githubusercontent.com/cloudflare/workers-sdk/main/packages/wrangler/config-schema.json",
90
+ "name": "${projectName}",
91
+ "main": "src/index.ts",
92
+ "compatibility_date": "2024-12-01",
93
+ "compatibility_flags": ["nodejs_compat"],
94
+
95
+ // Durable Objects
96
+ "durable_objects": {
97
+ "bindings": [
98
+ {
99
+ "name": "DO",
100
+ "class_name": "${className}",
101
+ "script_name": "${projectName}"
102
+ }
103
+ ]
104
+ },
105
+
106
+ "migrations": [
107
+ {
108
+ "tag": "v1",
109
+ "new_sqlite_classes": ["${className}"]
110
+ }
111
+ ]
112
+ }
113
+ `
114
+ }
115
+
116
+ /**
117
+ * Generate package.json content
118
+ */
119
+ function generatePackageJson(projectName: string): string {
120
+ const pkg = {
121
+ name: projectName,
122
+ version: '0.0.1',
123
+ private: true,
124
+ type: 'module',
125
+ scripts: {
126
+ dev: 'wrangler dev',
127
+ deploy: 'wrangler deploy',
128
+ typecheck: 'tsc --noEmit',
129
+ },
130
+ dependencies: {
131
+ dotdo: '^0.1.0',
132
+ },
133
+ devDependencies: {
134
+ '@cloudflare/workers-types': '^4.20241230.0',
135
+ typescript: '^5.7.0',
136
+ wrangler: '^3.99.0',
137
+ },
138
+ }
139
+ return JSON.stringify(pkg, null, 2) + '\n'
140
+ }
141
+
142
+ /**
143
+ * Generate tsconfig.json content
144
+ */
145
+ function generateTsconfig(): string {
146
+ const config = {
147
+ compilerOptions: {
148
+ target: 'ES2022',
149
+ module: 'ESNext',
150
+ moduleResolution: 'bundler',
151
+ strict: true,
152
+ skipLibCheck: true,
153
+ esModuleInterop: true,
154
+ resolveJsonModule: true,
155
+ isolatedModules: true,
156
+ noEmit: true,
157
+ lib: ['ES2022'],
158
+ types: ['@cloudflare/workers-types'],
159
+ },
160
+ include: ['src/**/*'],
161
+ exclude: ['node_modules'],
162
+ }
163
+ return JSON.stringify(config, null, 2) + '\n'
164
+ }
165
+
166
+ // ============================================================================
167
+ // Main Command
168
+ // ============================================================================
169
+
170
+ /**
171
+ * Run the init command
172
+ */
173
+ export async function run(args: string[], options: InitOptions = {}): Promise<void> {
174
+ const cwd = options.cwd ?? process.cwd()
175
+
176
+ // Get project name from args
177
+ const projectName = args[0]
178
+
179
+ if (!projectName) {
180
+ throw new Error('Please provide a project name: npx dotdo init <project-name>')
181
+ }
182
+
183
+ // Validate project name
184
+ validateProjectName(projectName)
185
+
186
+ // Determine project directory and name for files
187
+ let projectDir: string
188
+ let actualProjectName: string
189
+
190
+ if (projectName === '.') {
191
+ // Initialize in current directory
192
+ projectDir = cwd
193
+ actualProjectName = path.basename(cwd)
194
+ } else {
195
+ // Create new directory
196
+ projectDir = path.join(cwd, projectName)
197
+ actualProjectName = projectName
198
+
199
+ // Check if directory already exists
200
+ if (fs.existsSync(projectDir)) {
201
+ throw new Error(`Directory "${projectName}" already exists. Please choose a different name or remove the existing directory.`)
202
+ }
203
+
204
+ // Create project directory
205
+ fs.mkdirSync(projectDir, { recursive: true })
206
+ }
207
+
208
+ // Derive class name from project name
209
+ const className = toPascalCase(actualProjectName)
210
+
211
+ // Create src directory
212
+ const srcDir = path.join(projectDir, 'src')
213
+ fs.mkdirSync(srcDir, { recursive: true })
214
+
215
+ // Write files
216
+ fs.writeFileSync(
217
+ path.join(srcDir, 'index.ts'),
218
+ generateIndexTs(className)
219
+ )
220
+
221
+ fs.writeFileSync(
222
+ path.join(projectDir, 'wrangler.jsonc'),
223
+ generateWranglerJsonc(actualProjectName, className)
224
+ )
225
+
226
+ fs.writeFileSync(
227
+ path.join(projectDir, 'package.json'),
228
+ generatePackageJson(actualProjectName)
229
+ )
230
+
231
+ fs.writeFileSync(
232
+ path.join(projectDir, 'tsconfig.json'),
233
+ generateTsconfig()
234
+ )
235
+
236
+ // Print success message
237
+ console.log(`\nProject "${actualProjectName}" created successfully!\n`)
238
+ console.log('Next steps:')
239
+
240
+ if (projectName !== '.') {
241
+ console.log(` cd ${projectName}`)
242
+ }
243
+
244
+ console.log(' npm install')
245
+ console.log(' npm run dev')
246
+ console.log('')
247
+ }