@weborigami/async-tree 0.0.67-beta.2 → 0.0.69

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/async-tree",
3
- "version": "0.0.67-beta.2",
3
+ "version": "0.0.69",
4
4
  "description": "Asynchronous tree drivers based on standard JavaScript classes",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -11,7 +11,7 @@
11
11
  "typescript": "5.6.2"
12
12
  },
13
13
  "dependencies": {
14
- "@weborigami/types": "0.0.67-beta.2"
14
+ "@weborigami/types": "0.0.69"
15
15
  },
16
16
  "scripts": {
17
17
  "test": "node --test --test-reporter=spec",
package/src/Tree.js CHANGED
@@ -332,14 +332,9 @@ export async function plain(treelike) {
332
332
  if (tree instanceof ObjectTree && keys.length === 0) {
333
333
  return tree.object instanceof Array ? [] : {};
334
334
  }
335
- const object = {};
336
- for (let i = 0; i < keys.length; i++) {
337
- // Normalize slashes in keys.
338
- const key = trailingSlash.remove(keys[i]);
339
- const value = values[i];
340
- object[key] = value;
341
- }
342
- return castArrayLike(object);
335
+ // Normalize slashes in keys.
336
+ keys = keys.map(trailingSlash.remove);
337
+ return castArrayLike(keys, values);
343
338
  });
344
339
  }
345
340
 
@@ -2,7 +2,7 @@ import { AsyncTree } from "@weborigami/types";
2
2
  import { Packed, PlainObject, StringLike } from "../index.ts";
3
3
 
4
4
  export function box(value: any): any;
5
- export function castArrayLike(object: any): any;
5
+ export function castArrayLike(keys: any[], values: any[]): any;
6
6
  export function getRealmObjectPrototype(object: any): any;
7
7
  export const hiddenFileNames: string[];
8
8
  export function isPacked(obj: any): obj is Packed;
@@ -11,6 +11,7 @@ export function isStringLike(obj: any): obj is StringLike;
11
11
  export function isUnpackable(obj): obj is { unpack: () => any };
12
12
  export function keysFromPath(path: string): string[];
13
13
  export const naturalOrder: (a: string, b: string) => number;
14
+ export function pathFromKeys(keys: string[]): string;
14
15
  export function pipeline(start: any, ...functions: Function[]): Promise<any>;
15
16
  export function setParent(child: any, parent: AsyncTree): void;
16
17
  export function toPlainValue(object: any): Promise<any>;
package/src/utilities.js CHANGED
@@ -27,24 +27,38 @@ export function box(value) {
27
27
  }
28
28
 
29
29
  /**
30
- * If the given plain object has only sequential integer keys, return it as an
31
- * array. Otherwise return it as is.
30
+ * Create an array or plain object from the given keys and values.
32
31
  *
33
- * @param {any} object
32
+ * If the given plain object has only sequential integer keys, return the
33
+ * values as an array. Otherwise, create a plain object with the keys and
34
+ * values.
35
+ *
36
+ * @param {any[]} keys
37
+ * @param {any[]} values
34
38
  */
35
- export function castArrayLike(object) {
36
- let hasKeys = false;
37
- let expectedIndex = 0;
38
- for (const key in object) {
39
- hasKeys = true;
40
- const index = Number(key);
41
- if (key === "" || isNaN(index) || index !== expectedIndex) {
42
- // Not an array-like object.
43
- return object;
39
+ export function castArrayLike(keys, values) {
40
+ let isArrayLike = false;
41
+
42
+ // Need at least one key to count as an array
43
+ if (keys.length > 0) {
44
+ // Assume it's an array
45
+ isArrayLike = true;
46
+ // Then check if all the keys are sequential integers
47
+ let expectedIndex = 0;
48
+ for (const key of keys) {
49
+ const index = Number(key);
50
+ if (key === "" || isNaN(index) || index !== expectedIndex) {
51
+ // Not array-like
52
+ isArrayLike = false;
53
+ break;
54
+ }
55
+ expectedIndex++;
44
56
  }
45
- expectedIndex++;
46
57
  }
47
- return hasKeys ? Object.values(object) : object;
58
+
59
+ return isArrayLike
60
+ ? values
61
+ : Object.fromEntries(keys.map((key, i) => [key, values[i]]));
48
62
  }
49
63
 
50
64
  /**
@@ -196,6 +210,19 @@ export const naturalOrder = new Intl.Collator(undefined, {
196
210
  numeric: true,
197
211
  }).compare;
198
212
 
213
+ /**
214
+ * Return a slash-separated path for the given keys.
215
+ *
216
+ * This takes care to avoid adding consecutive slashes if they keys themselves
217
+ * already have trailing slashes.
218
+ *
219
+ * @param {string[]} keys
220
+ */
221
+ export function pathFromKeys(keys) {
222
+ const normalized = keys.map((key) => trailingSlash.remove(key));
223
+ return normalized.join("/");
224
+ }
225
+
199
226
  /**
200
227
  * Apply a series of functions to a value, passing the result of each function
201
228
  * to the next one.
@@ -55,6 +55,12 @@ describe("utilities", () => {
55
55
  assert.deepEqual(strings, ["file1", "file9", "file10"]);
56
56
  });
57
57
 
58
+ test("pathFromKeys() returns a slash-separated path from keys", () => {
59
+ assert.equal(utilities.pathFromKeys([]), "");
60
+ assert.equal(utilities.pathFromKeys(["a", "b", "c"]), "a/b/c");
61
+ assert.equal(utilities.pathFromKeys(["a/", "b/", "c"]), "a/b/c");
62
+ });
63
+
58
64
  test("pipeline applies a series of functions to a value", async () => {
59
65
  const addOne = (n) => n + 1;
60
66
  const double = (n) => n * 2;