@ai-matrx/associations 0.7.5 → 0.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changelog — @ai-matrx/associations
2
2
 
3
+ ## 0.8.0 — 2026-09-07
4
+
5
+ **Consumer action (C28).** Two exports MOVED OUT of this package.
6
+
7
+ | was | now |
8
+ |---|---|
9
+ | `import { formatRelativeTime } from "@ai-matrx/associations/react"` | `import { formatRelativeTime } from "@ai-matrx/kit/format"` |
10
+ | `import { isUuid } from "@ai-matrx/associations/core"` | `import { isUuidShape } from "@ai-matrx/kit/uuid"` |
11
+
12
+ **`formatRelativeTime` keeps its exact voice behind two options.** This
13
+ package's copy was the `Intl.RelativeTimeFormat` one that echoes an
14
+ unparseable input instead of an em-dash. Kit's default style is the dense
15
+ `"2m ago"` form, so pass the options to keep this behaviour byte-for-byte:
16
+
17
+ ```ts
18
+ formatRelativeTime(iso, { style: "intl", fallbackToInput: true })
19
+ ```
20
+
21
+ An explicit `now` moves from the second positional argument into the options
22
+ bag: `formatRelativeTime(iso, now)` becomes
23
+ `formatRelativeTime(iso, { now, style: "intl", fallbackToInput: true })`.
24
+
25
+ **`isUuid` -> `isUuidShape`.** The rename is the point. The fleet had TWO
26
+ predicates both called `isUuid` — this package's LAX 8-4-4-4-12 shape check,
27
+ and a STRICT RFC-4122 one on six matrx-frontend API doors — and the difference
28
+ was invisible at the call site. Both now live in `@ai-matrx/kit/uuid` under
29
+ names that say which is which, and `isUuidShape` is the drop-in for this one. A
30
+ bare `isUuid` is deliberately not exported anywhere: a caller must choose.
31
+ `isRfc4122Uuid` REJECTS things `isUuidShape` accepts (the nil UUID, every
32
+ v6/v7/v8 id) — never swap one for the other to make a test pass.
33
+
34
+ **Why.** Duplication census finding H1 (2026-09-07): this package and
35
+ `@ai-matrx/diff` each defined their own `formatRelativeTime`, so ~16 host twins
36
+ had no correct owner. The `assoc_*` guards still validate ids exactly as
37
+ before, proven end-to-end by the existing guard suite.
38
+
39
+ New dependency: `@ai-matrx/kit` (`latest`).
40
+
41
+ ## 0.7.6
42
+
43
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
44
+ `git diff npm/associations/v0.7.5..npm/associations/v0.7.6 -- apps/shared/associations`).
45
+ No source changes intended and no consumer action required.
46
+
3
47
  ## 0.7.5 — 2026-09-02 (recents in token-specific attach pickers)
4
48
 
5
49
  - The per-token picker opened by an association card's `+` control now shows
@@ -47,7 +47,6 @@ __export(core_exports, {
47
47
  isContentSourceEdge: () => isContentSourceEdge,
48
48
  isMembershipMetadata: () => isMembershipMetadata,
49
49
  isTransportFailure: () => isTransportFailure,
50
- isUuid: () => isUuid,
51
50
  ok: () => ok,
52
51
  resolveEntityToken: () => resolveEntityToken
53
52
  });
@@ -76,6 +75,9 @@ function createDefaultErrorSink() {
76
75
  };
77
76
  }
78
77
 
78
+ // src/core/guards.ts
79
+ var import_uuid = require("@ai-matrx/kit/uuid");
80
+
79
81
  // src/entity-types.generated.ts
80
82
  var ENTITY_TYPE_METADATA = {
81
83
  "access_request": { token: "access_request", schema: "iam", table: "access_requests", label: "Access Request", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: "System", referencePickable: false, titleColumn: null, contentRole: "utility", referenceCategory: null },
@@ -1401,10 +1403,6 @@ function isEntityTypeToken(value) {
1401
1403
  }
1402
1404
 
1403
1405
  // src/core/guards.ts
1404
- var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1405
- function isUuid(value) {
1406
- return typeof value === "string" && UUID_RE.test(value);
1407
- }
1408
1406
  function show(value) {
1409
1407
  if (typeof value === "string") return JSON.stringify(value);
1410
1408
  if (value === null || value === void 0) return String(value);
@@ -1439,11 +1437,11 @@ function createAssociationGuards(errorSink) {
1439
1437
  }
1440
1438
  return {
1441
1439
  checkUuid(field, value) {
1442
- return isUuid(value) ? null : invalid(field, value, "must be a UUID");
1440
+ return (0, import_uuid.isUuidShape)(value) ? null : invalid(field, value, "must be a UUID");
1443
1441
  },
1444
1442
  checkUuidArray(field, values) {
1445
1443
  for (let i = 0; i < values.length; i++) {
1446
- if (!isUuid(values[i]))
1444
+ if (!(0, import_uuid.isUuidShape)(values[i]))
1447
1445
  return invalid(`${field}[${i}]`, values[i], "must be a UUID");
1448
1446
  }
1449
1447
  return null;