npm.io
0.17.6 • Published 9h ago

@owsp/js

Licence
Version
0.17.6
Deps
0
Size
3.7 MB
Vulns
0
Weekly
0

@owsp/js

Runtime utilities for OpenWinSpec schemas: projection via x-partial, canonical stringification (4-decimal numbers), hashing, and validation helpers.

Quick usage

import {
  listSerializeFields,
  extractBySerializeGroup,
  hashBySerializeGroup,
  printHashedFieldsBySerializeGroup,
} from "@owsp/js";

const alias = "Material Profile System"; // schema title

// Inspect which fields participate in a group
const fields = listSerializeFields(alias, "summary");

// Build a projection and hash it deterministically
const projection = extractBySerializeGroup(alias, data, "summary");
const hash = hashBySerializeGroup(alias, data, "summary");

// Print hash + full list of normalized hashed paths
printHashedFieldsBySerializeGroup(alias, data, "summary");

See docs: ../../docs/guide-x-partial.md.

Validation: x-uniqueBy

AjvValidator supports custom schema keyword x-uniqueBy for arrays of objects.

  • Use it when uniqueness must be enforced by selected fields, for example shortName.
  • It supports single-field and composite uniqueness.

Schema example:

properties:
  colorways:
    type: array
    x-uniqueBy: [shortName]
    items:
      $ref: "./profile-system-colorway.json"

Notes:

  • This is a runtime custom keyword in AjvValidator.
  • It complements uniqueItems (which checks full item equality, not selected fields).

Details: ../../docs/guide-x-unique-by.md.

Schema property ordering (x-order)

The package exposes helpers to order object properties according to x-order annotations in schemas. This is useful for stable serialization/UI forms.

APIs:

  • Auto-detect schema and order:
import { orderObject } from "@owsp/js";

const ordered = orderObject(data);
  • Order by bundle type (when known):
import { orderObjectByType, BundleType } from "@owsp/js";

const ordered = orderObjectByType(BundleType.MaterialSystem, data);
  • Order by schema $id (internal tools):
import { orderObjectBySchemaId } from "@owsp/js";

const ordered = orderObjectBySchemaId(
  "https://openwinspec.org/schemas/v1/material/profile/profile-system.json",
  data
);

Details: ../../docs/schema-ordering.md.

Behavior notes:

  • If some known properties have x-order, they come first by x-order value, then known properties without x-order (sorted by key), then unknown properties (sorted by key).
  • If at a given object level none of the known properties have x-order, the original key order is preserved at that level; nested values are still processed recursively and may be ordered if their schemas specify x-order.

Unit conversions

The package provides utilities to convert values between different units of measurement.

APIs:

  • Generic conversion with explicit category:
import { convert } from "@owsp/js";

convert(1500, "mm", "m", "length");    // 1.5
convert(500, "g", "kg", "mass");       // 0.5
convert(5000, "cm2", "m2", "area");    // 0.5
  • Type-safe category-specific functions:
import { convertLength, convertMass, convertArea, convertVolume } from "@owsp/js";

convertLength(1500, "mm", "m");        // 1.5
convertMass(500, "g", "kg");           // 0.5
convertArea(5000, "cm2", "m2");        // 0.5
convertVolume(250, "l", "m3");         // 0.25

Supported categories:

  • Length: mm, cm, m, in, ft
  • Area: mm², cm², m²
  • Mass: g, kg
  • Volume: l, m³
  • Countable: pcs, pkg, pallet, roll, sheet, set

Details: ../../docs/unit-conversions.md.

Build & test

nx build js
nx test js

Projection & Sorting Details

  • Deep projection: extractBySerializeGroup() walks nested objects/arrays, resolving $ref, oneOf, and allOf to collect fields annotated with x-partial.
  • Array sorting: If a schema property has x-partial.sortArrayBy: [key1, ...], arrays are sorted deterministically by these keys. Numeric keys sort ascending numerically; otherwise comparison falls back to canonical JSON strings.
  • Post-projection sort: Arrays are re-sorted after projecting inner items to ensure final ordering matches sorting rules.
  • Targeted fallback for glazing: For glazing assemblies, inner arrays glazings[*].seals and glazings[*].glazing_beads project as {vendor, id} when no x-partial fields are present, with thickness included when available. This avoids changing schema structure.
  • Scope: The glazing fallback is deliberate and not applied to other assemblies (e.g., sash_seal). Behavior for other assemblies depends on their x-partial annotations.

Hashed Fields Command

Use printHashedFieldsBySerializeGroup() when you want to inspect exactly which projection paths participate in hash generation for concrete input data.

import {
  inspectHashedFieldsBySerializeGroup,
  listHashedPathsBySerializeGroup,
  printHashedFieldsBySerializeGroup,
} from "@owsp/js";

const alias = "Material Profile System";
const group = "default";

const paths = listHashedPathsBySerializeGroup(alias, data, group);
const inspected = inspectHashedFieldsBySerializeGroup(alias, data, group);
printHashedFieldsBySerializeGroup(alias, data, group);

console.log(inspected.hash);
console.log(paths);

Notes:

  • Paths are normalized with [] for arrays (for example: /colorways[]/details/frames[]/type).
  • The list is data-dependent: only paths present in the current projection are included.
  • You can disable normalization or container paths via options: listHashedPathsBySerializeGroup(alias, data, group, { normalizeArrays: false, includeContainers: false }).

CLI Script (Saved Projection + Canonical)

For quick local checks, use the repository script:

node scripts/inspect-hashed-projection.js --input packages/schemas/src/v1/examples/material/system/delight.rhs.profile.material-system.json --alias "Material Profile System" --group default --outDir tmp --outPrefix projection-delight

Script outputs:

  • tmp/projection-delight.json - pretty JSON projection used for hash.
  • tmp/projection-delight-canonical.json - canonical JSON string (sorted keys, fixed number format).
  • tmp/projection-delight-meta.json - hash, paths count, and full hashed paths list.

Arguments:

  • --input path to input JSON file.
  • --alias schema title (default: Material Profile System).
  • --group serialize group (default: default).
  • --outDir output directory (default: tmp).
  • --outPrefix output files prefix (default: projection-delight).