@qodalis/cli-files 2.0.0-beta.12 → 2.0.0-beta.14
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/package.json +2 -2
- package/public-api.d.mts +89 -2
- package/public-api.d.ts +89 -2
- package/public-api.js +357 -60
- package/public-api.js.map +1 -1
- package/public-api.mjs +352 -62
- package/public-api.mjs.map +1 -1
- package/umd/index.global.js +209 -39
package/umd/index.global.js
CHANGED
|
@@ -628,14 +628,14 @@ var files = (() => {
|
|
|
628
628
|
var require_sort = __commonJS({
|
|
629
629
|
"../../node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/sort.js"(exports$1, module2) {
|
|
630
630
|
var compareBuild = require_compare_build();
|
|
631
|
-
var sort = (
|
|
631
|
+
var sort = (list2, loose) => list2.sort((a, b) => compareBuild(a, b, loose));
|
|
632
632
|
module2.exports = sort;
|
|
633
633
|
}
|
|
634
634
|
});
|
|
635
635
|
var require_rsort = __commonJS({
|
|
636
636
|
"../../node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/rsort.js"(exports$1, module2) {
|
|
637
637
|
var compareBuild = require_compare_build();
|
|
638
|
-
var rsort = (
|
|
638
|
+
var rsort = (list2, loose) => list2.sort((a, b) => compareBuild(b, a, loose));
|
|
639
639
|
module2.exports = rsort;
|
|
640
640
|
}
|
|
641
641
|
});
|
|
@@ -1834,6 +1834,21 @@ var files = (() => {
|
|
|
1834
1834
|
return CliForegroundColor2;
|
|
1835
1835
|
})(CliForegroundColor || {});
|
|
1836
1836
|
var ICliCompletionProvider_TOKEN = "cli-completion-provider";
|
|
1837
|
+
function resolveHeaders(provider) {
|
|
1838
|
+
if (!provider) return {};
|
|
1839
|
+
return typeof provider === "function" ? provider() : provider;
|
|
1840
|
+
}
|
|
1841
|
+
var CliAccessDeniedError = class _CliAccessDeniedError extends Error {
|
|
1842
|
+
constructor(message = "permission denied") {
|
|
1843
|
+
super(message);
|
|
1844
|
+
this.code = "EACCES";
|
|
1845
|
+
this.name = "CliAccessDeniedError";
|
|
1846
|
+
Object.setPrototypeOf(this, _CliAccessDeniedError.prototype);
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
function isCliAccessDeniedError(error) {
|
|
1850
|
+
return error instanceof CliAccessDeniedError || !!error && typeof error === "object" && error.name === "CliAccessDeniedError";
|
|
1851
|
+
}
|
|
1837
1852
|
var DefaultLibraryAuthor = {
|
|
1838
1853
|
name: "Nicolae Lupei",
|
|
1839
1854
|
email: "nicolae.lupei@qodalis.com"
|
|
@@ -1860,9 +1875,12 @@ var files = (() => {
|
|
|
1860
1875
|
* Returns the negotiated API version and the base path for all subsequent calls,
|
|
1861
1876
|
* or null if the server is unreachable or incompatible.
|
|
1862
1877
|
*/
|
|
1863
|
-
static async discover(baseUrl) {
|
|
1878
|
+
static async discover(baseUrl, headers) {
|
|
1864
1879
|
try {
|
|
1865
|
-
const
|
|
1880
|
+
const resolved = resolveHeaders(headers);
|
|
1881
|
+
const response = await fetch(`${baseUrl}${VERSIONS_ENDPOINT}`, {
|
|
1882
|
+
headers: Object.keys(resolved).length > 0 ? resolved : void 0
|
|
1883
|
+
});
|
|
1866
1884
|
if (!response.ok) return null;
|
|
1867
1885
|
const info = await response.json();
|
|
1868
1886
|
const version = this.negotiate(info);
|
|
@@ -2694,7 +2712,7 @@ var files = (() => {
|
|
|
2694
2712
|
};
|
|
2695
2713
|
|
|
2696
2714
|
// src/lib/version.ts
|
|
2697
|
-
var LIBRARY_VERSION = "2.0.0-beta.
|
|
2715
|
+
var LIBRARY_VERSION = "2.0.0-beta.14";
|
|
2698
2716
|
var API_VERSION2 = 2;
|
|
2699
2717
|
|
|
2700
2718
|
// src/lib/interfaces/i-file-system-service.ts
|
|
@@ -2707,6 +2725,7 @@ var files = (() => {
|
|
|
2707
2725
|
var CWD_KEY = "cwd";
|
|
2708
2726
|
var HOME_KEY = "home";
|
|
2709
2727
|
var DEFAULT_HOME = "/";
|
|
2728
|
+
var ANONYMOUS_OWNERSHIP = { uid: "nobody", gid: "nogroup" };
|
|
2710
2729
|
function createSeedFileSystem() {
|
|
2711
2730
|
const now = Date.now();
|
|
2712
2731
|
return {
|
|
@@ -2754,6 +2773,88 @@ var files = (() => {
|
|
|
2754
2773
|
this.homePath = DEFAULT_HOME;
|
|
2755
2774
|
this.currentUid = null;
|
|
2756
2775
|
this.currentGroups = [];
|
|
2776
|
+
this.systemDepth = 0;
|
|
2777
|
+
}
|
|
2778
|
+
// --- Access control ---
|
|
2779
|
+
setAccessPolicy(policy) {
|
|
2780
|
+
this.accessPolicy = policy;
|
|
2781
|
+
}
|
|
2782
|
+
runAsSystem(fn) {
|
|
2783
|
+
this.systemDepth++;
|
|
2784
|
+
try {
|
|
2785
|
+
return fn();
|
|
2786
|
+
} finally {
|
|
2787
|
+
this.systemDepth--;
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
reassignOwner(fromUid, toUid) {
|
|
2791
|
+
const from = fromUid.toLowerCase();
|
|
2792
|
+
if (!from || !toUid) return 0;
|
|
2793
|
+
let changed = 0;
|
|
2794
|
+
const visit = (node) => {
|
|
2795
|
+
if (node.ownership && node.ownership.uid.toLowerCase() === from) {
|
|
2796
|
+
node.ownership = { ...node.ownership, uid: toUid };
|
|
2797
|
+
changed++;
|
|
2798
|
+
}
|
|
2799
|
+
node.children?.forEach(visit);
|
|
2800
|
+
};
|
|
2801
|
+
visit(this.root);
|
|
2802
|
+
return changed;
|
|
2803
|
+
}
|
|
2804
|
+
canTraverse(path) {
|
|
2805
|
+
try {
|
|
2806
|
+
this.assertTraverse(this.resolvePath(path), "stat", path);
|
|
2807
|
+
return true;
|
|
2808
|
+
} catch {
|
|
2809
|
+
return false;
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
get enforcing() {
|
|
2813
|
+
return !!this.accessPolicy && this.systemDepth === 0;
|
|
2814
|
+
}
|
|
2815
|
+
deny(op, path, reason = "Permission denied") {
|
|
2816
|
+
throw new CliAccessDeniedError(`${op}: ${path}: ${reason}`);
|
|
2817
|
+
}
|
|
2818
|
+
/** `x` on every existing directory on the way to `resolved` (excluding the target). */
|
|
2819
|
+
assertTraverse(resolved, op, display) {
|
|
2820
|
+
if (!this.enforcing) return;
|
|
2821
|
+
const parts = resolved.split("/").filter(Boolean);
|
|
2822
|
+
let current = this.root;
|
|
2823
|
+
for (let i = 0; i < parts.length; i++) {
|
|
2824
|
+
if (!current || current.type !== "directory") return;
|
|
2825
|
+
if (!this.accessPolicy.canAccess(current, "execute")) this.deny(op, display);
|
|
2826
|
+
current = current.children?.find((c) => c.name === parts[i]);
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
assertAccess(node, action, op, display) {
|
|
2830
|
+
if (this.enforcing && !this.accessPolicy.canAccess(node, action)) this.deny(op, display);
|
|
2831
|
+
}
|
|
2832
|
+
/** Recursive delete: every directory inside must allow removing its entries (`w` + `x`, readable). */
|
|
2833
|
+
assertRemovableTree(dir, dirPath, display) {
|
|
2834
|
+
if (!this.enforcing) return;
|
|
2835
|
+
this.assertAccess(dir, "read", "rm", display);
|
|
2836
|
+
this.assertAccess(dir, "execute", "rm", display);
|
|
2837
|
+
if ((dir.children?.length ?? 0) > 0) this.assertAccess(dir, "write", "rm", display);
|
|
2838
|
+
for (const child of dir.children ?? []) {
|
|
2839
|
+
if (child.type === "directory") this.assertRemovableTree(child, `${dirPath}/${child.name}`, display);
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
/** Copying reads everything it copies: `r` on every file, `r` + `x` on every directory. */
|
|
2843
|
+
assertReadableTree(node, display) {
|
|
2844
|
+
if (!this.enforcing) return;
|
|
2845
|
+
this.assertAccess(node, "read", "cp", display);
|
|
2846
|
+
if (node.type !== "directory") return;
|
|
2847
|
+
this.assertAccess(node, "execute", "cp", display);
|
|
2848
|
+
for (const child of node.children ?? []) {
|
|
2849
|
+
this.assertReadableTree(child, `${display.replace(/\/+$/, "")}/${child.name}`);
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
/** Creating/removing entries needs `w` and `x` on the containing directory. */
|
|
2853
|
+
assertModifyDir(dir, dirPath, op, display) {
|
|
2854
|
+
if (!this.enforcing) return;
|
|
2855
|
+
this.assertTraverse(dirPath, op, display);
|
|
2856
|
+
this.assertAccess(dir, "execute", op, display);
|
|
2857
|
+
this.assertAccess(dir, "write", op, display);
|
|
2757
2858
|
}
|
|
2758
2859
|
// --- User context ---
|
|
2759
2860
|
setCurrentUser(uid, groups) {
|
|
@@ -2761,7 +2862,9 @@ var files = (() => {
|
|
|
2761
2862
|
this.currentGroups = groups;
|
|
2762
2863
|
}
|
|
2763
2864
|
getDefaultOwnership() {
|
|
2764
|
-
if (!this.currentUid)
|
|
2865
|
+
if (!this.currentUid) {
|
|
2866
|
+
return this.accessPolicy ? { ...ANONYMOUS_OWNERSHIP } : void 0;
|
|
2867
|
+
}
|
|
2765
2868
|
return {
|
|
2766
2869
|
uid: this.currentUid,
|
|
2767
2870
|
gid: this.currentGroups[0] || "users"
|
|
@@ -2780,6 +2883,8 @@ var files = (() => {
|
|
|
2780
2883
|
if (node.type !== "directory") {
|
|
2781
2884
|
throw new Error(`cd: ${path}: Not a directory`);
|
|
2782
2885
|
}
|
|
2886
|
+
this.assertTraverse(resolved, "cd", path);
|
|
2887
|
+
this.assertAccess(node, "execute", "cd", path);
|
|
2783
2888
|
this.cwd = resolved;
|
|
2784
2889
|
}
|
|
2785
2890
|
getHomePath() {
|
|
@@ -2836,6 +2941,8 @@ var files = (() => {
|
|
|
2836
2941
|
if (node.type !== "directory") {
|
|
2837
2942
|
throw new Error(`ls: ${path}: Not a directory`);
|
|
2838
2943
|
}
|
|
2944
|
+
this.assertTraverse(this.resolvePath(path), "ls", path);
|
|
2945
|
+
this.assertAccess(node, "read", "ls", path);
|
|
2839
2946
|
return node.children || [];
|
|
2840
2947
|
}
|
|
2841
2948
|
readFile(path) {
|
|
@@ -2846,6 +2953,8 @@ var files = (() => {
|
|
|
2846
2953
|
if (node.type === "directory") {
|
|
2847
2954
|
throw new Error(`cat: ${path}: Is a directory`);
|
|
2848
2955
|
}
|
|
2956
|
+
this.assertTraverse(this.resolvePath(path), "cat", path);
|
|
2957
|
+
this.assertAccess(node, "read", "cat", path);
|
|
2849
2958
|
return node.content ?? "";
|
|
2850
2959
|
}
|
|
2851
2960
|
exists(path) {
|
|
@@ -2870,6 +2979,10 @@ var files = (() => {
|
|
|
2870
2979
|
}
|
|
2871
2980
|
let child = current.children.find((c) => c.name === part);
|
|
2872
2981
|
if (!child) {
|
|
2982
|
+
if (this.enforcing) {
|
|
2983
|
+
this.assertAccess(current, "execute", "mkdir", path);
|
|
2984
|
+
this.assertAccess(current, "write", "mkdir", path);
|
|
2985
|
+
}
|
|
2873
2986
|
const now = Date.now();
|
|
2874
2987
|
child = {
|
|
2875
2988
|
name: part,
|
|
@@ -2885,6 +2998,8 @@ var files = (() => {
|
|
|
2885
2998
|
current.modifiedAt = now;
|
|
2886
2999
|
} else if (child.type !== "directory") {
|
|
2887
3000
|
throw new Error(`mkdir: ${part}: Not a directory`);
|
|
3001
|
+
} else {
|
|
3002
|
+
this.assertAccess(child, "execute", "mkdir", path);
|
|
2888
3003
|
}
|
|
2889
3004
|
current = child;
|
|
2890
3005
|
}
|
|
@@ -2903,6 +3018,7 @@ var files = (() => {
|
|
|
2903
3018
|
if (parent.children?.find((c) => c.name === dirName)) {
|
|
2904
3019
|
throw new Error(`mkdir: ${path}: File exists`);
|
|
2905
3020
|
}
|
|
3021
|
+
this.assertModifyDir(parent, parentPath, "mkdir", path);
|
|
2906
3022
|
const now = Date.now();
|
|
2907
3023
|
if (!parent.children) {
|
|
2908
3024
|
parent.children = [];
|
|
@@ -2937,6 +3053,12 @@ var files = (() => {
|
|
|
2937
3053
|
}
|
|
2938
3054
|
const existing = parent.children?.find((c) => c.name === fileName);
|
|
2939
3055
|
const now = Date.now();
|
|
3056
|
+
if (existing) {
|
|
3057
|
+
this.assertTraverse(resolved, "touch", path);
|
|
3058
|
+
this.assertAccess(existing, "write", "touch", path);
|
|
3059
|
+
} else {
|
|
3060
|
+
this.assertModifyDir(parent, parentPath, "touch", path);
|
|
3061
|
+
}
|
|
2940
3062
|
if (existing) {
|
|
2941
3063
|
existing.modifiedAt = now;
|
|
2942
3064
|
} else {
|
|
@@ -2963,6 +3085,8 @@ var files = (() => {
|
|
|
2963
3085
|
if (node.type === "directory") {
|
|
2964
3086
|
throw new Error(`write: ${path}: Is a directory`);
|
|
2965
3087
|
}
|
|
3088
|
+
this.assertTraverse(resolved, "write", path);
|
|
3089
|
+
this.assertAccess(node, "write", "write", path);
|
|
2966
3090
|
const now = Date.now();
|
|
2967
3091
|
node.content = append ? (node.content ?? "") + content : content;
|
|
2968
3092
|
node.size = new Blob([node.content]).size;
|
|
@@ -2991,6 +3115,8 @@ var files = (() => {
|
|
|
2991
3115
|
if (target.type === "directory" && !recursive) {
|
|
2992
3116
|
throw new Error(`rm: ${path}: Is a directory`);
|
|
2993
3117
|
}
|
|
3118
|
+
this.assertModifyDir(parent, parentPath, "rm", path);
|
|
3119
|
+
if (target.type === "directory") this.assertRemovableTree(target, resolved, path);
|
|
2994
3120
|
parent.children.splice(index, 1);
|
|
2995
3121
|
parent.modifiedAt = Date.now();
|
|
2996
3122
|
}
|
|
@@ -3005,10 +3131,13 @@ var files = (() => {
|
|
|
3005
3131
|
`cp: -r not specified; omitting directory '${src}'`
|
|
3006
3132
|
);
|
|
3007
3133
|
}
|
|
3134
|
+
this.assertTraverse(srcResolved, "cp", src);
|
|
3135
|
+
this.assertReadableTree(srcNode, src);
|
|
3008
3136
|
const destResolved = this.resolvePath(dest);
|
|
3009
3137
|
const destNode = this.getNode(destResolved);
|
|
3010
3138
|
if (destNode && destNode.type === "directory") {
|
|
3011
|
-
|
|
3139
|
+
this.assertModifyDir(destNode, destResolved, "cp", dest);
|
|
3140
|
+
const clone = this.ownedByCurrentUser(this.cloneNode(srcNode));
|
|
3012
3141
|
if (!destNode.children) {
|
|
3013
3142
|
destNode.children = [];
|
|
3014
3143
|
}
|
|
@@ -3028,7 +3157,8 @@ var files = (() => {
|
|
|
3028
3157
|
if (!parent || parent.type !== "directory") {
|
|
3029
3158
|
throw new Error(`cp: ${parentPath}: No such file or directory`);
|
|
3030
3159
|
}
|
|
3031
|
-
|
|
3160
|
+
this.assertModifyDir(parent, parentPath, "cp", dest);
|
|
3161
|
+
const clone = this.ownedByCurrentUser(this.cloneNode(srcNode));
|
|
3032
3162
|
clone.name = newName;
|
|
3033
3163
|
if (!parent.children) {
|
|
3034
3164
|
parent.children = [];
|
|
@@ -3060,10 +3190,12 @@ var files = (() => {
|
|
|
3060
3190
|
if (!srcParent || !srcParent.children) {
|
|
3061
3191
|
throw new Error(`mv: ${src}: No such file or directory`);
|
|
3062
3192
|
}
|
|
3193
|
+
this.assertModifyDir(srcParent, srcParentPath, "mv", src);
|
|
3063
3194
|
const srcIndex = srcParent.children.findIndex(
|
|
3064
3195
|
(c) => c.name === srcNode.name
|
|
3065
3196
|
);
|
|
3066
3197
|
if (destNode && destNode.type === "directory") {
|
|
3198
|
+
this.assertModifyDir(destNode, destResolved, "mv", dest);
|
|
3067
3199
|
if (!destNode.children) {
|
|
3068
3200
|
destNode.children = [];
|
|
3069
3201
|
}
|
|
@@ -3086,6 +3218,7 @@ var files = (() => {
|
|
|
3086
3218
|
`mv: ${destParentPath}: No such file or directory`
|
|
3087
3219
|
);
|
|
3088
3220
|
}
|
|
3221
|
+
this.assertModifyDir(destParent, destParentPath, "mv", dest);
|
|
3089
3222
|
srcParent.children.splice(srcIndex, 1);
|
|
3090
3223
|
srcNode.name = newName;
|
|
3091
3224
|
if (!destParent.children) {
|
|
@@ -3109,6 +3242,9 @@ var files = (() => {
|
|
|
3109
3242
|
if (!node) {
|
|
3110
3243
|
throw new Error(`chmod: ${path}: No such file or directory`);
|
|
3111
3244
|
}
|
|
3245
|
+
if (this.enforcing && !this.accessPolicy.canChangeOwnership(node)) {
|
|
3246
|
+
this.deny("chmod", path, "Operation not permitted");
|
|
3247
|
+
}
|
|
3112
3248
|
node.permissions = permissions;
|
|
3113
3249
|
}
|
|
3114
3250
|
chown(path, ownership) {
|
|
@@ -3117,6 +3253,9 @@ var files = (() => {
|
|
|
3117
3253
|
if (!node) {
|
|
3118
3254
|
throw new Error(`chown: ${path}: No such file or directory`);
|
|
3119
3255
|
}
|
|
3256
|
+
if (this.enforcing && !this.accessPolicy.canChangeOwnership(node, ownership)) {
|
|
3257
|
+
this.deny("chown", path, "Operation not permitted");
|
|
3258
|
+
}
|
|
3120
3259
|
node.ownership = ownership;
|
|
3121
3260
|
}
|
|
3122
3261
|
// --- Persistence ---
|
|
@@ -3158,6 +3297,18 @@ var files = (() => {
|
|
|
3158
3297
|
}
|
|
3159
3298
|
}
|
|
3160
3299
|
// --- Private helpers ---
|
|
3300
|
+
/** A copy belongs to whoever made it (like `cp` without `-p`) */
|
|
3301
|
+
ownedByCurrentUser(node) {
|
|
3302
|
+
const owner = this.getDefaultOwnership();
|
|
3303
|
+
if (owner) {
|
|
3304
|
+
const apply = (n) => {
|
|
3305
|
+
n.ownership = { ...owner };
|
|
3306
|
+
n.children?.forEach(apply);
|
|
3307
|
+
};
|
|
3308
|
+
apply(node);
|
|
3309
|
+
}
|
|
3310
|
+
return node;
|
|
3311
|
+
}
|
|
3161
3312
|
cloneNode(node) {
|
|
3162
3313
|
const now = Date.now();
|
|
3163
3314
|
const clone = {
|
|
@@ -3309,7 +3460,7 @@ var files = (() => {
|
|
|
3309
3460
|
];
|
|
3310
3461
|
}
|
|
3311
3462
|
async processCommand(command, context) {
|
|
3312
|
-
const fs = context.services.
|
|
3463
|
+
const fs = context.services.getRequired(
|
|
3313
3464
|
IFileSystemService_TOKEN
|
|
3314
3465
|
);
|
|
3315
3466
|
const targetPath = command.value || fs.getCurrentDirectory();
|
|
@@ -3382,7 +3533,7 @@ var files = (() => {
|
|
|
3382
3533
|
this.metadata = { icon: "\u{1F4C1}", module: "file management" };
|
|
3383
3534
|
}
|
|
3384
3535
|
async processCommand(command, context) {
|
|
3385
|
-
const fs = context.services.
|
|
3536
|
+
const fs = context.services.getRequired(
|
|
3386
3537
|
IFileSystemService_TOKEN
|
|
3387
3538
|
);
|
|
3388
3539
|
const target = command.value || "~";
|
|
@@ -3405,7 +3556,7 @@ var files = (() => {
|
|
|
3405
3556
|
this.metadata = { icon: "\u{1F4C2}", module: "file management" };
|
|
3406
3557
|
}
|
|
3407
3558
|
async processCommand(command, context) {
|
|
3408
|
-
const fs = context.services.
|
|
3559
|
+
const fs = context.services.getRequired(
|
|
3409
3560
|
IFileSystemService_TOKEN
|
|
3410
3561
|
);
|
|
3411
3562
|
context.writer.writeln(fs.getCurrentDirectory());
|
|
@@ -3433,7 +3584,7 @@ var files = (() => {
|
|
|
3433
3584
|
];
|
|
3434
3585
|
}
|
|
3435
3586
|
async processCommand(command, context) {
|
|
3436
|
-
const fs = context.services.
|
|
3587
|
+
const fs = context.services.getRequired(
|
|
3437
3588
|
IFileSystemService_TOKEN
|
|
3438
3589
|
);
|
|
3439
3590
|
const path = command.value;
|
|
@@ -3463,7 +3614,7 @@ var files = (() => {
|
|
|
3463
3614
|
this.metadata = { icon: "\u{1F5D1}", module: "file management" };
|
|
3464
3615
|
}
|
|
3465
3616
|
async processCommand(command, context) {
|
|
3466
|
-
const fs = context.services.
|
|
3617
|
+
const fs = context.services.getRequired(
|
|
3467
3618
|
IFileSystemService_TOKEN
|
|
3468
3619
|
);
|
|
3469
3620
|
const path = command.value;
|
|
@@ -3509,7 +3660,7 @@ var files = (() => {
|
|
|
3509
3660
|
this.metadata = { icon: "\u{1F4C4}", module: "file management" };
|
|
3510
3661
|
}
|
|
3511
3662
|
async processCommand(command, context) {
|
|
3512
|
-
const fs = context.services.
|
|
3663
|
+
const fs = context.services.getRequired(
|
|
3513
3664
|
IFileSystemService_TOKEN
|
|
3514
3665
|
);
|
|
3515
3666
|
const path = command.value;
|
|
@@ -3538,7 +3689,7 @@ var files = (() => {
|
|
|
3538
3689
|
this.metadata = { icon: "\u{1F4D6}", module: "file management" };
|
|
3539
3690
|
}
|
|
3540
3691
|
async processCommand(command, context) {
|
|
3541
|
-
const fs = context.services.
|
|
3692
|
+
const fs = context.services.getRequired(
|
|
3542
3693
|
IFileSystemService_TOKEN
|
|
3543
3694
|
);
|
|
3544
3695
|
const path = command.value;
|
|
@@ -3579,7 +3730,7 @@ var files = (() => {
|
|
|
3579
3730
|
}
|
|
3580
3731
|
return;
|
|
3581
3732
|
}
|
|
3582
|
-
const fs = context.services.
|
|
3733
|
+
const fs = context.services.getRequired(
|
|
3583
3734
|
IFileSystemService_TOKEN
|
|
3584
3735
|
);
|
|
3585
3736
|
let text;
|
|
@@ -3653,7 +3804,7 @@ var files = (() => {
|
|
|
3653
3804
|
];
|
|
3654
3805
|
}
|
|
3655
3806
|
async processCommand(command, context) {
|
|
3656
|
-
const fs = context.services.
|
|
3807
|
+
const fs = context.services.getRequired(
|
|
3657
3808
|
IFileSystemService_TOKEN
|
|
3658
3809
|
);
|
|
3659
3810
|
const path = command.value;
|
|
@@ -3704,7 +3855,7 @@ var files = (() => {
|
|
|
3704
3855
|
];
|
|
3705
3856
|
}
|
|
3706
3857
|
async processCommand(command, context) {
|
|
3707
|
-
const fs = context.services.
|
|
3858
|
+
const fs = context.services.getRequired(
|
|
3708
3859
|
IFileSystemService_TOKEN
|
|
3709
3860
|
);
|
|
3710
3861
|
const recursive = command.args["recursive"] || command.args["r"] || command.args["R"];
|
|
@@ -3742,7 +3893,7 @@ var files = (() => {
|
|
|
3742
3893
|
this.metadata = { icon: "\u{1F4E6}", module: "file management" };
|
|
3743
3894
|
}
|
|
3744
3895
|
async processCommand(command, context) {
|
|
3745
|
-
const fs = context.services.
|
|
3896
|
+
const fs = context.services.getRequired(
|
|
3746
3897
|
IFileSystemService_TOKEN
|
|
3747
3898
|
);
|
|
3748
3899
|
const parts = this.parseArgs(command);
|
|
@@ -3766,6 +3917,16 @@ var files = (() => {
|
|
|
3766
3917
|
}
|
|
3767
3918
|
};
|
|
3768
3919
|
|
|
3920
|
+
// src/lib/utils/readable-children.ts
|
|
3921
|
+
function readableChildren(fs, path) {
|
|
3922
|
+
try {
|
|
3923
|
+
return fs.listDirectory(path);
|
|
3924
|
+
} catch (e) {
|
|
3925
|
+
if (isCliAccessDeniedError(e)) return null;
|
|
3926
|
+
throw e;
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3769
3930
|
// src/lib/processors/cli-tree-command-processor.ts
|
|
3770
3931
|
var CliTreeCommandProcessor = class {
|
|
3771
3932
|
constructor() {
|
|
@@ -3786,7 +3947,7 @@ var files = (() => {
|
|
|
3786
3947
|
];
|
|
3787
3948
|
}
|
|
3788
3949
|
async processCommand(command, context) {
|
|
3789
|
-
const fs = context.services.
|
|
3950
|
+
const fs = context.services.getRequired(
|
|
3790
3951
|
IFileSystemService_TOKEN
|
|
3791
3952
|
);
|
|
3792
3953
|
const targetPath = command.value || fs.getCurrentDirectory();
|
|
@@ -3813,7 +3974,8 @@ var files = (() => {
|
|
|
3813
3974
|
)
|
|
3814
3975
|
);
|
|
3815
3976
|
const counts = { dirs: 0, files: 0 };
|
|
3816
|
-
this.
|
|
3977
|
+
this.fs = fs;
|
|
3978
|
+
this.printTree(node, "", true, 0, maxDepth, context, counts, resolvedPath);
|
|
3817
3979
|
context.writer.writeln();
|
|
3818
3980
|
context.writer.writeln(
|
|
3819
3981
|
`${counts.dirs} directories, ${counts.files} files`
|
|
@@ -3822,11 +3984,15 @@ var files = (() => {
|
|
|
3822
3984
|
context.writer.writeError(e.message);
|
|
3823
3985
|
}
|
|
3824
3986
|
}
|
|
3825
|
-
printTree(node, prefix, isRoot, depth, maxDepth, context, counts) {
|
|
3826
|
-
if (
|
|
3987
|
+
printTree(node, prefix, isRoot, depth, maxDepth, context, counts, path = "/") {
|
|
3988
|
+
if (depth >= maxDepth) {
|
|
3989
|
+
return;
|
|
3990
|
+
}
|
|
3991
|
+
const visible = this.fs ? readableChildren(this.fs, path) : node.children;
|
|
3992
|
+
if (!visible) {
|
|
3827
3993
|
return;
|
|
3828
3994
|
}
|
|
3829
|
-
const children = [...
|
|
3995
|
+
const children = [...visible].sort((a, b) => {
|
|
3830
3996
|
if (a.type !== b.type) {
|
|
3831
3997
|
return a.type === "directory" ? -1 : 1;
|
|
3832
3998
|
}
|
|
@@ -3851,7 +4017,8 @@ var files = (() => {
|
|
|
3851
4017
|
depth + 1,
|
|
3852
4018
|
maxDepth,
|
|
3853
4019
|
context,
|
|
3854
|
-
counts
|
|
4020
|
+
counts,
|
|
4021
|
+
path === "/" ? `/${child.name}` : `${path}/${child.name}`
|
|
3855
4022
|
);
|
|
3856
4023
|
} else {
|
|
3857
4024
|
counts.files++;
|
|
@@ -3881,7 +4048,7 @@ var files = (() => {
|
|
|
3881
4048
|
];
|
|
3882
4049
|
}
|
|
3883
4050
|
async processCommand(command, context) {
|
|
3884
|
-
const fs = context.services.
|
|
4051
|
+
const fs = context.services.getRequired(
|
|
3885
4052
|
IFileSystemService_TOKEN
|
|
3886
4053
|
);
|
|
3887
4054
|
const count = parseInt(
|
|
@@ -3948,7 +4115,7 @@ var files = (() => {
|
|
|
3948
4115
|
];
|
|
3949
4116
|
}
|
|
3950
4117
|
async processCommand(command, context) {
|
|
3951
|
-
const fs = context.services.
|
|
4118
|
+
const fs = context.services.getRequired(
|
|
3952
4119
|
IFileSystemService_TOKEN
|
|
3953
4120
|
);
|
|
3954
4121
|
const count = parseInt(
|
|
@@ -4029,7 +4196,7 @@ var files = (() => {
|
|
|
4029
4196
|
];
|
|
4030
4197
|
}
|
|
4031
4198
|
async processCommand(command, context) {
|
|
4032
|
-
const fs = context.services.
|
|
4199
|
+
const fs = context.services.getRequired(
|
|
4033
4200
|
IFileSystemService_TOKEN
|
|
4034
4201
|
);
|
|
4035
4202
|
const showLines = command.args["lines"] || command.args["l"] || false;
|
|
@@ -4125,7 +4292,7 @@ var files = (() => {
|
|
|
4125
4292
|
];
|
|
4126
4293
|
}
|
|
4127
4294
|
async processCommand(command, context) {
|
|
4128
|
-
const fs = context.services.
|
|
4295
|
+
const fs = context.services.getRequired(
|
|
4129
4296
|
IFileSystemService_TOKEN
|
|
4130
4297
|
);
|
|
4131
4298
|
const searchPath = this.parseSearchPath(command) || fs.getCurrentDirectory();
|
|
@@ -4149,6 +4316,7 @@ var files = (() => {
|
|
|
4149
4316
|
const resolvedBase = fs.resolvePath(searchPath);
|
|
4150
4317
|
const nameRegex = namePattern ? this.globToRegex(namePattern) : null;
|
|
4151
4318
|
const results = [];
|
|
4319
|
+
this.fs = fs;
|
|
4152
4320
|
this.walk(
|
|
4153
4321
|
node,
|
|
4154
4322
|
resolvedBase,
|
|
@@ -4176,8 +4344,9 @@ var files = (() => {
|
|
|
4176
4344
|
return new RegExp(`^${regexStr}$`, "i");
|
|
4177
4345
|
}
|
|
4178
4346
|
walk(node, currentPath, depth, maxDepth, nameRegex, typeFilter, results) {
|
|
4179
|
-
|
|
4180
|
-
|
|
4347
|
+
const children = this.fs ? readableChildren(this.fs, currentPath) : node.children;
|
|
4348
|
+
if (!children) return;
|
|
4349
|
+
for (const child of children) {
|
|
4181
4350
|
const childPath = currentPath === "/" ? `/${child.name}` : `${currentPath}/${child.name}`;
|
|
4182
4351
|
let matches = true;
|
|
4183
4352
|
if (nameRegex && !nameRegex.test(child.name)) {
|
|
@@ -4262,7 +4431,7 @@ var files = (() => {
|
|
|
4262
4431
|
];
|
|
4263
4432
|
}
|
|
4264
4433
|
async processCommand(command, context) {
|
|
4265
|
-
const fs = context.services.
|
|
4434
|
+
const fs = context.services.getRequired(
|
|
4266
4435
|
IFileSystemService_TOKEN
|
|
4267
4436
|
);
|
|
4268
4437
|
const ignoreCase = command.args["ignore-case"] || command.args["i"] || false;
|
|
@@ -4410,8 +4579,9 @@ var files = (() => {
|
|
|
4410
4579
|
};
|
|
4411
4580
|
}
|
|
4412
4581
|
collectFiles(fs, basePath, node, result) {
|
|
4413
|
-
|
|
4414
|
-
|
|
4582
|
+
const children = readableChildren(fs, basePath);
|
|
4583
|
+
if (!children) return;
|
|
4584
|
+
for (const child of children) {
|
|
4415
4585
|
const childPath = basePath === "/" ? `/${child.name}` : `${basePath}/${child.name}`;
|
|
4416
4586
|
if (child.type === "file") {
|
|
4417
4587
|
result.push(childPath);
|
|
@@ -4443,7 +4613,7 @@ var files = (() => {
|
|
|
4443
4613
|
];
|
|
4444
4614
|
}
|
|
4445
4615
|
async processCommand(command, context) {
|
|
4446
|
-
const fs = context.services.
|
|
4616
|
+
const fs = context.services.getRequired(
|
|
4447
4617
|
IFileSystemService_TOKEN
|
|
4448
4618
|
);
|
|
4449
4619
|
let filePath = (command.value || "").trim();
|
|
@@ -4571,7 +4741,6 @@ var files = (() => {
|
|
|
4571
4741
|
}
|
|
4572
4742
|
|
|
4573
4743
|
// src/cli-entrypoint.ts
|
|
4574
|
-
var fsService = new IndexedDbFileSystemService();
|
|
4575
4744
|
var module = {
|
|
4576
4745
|
apiVersion: API_VERSION2,
|
|
4577
4746
|
name: "@qodalis/cli-files",
|
|
@@ -4598,16 +4767,17 @@ var files = (() => {
|
|
|
4598
4767
|
services: [
|
|
4599
4768
|
{
|
|
4600
4769
|
provide: IFileSystemService_TOKEN,
|
|
4601
|
-
|
|
4770
|
+
useClass: IndexedDbFileSystemService
|
|
4602
4771
|
},
|
|
4603
4772
|
{
|
|
4604
4773
|
provide: ICliCompletionProvider_TOKEN,
|
|
4605
|
-
|
|
4774
|
+
useClass: FilePathCompletionProvider,
|
|
4775
|
+
deps: [IFileSystemService_TOKEN],
|
|
4606
4776
|
multi: true
|
|
4607
4777
|
}
|
|
4608
4778
|
],
|
|
4609
4779
|
async onInit(context) {
|
|
4610
|
-
const fs = context.services.
|
|
4780
|
+
const fs = context.services.getRequired(
|
|
4611
4781
|
IFileSystemService_TOKEN
|
|
4612
4782
|
);
|
|
4613
4783
|
await fs.initialize();
|