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.
- package/cli/README.md +238 -0
- package/cli/agent.ts +72 -0
- package/cli/bin.js +44 -0
- package/cli/bin.ts +38 -0
- package/cli/build.ts +157 -0
- package/cli/commands/auth/login.ts +14 -0
- package/cli/commands/auth/logout.ts +6 -0
- package/cli/commands/auth/whoami.ts +16 -0
- package/cli/commands/deploy-multi.ts +245 -0
- package/cli/commands/dev/deploy.ts +100 -0
- package/cli/commands/dev/dev.ts +95 -0
- package/cli/commands/dev/logs.ts +91 -0
- package/cli/commands/dev-local.ts +88 -0
- package/cli/commands/do-ops.ts +314 -0
- package/cli/commands/index.ts +100 -0
- package/cli/commands/init.ts +247 -0
- package/cli/commands/introspect/emitter.ts +315 -0
- package/cli/commands/introspect/index.ts +193 -0
- package/cli/commands/link.ts +598 -0
- package/cli/commands/snippets.ts +415 -0
- package/cli/commands/tunnel.ts +239 -0
- package/cli/device-auth.ts +289 -0
- package/cli/fallback.ts +12 -0
- package/cli/index.ts +121 -0
- package/cli/main.ts +246 -0
- package/cli/mcp-stdio.ts +790 -0
- package/cli/package.json +62 -0
- package/cli/runtime/do-registry.ts +193 -0
- package/cli/runtime/embedded-db.ts +344 -0
- package/cli/runtime/index.ts +9 -0
- package/cli/runtime/miniflare-adapter.ts +162 -0
- package/cli/sandbox.ts +82 -0
- package/cli/src/args.ts +174 -0
- package/cli/src/auth.ts +55 -0
- package/cli/src/commands/call.ts +84 -0
- package/cli/src/commands/charge.ts +96 -0
- package/cli/src/commands/config.ts +115 -0
- package/cli/src/commands/email.ts +112 -0
- package/cli/src/commands/llm.ts +115 -0
- package/cli/src/commands/queue.ts +134 -0
- package/cli/src/commands/text.ts +86 -0
- package/cli/src/config.ts +185 -0
- package/cli/src/output.ts +246 -0
- package/cli/src/rpc.ts +192 -0
- package/cli/utils/config.ts +282 -0
- package/cli/utils/detect.ts +73 -0
- package/cli/utils/index.ts +15 -0
- package/cli/utils/logger.ts +232 -0
- package/dist/ai/template-literals.js +2 -2
- package/dist/ai/template-literals.js.map +1 -1
- package/dist/api/middleware/auth.js +3 -2
- package/dist/api/middleware/auth.js.map +1 -1
- package/dist/db/iceberg/inverted-index.js +1 -1
- package/dist/db/iceberg/inverted-index.js.map +1 -1
- package/dist/db/iceberg/puffin.js.map +1 -1
- package/dist/db/json-indexes.js.map +1 -1
- package/dist/db/objects.js.map +1 -1
- package/dist/db/primitives/dag-scheduler/index.js +1 -1
- package/dist/db/primitives/dag-scheduler/index.js.map +1 -1
- package/dist/db/primitives/observability.js.map +1 -1
- package/dist/db/primitives/schema-evolution.js.map +1 -1
- package/dist/db/primitives/temporal-store.js.map +1 -1
- package/dist/db/primitives/typed-column-store.js.map +1 -1
- package/dist/db/primitives/utils/duration.js.map +1 -1
- package/dist/db/primitives/utils/murmur3.js +12 -14
- package/dist/db/primitives/utils/murmur3.js.map +1 -1
- package/dist/db/primitives/window-manager.js.map +1 -1
- package/dist/db/stores.js.map +1 -1
- package/dist/db/things.js.map +1 -1
- package/dist/lib/DODispatcher.js +2 -2
- package/dist/lib/DODispatcher.js.map +1 -1
- package/dist/lib/auto-wiring.js.map +1 -1
- package/dist/lib/channels/email.js +1 -1
- package/dist/lib/channels/email.js.map +1 -1
- package/dist/lib/channels/slack-blockkit.js.map +1 -1
- package/dist/lib/cloudflare/ai.js +1 -1
- package/dist/lib/cloudflare/ai.js.map +1 -1
- package/dist/lib/cloudflare/kv.js +1 -1
- package/dist/lib/cloudflare/kv.js.map +1 -1
- package/dist/lib/cloudflare/r2.js +3 -3
- package/dist/lib/cloudflare/r2.js.map +1 -1
- package/dist/lib/cloudflare/vectorize.js.map +1 -1
- package/dist/lib/cloudflare/workflows.js.map +1 -1
- package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -1
- package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -1
- package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -1
- package/dist/lib/executors/HumanFunctionExecutor.js +1 -1
- package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -1
- package/dist/lib/executors/ParallelStepExecutor.js.map +1 -1
- package/dist/lib/experiments.js.map +1 -1
- package/dist/lib/flags/store.js.map +1 -1
- package/dist/lib/functions/FunctionComposition.js.map +1 -1
- package/dist/lib/functions/FunctionMiddleware.js.map +1 -1
- package/dist/lib/functions/FunctionRegistry.js.map +1 -1
- package/dist/lib/humans/templates.js.map +1 -1
- package/dist/lib/identity.js +2 -2
- package/dist/lib/identity.js.map +1 -1
- package/dist/lib/logging/index.js.map +1 -1
- package/dist/lib/mixins/bash.js +1 -73
- package/dist/lib/mixins/bash.js.map +1 -1
- package/dist/lib/mixins/git.js +0 -5
- package/dist/lib/mixins/git.js.map +1 -1
- package/dist/lib/mixins/npm.js.map +1 -1
- package/dist/lib/noun-id.js.map +1 -1
- package/dist/lib/rate-limit/sliding-window.js.map +1 -1
- package/dist/lib/rpc/bindings.js.map +1 -1
- package/dist/lib/safe-stringify.js.map +1 -1
- package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -1
- package/dist/lib/sqids.js.map +1 -1
- package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -1
- package/dist/lib/sql/adapters/pgsql-parser.js +19 -18
- package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -1
- package/dist/metrics/hunch.js.map +1 -1
- package/dist/objects/API.js +1 -1
- package/dist/objects/API.js.map +1 -1
- package/dist/objects/Agent.js.map +1 -1
- package/dist/objects/Browser.js.map +1 -1
- package/dist/objects/CLI.js.map +1 -1
- package/dist/objects/DOBase.js.map +1 -1
- package/dist/objects/DOCache.js +153 -0
- package/dist/objects/DOCache.js.map +1 -0
- package/dist/objects/DOFull.js.map +1 -1
- package/dist/objects/Entity.js.map +1 -1
- package/dist/objects/Human.js.map +1 -1
- package/dist/objects/IcebergMetadataDO.js.map +1 -1
- package/dist/objects/IntegrationsDO.js.map +1 -1
- package/dist/objects/ObservabilityBroadcaster.js.map +1 -1
- package/dist/objects/Package.js.map +1 -1
- package/dist/objects/Product.js +1 -1
- package/dist/objects/Product.js.map +1 -1
- package/dist/objects/SaaS.js.map +1 -1
- package/dist/objects/SandboxDO.js.map +1 -1
- package/dist/objects/Service.js.map +1 -1
- package/dist/objects/VectorShardDO.js +9 -7
- package/dist/objects/VectorShardDO.js.map +1 -1
- package/dist/objects/Workflow.js.map +1 -1
- package/dist/objects/WorkflowFactory.js.map +1 -1
- package/dist/objects/WorkflowRuntime.js.map +1 -1
- package/dist/objects/lifecycle/Branch.js.map +1 -1
- package/dist/objects/lifecycle/Clone.js +1 -1
- package/dist/objects/lifecycle/Clone.js.map +1 -1
- package/dist/objects/lifecycle/Compact.js.map +1 -1
- package/dist/objects/lifecycle/Shard.js.map +1 -1
- package/dist/objects/persistence/checkpoint-manager.js.map +1 -1
- package/dist/objects/persistence/migration-runner.js.map +1 -1
- package/dist/objects/persistence/replication-manager.js +2 -2
- package/dist/objects/persistence/replication-manager.js.map +1 -1
- package/dist/objects/persistence/tiered-storage-manager.js.map +1 -1
- package/dist/objects/persistence/wal-manager.js.map +1 -1
- package/dist/objects/transport/auth-layer.js.map +1 -1
- package/dist/objects/transport/chain.js.map +1 -1
- package/dist/objects/transport/mcp-server.js +7 -6
- package/dist/objects/transport/mcp-server.js.map +1 -1
- package/dist/objects/transport/rest-autowire.js +3 -2
- package/dist/objects/transport/rest-autowire.js.map +1 -1
- package/dist/objects/transport/rest-router.js.map +1 -1
- package/dist/objects/transport/rpc-server.js +18 -15
- package/dist/objects/transport/rpc-server.js.map +1 -1
- package/dist/objects/transport/shared.js +2 -1
- package/dist/objects/transport/shared.js.map +1 -1
- package/dist/snippets/artifacts-ingest.js.map +1 -1
- package/dist/snippets/artifacts-serve.js.map +1 -1
- package/dist/snippets/search.js.map +1 -1
- package/dist/workflows/ScheduleManager.js.map +1 -1
- package/dist/workflows/StepResultStorage.js.map +1 -1
- package/dist/workflows/WaitForEventManager.js.map +1 -1
- package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -1
- package/dist/workflows/compat/inngest/index.js.map +1 -1
- package/dist/workflows/compat/qstash/index.js.map +1 -1
- package/dist/workflows/compat/temporal/client.js.map +1 -1
- package/dist/workflows/compat/temporal/index.js.map +1 -1
- package/dist/workflows/compat/trigger/index.js.map +1 -1
- package/dist/workflows/compat/utils/index.js.map +1 -1
- package/dist/workflows/context/correlation.js +2 -2
- package/dist/workflows/context/correlation.js.map +1 -1
- package/dist/workflows/context/experiment.js +1 -1
- package/dist/workflows/context/experiment.js.map +1 -1
- package/dist/workflows/context/flag.js +1 -1
- package/dist/workflows/context/flag.js.map +1 -1
- package/dist/workflows/context/measure.js +1 -1
- package/dist/workflows/context/measure.js.map +1 -1
- package/dist/workflows/context/rate-limit.js.map +1 -1
- package/dist/workflows/data/entity-events/entity-events.js.map +1 -1
- package/dist/workflows/data/experiment/index.js.map +1 -1
- package/dist/workflows/data/goal/context.js +1 -1
- package/dist/workflows/data/goal/context.js.map +1 -1
- package/dist/workflows/data/measure/index.js +1 -1
- package/dist/workflows/data/measure/index.js.map +1 -1
- package/dist/workflows/data/stream/index.js +10 -76
- package/dist/workflows/data/stream/index.js.map +1 -1
- package/dist/workflows/data/track/context.js.map +1 -1
- package/dist/workflows/data/view/context.js.map +1 -1
- package/dist/workflows/domain.js.map +1 -1
- package/dist/workflows/flags.js +1 -1
- package/dist/workflows/flags.js.map +1 -1
- package/dist/workflows/hash.js.map +1 -1
- package/dist/workflows/on.js +1 -1
- package/dist/workflows/on.js.map +1 -1
- package/dist/workflows/schedule-builder.js.map +1 -1
- package/dist/workflows/visibility/index.js +0 -2
- package/dist/workflows/visibility/index.js.map +1 -1
- package/dist/workflows/visibility/query-parser.js.map +1 -1
- package/package.json +18 -3
- package/dist/api/analytics/router.js +0 -601
- package/dist/api/analytics/router.js.map +0 -1
- package/dist/api/index.js +0 -158
- package/dist/api/index.js.map +0 -1
- package/dist/api/middleware/error-handling.js +0 -176
- package/dist/api/middleware/error-handling.js.map +0 -1
- package/dist/api/middleware/request-id.js +0 -21
- package/dist/api/middleware/request-id.js.map +0 -1
- package/dist/api/pages.js +0 -1180
- package/dist/api/pages.js.map +0 -1
- package/dist/api/routes/api.js +0 -612
- package/dist/api/routes/api.js.map +0 -1
- package/dist/api/routes/browsers.js +0 -471
- package/dist/api/routes/browsers.js.map +0 -1
- package/dist/api/routes/do.js +0 -188
- package/dist/api/routes/do.js.map +0 -1
- package/dist/api/routes/mcp.js +0 -459
- package/dist/api/routes/mcp.js.map +0 -1
- package/dist/api/routes/obs.js +0 -445
- package/dist/api/routes/obs.js.map +0 -1
- package/dist/api/routes/openapi.js +0 -794
- package/dist/api/routes/openapi.js.map +0 -1
- package/dist/api/routes/rpc.js +0 -1103
- package/dist/api/routes/rpc.js.map +0 -1
- package/dist/api/routes/sandboxes.js +0 -389
- package/dist/api/routes/sandboxes.js.map +0 -1
- package/dist/api/test-do.js +0 -38
- package/dist/api/test-do.js.map +0 -1
- package/dist/api/types.js +0 -11
- package/dist/api/types.js.map +0 -1
- package/dist/cli/bin.js +0 -2
- package/dist/cli/main.js +0 -52342
- package/dist/do/bash.js +0 -35
- package/dist/do/bash.js.map +0 -1
- package/dist/do/fs.js +0 -25
- package/dist/do/fs.js.map +0 -1
- package/dist/do/full.js +0 -61
- package/dist/do/full.js.map +0 -1
- package/dist/do/git.js +0 -28
- package/dist/do/git.js.map +0 -1
- package/dist/do/index.js +0 -52
- package/dist/do/index.js.map +0 -1
- package/dist/lib/agent/tools/bash.js +0 -336
- package/dist/lib/agent/tools/bash.js.map +0 -1
- package/dist/lib/agent/tools/edit.js +0 -157
- package/dist/lib/agent/tools/edit.js.map +0 -1
- package/dist/lib/agent/tools/glob.js +0 -137
- package/dist/lib/agent/tools/glob.js.map +0 -1
- package/dist/lib/agent/tools/grep.js +0 -315
- package/dist/lib/agent/tools/grep.js.map +0 -1
- package/dist/lib/agent/tools/index.js +0 -71
- package/dist/lib/agent/tools/index.js.map +0 -1
- package/dist/lib/agent/tools/read.js +0 -212
- package/dist/lib/agent/tools/read.js.map +0 -1
- package/dist/lib/agent/tools/types.js +0 -197
- package/dist/lib/agent/tools/types.js.map +0 -1
- package/dist/lib/agent/tools/write.js +0 -159
- package/dist/lib/agent/tools/write.js.map +0 -1
- package/dist/lib/mixins/index.js +0 -29
- package/dist/lib/mixins/index.js.map +0 -1
- package/dist/primitives/bashx/src/ast/analyze.js +0 -1472
- package/dist/primitives/bashx/src/ast/analyze.js.map +0 -1
- package/dist/primitives/bashx/src/ast/parser.js +0 -1488
- package/dist/primitives/bashx/src/ast/parser.js.map +0 -1
- package/dist/primitives/bashx/src/do/commands/crypto.js +0 -1954
- package/dist/primitives/bashx/src/do/commands/crypto.js.map +0 -1
- package/dist/primitives/bashx/src/do/commands/data-processing.js +0 -1812
- package/dist/primitives/bashx/src/do/commands/data-processing.js.map +0 -1
- package/dist/primitives/bashx/src/do/commands/extended-utils.js +0 -804
- package/dist/primitives/bashx/src/do/commands/extended-utils.js.map +0 -1
- package/dist/primitives/bashx/src/do/commands/math-control.js +0 -1122
- package/dist/primitives/bashx/src/do/commands/math-control.js.map +0 -1
- package/dist/primitives/bashx/src/do/commands/posix-utils.js +0 -1015
- package/dist/primitives/bashx/src/do/commands/posix-utils.js.map +0 -1
- package/dist/primitives/bashx/src/do/commands/system-utils.js +0 -687
- package/dist/primitives/bashx/src/do/commands/system-utils.js.map +0 -1
- package/dist/primitives/bashx/src/do/commands/test-command.js +0 -523
- package/dist/primitives/bashx/src/do/commands/test-command.js.map +0 -1
- package/dist/primitives/bashx/src/do/commands/text-processing.js +0 -1550
- package/dist/primitives/bashx/src/do/commands/text-processing.js.map +0 -1
- package/dist/primitives/bashx/src/do/container-executor.js +0 -429
- package/dist/primitives/bashx/src/do/container-executor.js.map +0 -1
- package/dist/primitives/bashx/src/do/index.js +0 -668
- package/dist/primitives/bashx/src/do/index.js.map +0 -1
- package/dist/primitives/bashx/src/do/tiered-executor.js +0 -2647
- package/dist/primitives/bashx/src/do/tiered-executor.js.map +0 -1
- package/dist/primitives/bashx/src/do/worker.js +0 -352
- package/dist/primitives/bashx/src/do/worker.js.map +0 -1
- package/dist/primitives/bashx/src/types.js +0 -10
- package/dist/primitives/bashx/src/types.js.map +0 -1
- package/dist/primitives/fsx/core/backend.js +0 -480
- package/dist/primitives/fsx/core/backend.js.map +0 -1
- package/dist/primitives/fsx/core/constants.js +0 -140
- package/dist/primitives/fsx/core/constants.js.map +0 -1
- package/dist/primitives/fsx/core/fsx.js +0 -1184
- package/dist/primitives/fsx/core/fsx.js.map +0 -1
- package/dist/primitives/fsx/core/glob/glob.js +0 -438
- package/dist/primitives/fsx/core/glob/glob.js.map +0 -1
- package/dist/primitives/fsx/core/glob/index.js +0 -8
- package/dist/primitives/fsx/core/glob/index.js.map +0 -1
- package/dist/primitives/fsx/core/glob/match.js +0 -392
- package/dist/primitives/fsx/core/glob/match.js.map +0 -1
- package/dist/primitives/fsx/core/types.js +0 -307
- package/dist/primitives/fsx/core/types.js.map +0 -1
- package/dist/sdk/capnweb-compat.js +0 -42
- package/dist/sdk/capnweb-compat.js.map +0 -1
- package/dist/sdk/client.js +0 -20
- package/dist/sdk/client.js.map +0 -1
- package/dist/sdk/index.js +0 -17
- package/dist/sdk/index.js.map +0 -1
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Device Authorization Module
|
|
3
|
+
*
|
|
4
|
+
* Uses oauth.do/node for OAuth 2.0 Device Authorization Grant (RFC 8628)
|
|
5
|
+
*
|
|
6
|
+
* @see https://oauth.do/node
|
|
7
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFile, writeFile, unlink, mkdir, access } from 'fs/promises'
|
|
11
|
+
import { homedir } from 'os'
|
|
12
|
+
import { join } from 'path'
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Constants
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
const OAUTH_BASE_URL = 'https://oauth.do'
|
|
19
|
+
const DEFAULT_CLIENT_ID = 'org.ai-cli'
|
|
20
|
+
const CONFIG_DIR_NAME = '.org.ai'
|
|
21
|
+
const CREDENTIALS_FILE_NAME = 'credentials.json'
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Type Exports
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
export interface DeviceCodeResponse {
|
|
28
|
+
device_code: string
|
|
29
|
+
user_code: string
|
|
30
|
+
verification_uri: string
|
|
31
|
+
verification_uri_complete?: string
|
|
32
|
+
expires_in: number
|
|
33
|
+
interval: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface TokenResponse {
|
|
37
|
+
access_token: string
|
|
38
|
+
token_type: string
|
|
39
|
+
expires_in?: number
|
|
40
|
+
refresh_token?: string
|
|
41
|
+
scope?: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface PollError extends Error {
|
|
45
|
+
code: 'authorization_pending' | 'slow_down' | 'access_denied' | 'expired_token' | 'timeout'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface PollOptions {
|
|
49
|
+
interval: number
|
|
50
|
+
maxAttempts: number
|
|
51
|
+
onProgress?: (status: { attempt: number; maxAttempts: number }) => void
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface RequestDeviceCodeOptions {
|
|
55
|
+
scope?: string
|
|
56
|
+
clientId?: string
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface StoredToken {
|
|
60
|
+
access_token: string
|
|
61
|
+
token_type: string
|
|
62
|
+
refresh_token?: string
|
|
63
|
+
expires_at?: number
|
|
64
|
+
scope?: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// Helper Functions
|
|
69
|
+
// ============================================================================
|
|
70
|
+
|
|
71
|
+
function createPollError(code: PollError['code'], message: string): PollError {
|
|
72
|
+
const error = new Error(message) as PollError
|
|
73
|
+
error.code = code
|
|
74
|
+
return error
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function sleep(ms: number): Promise<void> {
|
|
78
|
+
return new Promise((resolve) => setTimeout(resolve, ms))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Config Path
|
|
83
|
+
// ============================================================================
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get the config file path
|
|
87
|
+
*/
|
|
88
|
+
export function getConfigPath(): string {
|
|
89
|
+
return join(homedir(), CONFIG_DIR_NAME, CREDENTIALS_FILE_NAME)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get the config directory path
|
|
94
|
+
*/
|
|
95
|
+
function getConfigDir(): string {
|
|
96
|
+
return join(homedir(), CONFIG_DIR_NAME)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Device Code Request
|
|
101
|
+
// ============================================================================
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Request a device code from the OAuth server
|
|
105
|
+
*/
|
|
106
|
+
export async function requestDeviceCode(options?: RequestDeviceCodeOptions): Promise<DeviceCodeResponse> {
|
|
107
|
+
const clientId = options?.clientId ?? DEFAULT_CLIENT_ID
|
|
108
|
+
const scope = options?.scope ?? 'openid profile email'
|
|
109
|
+
|
|
110
|
+
const body = new URLSearchParams({
|
|
111
|
+
client_id: clientId,
|
|
112
|
+
scope: scope,
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
const response = await fetch(`${OAUTH_BASE_URL}/device/code`, {
|
|
116
|
+
method: 'POST',
|
|
117
|
+
headers: {
|
|
118
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
119
|
+
},
|
|
120
|
+
body: body.toString(),
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
const errorData = await response.json().catch(() => ({}))
|
|
125
|
+
const errorCode = errorData.error || 'unknown_error'
|
|
126
|
+
const errorDescription = errorData.error_description || `Request failed with status ${response.status}`
|
|
127
|
+
throw new Error(`${errorCode}: ${errorDescription}`)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return response.json()
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// ============================================================================
|
|
134
|
+
// Token Polling
|
|
135
|
+
// ============================================================================
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Poll the OAuth server for a token
|
|
139
|
+
*/
|
|
140
|
+
export async function pollForToken(deviceCode: string, options: PollOptions): Promise<TokenResponse> {
|
|
141
|
+
const { maxAttempts, onProgress } = options
|
|
142
|
+
let interval = options.interval
|
|
143
|
+
let attempt = 0
|
|
144
|
+
|
|
145
|
+
while (attempt < maxAttempts) {
|
|
146
|
+
attempt++
|
|
147
|
+
|
|
148
|
+
// Call onProgress before attempting (for first attempt)
|
|
149
|
+
if (onProgress && attempt > 1) {
|
|
150
|
+
onProgress({ attempt: attempt - 1, maxAttempts })
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const body = new URLSearchParams({
|
|
154
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
155
|
+
device_code: deviceCode,
|
|
156
|
+
client_id: DEFAULT_CLIENT_ID,
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
const response = await fetch(`${OAUTH_BASE_URL}/token`, {
|
|
160
|
+
method: 'POST',
|
|
161
|
+
headers: {
|
|
162
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
163
|
+
},
|
|
164
|
+
body: body.toString(),
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
if (response.ok) {
|
|
168
|
+
return response.json()
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const errorData = await response.json().catch(() => ({ error: 'unknown_error' }))
|
|
172
|
+
const errorCode = errorData.error
|
|
173
|
+
|
|
174
|
+
if (errorCode === 'authorization_pending') {
|
|
175
|
+
// Wait and continue polling
|
|
176
|
+
await sleep(interval * 1000)
|
|
177
|
+
continue
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (errorCode === 'slow_down') {
|
|
181
|
+
// Increase interval by 5 seconds and continue polling
|
|
182
|
+
interval += 5
|
|
183
|
+
await sleep(interval * 1000)
|
|
184
|
+
continue
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (errorCode === 'access_denied') {
|
|
188
|
+
throw createPollError('access_denied', 'access_denied: User denied access')
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (errorCode === 'expired_token') {
|
|
192
|
+
throw createPollError('expired_token', 'expired_token: Device code expired')
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Unknown error
|
|
196
|
+
throw new Error(errorData.error_description || errorCode || 'Token request failed')
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Max attempts reached
|
|
200
|
+
throw createPollError('timeout', 'timeout: Polling timed out waiting for authorization')
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ============================================================================
|
|
204
|
+
// Token Storage
|
|
205
|
+
// ============================================================================
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Store a token to the local config file
|
|
209
|
+
*/
|
|
210
|
+
export async function storeToken(token: TokenResponse): Promise<void> {
|
|
211
|
+
const configDir = getConfigDir()
|
|
212
|
+
const configPath = getConfigPath()
|
|
213
|
+
|
|
214
|
+
// Check if directory exists, create if not
|
|
215
|
+
try {
|
|
216
|
+
await access(configDir)
|
|
217
|
+
} catch {
|
|
218
|
+
await mkdir(configDir, { recursive: true, mode: 0o700 })
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Build stored token data
|
|
222
|
+
const storedToken: StoredToken = {
|
|
223
|
+
access_token: token.access_token,
|
|
224
|
+
token_type: token.token_type,
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (token.refresh_token) {
|
|
228
|
+
storedToken.refresh_token = token.refresh_token
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (token.expires_in) {
|
|
232
|
+
storedToken.expires_at = Date.now() + token.expires_in * 1000
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (token.scope) {
|
|
236
|
+
storedToken.scope = token.scope
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Write token file with secure permissions
|
|
240
|
+
await writeFile(configPath, JSON.stringify(storedToken, null, 2), { mode: 0o600 })
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get the stored token from the local config file
|
|
245
|
+
*/
|
|
246
|
+
export async function getStoredToken(): Promise<StoredToken | null> {
|
|
247
|
+
const configPath = getConfigPath()
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
const content = await readFile(configPath, 'utf-8')
|
|
251
|
+
const data = JSON.parse(content)
|
|
252
|
+
|
|
253
|
+
// Validate token structure
|
|
254
|
+
if (!data.access_token || !data.token_type) {
|
|
255
|
+
return null
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Check expiration (only if no refresh token available)
|
|
259
|
+
if (data.expires_at && data.expires_at < Date.now() && !data.refresh_token) {
|
|
260
|
+
return null
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return data as StoredToken
|
|
264
|
+
} catch (error: unknown) {
|
|
265
|
+
// File doesn't exist or other error
|
|
266
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
|
|
267
|
+
return null
|
|
268
|
+
}
|
|
269
|
+
// JSON parse error or other issues
|
|
270
|
+
return null
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Clear the stored token
|
|
276
|
+
*/
|
|
277
|
+
export async function clearToken(): Promise<boolean> {
|
|
278
|
+
const configPath = getConfigPath()
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
await unlink(configPath)
|
|
282
|
+
return true
|
|
283
|
+
} catch (error: unknown) {
|
|
284
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
|
|
285
|
+
return false
|
|
286
|
+
}
|
|
287
|
+
throw error
|
|
288
|
+
}
|
|
289
|
+
}
|
package/cli/fallback.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Fallback Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles unrecognized commands by passing them to AI for processing.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Process natural language input through AI
|
|
9
|
+
*/
|
|
10
|
+
export async function fallback(_input: string[]): Promise<void> {
|
|
11
|
+
// Placeholder - AI integration will be implemented
|
|
12
|
+
}
|
package/cli/index.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Router
|
|
3
|
+
*
|
|
4
|
+
* Routes CLI commands to appropriate handlers or AI fallback.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { commands } from './commands/index'
|
|
8
|
+
import pkg from '../package.json'
|
|
9
|
+
|
|
10
|
+
export type RouteResult =
|
|
11
|
+
| { type: 'help' }
|
|
12
|
+
| { type: 'version' }
|
|
13
|
+
| { type: 'command'; name: string; args: string[] }
|
|
14
|
+
| { type: 'fallback'; input: string[] }
|
|
15
|
+
|
|
16
|
+
/** Known command names */
|
|
17
|
+
const knownCommands = [
|
|
18
|
+
// Auth commands
|
|
19
|
+
'login',
|
|
20
|
+
'logout',
|
|
21
|
+
// Dev commands
|
|
22
|
+
'dev',
|
|
23
|
+
'build',
|
|
24
|
+
'deploy',
|
|
25
|
+
'init',
|
|
26
|
+
'introspect',
|
|
27
|
+
// Service commands (cli.do)
|
|
28
|
+
'call',
|
|
29
|
+
'text',
|
|
30
|
+
'email',
|
|
31
|
+
'charge',
|
|
32
|
+
'queue',
|
|
33
|
+
'llm',
|
|
34
|
+
'config',
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
/** Version from package.json */
|
|
38
|
+
export const version = pkg.version
|
|
39
|
+
|
|
40
|
+
/** Help text for CLI */
|
|
41
|
+
export const helpText = `
|
|
42
|
+
Usage: do [command] [options]
|
|
43
|
+
|
|
44
|
+
Service Commands (cli.do):
|
|
45
|
+
call Make voice calls via calls.do
|
|
46
|
+
do call +15551234567 "Your appointment is tomorrow"
|
|
47
|
+
|
|
48
|
+
text Send SMS/MMS via texts.do
|
|
49
|
+
do text +15551234567 "Reply YES to confirm"
|
|
50
|
+
|
|
51
|
+
email Send emails via emails.do
|
|
52
|
+
do email user@example.com --template=welcome
|
|
53
|
+
|
|
54
|
+
charge Create charges via payments.do
|
|
55
|
+
do charge cus_123 --amount=9900
|
|
56
|
+
|
|
57
|
+
queue Queue operations via queue.do
|
|
58
|
+
do queue publish my-queue '{"event": "user.signup"}'
|
|
59
|
+
|
|
60
|
+
llm LLM requests via llm.do (with streaming)
|
|
61
|
+
do llm "Summarize this document" --model=claude-sonnet
|
|
62
|
+
|
|
63
|
+
config Manage CLI configuration
|
|
64
|
+
do config set json_output true
|
|
65
|
+
|
|
66
|
+
Auth Commands:
|
|
67
|
+
login Log in to your account (id.org.ai OAuth)
|
|
68
|
+
logout Log out of your account
|
|
69
|
+
|
|
70
|
+
Dev Commands:
|
|
71
|
+
dev Start development server
|
|
72
|
+
build Build the project
|
|
73
|
+
deploy Deploy to production
|
|
74
|
+
init Initialize a new project
|
|
75
|
+
introspect Generate .do/types.d.ts from DB.mdx schemas
|
|
76
|
+
|
|
77
|
+
Options:
|
|
78
|
+
-h, --help Show help
|
|
79
|
+
-v, --version Show version
|
|
80
|
+
--json Output JSON (for service commands)
|
|
81
|
+
|
|
82
|
+
Any unrecognized commands will be passed to the AI fallback for natural language processing.
|
|
83
|
+
`
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Parse process.argv to extract CLI arguments
|
|
87
|
+
* Strips the runtime and script path
|
|
88
|
+
*/
|
|
89
|
+
export function parseArgv(argv: string[]): string[] {
|
|
90
|
+
return argv.slice(2)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Route CLI input to the appropriate handler
|
|
95
|
+
*/
|
|
96
|
+
export function route(argv: string[]): RouteResult {
|
|
97
|
+
const [command, ...args] = argv
|
|
98
|
+
|
|
99
|
+
// No command or help flag
|
|
100
|
+
if (!command || command === '--help' || command === '-h') {
|
|
101
|
+
return { type: 'help' }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Version flag
|
|
105
|
+
if (command === '--version' || command === '-v') {
|
|
106
|
+
return { type: 'version' }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// help command with no additional args
|
|
110
|
+
if (command === 'help' && args.length === 0) {
|
|
111
|
+
return { type: 'help' }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Known commands
|
|
115
|
+
if (knownCommands.includes(command)) {
|
|
116
|
+
return { type: 'command', name: command, args }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// AI fallback for unknown commands
|
|
120
|
+
return { type: 'fallback', input: argv }
|
|
121
|
+
}
|
package/cli/main.ts
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* dotdo CLI Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Self-contained CLI for Durable Objects development.
|
|
6
|
+
* Includes embedded runtime with full DO support for local development.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* dotdo dev - Start local development server
|
|
10
|
+
* dotdo do:list - List Durable Objects
|
|
11
|
+
* dotdo deploy - Deploy to production
|
|
12
|
+
* dotdo tunnel - Expose local server via CF Tunnel
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Command } from 'commander'
|
|
16
|
+
import { devCommand } from './commands/dev-local'
|
|
17
|
+
import { doCommand } from './commands/do-ops'
|
|
18
|
+
import { tunnelCommand } from './commands/tunnel'
|
|
19
|
+
import { deployCommand } from './commands/deploy-multi'
|
|
20
|
+
import { createLogger } from './utils/logger'
|
|
21
|
+
|
|
22
|
+
const logger = createLogger('cli')
|
|
23
|
+
|
|
24
|
+
// Package info
|
|
25
|
+
const pkg = {
|
|
26
|
+
name: 'dotdo',
|
|
27
|
+
version: '0.1.0',
|
|
28
|
+
description: 'Self-contained CLI for Durable Objects development',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const program = new Command()
|
|
32
|
+
.name('dotdo')
|
|
33
|
+
.description(pkg.description)
|
|
34
|
+
.version(pkg.version, '-v, --version', 'Show version number')
|
|
35
|
+
.option('--debug', 'Enable debug output')
|
|
36
|
+
|
|
37
|
+
// Handle debug flag at parse time
|
|
38
|
+
const originalParse = program.parse.bind(program)
|
|
39
|
+
program.parse = function (argv?: readonly string[], options?: { from: 'node' | 'electron' | 'user' }) {
|
|
40
|
+
// Pre-parse to check for --debug flag
|
|
41
|
+
const args = argv ?? process.argv
|
|
42
|
+
if (args.includes('--debug')) {
|
|
43
|
+
process.env.DEBUG = '1'
|
|
44
|
+
}
|
|
45
|
+
return originalParse(argv, options)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Add commands
|
|
49
|
+
program.addCommand(devCommand)
|
|
50
|
+
program.addCommand(doCommand)
|
|
51
|
+
program.addCommand(tunnelCommand)
|
|
52
|
+
program.addCommand(deployCommand)
|
|
53
|
+
|
|
54
|
+
// Init command
|
|
55
|
+
program
|
|
56
|
+
.command('init')
|
|
57
|
+
.description('Initialize a new dotdo project')
|
|
58
|
+
.option('-t, --template <template>', 'Project template', 'default')
|
|
59
|
+
.option('--no-git', 'Skip git initialization')
|
|
60
|
+
.action(async (options) => {
|
|
61
|
+
logger.info('Initializing new dotdo project...')
|
|
62
|
+
|
|
63
|
+
const fs = await import('fs')
|
|
64
|
+
const path = await import('path')
|
|
65
|
+
|
|
66
|
+
const cwd = process.cwd()
|
|
67
|
+
|
|
68
|
+
// Create basic structure
|
|
69
|
+
const dirs = ['.dotdo', 'objects', 'api']
|
|
70
|
+
for (const dir of dirs) {
|
|
71
|
+
const dirPath = path.join(cwd, dir)
|
|
72
|
+
if (!fs.existsSync(dirPath)) {
|
|
73
|
+
fs.mkdirSync(dirPath, { recursive: true })
|
|
74
|
+
logger.debug(`Created: ${dir}/`)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Create dotdo.config.ts
|
|
79
|
+
const configPath = path.join(cwd, 'dotdo.config.ts')
|
|
80
|
+
if (!fs.existsSync(configPath)) {
|
|
81
|
+
const configContent = `/**
|
|
82
|
+
* dotdo configuration
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
import type { DotdoConfig } from 'dotdo/cli'
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
port: 8787,
|
|
89
|
+
entryPoint: 'index.ts',
|
|
90
|
+
compatibilityDate: '2024-01-01',
|
|
91
|
+
compatibilityFlags: ['nodejs_compat'],
|
|
92
|
+
} satisfies DotdoConfig
|
|
93
|
+
`
|
|
94
|
+
fs.writeFileSync(configPath, configContent)
|
|
95
|
+
logger.debug('Created: dotdo.config.ts')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Create example DO
|
|
99
|
+
const examplePath = path.join(cwd, 'objects', 'Counter.ts')
|
|
100
|
+
if (!fs.existsSync(examplePath)) {
|
|
101
|
+
const exampleContent = `/**
|
|
102
|
+
* Example Durable Object: Counter
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
export class Counter extends DurableObject {
|
|
106
|
+
private count: number = 0
|
|
107
|
+
|
|
108
|
+
constructor(ctx: DurableObjectState, env: Env) {
|
|
109
|
+
super(ctx, env)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async fetch(request: Request): Promise<Response> {
|
|
113
|
+
const url = new URL(request.url)
|
|
114
|
+
|
|
115
|
+
if (url.pathname === '/increment') {
|
|
116
|
+
this.count++
|
|
117
|
+
await this.ctx.storage.put('count', this.count)
|
|
118
|
+
return new Response(JSON.stringify({ count: this.count }))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (url.pathname === '/decrement') {
|
|
122
|
+
this.count--
|
|
123
|
+
await this.ctx.storage.put('count', this.count)
|
|
124
|
+
return new Response(JSON.stringify({ count: this.count }))
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return new Response(JSON.stringify({ count: this.count }))
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
`
|
|
131
|
+
fs.writeFileSync(examplePath, exampleContent)
|
|
132
|
+
logger.debug('Created: objects/Counter.ts')
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Create index.ts
|
|
136
|
+
const indexPath = path.join(cwd, 'index.ts')
|
|
137
|
+
if (!fs.existsSync(indexPath)) {
|
|
138
|
+
const indexContent = `/**
|
|
139
|
+
* Worker entry point
|
|
140
|
+
*/
|
|
141
|
+
|
|
142
|
+
import { Counter } from './objects/Counter'
|
|
143
|
+
|
|
144
|
+
export { Counter }
|
|
145
|
+
|
|
146
|
+
export default {
|
|
147
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
148
|
+
const url = new URL(request.url)
|
|
149
|
+
|
|
150
|
+
// Route to Counter DO
|
|
151
|
+
if (url.pathname.startsWith('/counter')) {
|
|
152
|
+
const id = env.COUNTER.idFromName('default')
|
|
153
|
+
const counter = env.COUNTER.get(id)
|
|
154
|
+
return counter.fetch(request)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return new Response('Hello from dotdo!')
|
|
158
|
+
},
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
interface Env {
|
|
162
|
+
COUNTER: DurableObjectNamespace
|
|
163
|
+
}
|
|
164
|
+
`
|
|
165
|
+
fs.writeFileSync(indexPath, indexContent)
|
|
166
|
+
logger.debug('Created: index.ts')
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Initialize git
|
|
170
|
+
if (options.git) {
|
|
171
|
+
const { execSync } = await import('child_process')
|
|
172
|
+
try {
|
|
173
|
+
if (!fs.existsSync(path.join(cwd, '.git'))) {
|
|
174
|
+
execSync('git init', { cwd, stdio: 'ignore' })
|
|
175
|
+
logger.debug('Initialized git repository')
|
|
176
|
+
}
|
|
177
|
+
} catch {
|
|
178
|
+
// Git not available
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
console.log()
|
|
183
|
+
logger.success('Project initialized!')
|
|
184
|
+
console.log()
|
|
185
|
+
console.log(' Next steps:')
|
|
186
|
+
console.log(' 1. Run: dotdo dev')
|
|
187
|
+
console.log(' 2. Visit: http://localhost:8787')
|
|
188
|
+
console.log(' 3. Try: http://localhost:8787/counter/increment')
|
|
189
|
+
console.log()
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
// Logs command
|
|
193
|
+
program
|
|
194
|
+
.command('logs')
|
|
195
|
+
.description('Stream logs from deployed workers')
|
|
196
|
+
.option('-f, --follow', 'Follow log output', true)
|
|
197
|
+
.option('--format <format>', 'Output format (json, pretty)', 'pretty')
|
|
198
|
+
.action(async (options) => {
|
|
199
|
+
const { spawn } = await import('child_process')
|
|
200
|
+
|
|
201
|
+
const args = ['wrangler', 'tail']
|
|
202
|
+
if (options.format === 'json') {
|
|
203
|
+
args.push('--format', 'json')
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const proc = spawn('bunx', args, {
|
|
207
|
+
stdio: 'inherit',
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
proc.on('error', (error) => {
|
|
211
|
+
logger.error('Failed to start wrangler tail', { error: error.message })
|
|
212
|
+
process.exit(1)
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// Build command
|
|
217
|
+
program
|
|
218
|
+
.command('build')
|
|
219
|
+
.description('Build the project')
|
|
220
|
+
.option('-w, --watch', 'Watch for changes')
|
|
221
|
+
.action(async (options) => {
|
|
222
|
+
const { spawn } = await import('child_process')
|
|
223
|
+
|
|
224
|
+
logger.info('Building project...')
|
|
225
|
+
|
|
226
|
+
const args = ['tsc', '-p', 'tsconfig.json']
|
|
227
|
+
if (options.watch) {
|
|
228
|
+
args.push('--watch')
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const proc = spawn('bunx', args, {
|
|
232
|
+
stdio: 'inherit',
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
proc.on('exit', (code) => {
|
|
236
|
+
if (code === 0) {
|
|
237
|
+
logger.success('Build complete')
|
|
238
|
+
} else {
|
|
239
|
+
logger.error('Build failed')
|
|
240
|
+
process.exit(code ?? 1)
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
// Parse arguments
|
|
246
|
+
program.parse()
|