@scelar/nodepod 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +43 -0
- package/README.md +240 -0
- package/dist/child_process-BJOMsZje.js +8233 -0
- package/dist/child_process-BJOMsZje.js.map +1 -0
- package/dist/child_process-Cj8vOcuc.cjs +7434 -0
- package/dist/child_process-Cj8vOcuc.cjs.map +1 -0
- package/dist/index-Cb1Cgdnd.js +35308 -0
- package/dist/index-Cb1Cgdnd.js.map +1 -0
- package/dist/index-DsMGS-xc.cjs +37195 -0
- package/dist/index-DsMGS-xc.cjs.map +1 -0
- package/dist/index.cjs +65 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.mjs +59 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +95 -0
- package/src/__tests__/smoke.test.ts +11 -0
- package/src/constants/cdn-urls.ts +18 -0
- package/src/constants/config.ts +236 -0
- package/src/cross-origin.ts +26 -0
- package/src/engine-factory.ts +176 -0
- package/src/engine-types.ts +56 -0
- package/src/helpers/byte-encoding.ts +39 -0
- package/src/helpers/digest.ts +9 -0
- package/src/helpers/event-loop.ts +96 -0
- package/src/helpers/wasm-cache.ts +133 -0
- package/src/iframe-sandbox.ts +141 -0
- package/src/index.ts +192 -0
- package/src/isolation-helpers.ts +148 -0
- package/src/memory-volume.ts +941 -0
- package/src/module-transformer.ts +368 -0
- package/src/packages/archive-extractor.ts +248 -0
- package/src/packages/browser-bundler.ts +284 -0
- package/src/packages/installer.ts +396 -0
- package/src/packages/registry-client.ts +131 -0
- package/src/packages/version-resolver.ts +411 -0
- package/src/polyfills/assert.ts +384 -0
- package/src/polyfills/async_hooks.ts +144 -0
- package/src/polyfills/buffer.ts +628 -0
- package/src/polyfills/child_process.ts +2288 -0
- package/src/polyfills/chokidar.ts +336 -0
- package/src/polyfills/cluster.ts +106 -0
- package/src/polyfills/console.ts +136 -0
- package/src/polyfills/constants.ts +123 -0
- package/src/polyfills/crypto.ts +885 -0
- package/src/polyfills/dgram.ts +87 -0
- package/src/polyfills/diagnostics_channel.ts +76 -0
- package/src/polyfills/dns.ts +134 -0
- package/src/polyfills/domain.ts +68 -0
- package/src/polyfills/esbuild.ts +854 -0
- package/src/polyfills/events.ts +276 -0
- package/src/polyfills/fs.ts +2888 -0
- package/src/polyfills/fsevents.ts +79 -0
- package/src/polyfills/http.ts +1449 -0
- package/src/polyfills/http2.ts +199 -0
- package/src/polyfills/https.ts +76 -0
- package/src/polyfills/inspector.ts +62 -0
- package/src/polyfills/lightningcss.ts +105 -0
- package/src/polyfills/module.ts +191 -0
- package/src/polyfills/net.ts +353 -0
- package/src/polyfills/os.ts +238 -0
- package/src/polyfills/path.ts +206 -0
- package/src/polyfills/perf_hooks.ts +102 -0
- package/src/polyfills/process.ts +690 -0
- package/src/polyfills/punycode.ts +159 -0
- package/src/polyfills/querystring.ts +93 -0
- package/src/polyfills/quic.ts +118 -0
- package/src/polyfills/readdirp.ts +229 -0
- package/src/polyfills/readline.ts +692 -0
- package/src/polyfills/repl.ts +134 -0
- package/src/polyfills/rollup.ts +119 -0
- package/src/polyfills/sea.ts +33 -0
- package/src/polyfills/sqlite.ts +78 -0
- package/src/polyfills/stream.ts +1620 -0
- package/src/polyfills/string_decoder.ts +25 -0
- package/src/polyfills/tailwindcss-oxide.ts +309 -0
- package/src/polyfills/test.ts +197 -0
- package/src/polyfills/timers.ts +32 -0
- package/src/polyfills/tls.ts +105 -0
- package/src/polyfills/trace_events.ts +50 -0
- package/src/polyfills/tty.ts +71 -0
- package/src/polyfills/url.ts +174 -0
- package/src/polyfills/util.ts +559 -0
- package/src/polyfills/v8.ts +126 -0
- package/src/polyfills/vm.ts +132 -0
- package/src/polyfills/volume-registry.ts +15 -0
- package/src/polyfills/wasi.ts +44 -0
- package/src/polyfills/worker_threads.ts +326 -0
- package/src/polyfills/ws.ts +595 -0
- package/src/polyfills/zlib.ts +881 -0
- package/src/request-proxy.ts +716 -0
- package/src/script-engine.ts +3375 -0
- package/src/sdk/nodepod-fs.ts +93 -0
- package/src/sdk/nodepod-process.ts +86 -0
- package/src/sdk/nodepod-terminal.ts +350 -0
- package/src/sdk/nodepod.ts +509 -0
- package/src/sdk/types.ts +70 -0
- package/src/shell/commands/bun.ts +121 -0
- package/src/shell/commands/directory.ts +297 -0
- package/src/shell/commands/file-ops.ts +525 -0
- package/src/shell/commands/git.ts +2142 -0
- package/src/shell/commands/node.ts +80 -0
- package/src/shell/commands/npm.ts +198 -0
- package/src/shell/commands/pm-types.ts +45 -0
- package/src/shell/commands/pnpm.ts +82 -0
- package/src/shell/commands/search.ts +264 -0
- package/src/shell/commands/shell-env.ts +352 -0
- package/src/shell/commands/text-processing.ts +1152 -0
- package/src/shell/commands/yarn.ts +84 -0
- package/src/shell/shell-builtins.ts +19 -0
- package/src/shell/shell-helpers.ts +250 -0
- package/src/shell/shell-interpreter.ts +514 -0
- package/src/shell/shell-parser.ts +429 -0
- package/src/shell/shell-types.ts +85 -0
- package/src/syntax-transforms.ts +561 -0
- package/src/threading/engine-worker.ts +64 -0
- package/src/threading/inline-worker.ts +372 -0
- package/src/threading/offload-types.ts +112 -0
- package/src/threading/offload-worker.ts +383 -0
- package/src/threading/offload.ts +271 -0
- package/src/threading/process-context.ts +92 -0
- package/src/threading/process-handle.ts +275 -0
- package/src/threading/process-manager.ts +956 -0
- package/src/threading/process-worker-entry.ts +854 -0
- package/src/threading/shared-vfs.ts +352 -0
- package/src/threading/sync-channel.ts +135 -0
- package/src/threading/task-queue.ts +177 -0
- package/src/threading/vfs-bridge.ts +231 -0
- package/src/threading/worker-pool.ts +233 -0
- package/src/threading/worker-protocol.ts +358 -0
- package/src/threading/worker-vfs.ts +218 -0
- package/src/types/externals.d.ts +38 -0
- package/src/types/fs-streams.ts +142 -0
- package/src/types/manifest.ts +17 -0
- package/src/worker-sandbox.ts +90 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import type { BuiltinFn, ShellContext } from "../shell-types";
|
|
2
|
+
import {
|
|
3
|
+
ok,
|
|
4
|
+
fail,
|
|
5
|
+
EXIT_FAIL,
|
|
6
|
+
resolvePath,
|
|
7
|
+
parseArgs,
|
|
8
|
+
pathModule,
|
|
9
|
+
MONTHS_SHORT,
|
|
10
|
+
MONTHS_LONG,
|
|
11
|
+
DAYS_SHORT,
|
|
12
|
+
DAYS_LONG,
|
|
13
|
+
} from "../shell-helpers";
|
|
14
|
+
|
|
15
|
+
// set by the registry so `which` and `type` can check builtins
|
|
16
|
+
let _builtins: Map<string, BuiltinFn> | null = null;
|
|
17
|
+
|
|
18
|
+
export function setBuiltinsRef(b: Map<string, BuiltinFn>): void {
|
|
19
|
+
_builtins = b;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* ------------------------------------------------------------------ */
|
|
23
|
+
/* Commands */
|
|
24
|
+
/* ------------------------------------------------------------------ */
|
|
25
|
+
|
|
26
|
+
const exportCmd: BuiltinFn = (args, ctx) => {
|
|
27
|
+
if (args.length === 0) {
|
|
28
|
+
let out = "";
|
|
29
|
+
for (const [k, v] of Object.entries(ctx.env)) {
|
|
30
|
+
out += `declare -x ${k}="${v}"\n`;
|
|
31
|
+
}
|
|
32
|
+
return ok(out);
|
|
33
|
+
}
|
|
34
|
+
for (const arg of args) {
|
|
35
|
+
const eq = arg.indexOf("=");
|
|
36
|
+
if (eq > 0) {
|
|
37
|
+
ctx.env[arg.slice(0, eq)] = arg.slice(eq + 1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return ok();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const unset: BuiltinFn = (args, ctx) => {
|
|
44
|
+
for (const name of args) delete ctx.env[name];
|
|
45
|
+
return ok();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const envCmd: BuiltinFn = (_args, ctx) => {
|
|
49
|
+
let out = "";
|
|
50
|
+
for (const [k, v] of Object.entries(ctx.env)) out += `${k}=${v}\n`;
|
|
51
|
+
return ok(out);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const which: BuiltinFn = (args, ctx) => {
|
|
55
|
+
if (args.length === 0) return fail("which: missing argument\n");
|
|
56
|
+
|
|
57
|
+
const { flags } = parseArgs(args, ["a"]);
|
|
58
|
+
const showAll = flags.has("a");
|
|
59
|
+
const names = args.filter((a) => !a.startsWith("-"));
|
|
60
|
+
|
|
61
|
+
let out = "";
|
|
62
|
+
for (const name of names) {
|
|
63
|
+
const found: string[] = [];
|
|
64
|
+
|
|
65
|
+
if (_builtins?.has(name)) found.push(`${name}: shell built-in command`);
|
|
66
|
+
|
|
67
|
+
const knownBins: Record<string, string> = {
|
|
68
|
+
node: "/usr/local/bin/node",
|
|
69
|
+
npm: "/usr/local/bin/npm",
|
|
70
|
+
npx: "/usr/local/bin/npx",
|
|
71
|
+
pnpm: "/usr/local/bin/pnpm",
|
|
72
|
+
yarn: "/usr/local/bin/yarn",
|
|
73
|
+
bun: "/usr/local/bin/bun",
|
|
74
|
+
bunx: "/usr/local/bin/bunx",
|
|
75
|
+
};
|
|
76
|
+
if (knownBins[name]) found.push(knownBins[name]);
|
|
77
|
+
|
|
78
|
+
const binPath = `/node_modules/.bin/${name}`;
|
|
79
|
+
if (ctx.volume.existsSync(binPath)) found.push(binPath);
|
|
80
|
+
|
|
81
|
+
const pathDirs = (ctx.env.PATH || "").split(":").filter(Boolean);
|
|
82
|
+
for (const dir of pathDirs) {
|
|
83
|
+
const candidate = `${dir}/${name}`;
|
|
84
|
+
if (ctx.volume.existsSync(candidate)) {
|
|
85
|
+
if (!found.includes(candidate)) found.push(candidate);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (found.length === 0) {
|
|
90
|
+
out += `${name} not found\n`;
|
|
91
|
+
} else if (showAll) {
|
|
92
|
+
for (const f of found) out += f + "\n";
|
|
93
|
+
} else {
|
|
94
|
+
out += found[0] + "\n";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return out.includes("not found")
|
|
98
|
+
? { stdout: out, stderr: "", exitCode: 1 }
|
|
99
|
+
: ok(out);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const typeCmd: BuiltinFn = (args, ctx) => {
|
|
103
|
+
if (args.length === 0) return fail("type: missing argument\n");
|
|
104
|
+
const name = args[0];
|
|
105
|
+
if (_builtins?.has(name)) return ok(`${name} is a shell builtin\n`);
|
|
106
|
+
|
|
107
|
+
const w = which([name], ctx);
|
|
108
|
+
if (typeof w === "object" && "exitCode" in w && w.exitCode === 0) {
|
|
109
|
+
return ok(`${name} is ${w.stdout.trim()}\n`);
|
|
110
|
+
}
|
|
111
|
+
return fail(`type: ${name}: not found\n`);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const trueCmd: BuiltinFn = () => ok();
|
|
115
|
+
const falseCmd: BuiltinFn = () => EXIT_FAIL;
|
|
116
|
+
|
|
117
|
+
const exitCmd: BuiltinFn = (args) => {
|
|
118
|
+
const code = args[0] ? parseInt(args[0], 10) : 0;
|
|
119
|
+
return { stdout: "", stderr: "", exitCode: code };
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const clear: BuiltinFn = () => ok("\x1b[2J\x1b[H");
|
|
123
|
+
|
|
124
|
+
/* ------------------------------------------------------------------ */
|
|
125
|
+
/* test / [ */
|
|
126
|
+
/* ------------------------------------------------------------------ */
|
|
127
|
+
|
|
128
|
+
function evalTest(args: string[], ctx: ShellContext): boolean {
|
|
129
|
+
if (args.length === 0) return false;
|
|
130
|
+
|
|
131
|
+
if (args[0] === "!") return !evalTest(args.slice(1), ctx);
|
|
132
|
+
|
|
133
|
+
if (args[0] === "(" && args[args.length - 1] === ")") {
|
|
134
|
+
return evalTest(args.slice(1, -1), ctx);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
for (let i = 0; i < args.length; i++) {
|
|
138
|
+
if (args[i] === "-o") {
|
|
139
|
+
return (
|
|
140
|
+
evalTest(args.slice(0, i), ctx) || evalTest(args.slice(i + 1), ctx)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
for (let i = 0; i < args.length; i++) {
|
|
145
|
+
if (args[i] === "-a") {
|
|
146
|
+
return (
|
|
147
|
+
evalTest(args.slice(0, i), ctx) && evalTest(args.slice(i + 1), ctx)
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (args.length === 1) return args[0].length > 0;
|
|
153
|
+
|
|
154
|
+
if (args.length === 2) {
|
|
155
|
+
const [flag, val] = args;
|
|
156
|
+
const p = resolvePath(val, ctx.cwd);
|
|
157
|
+
|
|
158
|
+
if (flag === "-f") {
|
|
159
|
+
try { return ctx.volume.statSync(p).isFile(); } catch { return false; }
|
|
160
|
+
}
|
|
161
|
+
if (flag === "-d") {
|
|
162
|
+
try { return ctx.volume.statSync(p).isDirectory(); } catch { return false; }
|
|
163
|
+
}
|
|
164
|
+
if (flag === "-e") return ctx.volume.existsSync(p);
|
|
165
|
+
if (flag === "-L" || flag === "-h") return ctx.volume.existsSync(p);
|
|
166
|
+
if (flag === "-s") {
|
|
167
|
+
try { return ctx.volume.readFileSync(p).length > 0; } catch { return false; }
|
|
168
|
+
}
|
|
169
|
+
if (flag === "-r" || flag === "-w") return ctx.volume.existsSync(p);
|
|
170
|
+
if (flag === "-x") {
|
|
171
|
+
if (ctx.volume.existsSync(p)) {
|
|
172
|
+
const ext = pathModule.extname(p);
|
|
173
|
+
return ext === ".sh" || ext === "" || p.includes("/bin/");
|
|
174
|
+
}
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
if (flag === "-n") return val.length > 0;
|
|
178
|
+
if (flag === "-z") return val.length === 0;
|
|
179
|
+
if (flag === "-t") return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (args.length === 3) {
|
|
183
|
+
const [left, op, right] = args;
|
|
184
|
+
if (op === "=" || op === "==") return left === right;
|
|
185
|
+
if (op === "!=") return left !== right;
|
|
186
|
+
if (op === "-eq") return parseInt(left) === parseInt(right);
|
|
187
|
+
if (op === "-ne") return parseInt(left) !== parseInt(right);
|
|
188
|
+
if (op === "-lt") return parseInt(left) < parseInt(right);
|
|
189
|
+
if (op === "-le") return parseInt(left) <= parseInt(right);
|
|
190
|
+
if (op === "-gt") return parseInt(left) > parseInt(right);
|
|
191
|
+
if (op === "-ge") return parseInt(left) >= parseInt(right);
|
|
192
|
+
|
|
193
|
+
if (op === "-nt" || op === "-ot" || op === "-ef") {
|
|
194
|
+
try {
|
|
195
|
+
const sl = ctx.volume.statSync(resolvePath(left, ctx.cwd));
|
|
196
|
+
const sr = ctx.volume.statSync(resolvePath(right, ctx.cwd));
|
|
197
|
+
if (op === "-nt") return (sl.mtimeMs || 0) > (sr.mtimeMs || 0);
|
|
198
|
+
if (op === "-ot") return (sl.mtimeMs || 0) < (sr.mtimeMs || 0);
|
|
199
|
+
if (op === "-ef")
|
|
200
|
+
return resolvePath(left, ctx.cwd) === resolvePath(right, ctx.cwd);
|
|
201
|
+
} catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const test_cmd: BuiltinFn = (args, ctx) => {
|
|
211
|
+
const testArgs = [...args];
|
|
212
|
+
if (testArgs[testArgs.length - 1] === "]") testArgs.pop();
|
|
213
|
+
return { stdout: "", stderr: "", exitCode: evalTest(testArgs, ctx) ? 0 : 1 };
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/* ------------------------------------------------------------------ */
|
|
217
|
+
/* date */
|
|
218
|
+
/* ------------------------------------------------------------------ */
|
|
219
|
+
|
|
220
|
+
function getTimezoneAbbr(d: Date): string {
|
|
221
|
+
const str = d.toTimeString();
|
|
222
|
+
const m = str.match(/\((.+?)\)/);
|
|
223
|
+
if (m) {
|
|
224
|
+
const words = m[1].split(" ");
|
|
225
|
+
if (words.length === 1) return words[0];
|
|
226
|
+
return words.map((w) => w[0]).join("");
|
|
227
|
+
}
|
|
228
|
+
const off = -d.getTimezoneOffset();
|
|
229
|
+
const sign = off >= 0 ? "+" : "-";
|
|
230
|
+
const h = String(Math.floor(Math.abs(off) / 60)).padStart(2, "0");
|
|
231
|
+
const min = String(Math.abs(off) % 60).padStart(2, "0");
|
|
232
|
+
return `${sign}${h}${min}`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function formatDate(d: Date, fmt: string, utc: boolean): string {
|
|
236
|
+
const g = utc
|
|
237
|
+
? {
|
|
238
|
+
Y: d.getUTCFullYear(), m: d.getUTCMonth(), d: d.getUTCDate(),
|
|
239
|
+
H: d.getUTCHours(), M: d.getUTCMinutes(), S: d.getUTCSeconds(),
|
|
240
|
+
w: d.getUTCDay(),
|
|
241
|
+
}
|
|
242
|
+
: {
|
|
243
|
+
Y: d.getFullYear(), m: d.getMonth(), d: d.getDate(),
|
|
244
|
+
H: d.getHours(), M: d.getMinutes(), S: d.getSeconds(),
|
|
245
|
+
w: d.getDay(),
|
|
246
|
+
};
|
|
247
|
+
let out = "";
|
|
248
|
+
for (let i = 0; i < fmt.length; i++) {
|
|
249
|
+
if (fmt[i] === "%" && i + 1 < fmt.length) {
|
|
250
|
+
const s = fmt[++i];
|
|
251
|
+
if (s === "Y") out += g.Y;
|
|
252
|
+
else if (s === "y") out += String(g.Y).slice(-2);
|
|
253
|
+
else if (s === "m") out += String(g.m + 1).padStart(2, "0");
|
|
254
|
+
else if (s === "d") out += String(g.d).padStart(2, "0");
|
|
255
|
+
else if (s === "e") out += String(g.d).padStart(2, " ");
|
|
256
|
+
else if (s === "H") out += String(g.H).padStart(2, "0");
|
|
257
|
+
else if (s === "M") out += String(g.M).padStart(2, "0");
|
|
258
|
+
else if (s === "S") out += String(g.S).padStart(2, "0");
|
|
259
|
+
else if (s === "I") out += String(g.H % 12 || 12).padStart(2, "0");
|
|
260
|
+
else if (s === "p") out += g.H < 12 ? "AM" : "PM";
|
|
261
|
+
else if (s === "P") out += g.H < 12 ? "am" : "pm";
|
|
262
|
+
else if (s === "a") out += DAYS_SHORT[g.w];
|
|
263
|
+
else if (s === "A") out += DAYS_LONG[g.w];
|
|
264
|
+
else if (s === "b" || s === "h") out += MONTHS_SHORT[g.m];
|
|
265
|
+
else if (s === "B") out += MONTHS_LONG[g.m];
|
|
266
|
+
else if (s === "w") out += g.w;
|
|
267
|
+
else if (s === "u") out += g.w === 0 ? 7 : g.w;
|
|
268
|
+
else if (s === "j") {
|
|
269
|
+
const jan1 = new Date(g.Y, 0, 1);
|
|
270
|
+
const diff = d.getTime() - jan1.getTime();
|
|
271
|
+
out += String(Math.floor(diff / 86400000) + 1).padStart(3, "0");
|
|
272
|
+
} else if (s === "s") out += Math.floor(d.getTime() / 1000);
|
|
273
|
+
else if (s === "N") out += String(d.getMilliseconds() * 1000000).padStart(9, "0");
|
|
274
|
+
else if (s === "n") out += "\n";
|
|
275
|
+
else if (s === "t") out += "\t";
|
|
276
|
+
else if (s === "T")
|
|
277
|
+
out += `${String(g.H).padStart(2, "0")}:${String(g.M).padStart(2, "0")}:${String(g.S).padStart(2, "0")}`;
|
|
278
|
+
else if (s === "R")
|
|
279
|
+
out += `${String(g.H).padStart(2, "0")}:${String(g.M).padStart(2, "0")}`;
|
|
280
|
+
else if (s === "F")
|
|
281
|
+
out += `${g.Y}-${String(g.m + 1).padStart(2, "0")}-${String(g.d).padStart(2, "0")}`;
|
|
282
|
+
else if (s === "D")
|
|
283
|
+
out += `${String(g.m + 1).padStart(2, "0")}/${String(g.d).padStart(2, "0")}/${String(g.Y).slice(-2)}`;
|
|
284
|
+
else if (s === "Z") out += utc ? "UTC" : getTimezoneAbbr(d);
|
|
285
|
+
else if (s === "%") out += "%";
|
|
286
|
+
else out += "%" + s;
|
|
287
|
+
} else {
|
|
288
|
+
out += fmt[i];
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return out;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const date_cmd: BuiltinFn = (args) => {
|
|
295
|
+
const { flags, opts, positional } = parseArgs(args, ["u", "R", "I"], ["d"]);
|
|
296
|
+
const utc = flags.has("u");
|
|
297
|
+
const rfc = flags.has("R");
|
|
298
|
+
const iso = flags.has("I");
|
|
299
|
+
const dateStr = opts["d"];
|
|
300
|
+
|
|
301
|
+
const d = dateStr ? new Date(dateStr) : new Date();
|
|
302
|
+
if (isNaN(d.getTime())) return fail(`date: invalid date '${dateStr}'\n`);
|
|
303
|
+
|
|
304
|
+
const fmt = positional.find((a) => a.startsWith("+"));
|
|
305
|
+
if (fmt) return ok(formatDate(d, fmt.slice(1), utc) + "\n");
|
|
306
|
+
if (rfc) return ok(d.toUTCString() + "\n");
|
|
307
|
+
if (iso) return ok(d.toISOString().slice(0, 10) + "\n");
|
|
308
|
+
|
|
309
|
+
const day = DAYS_SHORT[utc ? d.getUTCDay() : d.getDay()];
|
|
310
|
+
const mon = MONTHS_SHORT[utc ? d.getUTCMonth() : d.getMonth()];
|
|
311
|
+
const date = utc ? d.getUTCDate() : d.getDate();
|
|
312
|
+
const hh = String(utc ? d.getUTCHours() : d.getHours()).padStart(2, "0");
|
|
313
|
+
const mm = String(utc ? d.getUTCMinutes() : d.getMinutes()).padStart(2, "0");
|
|
314
|
+
const ss = String(utc ? d.getUTCSeconds() : d.getSeconds()).padStart(2, "0");
|
|
315
|
+
const year = utc ? d.getUTCFullYear() : d.getFullYear();
|
|
316
|
+
const tz = utc ? "UTC" : getTimezoneAbbr(d);
|
|
317
|
+
|
|
318
|
+
return ok(
|
|
319
|
+
`${day} ${mon} ${String(date).padStart(2, " ")} ${hh}:${mm}:${ss} ${tz} ${year}\n`,
|
|
320
|
+
);
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
/* ------------------------------------------------------------------ */
|
|
324
|
+
/* sleep */
|
|
325
|
+
/* ------------------------------------------------------------------ */
|
|
326
|
+
|
|
327
|
+
const sleep_cmd: BuiltinFn = async (args) => {
|
|
328
|
+
const seconds = parseFloat(args[0] || "0");
|
|
329
|
+
if (seconds > 0) await new Promise((r) => setTimeout(r, seconds * 1000));
|
|
330
|
+
return ok();
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
/* ------------------------------------------------------------------ */
|
|
334
|
+
/* Registry */
|
|
335
|
+
/* ------------------------------------------------------------------ */
|
|
336
|
+
|
|
337
|
+
export const shellEnvCommands: [string, BuiltinFn][] = [
|
|
338
|
+
["export", exportCmd],
|
|
339
|
+
["unset", unset],
|
|
340
|
+
["env", envCmd],
|
|
341
|
+
["which", which],
|
|
342
|
+
["type", typeCmd],
|
|
343
|
+
["true", trueCmd],
|
|
344
|
+
["false", falseCmd],
|
|
345
|
+
[":", trueCmd],
|
|
346
|
+
["exit", exitCmd],
|
|
347
|
+
["clear", clear],
|
|
348
|
+
["test", test_cmd],
|
|
349
|
+
["[", test_cmd],
|
|
350
|
+
["date", date_cmd],
|
|
351
|
+
["sleep", sleep_cmd],
|
|
352
|
+
];
|