@acid-cat/catalog 0.10.0 → 0.10.1

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/README.md CHANGED
@@ -9,6 +9,8 @@ pnpm add -D @acid-cat/catalog
9
9
  ```
10
10
 
11
11
  ```ts
12
+ import { writeFile } from "node:fs/promises";
13
+
12
14
  import { Catalog } from "@acid-cat/catalog";
13
15
 
14
16
  const catalog = new Catalog({ title: "Neighbourhood lending library" });
@@ -4,7 +4,5 @@
4
4
  */
5
5
  /** A catalog in canonical form, as text. */
6
6
  export declare function canonicalText(catalog: unknown): string;
7
- /** Put a catalog's members in canonical order. */
8
- export declare function canonicalCatalog(catalog: unknown): unknown;
9
7
  /** Order strings by Unicode code point, as Python, Go and Rust compare them. */
10
8
  export declare function byCodePoint(left: string, right: string): number;
package/dist/canonical.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/canonical.ts
1
+ // src/canonical.ts
2
2
  const isObject = (value) => value !== null && typeof value === "object";
3
3
  const CATALOG_ORDER = [
4
4
  "acidcat",
@@ -33,7 +33,10 @@ const EVENT_ORDER = [
33
33
  function canonicalText(catalog) {
34
34
  return `${write(canonicalCatalog(catalog), "")}\n`;
35
35
  }
36
- /** Put a catalog's members in canonical order. */
36
+ /**
37
+ * Put a catalog's members in canonical order. Each object becomes a `Map`, not a plain object, because a plain object
38
+ * puts integer-like keys such as "9" and "10" first, in numeric order, whatever order they were added in.
39
+ */
37
40
  function canonicalCatalog(catalog) {
38
41
  return ordered(catalog, CATALOG_ORDER, (key, value) => {
39
42
  if (key === "targets") return byKey(value, (target) => ordered(target, TARGET_ORDER, sortedMember));
@@ -45,15 +48,15 @@ function canonicalCatalog(catalog) {
45
48
  }
46
49
  /** The known members in their order, then every other member sorted by key. A value that is not an object is sorted. */
47
50
  function ordered(value, order, each) {
48
- if (!isObject(value)) return sorted(value);
49
- const known = order.filter((key) => key in value);
51
+ if (!isObject(value) || Array.isArray(value)) return sorted(value);
52
+ const known = order.filter((key) => Object.hasOwn(value, key));
50
53
  const others = Object.keys(value).filter((key) => !order.includes(key)).sort(byCodePoint);
51
- return Object.fromEntries([...known, ...others].map((key) => [key, each(key, value[key])]));
54
+ return new Map([...known, ...others].map((key) => [key, each(key, value[key])]));
52
55
  }
53
56
  /** A map keyed by name or id: its keys sorted, each value shaped by `each`. A value that is not an object is sorted. */
54
57
  function byKey(value, each) {
55
- if (!isObject(value)) return sorted(value);
56
- return Object.fromEntries(Object.keys(value).sort(byCodePoint).map((key) => [key, each(value[key])]));
58
+ if (!isObject(value) || Array.isArray(value)) return sorted(value);
59
+ return new Map(Object.keys(value).sort(byCodePoint).map((key) => [key, each(value[key])]));
57
60
  }
58
61
  function sortedMember(_key, value) {
59
62
  return sorted(value);
@@ -74,21 +77,21 @@ function byCodePoint(left, right) {
74
77
  }
75
78
  return a.length - b.length;
76
79
  }
77
- /** Write a JSON value with two-space indentation, one member or item per line. */
80
+ /** Write a JSON value with two-space indentation, one member or item per line. A `Map` keeps its order. */
78
81
  function write(value, indent) {
79
82
  if (Array.isArray(value)) {
80
83
  if (value.length === 0) return "[]";
81
84
  const inner = `${indent} `;
82
85
  return `[\n${value.map((item) => inner + write(item, inner)).join(",\n")}\n${indent}]`;
83
86
  }
84
- if (isObject(value)) {
85
- const keys = Object.keys(value);
86
- if (keys.length === 0) return "{}";
87
+ if (value instanceof Map) {
88
+ const entries = [...value];
89
+ if (entries.length === 0) return "{}";
87
90
  const inner = `${indent} `;
88
- return `{\n${keys.map((key) => `${inner}${JSON.stringify(key)}: ${write(value[key], inner)}`).join(",\n")}\n${indent}}`;
91
+ return `{\n${entries.map(([key, member]) => `${inner}${JSON.stringify(key)}: ${write(member, inner)}`).join(",\n")}\n${indent}}`;
89
92
  }
93
+ if (isObject(value)) return write(sorted(value), indent);
90
94
  if (typeof value === "number" && !Number.isFinite(value)) throw new TypeError("A catalog holds only finite numbers");
91
95
  return JSON.stringify(value);
92
96
  }
93
- //#endregion
94
- export { byCodePoint, canonicalCatalog, canonicalText };
97
+ export { byCodePoint, canonicalText };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { canonicalText } from "./canonical.js";
2
- //#region src/index.ts
2
+ // src/index.ts
3
3
  /**
4
4
  * Write an AcidCat catalog in TypeScript, and render it to the JSON document the toolchain checks.
5
5
  *
@@ -129,7 +129,7 @@ var Catalog = class {
129
129
  #referenceProblems(schema) {
130
130
  const problems = [];
131
131
  visit(schema, (node) => {
132
- if ("$defs" in node) problems.push("carries its own $defs; declare shared types with type()");
132
+ if (Object.hasOwn(node, "$defs")) problems.push("carries its own $defs; declare shared types with type()");
133
133
  if (node.$ref === void 0) return;
134
134
  const name = typeof node.$ref === "string" ? REFERENCE.exec(node.$ref)?.[1] : void 0;
135
135
  if (name === void 0 || !this.#types.has(name)) problems.push(`references ${typeof node.$ref === "string" ? node.$ref : JSON.stringify(node.$ref)}, which is not a type`);
@@ -149,5 +149,4 @@ function visit(value, onObject) {
149
149
  Object.values(value).forEach((item) => visit(item, onObject));
150
150
  }
151
151
  }
152
- //#endregion
153
152
  export { Catalog, canonicalText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acid-cat/catalog",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Write an AcidCat catalog in TypeScript and render it in canonical form.",
5
5
  "keywords": [
6
6
  "acidcat",
@@ -31,7 +31,7 @@
31
31
  "access": "public"
32
32
  },
33
33
  "devDependencies": {
34
- "@types/node": "26.6.5",
34
+ "@types/node": "26.6.6",
35
35
  "typescript": "7.0.2"
36
36
  }
37
37
  }