@poe-platform/safe-bash 0.1.70 → 0.1.72
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/dist/safe-bash/browser.d.ts +2 -1
- package/dist/safe-bash/browser.d.ts.map +1 -1
- package/dist/safe-bash/browser.js +81 -34
- package/dist/safe-bash/browser.js.map +3 -3
- package/dist/safe-bash/commands/directory-admission.d.ts +4 -0
- package/dist/safe-bash/commands/directory-admission.d.ts.map +1 -0
- package/dist/safe-bash/commands/directory-admission.js +27 -0
- package/dist/safe-bash/commands/directory-admission.js.map +1 -0
- package/dist/safe-bash/commands/filesystem.d.ts +1 -1
- package/dist/safe-bash/commands/filesystem.d.ts.map +1 -1
- package/dist/safe-bash/commands/filesystem.js +63 -38
- package/dist/safe-bash/commands/filesystem.js.map +1 -1
- package/dist/safe-bash/commands/find.d.ts +1 -1
- package/dist/safe-bash/commands/find.d.ts.map +1 -1
- package/dist/safe-bash/commands/find.js +5 -3
- package/dist/safe-bash/commands/find.js.map +1 -1
- package/dist/safe-bash/commands/index.d.ts +1 -0
- package/dist/safe-bash/commands/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/index.js +1 -1
- package/dist/safe-bash/commands/index.js.map +1 -1
- package/dist/safe-bash/contracts/filesystem.d.ts +1 -1
- package/dist/safe-bash/contracts/filesystem.d.ts.map +1 -1
- package/dist/safe-bash/plugins/index.d.ts +1 -0
- package/dist/safe-bash/plugins/index.d.ts.map +1 -1
- package/dist/safe-bash/plugins/index.js +1 -1
- package/dist/safe-bash/plugins/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -14,7 +14,8 @@ export { portableSearchCommands, type PortableSearchOptions } from "./commands/s
|
|
|
14
14
|
export * from "./commands/regex-execution/public.js";
|
|
15
15
|
export interface BrowserCommandsOptions {
|
|
16
16
|
readonly replace?: boolean;
|
|
17
|
+
readonly maxDirectoryEntries?: number;
|
|
17
18
|
}
|
|
18
|
-
export declare function createBrowserCommands(): readonly CommandDefinition[];
|
|
19
|
+
export declare function createBrowserCommands(options?: BrowserCommandsOptions): readonly CommandDefinition[];
|
|
19
20
|
export declare function browserCommands(options?: BrowserCommandsOptions): VirtualShellPlugin;
|
|
20
21
|
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAOlF,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,YAAY,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,YAAY,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AACjG,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACnG,cAAc,sCAAsC,CAAC;AAErD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAOlF,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,YAAY,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,YAAY,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AACjG,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACnG,cAAc,sCAAsC,CAAC;AAErD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACvC;AAED,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,SAAS,iBAAiB,EAAE,CAKxG;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,kBAAkB,CAaxF"}
|
|
@@ -3405,7 +3405,34 @@ async function moveAcrossDevices(context, source, target, noClobber, budget) {
|
|
|
3405
3405
|
return true;
|
|
3406
3406
|
}
|
|
3407
3407
|
|
|
3408
|
+
// packages/safe-bash/src/commands/directory-admission.ts
|
|
3409
|
+
init_platform();
|
|
3410
|
+
function createDirectoryReader(maxEntries = 1e4) {
|
|
3411
|
+
if (!Number.isSafeInteger(maxEntries) || maxEntries < 0) {
|
|
3412
|
+
throw new RangeError("maxDirectoryEntries must be a nonnegative safe integer");
|
|
3413
|
+
}
|
|
3414
|
+
return async (context, path, ordered = false) => {
|
|
3415
|
+
context.signal.throwIfAborted();
|
|
3416
|
+
const entries = await context.fs.readdir(path, { signal: context.signal, maxEntries });
|
|
3417
|
+
context.signal.throwIfAborted();
|
|
3418
|
+
if (entries.length > maxEntries) {
|
|
3419
|
+
throw new FsError("EFBIG", { syscall: "readdir", path, message: "directory entry limit exceeded" });
|
|
3420
|
+
}
|
|
3421
|
+
await yieldTurn(context.signal);
|
|
3422
|
+
if (ordered) {
|
|
3423
|
+
for (let index = 1; index < entries.length; index++) {
|
|
3424
|
+
if (index % 256 === 0) await yieldTurn(context.signal);
|
|
3425
|
+
if (entries[index - 1].name > entries[index].name) {
|
|
3426
|
+
return entries.slice().sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
}
|
|
3430
|
+
return entries;
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3408
3434
|
// packages/safe-bash/src/commands/filesystem.ts
|
|
3435
|
+
var MAX_RECURSIVE_DIRECTORY_DEPTH = 1024;
|
|
3409
3436
|
async function preflightOperands(context, operands, check) {
|
|
3410
3437
|
for (const operand of operands) {
|
|
3411
3438
|
try {
|
|
@@ -3441,22 +3468,22 @@ function needCapability(context, capability) {
|
|
|
3441
3468
|
if (!context.fs.capabilitiesFor && context.fs.capabilities[declaration] === false) throw new FsError("ENOTSUP", { syscall: capability });
|
|
3442
3469
|
if (!context.fs[capability]) throw new FsError("ENOTSUP", { syscall: capability });
|
|
3443
3470
|
}
|
|
3444
|
-
async function admitEmptyDirectory(context, path) {
|
|
3471
|
+
async function admitEmptyDirectory(context, path, readDirectory) {
|
|
3445
3472
|
try {
|
|
3446
3473
|
await admitFilesystemModes(context, "rmdir", ["directory"], [path]);
|
|
3447
3474
|
} catch (error) {
|
|
3448
3475
|
context.signal.throwIfAborted();
|
|
3449
3476
|
if (codeOf(error) === "ENOTSUP") {
|
|
3450
3477
|
const capabilities = await context.fs.capabilitiesFor?.(path, { signal: context.signal }) ?? context.fs.capabilities;
|
|
3451
|
-
if (capabilities.write !== false && capabilities.readdir !== false && (await context
|
|
3478
|
+
if (capabilities.write !== false && capabilities.readdir !== false && (await readDirectory(context, path)).length) {
|
|
3452
3479
|
throw new FsError("ENOTEMPTY", { syscall: "rmdir", path, cause: error });
|
|
3453
3480
|
}
|
|
3454
3481
|
}
|
|
3455
3482
|
throw error;
|
|
3456
3483
|
}
|
|
3457
3484
|
}
|
|
3458
|
-
async function removeEmptyDirectory(context, path) {
|
|
3459
|
-
await admitEmptyDirectory(context, path);
|
|
3485
|
+
async function removeEmptyDirectory(context, path, readDirectory) {
|
|
3486
|
+
await admitEmptyDirectory(context, path, readDirectory);
|
|
3460
3487
|
context.signal.throwIfAborted();
|
|
3461
3488
|
if (!context.fs.rmdir) throw new FsError("ENOTSUP", { syscall: "rmdir", path });
|
|
3462
3489
|
await context.fs.rmdir(path, { signal: context.signal });
|
|
@@ -3468,7 +3495,7 @@ async function destinations(context, operands) {
|
|
|
3468
3495
|
if (operands.length > 2 && !directory) throw new FsError("ENOTDIR", { path: target });
|
|
3469
3496
|
return { target, directory, sources: operands.slice(0, -1) };
|
|
3470
3497
|
}
|
|
3471
|
-
async function copy(context, source, target, flags, top = true, ancestors = /* @__PURE__ */ new Set(), preflight = false) {
|
|
3498
|
+
async function copy(context, source, target, flags, readDirectory, top = true, ancestors = /* @__PURE__ */ new Set(), preflight = false) {
|
|
3472
3499
|
context.signal.throwIfAborted();
|
|
3473
3500
|
const link = await context.fs.lstat(source, { signal: context.signal });
|
|
3474
3501
|
const preserveLink = link.type === "symlink" && !flags.has("L") && (flags.has("P") || !top);
|
|
@@ -3488,11 +3515,19 @@ async function copy(context, source, target, flags, top = true, ancestors = /* @
|
|
|
3488
3515
|
if (isPathWithin(physicalSource, physicalTarget)) throw new FsError("EINVAL", { path: target, message: "cannot copy a directory into itself" });
|
|
3489
3516
|
if (ancestors.has(physicalSource)) throw new FsError("ELOOP", { path: source });
|
|
3490
3517
|
if (targetStat && targetStat.type !== "directory") throw new FsError("ENOTDIR", { path: target });
|
|
3518
|
+
context.signal.throwIfAborted();
|
|
3519
|
+
if (ancestors.size > MAX_RECURSIVE_DIRECTORY_DEPTH) {
|
|
3520
|
+
throw new FsError("ELOOP", { path: source, message: `cp directory depth limit exceeded (${MAX_RECURSIVE_DIRECTORY_DEPTH})` });
|
|
3521
|
+
}
|
|
3491
3522
|
await admitFilesystemModes(context, "cp", ["recursive"], [target]);
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
await
|
|
3523
|
+
ancestors.add(physicalSource);
|
|
3524
|
+
try {
|
|
3525
|
+
if (!targetStat && !preflight) await context.fs.mkdir(target, { mode: sourceStat.mode & 511, signal: context.signal });
|
|
3526
|
+
for (const entry of await readDirectory(context, source, true)) {
|
|
3527
|
+
await copy(context, joinPath(source, entry.name), joinPath(target, entry.name), flags, readDirectory, false, ancestors, preflight);
|
|
3528
|
+
}
|
|
3529
|
+
} finally {
|
|
3530
|
+
ancestors.delete(physicalSource);
|
|
3496
3531
|
}
|
|
3497
3532
|
} else if (preserveLink) {
|
|
3498
3533
|
await admitFilesystemModes(context, "cp", ["symlink"], [target]);
|
|
@@ -3548,7 +3583,8 @@ function modeText(stat) {
|
|
|
3548
3583
|
if (stat.mode & 512) text = text.slice(0, 9) + (stat.mode & 1 ? "t" : "T");
|
|
3549
3584
|
return text;
|
|
3550
3585
|
}
|
|
3551
|
-
function filesystemCommands() {
|
|
3586
|
+
function filesystemCommands(maxDirectoryEntries) {
|
|
3587
|
+
const readDirectory = createDirectoryReader(maxDirectoryEntries);
|
|
3552
3588
|
return [
|
|
3553
3589
|
define("mkdir", async (context) => {
|
|
3554
3590
|
const parsed = options(context.args, "pm:v", { parents: "p", mode: "m", verbose: "v" });
|
|
@@ -3613,6 +3649,7 @@ function filesystemCommands() {
|
|
|
3613
3649
|
source,
|
|
3614
3650
|
destination.directory ? joinPath(destination.target, basename(source)) : destination.target,
|
|
3615
3651
|
parsed.flags,
|
|
3652
|
+
readDirectory,
|
|
3616
3653
|
true,
|
|
3617
3654
|
/* @__PURE__ */ new Set(),
|
|
3618
3655
|
true
|
|
@@ -3620,7 +3657,7 @@ function filesystemCommands() {
|
|
|
3620
3657
|
});
|
|
3621
3658
|
return eachOperand(context, destination.sources, async (operand) => {
|
|
3622
3659
|
const source = pathOf(context, operand);
|
|
3623
|
-
await copy(context, source, destination.directory ? joinPath(destination.target, basename(source)) : destination.target, parsed.flags);
|
|
3660
|
+
await copy(context, source, destination.directory ? joinPath(destination.target, basename(source)) : destination.target, parsed.flags, readDirectory);
|
|
3624
3661
|
});
|
|
3625
3662
|
}),
|
|
3626
3663
|
define("mv", async (context) => {
|
|
@@ -3659,7 +3696,7 @@ function filesystemCommands() {
|
|
|
3659
3696
|
const stat = await maybeStat(context, path, false);
|
|
3660
3697
|
if (!stat) return;
|
|
3661
3698
|
const mode = stat.type === "directory" ? parsed.flags.has("r") || parsed.flags.has("R") ? "recursive" : "directory" : "file";
|
|
3662
|
-
if (mode === "directory") await admitEmptyDirectory(context, path);
|
|
3699
|
+
if (mode === "directory") await admitEmptyDirectory(context, path, readDirectory);
|
|
3663
3700
|
else await admitFilesystemModes(context, "rm", [mode], [path]);
|
|
3664
3701
|
});
|
|
3665
3702
|
return eachOperand(context, parsed.operands, async (operand) => {
|
|
@@ -3674,7 +3711,7 @@ function filesystemCommands() {
|
|
|
3674
3711
|
if (stat.type === "directory" && !recursive && !parsed.flags.has("d")) throw new FsError("EISDIR", { path });
|
|
3675
3712
|
if (stat.type === "directory" && !recursive) {
|
|
3676
3713
|
try {
|
|
3677
|
-
await removeEmptyDirectory(context, path);
|
|
3714
|
+
await removeEmptyDirectory(context, path, readDirectory);
|
|
3678
3715
|
} catch (error) {
|
|
3679
3716
|
context.signal.throwIfAborted();
|
|
3680
3717
|
if (!parsed.flags.has("f") || codeOf(error) !== "ENOENT") throw error;
|
|
@@ -3693,7 +3730,7 @@ function filesystemCommands() {
|
|
|
3693
3730
|
let path = pathOf(context, operand);
|
|
3694
3731
|
const stop = dirname(pathOf(context, operand.split("/").find((part) => part && part !== ".") ?? operand));
|
|
3695
3732
|
do {
|
|
3696
|
-
await admitEmptyDirectory(context, path);
|
|
3733
|
+
await admitEmptyDirectory(context, path, readDirectory);
|
|
3697
3734
|
path = dirname(path);
|
|
3698
3735
|
} while (parsed.flags.has("p") && path !== "/" && path !== stop);
|
|
3699
3736
|
});
|
|
@@ -3702,7 +3739,7 @@ function filesystemCommands() {
|
|
|
3702
3739
|
const stop = dirname(pathOf(context, operand.split("/").find((part) => part && part !== ".") ?? operand));
|
|
3703
3740
|
do {
|
|
3704
3741
|
if (path === "/") throw new FsError("EBUSY", { path });
|
|
3705
|
-
await removeEmptyDirectory(context, path);
|
|
3742
|
+
await removeEmptyDirectory(context, path, readDirectory);
|
|
3706
3743
|
if (parsed.flags.has("v")) await output(context, `rmdir: removing directory '${path}'
|
|
3707
3744
|
`);
|
|
3708
3745
|
path = dirname(path);
|
|
@@ -3828,23 +3865,33 @@ function filesystemCommands() {
|
|
|
3828
3865
|
await admitFilesystemModes(context, "ls", ["directory"], [path]);
|
|
3829
3866
|
const physical = await context.fs.realpath(path, { signal: context.signal });
|
|
3830
3867
|
if (ancestors.has(physical)) throw new FsError("ELOOP", { path });
|
|
3831
|
-
|
|
3832
|
-
if (
|
|
3833
|
-
|
|
3834
|
-
`);
|
|
3835
|
-
headerWritten = true;
|
|
3868
|
+
context.signal.throwIfAborted();
|
|
3869
|
+
if (ancestors.size > MAX_RECURSIVE_DIRECTORY_DEPTH) {
|
|
3870
|
+
throw new FsError("ELOOP", { path, message: `ls directory depth limit exceeded (${MAX_RECURSIVE_DIRECTORY_DEPTH})` });
|
|
3836
3871
|
}
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
const
|
|
3846
|
-
|
|
3847
|
-
|
|
3872
|
+
ancestors.add(physical);
|
|
3873
|
+
try {
|
|
3874
|
+
if (header) {
|
|
3875
|
+
await output(context, `${headerWritten ? "\n" : ""}${display}:
|
|
3876
|
+
`);
|
|
3877
|
+
headerWritten = true;
|
|
3878
|
+
}
|
|
3879
|
+
const entries = await readDirectory(context, path, true);
|
|
3880
|
+
const names = entries.map((entry) => entry.name).filter((name2) => parsed.flags.has("a") || parsed.flags.has("A") || !name2.startsWith("."));
|
|
3881
|
+
if (parsed.flags.has("a")) for (const name2 of [".", ".."]) {
|
|
3882
|
+
const index = names.findIndex((entry) => entry > name2);
|
|
3883
|
+
names.splice(index < 0 ? names.length : index, 0, name2);
|
|
3884
|
+
}
|
|
3885
|
+
if (parsed.flags.has("r")) names.reverse();
|
|
3886
|
+
for (const name2 of names) await render(joinPath(path, name2), name2);
|
|
3887
|
+
if (parsed.flags.has("R")) for (const name2 of names) {
|
|
3888
|
+
if (name2 === "." || name2 === "..") continue;
|
|
3889
|
+
const child = joinPath(path, name2);
|
|
3890
|
+
const childStat = await context.fs[parsed.flags.has("L") ? "stat" : "lstat"](child, { signal: context.signal });
|
|
3891
|
+
if (childStat.type === "directory") await list(child, `${display.replace(/\/$/u, "")}/${name2}`, true, ancestors);
|
|
3892
|
+
}
|
|
3893
|
+
} finally {
|
|
3894
|
+
ancestors.delete(physical);
|
|
3848
3895
|
}
|
|
3849
3896
|
};
|
|
3850
3897
|
return eachOperand(context, operands, (operand) => list(pathOf(context, operand), operand, operands.length > 1 || parsed.flags.has("R")));
|
|
@@ -18866,10 +18913,10 @@ function createBoundedRegexProvider(input3 = {}) {
|
|
|
18866
18913
|
}
|
|
18867
18914
|
|
|
18868
18915
|
// packages/safe-bash/src/browser.ts
|
|
18869
|
-
function createBrowserCommands() {
|
|
18916
|
+
function createBrowserCommands(options3 = {}) {
|
|
18870
18917
|
return [
|
|
18871
18918
|
...basicCommands(),
|
|
18872
|
-
...filesystemCommands(),
|
|
18919
|
+
...filesystemCommands(options3.maxDirectoryEntries),
|
|
18873
18920
|
...predicateCommands(),
|
|
18874
18921
|
...streamCommands(),
|
|
18875
18922
|
...textCommands()
|
|
@@ -18879,7 +18926,7 @@ function browserCommands(options3 = {}) {
|
|
|
18879
18926
|
return {
|
|
18880
18927
|
name: "browser-commands",
|
|
18881
18928
|
setup(host) {
|
|
18882
|
-
const commands = createBrowserCommands();
|
|
18929
|
+
const commands = createBrowserCommands(options3);
|
|
18883
18930
|
if (!options3.replace) {
|
|
18884
18931
|
for (const command2 of commands) {
|
|
18885
18932
|
if (host.commands.has(command2.name)) throw new Error(`Command already registered: ${command2.name}`);
|