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
|
@@ -1,804 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extended Utility Commands
|
|
3
|
-
*
|
|
4
|
-
* Native implementations for extended utility commands:
|
|
5
|
-
* - env: Run with modified environment
|
|
6
|
-
* - id: Print user/group identity
|
|
7
|
-
* - uname: Print system info
|
|
8
|
-
* - timeout: Run command with time limit
|
|
9
|
-
* - tac: Reverse line order
|
|
10
|
-
* - shuf: Shuffle lines (Fisher-Yates)
|
|
11
|
-
*
|
|
12
|
-
* @module bashx/do/commands/extended-utils
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* Parse env command arguments
|
|
16
|
-
*
|
|
17
|
-
* @param args - Command line arguments
|
|
18
|
-
* @returns Parsed env options
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```typescript
|
|
22
|
-
* parseEnvArgs(['-i', 'PATH=/usr/bin', 'ls'])
|
|
23
|
-
* // => { ignoreEnvironment: true, variables: { PATH: '/usr/bin' }, command: ['ls'] }
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export function parseEnvArgs(args) {
|
|
27
|
-
const options = {
|
|
28
|
-
ignoreEnvironment: false,
|
|
29
|
-
variables: {},
|
|
30
|
-
unset: [],
|
|
31
|
-
command: [],
|
|
32
|
-
};
|
|
33
|
-
let i = 0;
|
|
34
|
-
while (i < args.length) {
|
|
35
|
-
const arg = args[i];
|
|
36
|
-
if (arg === '-i' || arg === '--ignore-environment') {
|
|
37
|
-
options.ignoreEnvironment = true;
|
|
38
|
-
i++;
|
|
39
|
-
}
|
|
40
|
-
else if (arg === '-u' || arg === '--unset') {
|
|
41
|
-
if (args[i + 1]) {
|
|
42
|
-
options.unset.push(args[i + 1]);
|
|
43
|
-
i += 2;
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
i++;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
else if (arg.startsWith('-u')) {
|
|
50
|
-
// Handle -uVAR form
|
|
51
|
-
options.unset.push(arg.slice(2));
|
|
52
|
-
i++;
|
|
53
|
-
}
|
|
54
|
-
else if (arg === '-C' || arg === '--chdir') {
|
|
55
|
-
if (args[i + 1]) {
|
|
56
|
-
options.chdir = args[i + 1];
|
|
57
|
-
i += 2;
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
i++;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else if (arg.includes('=') && !arg.startsWith('-')) {
|
|
64
|
-
// VAR=value assignment
|
|
65
|
-
const eqIdx = arg.indexOf('=');
|
|
66
|
-
const varName = arg.slice(0, eqIdx);
|
|
67
|
-
const varValue = arg.slice(eqIdx + 1);
|
|
68
|
-
options.variables[varName] = varValue;
|
|
69
|
-
i++;
|
|
70
|
-
}
|
|
71
|
-
else if (arg === '--') {
|
|
72
|
-
// End of options, rest is command
|
|
73
|
-
options.command = args.slice(i + 1);
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
else if (!arg.startsWith('-')) {
|
|
77
|
-
// Start of command
|
|
78
|
-
options.command = args.slice(i);
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
// Unknown option, treat as command
|
|
83
|
-
options.command = args.slice(i);
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return options;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Execute env command - run with modified environment
|
|
91
|
-
*
|
|
92
|
-
* When called with no command, prints the environment.
|
|
93
|
-
* When called with a command, runs it with the modified environment.
|
|
94
|
-
*
|
|
95
|
-
* @param baseEnv - Base environment to start with
|
|
96
|
-
* @param options - Env options
|
|
97
|
-
* @returns Modified environment or result of command execution
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```typescript
|
|
101
|
-
* // Print modified environment
|
|
102
|
-
* executeEnv({ HOME: '/root' }, { variables: { FOO: 'bar' } })
|
|
103
|
-
* // => { env: { HOME: '/root', FOO: 'bar' }, command: undefined }
|
|
104
|
-
*
|
|
105
|
-
* // Prepare environment for command
|
|
106
|
-
* executeEnv({}, { ignoreEnvironment: true, variables: { PATH: '/bin' } })
|
|
107
|
-
* // => { env: { PATH: '/bin' }, command: undefined }
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
|
-
export function executeEnv(baseEnv, options) {
|
|
111
|
-
// Start with empty or base environment
|
|
112
|
-
let env = options.ignoreEnvironment ? {} : { ...baseEnv };
|
|
113
|
-
// Unset specified variables
|
|
114
|
-
if (options.unset) {
|
|
115
|
-
for (const varName of options.unset) {
|
|
116
|
-
delete env[varName];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// Set new variables
|
|
120
|
-
if (options.variables) {
|
|
121
|
-
env = { ...env, ...options.variables };
|
|
122
|
-
}
|
|
123
|
-
return {
|
|
124
|
-
env,
|
|
125
|
-
command: options.command && options.command.length > 0 ? options.command : undefined,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Format environment for output
|
|
130
|
-
*
|
|
131
|
-
* @param env - Environment variables
|
|
132
|
-
* @returns Formatted string (one VAR=value per line)
|
|
133
|
-
*/
|
|
134
|
-
export function formatEnv(env) {
|
|
135
|
-
return Object.entries(env)
|
|
136
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
137
|
-
.map(([k, v]) => `${k}=${v}`)
|
|
138
|
-
.join('\n') + (Object.keys(env).length > 0 ? '\n' : '');
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Parse id command arguments
|
|
142
|
-
*
|
|
143
|
-
* @param args - Command line arguments
|
|
144
|
-
* @returns Parsed id options
|
|
145
|
-
*/
|
|
146
|
-
export function parseIdArgs(args) {
|
|
147
|
-
const options = {};
|
|
148
|
-
for (let i = 0; i < args.length; i++) {
|
|
149
|
-
const arg = args[i];
|
|
150
|
-
if (arg === '-u' || arg === '--user') {
|
|
151
|
-
options.user = true;
|
|
152
|
-
}
|
|
153
|
-
else if (arg === '-g' || arg === '--group') {
|
|
154
|
-
options.group = true;
|
|
155
|
-
}
|
|
156
|
-
else if (arg === '-n' || arg === '--name') {
|
|
157
|
-
options.name = true;
|
|
158
|
-
}
|
|
159
|
-
else if (arg === '-r' || arg === '--real') {
|
|
160
|
-
options.real = true;
|
|
161
|
-
}
|
|
162
|
-
else if (arg === '-G' || arg === '--groups') {
|
|
163
|
-
options.groups = true;
|
|
164
|
-
}
|
|
165
|
-
else if (!arg.startsWith('-')) {
|
|
166
|
-
options.username = arg;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return options;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Execute id command - print user/group identity
|
|
173
|
-
*
|
|
174
|
-
* @param identity - Identity information to format
|
|
175
|
-
* @param options - Id options
|
|
176
|
-
* @returns Formatted identity string
|
|
177
|
-
*
|
|
178
|
-
* @example
|
|
179
|
-
* ```typescript
|
|
180
|
-
* const identity = { uid: 1000, gid: 1000, username: 'user', groupname: 'user', groups: [] }
|
|
181
|
-
*
|
|
182
|
-
* executeId(identity, {})
|
|
183
|
-
* // => 'uid=1000(user) gid=1000(user) groups=1000(user)'
|
|
184
|
-
*
|
|
185
|
-
* executeId(identity, { user: true })
|
|
186
|
-
* // => '1000'
|
|
187
|
-
*
|
|
188
|
-
* executeId(identity, { user: true, name: true })
|
|
189
|
-
* // => 'user'
|
|
190
|
-
* ```
|
|
191
|
-
*/
|
|
192
|
-
export function executeId(identity, options = {}) {
|
|
193
|
-
// Handle -G (all groups)
|
|
194
|
-
if (options.groups) {
|
|
195
|
-
if (options.name) {
|
|
196
|
-
return identity.groups.map(g => g.name).join(' ');
|
|
197
|
-
}
|
|
198
|
-
return identity.groups.map(g => g.gid).join(' ');
|
|
199
|
-
}
|
|
200
|
-
// Handle -u (user)
|
|
201
|
-
if (options.user) {
|
|
202
|
-
const uid = options.real ? identity.uid : (identity.euid ?? identity.uid);
|
|
203
|
-
if (options.name) {
|
|
204
|
-
return identity.username;
|
|
205
|
-
}
|
|
206
|
-
return String(uid);
|
|
207
|
-
}
|
|
208
|
-
// Handle -g (group)
|
|
209
|
-
if (options.group) {
|
|
210
|
-
const gid = options.real ? identity.gid : (identity.egid ?? identity.gid);
|
|
211
|
-
if (options.name) {
|
|
212
|
-
return identity.groupname;
|
|
213
|
-
}
|
|
214
|
-
return String(gid);
|
|
215
|
-
}
|
|
216
|
-
// Default: full output
|
|
217
|
-
const parts = [];
|
|
218
|
-
parts.push(`uid=${identity.uid}(${identity.username})`);
|
|
219
|
-
parts.push(`gid=${identity.gid}(${identity.groupname})`);
|
|
220
|
-
const groupsStr = identity.groups.map(g => `${g.gid}(${g.name})`).join(',');
|
|
221
|
-
parts.push(`groups=${groupsStr || `${identity.gid}(${identity.groupname})`}`);
|
|
222
|
-
return parts.join(' ');
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Default identity for Workers environment
|
|
226
|
-
*/
|
|
227
|
-
export const DEFAULT_WORKER_IDENTITY = {
|
|
228
|
-
uid: 1000,
|
|
229
|
-
gid: 1000,
|
|
230
|
-
username: 'worker',
|
|
231
|
-
groupname: 'worker',
|
|
232
|
-
groups: [{ gid: 1000, name: 'worker' }],
|
|
233
|
-
};
|
|
234
|
-
/**
|
|
235
|
-
* Parse uname command arguments
|
|
236
|
-
*
|
|
237
|
-
* @param args - Command line arguments
|
|
238
|
-
* @returns Parsed uname options
|
|
239
|
-
*/
|
|
240
|
-
export function parseUnameArgs(args) {
|
|
241
|
-
const options = {};
|
|
242
|
-
for (const arg of args) {
|
|
243
|
-
if (arg === '-a' || arg === '--all') {
|
|
244
|
-
options.all = true;
|
|
245
|
-
}
|
|
246
|
-
else if (arg === '-s' || arg === '--kernel-name') {
|
|
247
|
-
options.kernelName = true;
|
|
248
|
-
}
|
|
249
|
-
else if (arg === '-n' || arg === '--nodename') {
|
|
250
|
-
options.nodeName = true;
|
|
251
|
-
}
|
|
252
|
-
else if (arg === '-r' || arg === '--kernel-release') {
|
|
253
|
-
options.kernelRelease = true;
|
|
254
|
-
}
|
|
255
|
-
else if (arg === '-v' || arg === '--kernel-version') {
|
|
256
|
-
options.kernelVersion = true;
|
|
257
|
-
}
|
|
258
|
-
else if (arg === '-m' || arg === '--machine') {
|
|
259
|
-
options.machine = true;
|
|
260
|
-
}
|
|
261
|
-
else if (arg === '-p' || arg === '--processor') {
|
|
262
|
-
options.processor = true;
|
|
263
|
-
}
|
|
264
|
-
else if (arg === '-i' || arg === '--hardware-platform') {
|
|
265
|
-
options.hardwarePlatform = true;
|
|
266
|
-
}
|
|
267
|
-
else if (arg === '-o' || arg === '--operating-system') {
|
|
268
|
-
options.operatingSystem = true;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
// If no options specified, default to -s
|
|
272
|
-
const hasAnyOption = options.all || options.kernelName || options.nodeName ||
|
|
273
|
-
options.kernelRelease || options.kernelVersion || options.machine ||
|
|
274
|
-
options.processor || options.hardwarePlatform || options.operatingSystem;
|
|
275
|
-
if (!hasAnyOption) {
|
|
276
|
-
options.kernelName = true;
|
|
277
|
-
}
|
|
278
|
-
return options;
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Execute uname command - print system information
|
|
282
|
-
*
|
|
283
|
-
* @param sysinfo - System information
|
|
284
|
-
* @param options - Uname options
|
|
285
|
-
* @returns Formatted system information string
|
|
286
|
-
*
|
|
287
|
-
* @example
|
|
288
|
-
* ```typescript
|
|
289
|
-
* const sysinfo = {
|
|
290
|
-
* kernelName: 'CloudflareWorkers',
|
|
291
|
-
* nodeName: 'edge',
|
|
292
|
-
* kernelRelease: '1.0.0',
|
|
293
|
-
* kernelVersion: '#1 SMP',
|
|
294
|
-
* machine: 'wasm32',
|
|
295
|
-
* processor: 'wasm32',
|
|
296
|
-
* hardwarePlatform: 'wasm32',
|
|
297
|
-
* operatingSystem: 'CloudflareWorkers'
|
|
298
|
-
* }
|
|
299
|
-
*
|
|
300
|
-
* executeUname(sysinfo, {})
|
|
301
|
-
* // => 'CloudflareWorkers'
|
|
302
|
-
*
|
|
303
|
-
* executeUname(sysinfo, { all: true })
|
|
304
|
-
* // => 'CloudflareWorkers edge 1.0.0 #1 SMP wasm32 wasm32 wasm32 CloudflareWorkers'
|
|
305
|
-
* ```
|
|
306
|
-
*/
|
|
307
|
-
export function executeUname(sysinfo, options = {}) {
|
|
308
|
-
const parts = [];
|
|
309
|
-
// Check if any option is specified
|
|
310
|
-
const hasAnyOption = options.all || options.kernelName || options.nodeName ||
|
|
311
|
-
options.kernelRelease || options.kernelVersion || options.machine ||
|
|
312
|
-
options.processor || options.hardwarePlatform || options.operatingSystem;
|
|
313
|
-
// Default to kernel name if no options specified
|
|
314
|
-
const effectiveOptions = hasAnyOption ? options : { ...options, kernelName: true };
|
|
315
|
-
if (effectiveOptions.all) {
|
|
316
|
-
parts.push(sysinfo.kernelName, sysinfo.nodeName, sysinfo.kernelRelease, sysinfo.kernelVersion, sysinfo.machine, sysinfo.processor, sysinfo.hardwarePlatform, sysinfo.operatingSystem);
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
if (effectiveOptions.kernelName)
|
|
320
|
-
parts.push(sysinfo.kernelName);
|
|
321
|
-
if (effectiveOptions.nodeName)
|
|
322
|
-
parts.push(sysinfo.nodeName);
|
|
323
|
-
if (effectiveOptions.kernelRelease)
|
|
324
|
-
parts.push(sysinfo.kernelRelease);
|
|
325
|
-
if (effectiveOptions.kernelVersion)
|
|
326
|
-
parts.push(sysinfo.kernelVersion);
|
|
327
|
-
if (effectiveOptions.machine)
|
|
328
|
-
parts.push(sysinfo.machine);
|
|
329
|
-
if (effectiveOptions.processor)
|
|
330
|
-
parts.push(sysinfo.processor);
|
|
331
|
-
if (effectiveOptions.hardwarePlatform)
|
|
332
|
-
parts.push(sysinfo.hardwarePlatform);
|
|
333
|
-
if (effectiveOptions.operatingSystem)
|
|
334
|
-
parts.push(sysinfo.operatingSystem);
|
|
335
|
-
}
|
|
336
|
-
return parts.join(' ');
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Default system info for Cloudflare Workers environment
|
|
340
|
-
*/
|
|
341
|
-
export const DEFAULT_WORKER_SYSINFO = {
|
|
342
|
-
kernelName: 'CloudflareWorkers',
|
|
343
|
-
nodeName: 'edge',
|
|
344
|
-
kernelRelease: '1.0.0',
|
|
345
|
-
kernelVersion: '#1 SMP',
|
|
346
|
-
machine: 'wasm32',
|
|
347
|
-
processor: 'wasm32',
|
|
348
|
-
hardwarePlatform: 'wasm32',
|
|
349
|
-
operatingSystem: 'CloudflareWorkers',
|
|
350
|
-
};
|
|
351
|
-
/**
|
|
352
|
-
* Time unit multipliers in milliseconds
|
|
353
|
-
*/
|
|
354
|
-
const TIME_UNIT_MS = {
|
|
355
|
-
s: 1000,
|
|
356
|
-
m: 60 * 1000,
|
|
357
|
-
h: 60 * 60 * 1000,
|
|
358
|
-
d: 24 * 60 * 60 * 1000,
|
|
359
|
-
};
|
|
360
|
-
/**
|
|
361
|
-
* Signal name to number mapping
|
|
362
|
-
*/
|
|
363
|
-
const SIGNAL_MAP = {
|
|
364
|
-
TERM: 15,
|
|
365
|
-
SIGTERM: 15,
|
|
366
|
-
KILL: 9,
|
|
367
|
-
SIGKILL: 9,
|
|
368
|
-
INT: 2,
|
|
369
|
-
SIGINT: 2,
|
|
370
|
-
HUP: 1,
|
|
371
|
-
SIGHUP: 1,
|
|
372
|
-
QUIT: 3,
|
|
373
|
-
SIGQUIT: 3,
|
|
374
|
-
ALRM: 14,
|
|
375
|
-
SIGALRM: 14,
|
|
376
|
-
USR1: 10,
|
|
377
|
-
SIGUSR1: 10,
|
|
378
|
-
USR2: 12,
|
|
379
|
-
SIGUSR2: 12,
|
|
380
|
-
};
|
|
381
|
-
/**
|
|
382
|
-
* Parse duration string to milliseconds
|
|
383
|
-
*
|
|
384
|
-
* @param duration - Duration string (e.g., '5', '1.5s', '2m', '1h')
|
|
385
|
-
* @returns Duration in milliseconds
|
|
386
|
-
* @throws Error if format is invalid
|
|
387
|
-
*/
|
|
388
|
-
export function parseTimeoutDuration(duration) {
|
|
389
|
-
if (duration === 'infinity') {
|
|
390
|
-
return Infinity;
|
|
391
|
-
}
|
|
392
|
-
const match = duration.match(/^(\d+(?:\.\d+)?)(s|m|h|d)?$/);
|
|
393
|
-
if (!match) {
|
|
394
|
-
throw new Error(`Invalid duration: ${duration}`);
|
|
395
|
-
}
|
|
396
|
-
const value = parseFloat(match[1]);
|
|
397
|
-
const unit = match[2] || 's';
|
|
398
|
-
return value * (TIME_UNIT_MS[unit] ?? 1000);
|
|
399
|
-
}
|
|
400
|
-
/**
|
|
401
|
-
* Parse signal name or number to signal number
|
|
402
|
-
*
|
|
403
|
-
* @param signal - Signal name (e.g., 'TERM', 'SIGKILL') or number
|
|
404
|
-
* @returns Signal number
|
|
405
|
-
*/
|
|
406
|
-
export function parseSignal(signal) {
|
|
407
|
-
if (typeof signal === 'number') {
|
|
408
|
-
return signal;
|
|
409
|
-
}
|
|
410
|
-
return SIGNAL_MAP[signal.toUpperCase()] ?? (parseInt(signal, 10) || 15);
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* Parse timeout command arguments
|
|
414
|
-
*
|
|
415
|
-
* @param args - Command line arguments
|
|
416
|
-
* @returns Parsed timeout options and command
|
|
417
|
-
*/
|
|
418
|
-
export function parseTimeoutArgs(args) {
|
|
419
|
-
const options = {
|
|
420
|
-
duration: '',
|
|
421
|
-
preserveStatus: false,
|
|
422
|
-
foreground: false,
|
|
423
|
-
verbose: false,
|
|
424
|
-
};
|
|
425
|
-
let i = 0;
|
|
426
|
-
while (i < args.length) {
|
|
427
|
-
const arg = args[i];
|
|
428
|
-
if (arg === '-k' || arg === '--kill-after') {
|
|
429
|
-
options.killAfter = args[++i];
|
|
430
|
-
i++;
|
|
431
|
-
}
|
|
432
|
-
else if (arg.startsWith('-k')) {
|
|
433
|
-
options.killAfter = arg.slice(2);
|
|
434
|
-
i++;
|
|
435
|
-
}
|
|
436
|
-
else if (arg === '-s' || arg === '--signal') {
|
|
437
|
-
options.signal = args[++i];
|
|
438
|
-
i++;
|
|
439
|
-
}
|
|
440
|
-
else if (arg.startsWith('-s')) {
|
|
441
|
-
options.signal = arg.slice(2);
|
|
442
|
-
i++;
|
|
443
|
-
}
|
|
444
|
-
else if (arg === '--preserve-status') {
|
|
445
|
-
options.preserveStatus = true;
|
|
446
|
-
i++;
|
|
447
|
-
}
|
|
448
|
-
else if (arg === '--foreground') {
|
|
449
|
-
options.foreground = true;
|
|
450
|
-
i++;
|
|
451
|
-
}
|
|
452
|
-
else if (arg === '-v' || arg === '--verbose') {
|
|
453
|
-
options.verbose = true;
|
|
454
|
-
i++;
|
|
455
|
-
}
|
|
456
|
-
else if (arg === '--') {
|
|
457
|
-
// Duration should already be set, rest is command
|
|
458
|
-
return { options, command: args.slice(i + 1) };
|
|
459
|
-
}
|
|
460
|
-
else if (!arg.startsWith('-') && !options.duration) {
|
|
461
|
-
options.duration = arg;
|
|
462
|
-
i++;
|
|
463
|
-
}
|
|
464
|
-
else {
|
|
465
|
-
// Start of command
|
|
466
|
-
return { options, command: args.slice(i) };
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
return { options, command: [] };
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* Execute timeout command wrapper
|
|
473
|
-
*
|
|
474
|
-
* This provides the timeout logic; the actual command execution
|
|
475
|
-
* is handled by the executor that calls this.
|
|
476
|
-
*
|
|
477
|
-
* @param options - Timeout options
|
|
478
|
-
* @param commandExecutor - Function to execute the command
|
|
479
|
-
* @returns Promise with result including timedOut flag
|
|
480
|
-
*/
|
|
481
|
-
export async function executeTimeout(options, command, commandExecutor) {
|
|
482
|
-
// Parse timeout duration
|
|
483
|
-
let timeoutMs;
|
|
484
|
-
try {
|
|
485
|
-
timeoutMs = parseTimeoutDuration(options.duration);
|
|
486
|
-
}
|
|
487
|
-
catch {
|
|
488
|
-
return {
|
|
489
|
-
exitCode: 125,
|
|
490
|
-
stdout: '',
|
|
491
|
-
stderr: `timeout: invalid time interval '${options.duration}'`,
|
|
492
|
-
timedOut: false,
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
// Determine signal to use
|
|
496
|
-
const signalNum = options.signal ? parseSignal(options.signal) : 15;
|
|
497
|
-
// Create abort controller for timeout
|
|
498
|
-
const controller = new AbortController();
|
|
499
|
-
let timedOut = false;
|
|
500
|
-
const timer = setTimeout(() => {
|
|
501
|
-
timedOut = true;
|
|
502
|
-
controller.abort();
|
|
503
|
-
}, timeoutMs);
|
|
504
|
-
try {
|
|
505
|
-
// Execute command with race against timeout
|
|
506
|
-
const result = await Promise.race([
|
|
507
|
-
commandExecutor(command),
|
|
508
|
-
new Promise((_, reject) => {
|
|
509
|
-
controller.signal.addEventListener('abort', () => {
|
|
510
|
-
reject(new Error('TIMEOUT'));
|
|
511
|
-
});
|
|
512
|
-
}),
|
|
513
|
-
]);
|
|
514
|
-
clearTimeout(timer);
|
|
515
|
-
return { ...result, timedOut: false };
|
|
516
|
-
}
|
|
517
|
-
catch (error) {
|
|
518
|
-
clearTimeout(timer);
|
|
519
|
-
if (timedOut) {
|
|
520
|
-
const exitCode = options.preserveStatus ? 128 + signalNum : 124;
|
|
521
|
-
let stderr = '';
|
|
522
|
-
if (options.verbose) {
|
|
523
|
-
stderr = `timeout: sending signal ${signalNum === 9 ? 'KILL' : 'TERM'} to command '${command}'`;
|
|
524
|
-
}
|
|
525
|
-
// SIGKILL exit code is 137 (128 + 9)
|
|
526
|
-
const finalExitCode = signalNum === 9 ? 137 : exitCode;
|
|
527
|
-
return {
|
|
528
|
-
exitCode: finalExitCode,
|
|
529
|
-
stdout: '',
|
|
530
|
-
stderr,
|
|
531
|
-
timedOut: true,
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
// Re-throw non-timeout errors
|
|
535
|
-
throw error;
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
|
-
* Parse tac command arguments
|
|
540
|
-
*
|
|
541
|
-
* @param args - Command line arguments
|
|
542
|
-
* @returns Parsed options and file paths
|
|
543
|
-
*/
|
|
544
|
-
export function parseTacArgs(args) {
|
|
545
|
-
const options = {};
|
|
546
|
-
const files = [];
|
|
547
|
-
let i = 0;
|
|
548
|
-
while (i < args.length) {
|
|
549
|
-
const arg = args[i];
|
|
550
|
-
if (arg === '-s' || arg === '--separator') {
|
|
551
|
-
options.separator = args[++i];
|
|
552
|
-
i++;
|
|
553
|
-
}
|
|
554
|
-
else if (arg.startsWith('-s')) {
|
|
555
|
-
options.separator = arg.slice(2);
|
|
556
|
-
i++;
|
|
557
|
-
}
|
|
558
|
-
else if (arg === '-b' || arg === '--before') {
|
|
559
|
-
options.before = true;
|
|
560
|
-
i++;
|
|
561
|
-
}
|
|
562
|
-
else if (arg === '-r' || arg === '--regex') {
|
|
563
|
-
options.regex = true;
|
|
564
|
-
i++;
|
|
565
|
-
}
|
|
566
|
-
else if (arg === '--') {
|
|
567
|
-
files.push(...args.slice(i + 1));
|
|
568
|
-
break;
|
|
569
|
-
}
|
|
570
|
-
else if (!arg.startsWith('-')) {
|
|
571
|
-
files.push(arg);
|
|
572
|
-
i++;
|
|
573
|
-
}
|
|
574
|
-
else {
|
|
575
|
-
i++;
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
return { options, files };
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* Execute tac command - reverse lines in file(s)
|
|
582
|
-
*
|
|
583
|
-
* @param input - Input string to reverse
|
|
584
|
-
* @param options - Tac options
|
|
585
|
-
* @returns Reversed content
|
|
586
|
-
*
|
|
587
|
-
* @example
|
|
588
|
-
* ```typescript
|
|
589
|
-
* executeTac('line1\nline2\nline3\n')
|
|
590
|
-
* // => 'line3\nline2\nline1\n'
|
|
591
|
-
*
|
|
592
|
-
* executeTac('a|b|c|', { separator: '|' })
|
|
593
|
-
* // => 'c|b|a|'
|
|
594
|
-
* ```
|
|
595
|
-
*/
|
|
596
|
-
export function executeTac(input, options = {}) {
|
|
597
|
-
const separator = options.separator ?? '\n';
|
|
598
|
-
// Split input by separator
|
|
599
|
-
let parts;
|
|
600
|
-
if (options.regex) {
|
|
601
|
-
parts = input.split(new RegExp(separator));
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
|
-
parts = input.split(separator);
|
|
605
|
-
}
|
|
606
|
-
// Handle trailing empty element from trailing separator
|
|
607
|
-
const hadTrailingSep = parts[parts.length - 1] === '';
|
|
608
|
-
if (hadTrailingSep) {
|
|
609
|
-
parts.pop();
|
|
610
|
-
}
|
|
611
|
-
// Reverse the parts
|
|
612
|
-
parts.reverse();
|
|
613
|
-
// Reconstruct with separator
|
|
614
|
-
if (options.before) {
|
|
615
|
-
// Separator before each record
|
|
616
|
-
return parts.map(p => separator + p).join('');
|
|
617
|
-
}
|
|
618
|
-
// Separator after each record (default)
|
|
619
|
-
return parts.join(separator) + (parts.length > 0 ? separator : '');
|
|
620
|
-
}
|
|
621
|
-
/**
|
|
622
|
-
* Parse shuf command arguments
|
|
623
|
-
*
|
|
624
|
-
* @param args - Command line arguments
|
|
625
|
-
* @returns Parsed options and input files
|
|
626
|
-
*/
|
|
627
|
-
export function parseShufArgs(args) {
|
|
628
|
-
const options = {};
|
|
629
|
-
const files = [];
|
|
630
|
-
let echoMode = false;
|
|
631
|
-
let i = 0;
|
|
632
|
-
while (i < args.length) {
|
|
633
|
-
const arg = args[i];
|
|
634
|
-
if (arg === '-n' || arg === '--head-count') {
|
|
635
|
-
options.count = parseInt(args[++i], 10);
|
|
636
|
-
i++;
|
|
637
|
-
}
|
|
638
|
-
else if (arg.startsWith('-n')) {
|
|
639
|
-
options.count = parseInt(arg.slice(2), 10);
|
|
640
|
-
i++;
|
|
641
|
-
}
|
|
642
|
-
else if (arg === '-r' || arg === '--repeat') {
|
|
643
|
-
options.replacement = true;
|
|
644
|
-
i++;
|
|
645
|
-
}
|
|
646
|
-
else if (arg === '-i' || arg === '--input-range') {
|
|
647
|
-
const range = args[++i];
|
|
648
|
-
const [lo, hi] = range.split('-').map(Number);
|
|
649
|
-
options.inputRange = { start: lo, end: hi };
|
|
650
|
-
i++;
|
|
651
|
-
}
|
|
652
|
-
else if (arg.startsWith('-i')) {
|
|
653
|
-
const range = arg.slice(2);
|
|
654
|
-
const [lo, hi] = range.split('-').map(Number);
|
|
655
|
-
options.inputRange = { start: lo, end: hi };
|
|
656
|
-
i++;
|
|
657
|
-
}
|
|
658
|
-
else if (arg === '-e' || arg === '--echo') {
|
|
659
|
-
echoMode = true;
|
|
660
|
-
i++;
|
|
661
|
-
}
|
|
662
|
-
else if (arg === '-o' || arg === '--output') {
|
|
663
|
-
options.outputFile = args[++i];
|
|
664
|
-
i++;
|
|
665
|
-
}
|
|
666
|
-
else if (arg.startsWith('-o')) {
|
|
667
|
-
options.outputFile = arg.slice(2);
|
|
668
|
-
i++;
|
|
669
|
-
}
|
|
670
|
-
else if (arg === '--random-source') {
|
|
671
|
-
options.randomSource = args[++i];
|
|
672
|
-
i++;
|
|
673
|
-
}
|
|
674
|
-
else if (arg === '-z' || arg === '--zero-terminated') {
|
|
675
|
-
options.zeroTerminated = true;
|
|
676
|
-
i++;
|
|
677
|
-
}
|
|
678
|
-
else if (arg === '--') {
|
|
679
|
-
if (echoMode) {
|
|
680
|
-
options.echoArgs = args.slice(i + 1);
|
|
681
|
-
}
|
|
682
|
-
else {
|
|
683
|
-
files.push(...args.slice(i + 1));
|
|
684
|
-
}
|
|
685
|
-
break;
|
|
686
|
-
}
|
|
687
|
-
else if (!arg.startsWith('-')) {
|
|
688
|
-
if (echoMode) {
|
|
689
|
-
options.echoArgs = options.echoArgs || [];
|
|
690
|
-
options.echoArgs.push(arg);
|
|
691
|
-
}
|
|
692
|
-
else {
|
|
693
|
-
files.push(arg);
|
|
694
|
-
}
|
|
695
|
-
i++;
|
|
696
|
-
}
|
|
697
|
-
else {
|
|
698
|
-
i++;
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
return { options, files };
|
|
702
|
-
}
|
|
703
|
-
/**
|
|
704
|
-
* Fisher-Yates shuffle algorithm
|
|
705
|
-
*
|
|
706
|
-
* @param array - Array to shuffle (mutated in place)
|
|
707
|
-
* @returns The shuffled array
|
|
708
|
-
*/
|
|
709
|
-
function fisherYatesShuffle(array) {
|
|
710
|
-
for (let i = array.length - 1; i > 0; i--) {
|
|
711
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
712
|
-
[array[i], array[j]] = [array[j], array[i]];
|
|
713
|
-
}
|
|
714
|
-
return array;
|
|
715
|
-
}
|
|
716
|
-
/**
|
|
717
|
-
* Sample with replacement
|
|
718
|
-
*
|
|
719
|
-
* @param array - Source array
|
|
720
|
-
* @param n - Number of items to sample
|
|
721
|
-
* @returns Sampled items (may contain duplicates)
|
|
722
|
-
*/
|
|
723
|
-
function sampleWithReplacement(array, n) {
|
|
724
|
-
const result = [];
|
|
725
|
-
for (let i = 0; i < n; i++) {
|
|
726
|
-
result.push(array[Math.floor(Math.random() * array.length)]);
|
|
727
|
-
}
|
|
728
|
-
return result;
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* Execute shuf command - shuffle/randomize lines
|
|
732
|
-
*
|
|
733
|
-
* @param lines - Input lines to shuffle (from stdin/file)
|
|
734
|
-
* @param options - Shuf options
|
|
735
|
-
* @returns Shuffled output
|
|
736
|
-
*
|
|
737
|
-
* @example
|
|
738
|
-
* ```typescript
|
|
739
|
-
* executeShuf(['a', 'b', 'c'], {})
|
|
740
|
-
* // => Random permutation of ['a', 'b', 'c']
|
|
741
|
-
*
|
|
742
|
-
* executeShuf([], { inputRange: { start: 1, end: 10 } })
|
|
743
|
-
* // => Random permutation of 1-10
|
|
744
|
-
*
|
|
745
|
-
* executeShuf([], { echoArgs: ['red', 'green', 'blue'], count: 1 })
|
|
746
|
-
* // => One random color
|
|
747
|
-
* ```
|
|
748
|
-
*/
|
|
749
|
-
export function executeShuf(lines, options = {}) {
|
|
750
|
-
let items;
|
|
751
|
-
// Determine input source
|
|
752
|
-
if (options.inputRange) {
|
|
753
|
-
const { start, end } = options.inputRange;
|
|
754
|
-
items = [];
|
|
755
|
-
for (let i = start; i <= end; i++) {
|
|
756
|
-
items.push(String(i));
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
else if (options.echoArgs && options.echoArgs.length > 0) {
|
|
760
|
-
items = options.echoArgs;
|
|
761
|
-
}
|
|
762
|
-
else {
|
|
763
|
-
items = lines.filter(l => l.length > 0);
|
|
764
|
-
}
|
|
765
|
-
// Handle -n 0
|
|
766
|
-
if (options.count === 0) {
|
|
767
|
-
return { result: '', exitCode: 0 };
|
|
768
|
-
}
|
|
769
|
-
let result;
|
|
770
|
-
if (options.replacement) {
|
|
771
|
-
// With replacement - can pick same item multiple times
|
|
772
|
-
const count = options.count ?? items.length;
|
|
773
|
-
result = sampleWithReplacement(items, count);
|
|
774
|
-
}
|
|
775
|
-
else {
|
|
776
|
-
// Without replacement - Fisher-Yates shuffle
|
|
777
|
-
result = fisherYatesShuffle([...items]);
|
|
778
|
-
// Limit to count if specified
|
|
779
|
-
if (options.count !== undefined) {
|
|
780
|
-
result = result.slice(0, Math.min(options.count, result.length));
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
const terminator = options.zeroTerminated ? '\0' : '\n';
|
|
784
|
-
return {
|
|
785
|
-
result: result.join(terminator) + (result.length > 0 ? terminator : ''),
|
|
786
|
-
exitCode: 0,
|
|
787
|
-
};
|
|
788
|
-
}
|
|
789
|
-
// ============================================================================
|
|
790
|
-
// COMMAND SET FOR TIERED EXECUTOR
|
|
791
|
-
// ============================================================================
|
|
792
|
-
/**
|
|
793
|
-
* Set of extended utility commands handled by this module
|
|
794
|
-
*/
|
|
795
|
-
export const EXTENDED_UTILS_COMMANDS = new Set([
|
|
796
|
-
'env', 'id', 'uname', 'timeout', 'tac', 'shuf',
|
|
797
|
-
]);
|
|
798
|
-
/**
|
|
799
|
-
* Check if a command is an extended utility command
|
|
800
|
-
*/
|
|
801
|
-
export function isExtendedUtilsCommand(cmd) {
|
|
802
|
-
return EXTENDED_UTILS_COMMANDS.has(cmd);
|
|
803
|
-
}
|
|
804
|
-
//# sourceMappingURL=extended-utils.js.map
|