@davidsouther/jiffies 2.0.6 → 2.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/LICENSE +7 -0
- package/lib/cjs/assert.d.ts +4 -1
- package/lib/cjs/assert.js +9 -3
- package/lib/cjs/components/select.d.ts +4 -1
- package/lib/cjs/debounce.d.ts +0 -1
- package/lib/cjs/dom/dom.d.ts +1 -1
- package/lib/cjs/dom/router/router.d.ts +1 -0
- package/lib/cjs/dom/router/router.js +3 -0
- package/lib/cjs/equal.d.ts +3 -0
- package/lib/cjs/equal.js +6 -1
- package/lib/cjs/fs.d.ts +4 -0
- package/lib/cjs/fs.js +38 -6
- package/lib/cjs/fs.test.js +37 -0
- package/lib/cjs/fs_node.d.ts +14 -0
- package/lib/cjs/fs_node.js +47 -0
- package/lib/cjs/transpile.mjs +1 -1
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/assert.d.ts +4 -1
- package/lib/esm/assert.js +7 -2
- package/lib/esm/components/select.d.ts +4 -1
- package/lib/esm/debounce.d.ts +0 -1
- package/lib/esm/dom/dom.d.ts +1 -1
- package/lib/esm/dom/router/router.d.ts +1 -0
- package/lib/esm/dom/router/router.js +3 -0
- package/lib/esm/equal.d.ts +3 -0
- package/lib/esm/equal.js +5 -1
- package/lib/esm/fs.d.ts +4 -0
- package/lib/esm/fs.js +38 -6
- package/lib/esm/fs.test.js +39 -2
- package/lib/esm/fs_node.d.ts +14 -0
- package/lib/esm/fs_node.js +42 -0
- package/lib/esm/transpile.mjs +1 -1
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/assert.ts +9 -3
- package/src/dom/dom.ts +4 -6
- package/src/dom/router/router.ts +3 -0
- package/src/equal.ts +11 -1
- package/src/fs.test.ts +51 -2
- package/src/fs.ts +48 -8
- package/src/fs_node.ts +46 -0
- package/src/transpile.mjs +1 -1
package/src/fs.test.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
FileSystem,
|
|
3
|
+
ObjectFileSystemAdapter,
|
|
4
|
+
RecordFileSystemAdapter,
|
|
5
|
+
} from "./fs.js";
|
|
6
|
+
import { describe, it, expect, beforeEach } from "./scope/index.js";
|
|
7
|
+
import { cleanState } from "./scope/state.js";
|
|
3
8
|
|
|
4
9
|
describe("FileSystem", () => {
|
|
5
10
|
describe("Writing", () => {
|
|
@@ -50,4 +55,48 @@ describe("FileSystem", () => {
|
|
|
50
55
|
expect(dir.sort()).toEqual(["bonjour", "hello"]);
|
|
51
56
|
});
|
|
52
57
|
});
|
|
58
|
+
|
|
59
|
+
describe("stat", () => {
|
|
60
|
+
const state = cleanState(() => {
|
|
61
|
+
const fsObj = {
|
|
62
|
+
"/deep/hello": "world",
|
|
63
|
+
"/deep/bonjour": "monde",
|
|
64
|
+
"/other/file": "text",
|
|
65
|
+
};
|
|
66
|
+
return { fs: new FileSystem(new RecordFileSystemAdapter(fsObj)) };
|
|
67
|
+
}, beforeEach);
|
|
68
|
+
|
|
69
|
+
it("stats a directory", async () => {
|
|
70
|
+
const deep = await state.fs.stat("/deep");
|
|
71
|
+
expect(deep.isDirectory()).toBe(true);
|
|
72
|
+
expect(deep.isFile()).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("stats a file", async () => {
|
|
76
|
+
const deep = await state.fs.stat("/deep/hello");
|
|
77
|
+
expect(deep.isDirectory()).toBe(false);
|
|
78
|
+
expect(deep.isFile()).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("ObjectFileSystem", () => {
|
|
83
|
+
it("treats object keys as directories and final values as strings", async () => {
|
|
84
|
+
let fs = new FileSystem(
|
|
85
|
+
new ObjectFileSystemAdapter({
|
|
86
|
+
deep: {
|
|
87
|
+
hello: "world",
|
|
88
|
+
bonjour: "monde",
|
|
89
|
+
},
|
|
90
|
+
other_file: "text",
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const deep = await fs.stat("/deep");
|
|
95
|
+
expect(deep.isDirectory()).toBe(true);
|
|
96
|
+
expect(deep.isFile()).toBe(false);
|
|
97
|
+
|
|
98
|
+
const deep_bonjour = await fs.readFile("/deep/bonjour");
|
|
99
|
+
expect(deep_bonjour).toBe("monde");
|
|
100
|
+
});
|
|
101
|
+
});
|
|
53
102
|
});
|
package/src/fs.ts
CHANGED
|
@@ -8,9 +8,11 @@ export interface Stats {
|
|
|
8
8
|
name: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export function basename(filename: PathLike) {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
export function basename(filename: PathLike): string {
|
|
12
|
+
if (filename.endsWith("/")) {
|
|
13
|
+
filename = filename.substring(0, filename.length - 1);
|
|
14
|
+
}
|
|
15
|
+
const basename = filename.split("/").at(-1) ?? "";
|
|
14
16
|
return basename;
|
|
15
17
|
}
|
|
16
18
|
|
|
@@ -108,8 +110,8 @@ export class RecordFileSystemAdapter implements FileSystemAdapter {
|
|
|
108
110
|
|
|
109
111
|
stat(path: PathLike): Promise<Stats> {
|
|
110
112
|
return new Promise((resolve, reject) => {
|
|
111
|
-
if (this.fs[path]
|
|
112
|
-
resolve({
|
|
113
|
+
if (this.fs[path]) {
|
|
114
|
+
return resolve({
|
|
113
115
|
name: basename(path),
|
|
114
116
|
isDirectory() {
|
|
115
117
|
return false;
|
|
@@ -118,9 +120,24 @@ export class RecordFileSystemAdapter implements FileSystemAdapter {
|
|
|
118
120
|
return true;
|
|
119
121
|
},
|
|
120
122
|
});
|
|
121
|
-
} else {
|
|
122
|
-
reject();
|
|
123
123
|
}
|
|
124
|
+
|
|
125
|
+
if (!path.endsWith("/")) path += "/";
|
|
126
|
+
for (let filename of Object.keys(this.fs)) {
|
|
127
|
+
if (filename.startsWith(path)) {
|
|
128
|
+
return resolve({
|
|
129
|
+
name: basename(path),
|
|
130
|
+
isDirectory() {
|
|
131
|
+
return true;
|
|
132
|
+
},
|
|
133
|
+
isFile() {
|
|
134
|
+
return false;
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
reject();
|
|
124
141
|
});
|
|
125
142
|
}
|
|
126
143
|
|
|
@@ -197,7 +214,30 @@ export class LocalStorageFileSystemAdapter extends RecordFileSystemAdapter {
|
|
|
197
214
|
}
|
|
198
215
|
}
|
|
199
216
|
|
|
200
|
-
export
|
|
217
|
+
export type ObjectFileSystem = { [k: string]: string | ObjectFileSystem };
|
|
218
|
+
export class ObjectFileSystemAdapter extends RecordFileSystemAdapter {
|
|
219
|
+
constructor(object: ObjectFileSystem) {
|
|
220
|
+
super(reduceObjectFileSystem(object));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function reduceObjectFileSystem(
|
|
225
|
+
object: ObjectFileSystem
|
|
226
|
+
): Record<string, string> {
|
|
227
|
+
let level: Record<string, string> = {};
|
|
228
|
+
|
|
229
|
+
for (let [k, v] of Object.entries(object)) {
|
|
230
|
+
if (typeof v == "string") {
|
|
231
|
+
level[`/${k}`] = v;
|
|
232
|
+
} else {
|
|
233
|
+
for (let [k2, v2] of Object.entries(reduceObjectFileSystem(v))) {
|
|
234
|
+
level[`/${k}/${k2}`] = v2;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return level;
|
|
240
|
+
}
|
|
201
241
|
|
|
202
242
|
export interface Tree {
|
|
203
243
|
[k: string]: string | Tree;
|
package/src/fs_node.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { FileSystem, FileSystemAdapter, Stats } from "./fs";
|
|
2
|
+
import { copyFile, readdir, readFile, rm, stat, writeFile } from "fs/promises";
|
|
3
|
+
import { basename, join } from "path";
|
|
4
|
+
|
|
5
|
+
export class NodeFileSystem extends FileSystem {
|
|
6
|
+
constructor(cd: string = process.cwd()) {
|
|
7
|
+
super(new NodeFileSystemAdapter());
|
|
8
|
+
this.cd(cd);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Jiffies FileSystemAdapter using NodeJS' fs/promises. */
|
|
13
|
+
export class NodeFileSystemAdapter implements FileSystemAdapter {
|
|
14
|
+
async stat(path: string): Promise<Stats> {
|
|
15
|
+
const fsStat = await stat(path);
|
|
16
|
+
return {
|
|
17
|
+
name: basename(path),
|
|
18
|
+
isDirectory() {
|
|
19
|
+
return fsStat.isDirectory();
|
|
20
|
+
},
|
|
21
|
+
isFile() {
|
|
22
|
+
return !fsStat.isDirectory();
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
readdir(path: string): Promise<string[]> {
|
|
27
|
+
return readdir(path);
|
|
28
|
+
}
|
|
29
|
+
async scandir(path: string): Promise<Stats[]> {
|
|
30
|
+
return Promise.all(
|
|
31
|
+
(await this.readdir(path)).map((name) => this.stat(join(path, name)))
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
copyFile(from: string, to: string): Promise<void> {
|
|
35
|
+
return copyFile(from, to);
|
|
36
|
+
}
|
|
37
|
+
readFile(path: string): Promise<string> {
|
|
38
|
+
return readFile(path, "utf-8");
|
|
39
|
+
}
|
|
40
|
+
writeFile(path: string, contents: string): Promise<void> {
|
|
41
|
+
return writeFile(path, contents, "utf-8");
|
|
42
|
+
}
|
|
43
|
+
rm(path: string): Promise<void> {
|
|
44
|
+
return rm(path);
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/transpile.mjs
CHANGED
|
@@ -14,7 +14,7 @@ export async function transpile(
|
|
|
14
14
|
/** @type string */ url,
|
|
15
15
|
/** @type {() => Promise<{toString(): string}>} */ get
|
|
16
16
|
) {
|
|
17
|
-
if (!tsmap.has(url)
|
|
17
|
+
if (!tsmap.has(url)) {
|
|
18
18
|
const source = ts.transpile(
|
|
19
19
|
(await get()).toString(),
|
|
20
20
|
compilerOptions,
|