@davidsouther/jiffies 2.0.5 → 2.0.7
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/awaitable.d.ts +1 -0
- package/lib/cjs/awaitable.js +2 -0
- 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/loader.d.mts +2 -1
- package/lib/cjs/loader.mjs +3 -2
- package/lib/cjs/scope/state.d.ts +2 -1
- package/lib/cjs/scope/state.js +3 -2
- package/lib/cjs/test_all.js +2 -2
- 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/awaitable.d.ts +1 -0
- package/lib/esm/awaitable.js +1 -0
- 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/loader.d.mts +2 -1
- package/lib/esm/loader.mjs +3 -2
- package/lib/esm/scope/state.d.ts +2 -1
- package/lib/esm/scope/state.js +3 -2
- package/lib/esm/test_all.js +2 -2
- 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/awaitable.ts +1 -0
- package/src/dom/dom.ts +4 -6
- package/src/dom/fc.ts +1 -1
- 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/loader.mjs +3 -2
- package/src/scope/state.ts +8 -5
- package/src/test_all.ts +2 -3
- package/src/transpile.mjs +1 -1
package/src/equal.ts
CHANGED
|
@@ -10,7 +10,7 @@ export const equalArrays = compareArrays(Object.is);
|
|
|
10
10
|
export const matchArrays: <A>(a: A[], b: A[], partial?: boolean) => boolean =
|
|
11
11
|
compareArrays(equals);
|
|
12
12
|
|
|
13
|
-
function asArray(a: Record<string,
|
|
13
|
+
export function asArray<T = unknown>(a: Record<string, T>): [string, T][] {
|
|
14
14
|
return Object.entries(a).sort((a, b) => a[0].localeCompare(b[0]));
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -25,6 +25,8 @@ export const matchObjects = (a: {}, b: {}, partial = true) => {
|
|
|
25
25
|
|
|
26
26
|
export function equals<A>(a: A | A[], b: A | A[], partial = false): boolean {
|
|
27
27
|
// runtime type checking
|
|
28
|
+
if (a === null && a === b) return true;
|
|
29
|
+
if (a === undefined && a === b) return true;
|
|
28
30
|
switch (typeof a) {
|
|
29
31
|
case "object":
|
|
30
32
|
if (b === undefined) {
|
|
@@ -41,3 +43,11 @@ export function equals<A>(a: A | A[], b: A | A[], partial = false): boolean {
|
|
|
41
43
|
return Object.is(a, b);
|
|
42
44
|
}
|
|
43
45
|
}
|
|
46
|
+
|
|
47
|
+
// prettier-ignore
|
|
48
|
+
export type Equals<T1, T2> =
|
|
49
|
+
(<T>() => (T extends T2 ? true : false)) extends
|
|
50
|
+
(<T>() => (T extends T1 ? true : false))
|
|
51
|
+
? true : false;
|
|
52
|
+
|
|
53
|
+
export type Not<B extends boolean> = B extends true ? false : true;
|
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/loader.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { transpile } from "./transpile.mjs";
|
|
|
5
5
|
|
|
6
6
|
const baseURL = pathToFileURL(`${cwd()}/`).href;
|
|
7
7
|
|
|
8
|
-
/** @returns {Promise<{url: string}>} */
|
|
8
|
+
/** @returns {Promise<{url: string, shortCircuit?: boolean}>} */
|
|
9
9
|
export async function resolve(
|
|
10
10
|
/** @type string */ specifier,
|
|
11
11
|
/** @type {{parentURL?: string}} */ context,
|
|
@@ -19,7 +19,8 @@ export async function resolve(
|
|
|
19
19
|
try {
|
|
20
20
|
const stats = await stat(fileURLToPath(tsURL));
|
|
21
21
|
if (stats.isFile()) {
|
|
22
|
-
return { url: tsSpecifier };
|
|
22
|
+
// return { url: tsSpecifier, shortCircuit: true };
|
|
23
|
+
return defaultResolve(tsSpecifier, context, defaultResolve);
|
|
23
24
|
}
|
|
24
25
|
} catch (e) {
|
|
25
26
|
// Do nothing
|
package/src/scope/state.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { Awaitable } from "../awaitable";
|
|
2
|
+
|
|
1
3
|
export function cleanState<State extends {}>(
|
|
2
|
-
init: () => State
|
|
3
|
-
runner: (action: () => void) => void
|
|
4
|
+
init: () => Awaitable<State>,
|
|
5
|
+
runner: (action: () => Promise<void>) => void
|
|
4
6
|
): State {
|
|
5
7
|
const state = {};
|
|
6
|
-
runner(() => {
|
|
7
|
-
|
|
8
|
+
runner(async () => {
|
|
9
|
+
const freshState = await init();
|
|
10
|
+
Object.assign(state, freshState);
|
|
8
11
|
});
|
|
9
12
|
return state as State;
|
|
10
|
-
}
|
|
13
|
+
}
|
package/src/test_all.ts
CHANGED
|
@@ -22,11 +22,10 @@ import "./lock.test.js";
|
|
|
22
22
|
import "./result.test.js";
|
|
23
23
|
import "./observable/observable.test.js";
|
|
24
24
|
|
|
25
|
-
import * as components from "./components/test.js";
|
|
26
|
-
import * as dom from "./dom/test.js";
|
|
27
|
-
|
|
28
25
|
if (process?.env.CI?.toLowerCase() !== "true") {
|
|
29
26
|
(async () => {
|
|
27
|
+
const components = await import("./components/test.js");
|
|
28
|
+
const dom = await import("./dom/test.js");
|
|
30
29
|
await components.loadTests();
|
|
31
30
|
await dom.loadTests();
|
|
32
31
|
})();
|
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,
|