@ai-matrx/associations 0.2.0 → 0.4.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,154 @@
1
1
  # Changelog — @ai-matrx/associations
2
2
 
3
+ ## 0.4.0 — 2026-08-29 (unreleased; W4 completion)
4
+
5
+ The three faces STOPPED at the W3+W4 build for missing design-system
6
+ primitives, now built against `@ai-matrx/design-system` 0.3.0 (Command
7
+ family incl. CommandDialog, the Select family, the CreatablePicker
8
+ composite) — the optional peer floor moves to **`>=0.3.0`**. Behavior ported
9
+ VERBATIM from the matrx-frontend originals (each re-read in full
10
+ 2026-08-29); only the measured seams inverted, chrome never vendored.
11
+
12
+ - **`AssociationEntitySelect` (`src/react/components/AssociationEntitySelect.tsx`)**
13
+ — the canonical "name dropdown" (display / inline rename / switch / add new
14
+ / unlink), adapter-driven via the already-shipping
15
+ `AssociationEntitySelectAdapter` contract + default adapter hook. Seams:
16
+ `getEntityInfo` → the store's registry merge engine (`Icon: null` →
17
+ `DefaultEntityIcon`); `@/lib/toast` → the notifier port;
18
+ `EntityDoorControls` → the entityDoors port's `DoorControls` (absent → the
19
+ name and rows render without doors, matching the picker precedent); lucide
20
+ → inlined glyphs (C19).
21
+ - **`CategorySelect` (`src/react/components/CategorySelect.tsx`)** — THE
22
+ single-value picker over one `platform.categories` dimension, the
23
+ CreatablePicker composite with the hierarchy parent-select in
24
+ `createExtra`. Seams: the Redux active-organization read
25
+ (`selectOrganizationId`) → the identity port's optional `ensureOrgId()`
26
+ (`orgId` prop wins; with neither, create refuses LOUDLY — notifier + no
27
+ RPC); toasts → notifier. NOTE: the origin's two-part success toast
28
+ (message + description) is joined into the notifier's single success
29
+ message (the port's `success(msg)` carries no description); content
30
+ preserved.
31
+ - **`CategoryTagPicker` (`src/react/components/CategoryTagPicker.tsx`)** —
32
+ THE multi-select tagger over the canonical `entity → category` edge
33
+ (full-role `setTargets` semantics verbatim, one write at a time). Seams:
34
+ the host-shaped `ensureOrgId` (`@/lib/organizations/personalOrg`) →
35
+ `identity.ensureOrgId` per the design's seam table, with the loud
36
+ `ensure_org_missing` refusal when neither the `orgId` prop nor the port
37
+ can answer; `console.error` → errorSink
38
+ (`category_tag_set_targets_failed` / `category_tag_create_failed`);
39
+ toasts → notifier; the `icon` prop's `LucideIcon` type → the structural
40
+ `TagPickerIcon`.
41
+ - **`buildCategoryHierarchy` → `/core`
42
+ (`src/core/categoryHierarchy.ts`)** — the two-level display-order util
43
+ both category faces consume, ported verbatim from
44
+ `features/scopes/utils/categoryHierarchy.ts` (pure, React-free), exported
45
+ from `/core`.
46
+ - **Four new inlined glyphs (C19)**: `ChevronDownIcon`,
47
+ `ChevronsUpDownIcon`, `CornerDownRightIcon`, `TagIcon`.
48
+ - **Token vocabulary regenerated from the live registry: 651 → 654 tokens**
49
+ (`platform_continued_access`, `route_manifest_entry`, `short_link` landed
50
+ after the 0.3.0 generation; caught by the W5 swap agent's token-parity
51
+ gate). `check:entity-types` green against live.
52
+ - 16 new jsdom behavioral tests (render + interaction + degradations against
53
+ fake ports) → 147 total; full gate green (`typecheck`, `test`,
54
+ `check:package` incl. the packed-tarball canary).
55
+
56
+
57
+ ## 0.3.0 — 2026-08-29 (unreleased; W3 + W4 of the extraction)
58
+
59
+ Waves 3 and 4: the `/react` subpath — the seven hooks riding the /core store
60
+ via `useSyncExternalStore`, and the faces/pickers/capture toolbar. Behavior
61
+ ported VERBATIM from the matrx-frontend originals (re-read in full
62
+ 2026-08-29); only the measured seams inverted onto the W1 ports. `/react` is
63
+ the package's ONE banner group: its dist chunks carry `"use client"` (tsup
64
+ banner + `scripts/stamp-client-boundary.mjs` belt); the root and `/core`
65
+ stay pure, and `verify-tarball` now proves both directions.
66
+
67
+ - **`AssociationsProvider` (`src/react/context.tsx`)** — the one React
68
+ binding point: the host constructs the /core store in its binding module
69
+ and mounts the provider with the five UI ports (notifier / windowShell /
70
+ capture / pickerOverrides / entityDoors). Every hook/face reaches the
71
+ store via `useAssociationsStore()`, which THROWS with a precise message
72
+ when no provider is mounted. `useNotifier()` implements the notifier
73
+ degradation: absent → warn ONCE via errorSink, every user-facing failure
74
+ still screams to the sink.
75
+ - **W3 hooks, signatures byte-compatible with the originals** (the W5 swap
76
+ is a re-export flip + Redux-fragment deletion, call sites unchanged):
77
+ `useAssociations` (+ `useEntityRelationships` alias + re-exported
78
+ `AssociationWriteResult`), `useContainerLinks` (incl. the viewer-aware
79
+ `conversation_files` branch, generation/stale guards verbatim),
80
+ `useEntityTitles` (labels never exempt the liveness read; one settled
81
+ round proves absence), `useCategories`, `useUniversalEntitySearch`
82
+ (debounce + recents via `ues_list`), `useAssociationCandidates`,
83
+ `useAssociationEntitySelectAdapter` (+ the
84
+ `AssociationEntitySelectAdapter` contract, which now lives with the
85
+ hook). Redux selectors/thunks → `useSyncExternalStore` over the store;
86
+ `@/lib/toast` → notifier; `console.error` → errorSink; the host `Json`
87
+ type → `unknown` (`ContainerLink.metadata`, `attach` metadata).
88
+ `useAssociationCandidates`' Redux `selectUserId` read became a LENIENT
89
+ identity-port read (null when unauthenticated): `ownerId` is a
90
+ candidate-read filter, not an auth gate — write paths keep the loud
91
+ `requireUserId` contract.
92
+ - **W4 faces**: `AssociationCard`, `AssociationCardGrid`, `AssociationList`
93
+ (+ `ContainerResourcesAdapter` + `useContainerLinksAdapter`),
94
+ `AssociationPicker` (+ `AssociationCandidateBody` + the
95
+ create-then-associate footer), `UniversalAssociationPicker`,
96
+ `AttachedItemsSheet`, `AssociationCaptureToolbar`, `AssociationWindow`,
97
+ `PrimaryEntityProvider`/`usePrimaryEntity`, plus the content-role chrome
98
+ (`CONTENT_ROLES`/`getContentRoleMeta` — display metadata is /react's;
99
+ the classification stays /core's) and the door-seam helpers
100
+ (`DoorRef`/`UnresolvedRef`).
101
+ - **Seam inversions (deliberate, per the design's Decision 2 table)**:
102
+ - the hardcoded `token === "file"` → FilePickerWindow branch became the
103
+ `pickerOverrides` port: `AssociationPicker` routes a registered token to
104
+ its override component (same `AssociationPickerProps` contract);
105
+ `UniversalAssociationPicker`'s browse mode opens the override too, so
106
+ "file enumeration only happens through the canonical picker" survives
107
+ the inversion; with no override the generic candidate list serves every
108
+ token (the documented degradation);
109
+ - `WindowPanel` → the `windowShell` port; absent → a package-internal
110
+ fixed centered overlay (non-draggable, same anatomy, page behind stays
111
+ interactive);
112
+ - `EntityRef`/`EntityDoorControls`/access-gate `UnresolvedEntityRef` →
113
+ the `entityDoors` port; absent → title text with the overlay `hrefFor`
114
+ anchor when present, plain text otherwise, and the package's plain
115
+ "Unavailable" chip for unreadable targets;
116
+ - the capture toolbar's `features/files` + `features/data-tables` imports
117
+ → the `capture` port, PER-HANDLER optional: chips render only when
118
+ their handler exists, zero handlers → no toolbar and no drop zone
119
+ (never dead buttons, never a drop that swallows files). The original's
120
+ "Add document" picker (a host command palette over
121
+ `listAccessibleDocuments`) has no capture handler by design — hosts
122
+ append it via `extraActions`. "New document" collects its name with an
123
+ inline input row (the original's `TextInputDialog` is host chrome) and
124
+ opens the created document through the registry's `hrefFor` overlay
125
+ instead of a hardcoded `/documents/…` route;
126
+ - lucide icons → the package's own inlined SVGs (C19); host shadcn
127
+ `Input`/`Skeleton`/`Button`/`cn` → `@ai-matrx/design-system` (new
128
+ OPTIONAL peer at the `>=0.2.0` floor, per C18 — never vendored twins).
129
+ - **Store additions (additive, /core)**: `AssociationsStore` now exposes
130
+ the bound `errorSink` and `identity` so /react surfaces scream and read
131
+ identity without a second binding.
132
+ - **W4 gaps (deliberately NOT built — design-system 0.2.0 lacks the
133
+ primitives; vendoring twins is banned)**: `AssociationEntitySelect`,
134
+ `CategorySelect`, `CategoryTagPicker`. They need a Command/combobox
135
+ family (cmdk-style CommandInput/List/Item/Group/Empty + CommandDialog),
136
+ a Select, and the CreatablePicker composite. The
137
+ `AssociationEntitySelectAdapter` contract + default adapter hook (the
138
+ Redux-free seam) shipped anyway, so those faces are a pure-chrome build
139
+ once design-system grows.
140
+ - Tests: 131 (from 97) — jsdom behavioral suites per hook (subscription
141
+ updates, in-flight dedup across two consumers, error surfaces,
142
+ create-then-attach retry + loud outcome) and per face (render +
143
+ interaction against fake ports, every degradation branch: no windowShell,
144
+ no entityDoors, picker override routing, zero capture handlers,
145
+ created-but-unlinked screams).
146
+ - Gate: `pnpm typecheck && pnpm test && pnpm check:package` green; the
147
+ tarball canary installs react + react-dom + `@ai-matrx/design-system`
148
+ (npm, 0.2.0) into the empty project and imports AND requires `/react`,
149
+ proves the `"use client"` banner on both /react chunks and its absence
150
+ on all four pure chunks.
151
+
3
152
  ## 0.2.0 — 2026-08-29 (unreleased; W2 of the extraction)
4
153
 
5
154
  Wave 2: the headless owns-persistence `/core` subpath — the service
package/README.md CHANGED
@@ -4,11 +4,12 @@ THE one way to relate two entities on the AI Matrx platform: association edges,
4
4
  categories, favorites/recents, and the generated entity-type vocabulary — shipped
5
5
  as one package a Matrx client or enterprise app installs.
6
6
 
7
- **v0.2 ships the types root and the headless `/core`** the service
8
- chokepoint, guards, the never-throw result funnel, the registry merge engine,
9
- and the subscribable cache store. The React faces (`/react`: hooks, cards,
10
- list, pickers, capture toolbar) arrive in the next waves. Everything below
11
- about the schema is binding — it is the package's product.
7
+ **v0.3 ships the types root, the headless `/core`, and the React binding
8
+ `/react`** — the service chokepoint, guards, the never-throw result funnel,
9
+ the registry merge engine, the subscribable cache store, the seven hooks, and
10
+ the association faces (cards, list, pickers, attached-items sheet, capture
11
+ toolbar). Everything below about the schema is binding — it is the package's
12
+ product.
12
13
 
13
14
  ```ts
14
15
  import {
@@ -46,6 +47,35 @@ await store.favorites.setFavorite("note", noteId, true);
46
47
  await assertDemandedSchema(supabase, { selfTest: true });
47
48
  ```
48
49
 
50
+ ```tsx
51
+ // /react — the banner'd React binding (peer: react >=18 and
52
+ // @ai-matrx/design-system >=0.2.0 for the faces' chrome). Bind ONCE:
53
+ import {
54
+ AssociationsProvider,
55
+ useAssociations, // the seven hooks keep the app originals' exact signatures
56
+ AssociationCardGrid, // + AssociationCard / AssociationList / pickers / capture toolbar
57
+ PrimaryEntityProvider,
58
+ } from "@ai-matrx/associations/react";
59
+
60
+ <AssociationsProvider
61
+ store={store} // the /core store from createAssociationsStore
62
+ notifier={toastAdapter} // optional — absent warns once, failures still hit errorSink
63
+ windowShell={windowAdapter} // optional — absent falls back to a fixed overlay
64
+ capture={captureHandlers} // optional, per-handler — chips render only when bound
65
+ pickerOverrides={{ file: FilePickerWindowAdapter }} // optional per-token pickers
66
+ entityDoors={{ EntityRef, DoorControls, UnresolvedRef }} // optional doors
67
+ >
68
+ <PrimaryEntityProvider value={{ type: "organization", id, orgId, label }}>
69
+ <AssociationCardGrid />
70
+ </PrimaryEntityProvider>
71
+ </AssociationsProvider>;
72
+ ```
73
+
74
+ The faces style with Tailwind semantic tokens (`bg-card`,
75
+ `text-muted-foreground`, …): register this package as a Tailwind v4 source in
76
+ the consuming app (`@source "../node_modules/@ai-matrx/associations/dist"`)
77
+ the same way `@ai-matrx/design-system` documents.
78
+
49
79
  ## The demanded schema — read this first
50
80
 
51
81
  This package is **opinionated like the Python `matrx-*` packages**: it does not
@@ -26,6 +26,7 @@ __export(core_exports, {
26
26
  SELF_TEST_MISSING_RPC: () => SELF_TEST_MISSING_RPC,
27
27
  assertDemandedSchema: () => assertDemandedSchema,
28
28
  associationsKey: () => associationsKey,
29
+ buildCategoryHierarchy: () => buildCategoryHierarchy,
29
30
  createAssociationGuards: () => createAssociationGuards,
30
31
  createAssociationHelpers: () => createAssociationHelpers,
31
32
  createAssociationsService: () => createAssociationsService,
@@ -475,6 +476,7 @@ var ENTITY_TYPE_METADATA = {
475
476
  "platform_actor_session": { token: "platform_actor_session", schema: "platform", table: "actor_session", label: "Actor session", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
476
477
  "platform_actor_token": { token: "platform_actor_token", schema: "platform", table: "actor_token", label: "Actor token", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
477
478
  "platform_actor_token_event": { token: "platform_actor_token_event", schema: "platform", table: "actor_token_event", label: "Actor token event", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
479
+ "platform_continued_access": { token: "platform_continued_access", schema: "platform", table: "continued_access", label: "Continued Access", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
478
480
  "platform_outcome_event": { token: "platform_outcome_event", schema: "platform", table: "outcome_event", label: "Outcome Event", baseTier: 1, isComponent: false, isModule: false, isListed: true, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
479
481
  "platform_outsider_consumer": { token: "platform_outsider_consumer", schema: "platform", table: "outsider_consumer", label: "Outsider consumer", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
480
482
  "platform_saved_view": { token: "platform_saved_view", schema: "platform", table: "saved_view", label: "Saved view", baseTier: 1, isComponent: false, isModule: false, isListed: true, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
@@ -503,6 +505,7 @@ var ENTITY_TYPE_METADATA = {
503
505
  "research_tag": { token: "research_tag", schema: "research", table: "rs_tag", label: "Research Tag", baseTier: 1, isComponent: true, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: "name", contentRole: null, referenceCategory: null },
504
506
  "research_template": { token: "research_template", schema: "research", table: "rs_template", label: "Research Template", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: true, titleColumn: "name", contentRole: null, referenceCategory: null },
505
507
  "research_topic": { token: "research_topic", schema: "research", table: "rs_topic", label: "Research Topic", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: true, titleColumn: "name", contentRole: null, referenceCategory: null },
508
+ "route_manifest_entry": { token: "route_manifest_entry", schema: "platform", table: "route_manifest", label: "Route Manifest Entry", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
506
509
  "rulebook": { token: "rulebook", schema: "platform", table: "rulebook", label: "Rulebook", baseTier: 1, isComponent: false, isModule: false, isListed: true, scopeable: true, category: "Knowledge", referencePickable: true, titleColumn: "name", contentRole: "source", referenceCategory: null },
507
510
  "sandbox_instance": { token: "sandbox_instance", schema: "public", table: "sandbox_instances", label: "Sandbox Instance", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
508
511
  "sch_agent_task": { token: "sch_agent_task", schema: "scheduler", table: "sch_agent_task", label: "Agent Task Config", baseTier: 1, isComponent: true, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
@@ -581,6 +584,7 @@ var ENTITY_TYPE_METADATA = {
581
584
  "seo_topic": { token: "seo_topic", schema: "seo", table: "topic", label: "SEO Topic", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: "seo", referencePickable: true, titleColumn: "name", contentRole: null, referenceCategory: null },
582
585
  "seo_web_analytics_daily": { token: "seo_web_analytics_daily", schema: "seo", table: "web_analytics_daily", label: "Web Analytics Daily", baseTier: 1, isComponent: true, isModule: false, isListed: false, scopeable: true, category: "marketing", referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
583
586
  "shared_canvas_item": { token: "shared_canvas_item", schema: "canvas", table: "shared_canvas_items", label: "Shared Canvas Item", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: true, titleColumn: "title", contentRole: null, referenceCategory: null },
587
+ "short_link": { token: "short_link", schema: "platform", table: "short_links", label: "Short Link", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
584
588
  "skill": { token: "skill", schema: "skill", table: "definition", label: "Skill", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: "Skills", referencePickable: true, titleColumn: "label", contentRole: "utility", referenceCategory: null },
585
589
  "skill_render_definition": { token: "skill_render_definition", schema: "skill", table: "render_definition", label: "Skill Render Definition", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: "Skills", referencePickable: true, titleColumn: "label", contentRole: null, referenceCategory: null },
586
590
  "sms_consent": { token: "sms_consent", schema: "communication", table: "sms_consent", label: "SMS Consent", baseTier: 1, isComponent: false, isModule: false, isListed: false, scopeable: true, category: null, referencePickable: false, titleColumn: null, contentRole: null, referenceCategory: null },
@@ -1128,6 +1132,7 @@ var ENTITY_TYPE_TOKENS = [
1128
1132
  "platform_actor_session",
1129
1133
  "platform_actor_token",
1130
1134
  "platform_actor_token_event",
1135
+ "platform_continued_access",
1131
1136
  "platform_outcome_event",
1132
1137
  "platform_outsider_consumer",
1133
1138
  "platform_saved_view",
@@ -1156,6 +1161,7 @@ var ENTITY_TYPE_TOKENS = [
1156
1161
  "research_tag",
1157
1162
  "research_template",
1158
1163
  "research_topic",
1164
+ "route_manifest_entry",
1159
1165
  "rulebook",
1160
1166
  "sandbox_instance",
1161
1167
  "sch_agent_task",
@@ -1234,6 +1240,7 @@ var ENTITY_TYPE_TOKENS = [
1234
1240
  "seo_topic",
1235
1241
  "seo_web_analytics_daily",
1236
1242
  "shared_canvas_item",
1243
+ "short_link",
1237
1244
  "skill",
1238
1245
  "skill_render_definition",
1239
1246
  "sms_consent",
@@ -3019,7 +3026,9 @@ function createAssociationsStore(config) {
3019
3026
  helpers,
3020
3027
  registry,
3021
3028
  services: { associations, categories },
3022
- registerEntityOverlay: registry.registerEntityOverlay
3029
+ registerEntityOverlay: registry.registerEntityOverlay,
3030
+ errorSink,
3031
+ identity: config.identity
3023
3032
  };
3024
3033
  }
3025
3034
 
@@ -3188,4 +3197,68 @@ function isContentSourceEdge(sourceType, metadata) {
3188
3197
  if (isMembershipMetadata(metadata)) return false;
3189
3198
  return true;
3190
3199
  }
3200
+
3201
+ // src/core/categoryHierarchy.ts
3202
+ function buildCategoryHierarchy(categories) {
3203
+ const byId = new Map(categories.map((category) => [category.id, category]));
3204
+ const hasHierarchy = categories.some(
3205
+ (category) => category.parentId !== null && byId.has(category.parentId)
3206
+ );
3207
+ if (!hasHierarchy) {
3208
+ return {
3209
+ items: categories.map((category) => ({
3210
+ category,
3211
+ depth: 0,
3212
+ parent: null,
3213
+ displayName: category.name
3214
+ })),
3215
+ roots: categories.filter((category) => category.parentId === null),
3216
+ hasHierarchy: false
3217
+ };
3218
+ }
3219
+ const roots = categories.filter(
3220
+ (category) => category.parentId === null || !byId.has(category.parentId)
3221
+ );
3222
+ const childrenByParent = /* @__PURE__ */ new Map();
3223
+ for (const category of categories) {
3224
+ if (!category.parentId || !byId.has(category.parentId)) continue;
3225
+ const children = childrenByParent.get(category.parentId) ?? [];
3226
+ children.push(category);
3227
+ childrenByParent.set(category.parentId, children);
3228
+ }
3229
+ const items = [];
3230
+ const seen = /* @__PURE__ */ new Set();
3231
+ for (const root of roots) {
3232
+ items.push({
3233
+ category: root,
3234
+ depth: 0,
3235
+ parent: null,
3236
+ displayName: root.name
3237
+ });
3238
+ seen.add(root.id);
3239
+ for (const child of childrenByParent.get(root.id) ?? []) {
3240
+ items.push({
3241
+ category: child,
3242
+ depth: 1,
3243
+ parent: root,
3244
+ displayName: `${root.name} / ${child.name}`
3245
+ });
3246
+ seen.add(child.id);
3247
+ }
3248
+ }
3249
+ for (const category of categories) {
3250
+ if (seen.has(category.id)) continue;
3251
+ items.push({
3252
+ category,
3253
+ depth: 0,
3254
+ parent: null,
3255
+ displayName: category.name
3256
+ });
3257
+ }
3258
+ return {
3259
+ items,
3260
+ roots: categories.filter((category) => category.parentId === null),
3261
+ hasHierarchy: true
3262
+ };
3263
+ }
3191
3264
  //# sourceMappingURL=index.cjs.map