@proveanything/smartlinks 1.11.8 → 1.11.9
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/dist/docs/API_SUMMARY.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
>
|
|
7
7
|
> Status: **standard**. New apps MUST follow this contract; existing apps SHOULD migrate.
|
|
8
8
|
>
|
|
9
|
-
> SDK: `@proveanything/smartlinks` ≥ **1.11
|
|
9
|
+
> SDK: `@proveanything/smartlinks` ≥ **1.11**.
|
|
10
|
+
> Admin shell (React only): `@proveanything/smartlinks-utils-ui` ≥ **0.7.6** — required for the admin side if using the React shell; not needed in public widgets.
|
|
10
11
|
|
|
11
12
|
---
|
|
12
13
|
|
|
@@ -22,10 +23,10 @@ Every records-based app fits into a 2×2:
|
|
|
22
23
|
That choice drives **three** things and nothing else:
|
|
23
24
|
|
|
24
25
|
1. **Manifest:** `cardinality: 'singleton' | 'collection'` and `allowFacetRules: boolean`.
|
|
25
|
-
2. **Admin
|
|
26
|
-
3. **Public
|
|
26
|
+
2. **Admin:** use `<RecordsAdminShell>` (React) or call the admin SDK functions directly. Pass `cardinality` + include `'rule'` in `scopes` if `allowFacetRules`.
|
|
27
|
+
3. **Public widget:** call `app.records.match()` (best match / singleton) or `app.records.resolveAll()` (all matches / collection). These are plain SDK calls with no framework dependency.
|
|
27
28
|
|
|
28
|
-
If you only remember one rule: **never write your own
|
|
29
|
+
If you only remember one rule: **never write your own resolution loop**. The server already walks the chain correctly — calling `match()` or `resolveAll()` is the entire public-side implementation.
|
|
29
30
|
|
|
30
31
|
---
|
|
31
32
|
|
|
@@ -115,7 +116,11 @@ Declare each record type once in `app.admin.json`. The shell and the platform re
|
|
|
115
116
|
|
|
116
117
|
---
|
|
117
118
|
|
|
118
|
-
## 4. Admin side
|
|
119
|
+
## 4. Admin side
|
|
120
|
+
|
|
121
|
+
> The admin shell and rule editor are part of `@proveanything/smartlinks-utils-ui`, which is a **React-only library**. It is only needed in admin dashboards — never import it in a public widget.
|
|
122
|
+
|
|
123
|
+
### `<RecordsAdminShell>` (React)
|
|
119
124
|
|
|
120
125
|
The shell owns: scope tabs, browser pane, rule editor, save/discard, dirty navigation, inheritance markers, deletion, CSV, bulk apply, deep linking. **You only supply the editor for one record's `data`.**
|
|
121
126
|
|
|
@@ -170,7 +175,18 @@ import { FacetRuleEditor } from '@proveanything/smartlinks-utils-ui/facet-rule-e
|
|
|
170
175
|
|
|
171
176
|
---
|
|
172
177
|
|
|
173
|
-
## 5. Public side
|
|
178
|
+
## 5. Public side
|
|
179
|
+
|
|
180
|
+
> **Do not import `@proveanything/smartlinks-utils-ui` in a public widget.** It is a React admin library. Public widgets only need `@proveanything/smartlinks`.
|
|
181
|
+
|
|
182
|
+
The SDK is framework-agnostic. Public widgets call two endpoints depending on cardinality:
|
|
183
|
+
|
|
184
|
+
| Cardinality | Call | What it does |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| **Singleton** (one answer) | `app.records.match()` | Server walks the chain, returns the best-matching record |
|
|
187
|
+
| **Collection** (all answers) | `app.records.resolveAll()` | Server walks the chain, returns every matching record |
|
|
188
|
+
|
|
189
|
+
Neither call requires React or any other framework — wrap them in whatever async pattern your widget uses.
|
|
174
190
|
|
|
175
191
|
> **Admin vs public — the rule is simple:**
|
|
176
192
|
>
|
|
@@ -189,65 +205,48 @@ import { FacetRuleEditor } from '@proveanything/smartlinks-utils-ui/facet-rule-e
|
|
|
189
205
|
> | `app.records.bulkDelete()` | ❌ admin only — no public path | ✅ |
|
|
190
206
|
> | `app.records.restore()` | ❌ admin only — no public path | ✅ |
|
|
191
207
|
> | `app.records.previewRule()` | ❌ admin only — no public path | ✅ |
|
|
192
|
-
>
|
|
193
|
-
> The `admin` parameter on `match()` and `resolveAll()` defaults to `false`, so public widgets that omit it are fine. **Never hardcode `true` in a public widget.** The hooks below always use the public path and are the recommended approach — prefer them over raw SDK calls in widget code.
|
|
194
|
-
|
|
195
|
-
There is exactly **one decision** to make on the public side, and it follows from the manifest's `cardinality`:
|
|
196
208
|
|
|
197
|
-
### 5a. Singleton
|
|
209
|
+
### 5a. Singleton — `app.records.match()` (best match wins)
|
|
198
210
|
|
|
199
|
-
Use
|
|
211
|
+
Use when the widget shows **one** answer for the current product (ingredients, nutrition, warranty terms, washing instructions).
|
|
200
212
|
|
|
201
|
-
```
|
|
213
|
+
```ts
|
|
202
214
|
import * as SL from '@proveanything/smartlinks';
|
|
203
|
-
import { useResolvedRecord } from '@proveanything/smartlinks-utils-ui/records-admin';
|
|
204
|
-
|
|
205
|
-
const { data, source, sourceRef, matchedAt, matchedRule, isLoading } =
|
|
206
|
-
useResolvedRecord<IngredientsConfig>({
|
|
207
|
-
SL,
|
|
208
|
-
appId,
|
|
209
|
-
collectionId,
|
|
210
|
-
recordType: 'ingredients',
|
|
211
|
-
productId,
|
|
212
|
-
variantId, // optional
|
|
213
|
-
batchId, // optional
|
|
214
|
-
proofId, // optional
|
|
215
|
-
});
|
|
216
|
-
```
|
|
217
215
|
|
|
218
|
-
|
|
216
|
+
const result = await SL.app.records.match(collectionId, appId, {
|
|
217
|
+
target: { productId, variantId, batchId }, // pass whatever context you have
|
|
218
|
+
strategy: 'best',
|
|
219
|
+
recordType: 'ingredients',
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// result.best.ingredients → the single highest-specificity record
|
|
223
|
+
// result.best.ingredients.matchedAt → 'product' | 'rule' | 'facet' | 'collection' | …
|
|
224
|
+
```
|
|
219
225
|
|
|
220
|
-
|
|
226
|
+
The server walks `proof → batch → variant → product → rule → facet → collection` and returns the first match.
|
|
221
227
|
|
|
222
|
-
### 5b. Collection
|
|
228
|
+
### 5b. Collection — `app.records.resolveAll()` (every match, ordered)
|
|
223
229
|
|
|
224
|
-
Use
|
|
230
|
+
Use when the widget shows **many** answers across the chain (FAQs, recipes, care tips, SOPs).
|
|
225
231
|
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
SL,
|
|
231
|
-
appId,
|
|
232
|
-
collectionId,
|
|
233
|
-
recordType: 'faq',
|
|
234
|
-
productId,
|
|
235
|
-
// sort: { kind: 'field', field: 'order', direction: 'asc' },
|
|
232
|
+
```ts
|
|
233
|
+
const result = await SL.app.records.resolveAll(collectionId, appId, {
|
|
234
|
+
target: { productId },
|
|
235
|
+
recordTypes: ['faq'],
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
-
//
|
|
238
|
+
// result.records → AppRecord[] sorted most-specific first
|
|
239
|
+
// each record has .matchedAt, .data, .scope
|
|
239
240
|
```
|
|
240
241
|
|
|
241
|
-
### 5c. Multi-type
|
|
242
|
-
|
|
243
|
-
When you need every record of every type that applies to a context (rare; mostly executors and SEO surfaces).
|
|
242
|
+
### 5c. Multi-type — `app.records.resolveAll()` with multiple record types
|
|
244
243
|
|
|
245
|
-
|
|
246
|
-
import { useResolveAllRecords } from '@proveanything/smartlinks-utils-ui/records-admin';
|
|
244
|
+
When you need records of several types in one call (rare; executors, SEO surfaces):
|
|
247
245
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
246
|
+
```ts
|
|
247
|
+
const result = await SL.app.records.resolveAll(collectionId, appId, {
|
|
248
|
+
target: { productId, facets: { brand: 'acme' } },
|
|
249
|
+
recordTypes: ['ingredients', 'nutrition', 'allergens'],
|
|
251
250
|
});
|
|
252
251
|
```
|
|
253
252
|
|
|
@@ -255,15 +254,15 @@ const { entries, isLoading } = useResolveAllRecords({
|
|
|
255
254
|
|
|
256
255
|
| ❌ Anti-pattern | ✅ Do this instead |
|
|
257
256
|
| ---------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
258
|
-
|
|
|
259
|
-
| Calling `SL.app.records.list(
|
|
260
|
-
| Calling `SL.app.records.
|
|
261
|
-
| Calling `SL.app.records.
|
|
262
|
-
| Calling `
|
|
263
|
-
|
|
|
257
|
+
| Importing anything from `@proveanything/smartlinks-utils-ui` in a public widget | That package is React-only and admin-only. Public widgets only use `@proveanything/smartlinks`. |
|
|
258
|
+
| Calling `SL.app.records.list()` and filtering client-side | `app.records.match()` (singleton) or `app.records.resolveAll()` (collection). The server walks the chain. |
|
|
259
|
+
| Calling `SL.app.records.list(…, true)` from a public widget | Omit the `admin` flag — it defaults to `false`. |
|
|
260
|
+
| Calling `SL.app.records.match(…, true)` from a public widget | Omit the `admin` flag — it defaults to `false`. |
|
|
261
|
+
| Calling `SL.app.records.resolveAll(…, true)` from a public widget | Omit the `admin` flag — it defaults to `false`. |
|
|
262
|
+
| Calling `upsert`, `bulkUpsert`, `bulkDelete`, or `previewRule` from widget code | Those are admin-only. Widget code reads data; it never writes records. |
|
|
263
|
+
| Walking the chain by hand with multiple `get` / `list` calls | One `match()` or `resolveAll()` call. The server handles the resolution order including rules. |
|
|
264
264
|
| Treating `facet:key:value` refs as the rule mechanism | Use `facetRule` (`{ all: [{ facetKey, anyOf: [...] }] }`). Multi-condition, scored by specificity. |
|
|
265
265
|
| Reading `matchedAt === 'global'` | There is no `'global'`. The top of the chain is `'collection'`. |
|
|
266
|
-
| Building your own `<FacetRuleEditor>` | Use the one from `@proveanything/smartlinks-utils-ui/facet-rule-editor`. |
|
|
267
266
|
|
|
268
267
|
---
|
|
269
268
|
|
|
@@ -305,24 +304,36 @@ interface EditorContext<TData> {
|
|
|
305
304
|
2. **Add `cardinality` and `allowFacetRules`** to every entry under `records` in `app.admin.json`.
|
|
306
305
|
3. **Add `'rule'` (and `'collection'` if missing) to `scopes`** wherever `allowFacetRules: true`.
|
|
307
306
|
4. **Pass `cardinality`** to `<RecordsAdminShell>`.
|
|
308
|
-
5. **Replace any handwritten chain walking** with `
|
|
309
|
-
6. **Delete any code that constructs `facet:key:value` refs** for matching. Use `facetRule` via the shell or `<FacetRuleEditor
|
|
307
|
+
5. **Replace any handwritten chain walking** with `app.records.match()` (singleton) or `app.records.resolveAll()` (collection). If you are using React, the `useResolvedRecord` / `useCollectedRecords` hooks from `@proveanything/smartlinks-utils-ui` wrap these calls — but they are **admin-side React helpers**, not for public widgets.
|
|
308
|
+
6. **Delete any code that constructs `facet:key:value` refs** for matching. Use `facetRule` via the shell or `<FacetRuleEditor>` (React admin) or pass `facetRule` directly in `upsert()` calls.
|
|
310
309
|
7. **Search for the word "global"** in your code/docs and rename to "collection" — this is the most common source of confusion.
|
|
311
310
|
|
|
312
311
|
---
|
|
313
312
|
|
|
314
313
|
## 8. Where the canonical exports live
|
|
315
314
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
|
319
|
-
|
|
|
315
|
+
### Public widgets (any framework)
|
|
316
|
+
|
|
317
|
+
| Need | Import from |
|
|
318
|
+
| ---- | ----------- |
|
|
319
|
+
| Best-match resolution (singleton) | `@proveanything/smartlinks` → `SL.app.records.match()` |
|
|
320
|
+
| All-matches resolution (collection) | `@proveanything/smartlinks` → `SL.app.records.resolveAll()` |
|
|
321
|
+
| Record CRUD (public path) | `@proveanything/smartlinks` → `SL.app.records.{list, get, create, update, remove, aggregate}` |
|
|
322
|
+
|
|
323
|
+
### Admin dashboards (React)
|
|
324
|
+
|
|
325
|
+
> All of the following are from `@proveanything/smartlinks-utils-ui`, a **React-only** package. Do not use in public widgets.
|
|
326
|
+
|
|
327
|
+
| Need | Import from |
|
|
328
|
+
| ---- | ----------- |
|
|
329
|
+
| Admin shell | `@proveanything/smartlinks-utils-ui/records-admin` → `RecordsAdminShell` |
|
|
330
|
+
| Standalone rule editor | `@proveanything/smartlinks-utils-ui/facet-rule-editor` → `FacetRuleEditor` |
|
|
320
331
|
| Conditions editor (non-facet) | `@proveanything/smartlinks-utils-ui/conditions-editor` → `ConditionsEditor` |
|
|
321
|
-
| Best-match
|
|
322
|
-
| All-matches hook
|
|
323
|
-
| Multi-type
|
|
324
|
-
| Rule preview
|
|
325
|
-
|
|
|
332
|
+
| Best-match hook (React convenience wrapper) | `@proveanything/smartlinks-utils-ui/records-admin` → `useResolvedRecord` |
|
|
333
|
+
| All-matches hook (React convenience wrapper) | `@proveanything/smartlinks-utils-ui/records-admin` → `useCollectedRecords` |
|
|
334
|
+
| Multi-type hook (React convenience wrapper) | `@proveanything/smartlinks-utils-ui/records-admin` → `useResolveAllRecords` |
|
|
335
|
+
| Rule preview hook | `@proveanything/smartlinks-utils-ui/records-admin` → `useRulePreview` |
|
|
336
|
+
| Admin record CRUD (admin path) | `@proveanything/smartlinks` → `SL.app.records.{upsert, bulkUpsert, bulkDelete, restore, previewRule}` |
|
|
326
337
|
|
|
327
338
|
---
|
|
328
339
|
|
package/docs/API_SUMMARY.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
>
|
|
7
7
|
> Status: **standard**. New apps MUST follow this contract; existing apps SHOULD migrate.
|
|
8
8
|
>
|
|
9
|
-
> SDK: `@proveanything/smartlinks` ≥ **1.11
|
|
9
|
+
> SDK: `@proveanything/smartlinks` ≥ **1.11**.
|
|
10
|
+
> Admin shell (React only): `@proveanything/smartlinks-utils-ui` ≥ **0.7.6** — required for the admin side if using the React shell; not needed in public widgets.
|
|
10
11
|
|
|
11
12
|
---
|
|
12
13
|
|
|
@@ -22,10 +23,10 @@ Every records-based app fits into a 2×2:
|
|
|
22
23
|
That choice drives **three** things and nothing else:
|
|
23
24
|
|
|
24
25
|
1. **Manifest:** `cardinality: 'singleton' | 'collection'` and `allowFacetRules: boolean`.
|
|
25
|
-
2. **Admin
|
|
26
|
-
3. **Public
|
|
26
|
+
2. **Admin:** use `<RecordsAdminShell>` (React) or call the admin SDK functions directly. Pass `cardinality` + include `'rule'` in `scopes` if `allowFacetRules`.
|
|
27
|
+
3. **Public widget:** call `app.records.match()` (best match / singleton) or `app.records.resolveAll()` (all matches / collection). These are plain SDK calls with no framework dependency.
|
|
27
28
|
|
|
28
|
-
If you only remember one rule: **never write your own
|
|
29
|
+
If you only remember one rule: **never write your own resolution loop**. The server already walks the chain correctly — calling `match()` or `resolveAll()` is the entire public-side implementation.
|
|
29
30
|
|
|
30
31
|
---
|
|
31
32
|
|
|
@@ -115,7 +116,11 @@ Declare each record type once in `app.admin.json`. The shell and the platform re
|
|
|
115
116
|
|
|
116
117
|
---
|
|
117
118
|
|
|
118
|
-
## 4. Admin side
|
|
119
|
+
## 4. Admin side
|
|
120
|
+
|
|
121
|
+
> The admin shell and rule editor are part of `@proveanything/smartlinks-utils-ui`, which is a **React-only library**. It is only needed in admin dashboards — never import it in a public widget.
|
|
122
|
+
|
|
123
|
+
### `<RecordsAdminShell>` (React)
|
|
119
124
|
|
|
120
125
|
The shell owns: scope tabs, browser pane, rule editor, save/discard, dirty navigation, inheritance markers, deletion, CSV, bulk apply, deep linking. **You only supply the editor for one record's `data`.**
|
|
121
126
|
|
|
@@ -170,7 +175,18 @@ import { FacetRuleEditor } from '@proveanything/smartlinks-utils-ui/facet-rule-e
|
|
|
170
175
|
|
|
171
176
|
---
|
|
172
177
|
|
|
173
|
-
## 5. Public side
|
|
178
|
+
## 5. Public side
|
|
179
|
+
|
|
180
|
+
> **Do not import `@proveanything/smartlinks-utils-ui` in a public widget.** It is a React admin library. Public widgets only need `@proveanything/smartlinks`.
|
|
181
|
+
|
|
182
|
+
The SDK is framework-agnostic. Public widgets call two endpoints depending on cardinality:
|
|
183
|
+
|
|
184
|
+
| Cardinality | Call | What it does |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| **Singleton** (one answer) | `app.records.match()` | Server walks the chain, returns the best-matching record |
|
|
187
|
+
| **Collection** (all answers) | `app.records.resolveAll()` | Server walks the chain, returns every matching record |
|
|
188
|
+
|
|
189
|
+
Neither call requires React or any other framework — wrap them in whatever async pattern your widget uses.
|
|
174
190
|
|
|
175
191
|
> **Admin vs public — the rule is simple:**
|
|
176
192
|
>
|
|
@@ -189,65 +205,48 @@ import { FacetRuleEditor } from '@proveanything/smartlinks-utils-ui/facet-rule-e
|
|
|
189
205
|
> | `app.records.bulkDelete()` | ❌ admin only — no public path | ✅ |
|
|
190
206
|
> | `app.records.restore()` | ❌ admin only — no public path | ✅ |
|
|
191
207
|
> | `app.records.previewRule()` | ❌ admin only — no public path | ✅ |
|
|
192
|
-
>
|
|
193
|
-
> The `admin` parameter on `match()` and `resolveAll()` defaults to `false`, so public widgets that omit it are fine. **Never hardcode `true` in a public widget.** The hooks below always use the public path and are the recommended approach — prefer them over raw SDK calls in widget code.
|
|
194
|
-
|
|
195
|
-
There is exactly **one decision** to make on the public side, and it follows from the manifest's `cardinality`:
|
|
196
208
|
|
|
197
|
-
### 5a. Singleton
|
|
209
|
+
### 5a. Singleton — `app.records.match()` (best match wins)
|
|
198
210
|
|
|
199
|
-
Use
|
|
211
|
+
Use when the widget shows **one** answer for the current product (ingredients, nutrition, warranty terms, washing instructions).
|
|
200
212
|
|
|
201
|
-
```
|
|
213
|
+
```ts
|
|
202
214
|
import * as SL from '@proveanything/smartlinks';
|
|
203
|
-
import { useResolvedRecord } from '@proveanything/smartlinks-utils-ui/records-admin';
|
|
204
|
-
|
|
205
|
-
const { data, source, sourceRef, matchedAt, matchedRule, isLoading } =
|
|
206
|
-
useResolvedRecord<IngredientsConfig>({
|
|
207
|
-
SL,
|
|
208
|
-
appId,
|
|
209
|
-
collectionId,
|
|
210
|
-
recordType: 'ingredients',
|
|
211
|
-
productId,
|
|
212
|
-
variantId, // optional
|
|
213
|
-
batchId, // optional
|
|
214
|
-
proofId, // optional
|
|
215
|
-
});
|
|
216
|
-
```
|
|
217
215
|
|
|
218
|
-
|
|
216
|
+
const result = await SL.app.records.match(collectionId, appId, {
|
|
217
|
+
target: { productId, variantId, batchId }, // pass whatever context you have
|
|
218
|
+
strategy: 'best',
|
|
219
|
+
recordType: 'ingredients',
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// result.best.ingredients → the single highest-specificity record
|
|
223
|
+
// result.best.ingredients.matchedAt → 'product' | 'rule' | 'facet' | 'collection' | …
|
|
224
|
+
```
|
|
219
225
|
|
|
220
|
-
|
|
226
|
+
The server walks `proof → batch → variant → product → rule → facet → collection` and returns the first match.
|
|
221
227
|
|
|
222
|
-
### 5b. Collection
|
|
228
|
+
### 5b. Collection — `app.records.resolveAll()` (every match, ordered)
|
|
223
229
|
|
|
224
|
-
Use
|
|
230
|
+
Use when the widget shows **many** answers across the chain (FAQs, recipes, care tips, SOPs).
|
|
225
231
|
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
SL,
|
|
231
|
-
appId,
|
|
232
|
-
collectionId,
|
|
233
|
-
recordType: 'faq',
|
|
234
|
-
productId,
|
|
235
|
-
// sort: { kind: 'field', field: 'order', direction: 'asc' },
|
|
232
|
+
```ts
|
|
233
|
+
const result = await SL.app.records.resolveAll(collectionId, appId, {
|
|
234
|
+
target: { productId },
|
|
235
|
+
recordTypes: ['faq'],
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
-
//
|
|
238
|
+
// result.records → AppRecord[] sorted most-specific first
|
|
239
|
+
// each record has .matchedAt, .data, .scope
|
|
239
240
|
```
|
|
240
241
|
|
|
241
|
-
### 5c. Multi-type
|
|
242
|
-
|
|
243
|
-
When you need every record of every type that applies to a context (rare; mostly executors and SEO surfaces).
|
|
242
|
+
### 5c. Multi-type — `app.records.resolveAll()` with multiple record types
|
|
244
243
|
|
|
245
|
-
|
|
246
|
-
import { useResolveAllRecords } from '@proveanything/smartlinks-utils-ui/records-admin';
|
|
244
|
+
When you need records of several types in one call (rare; executors, SEO surfaces):
|
|
247
245
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
246
|
+
```ts
|
|
247
|
+
const result = await SL.app.records.resolveAll(collectionId, appId, {
|
|
248
|
+
target: { productId, facets: { brand: 'acme' } },
|
|
249
|
+
recordTypes: ['ingredients', 'nutrition', 'allergens'],
|
|
251
250
|
});
|
|
252
251
|
```
|
|
253
252
|
|
|
@@ -255,15 +254,15 @@ const { entries, isLoading } = useResolveAllRecords({
|
|
|
255
254
|
|
|
256
255
|
| ❌ Anti-pattern | ✅ Do this instead |
|
|
257
256
|
| ---------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
258
|
-
|
|
|
259
|
-
| Calling `SL.app.records.list(
|
|
260
|
-
| Calling `SL.app.records.
|
|
261
|
-
| Calling `SL.app.records.
|
|
262
|
-
| Calling `
|
|
263
|
-
|
|
|
257
|
+
| Importing anything from `@proveanything/smartlinks-utils-ui` in a public widget | That package is React-only and admin-only. Public widgets only use `@proveanything/smartlinks`. |
|
|
258
|
+
| Calling `SL.app.records.list()` and filtering client-side | `app.records.match()` (singleton) or `app.records.resolveAll()` (collection). The server walks the chain. |
|
|
259
|
+
| Calling `SL.app.records.list(…, true)` from a public widget | Omit the `admin` flag — it defaults to `false`. |
|
|
260
|
+
| Calling `SL.app.records.match(…, true)` from a public widget | Omit the `admin` flag — it defaults to `false`. |
|
|
261
|
+
| Calling `SL.app.records.resolveAll(…, true)` from a public widget | Omit the `admin` flag — it defaults to `false`. |
|
|
262
|
+
| Calling `upsert`, `bulkUpsert`, `bulkDelete`, or `previewRule` from widget code | Those are admin-only. Widget code reads data; it never writes records. |
|
|
263
|
+
| Walking the chain by hand with multiple `get` / `list` calls | One `match()` or `resolveAll()` call. The server handles the resolution order including rules. |
|
|
264
264
|
| Treating `facet:key:value` refs as the rule mechanism | Use `facetRule` (`{ all: [{ facetKey, anyOf: [...] }] }`). Multi-condition, scored by specificity. |
|
|
265
265
|
| Reading `matchedAt === 'global'` | There is no `'global'`. The top of the chain is `'collection'`. |
|
|
266
|
-
| Building your own `<FacetRuleEditor>` | Use the one from `@proveanything/smartlinks-utils-ui/facet-rule-editor`. |
|
|
267
266
|
|
|
268
267
|
---
|
|
269
268
|
|
|
@@ -305,24 +304,36 @@ interface EditorContext<TData> {
|
|
|
305
304
|
2. **Add `cardinality` and `allowFacetRules`** to every entry under `records` in `app.admin.json`.
|
|
306
305
|
3. **Add `'rule'` (and `'collection'` if missing) to `scopes`** wherever `allowFacetRules: true`.
|
|
307
306
|
4. **Pass `cardinality`** to `<RecordsAdminShell>`.
|
|
308
|
-
5. **Replace any handwritten chain walking** with `
|
|
309
|
-
6. **Delete any code that constructs `facet:key:value` refs** for matching. Use `facetRule` via the shell or `<FacetRuleEditor
|
|
307
|
+
5. **Replace any handwritten chain walking** with `app.records.match()` (singleton) or `app.records.resolveAll()` (collection). If you are using React, the `useResolvedRecord` / `useCollectedRecords` hooks from `@proveanything/smartlinks-utils-ui` wrap these calls — but they are **admin-side React helpers**, not for public widgets.
|
|
308
|
+
6. **Delete any code that constructs `facet:key:value` refs** for matching. Use `facetRule` via the shell or `<FacetRuleEditor>` (React admin) or pass `facetRule` directly in `upsert()` calls.
|
|
310
309
|
7. **Search for the word "global"** in your code/docs and rename to "collection" — this is the most common source of confusion.
|
|
311
310
|
|
|
312
311
|
---
|
|
313
312
|
|
|
314
313
|
## 8. Where the canonical exports live
|
|
315
314
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
|
319
|
-
|
|
|
315
|
+
### Public widgets (any framework)
|
|
316
|
+
|
|
317
|
+
| Need | Import from |
|
|
318
|
+
| ---- | ----------- |
|
|
319
|
+
| Best-match resolution (singleton) | `@proveanything/smartlinks` → `SL.app.records.match()` |
|
|
320
|
+
| All-matches resolution (collection) | `@proveanything/smartlinks` → `SL.app.records.resolveAll()` |
|
|
321
|
+
| Record CRUD (public path) | `@proveanything/smartlinks` → `SL.app.records.{list, get, create, update, remove, aggregate}` |
|
|
322
|
+
|
|
323
|
+
### Admin dashboards (React)
|
|
324
|
+
|
|
325
|
+
> All of the following are from `@proveanything/smartlinks-utils-ui`, a **React-only** package. Do not use in public widgets.
|
|
326
|
+
|
|
327
|
+
| Need | Import from |
|
|
328
|
+
| ---- | ----------- |
|
|
329
|
+
| Admin shell | `@proveanything/smartlinks-utils-ui/records-admin` → `RecordsAdminShell` |
|
|
330
|
+
| Standalone rule editor | `@proveanything/smartlinks-utils-ui/facet-rule-editor` → `FacetRuleEditor` |
|
|
320
331
|
| Conditions editor (non-facet) | `@proveanything/smartlinks-utils-ui/conditions-editor` → `ConditionsEditor` |
|
|
321
|
-
| Best-match
|
|
322
|
-
| All-matches hook
|
|
323
|
-
| Multi-type
|
|
324
|
-
| Rule preview
|
|
325
|
-
|
|
|
332
|
+
| Best-match hook (React convenience wrapper) | `@proveanything/smartlinks-utils-ui/records-admin` → `useResolvedRecord` |
|
|
333
|
+
| All-matches hook (React convenience wrapper) | `@proveanything/smartlinks-utils-ui/records-admin` → `useCollectedRecords` |
|
|
334
|
+
| Multi-type hook (React convenience wrapper) | `@proveanything/smartlinks-utils-ui/records-admin` → `useResolveAllRecords` |
|
|
335
|
+
| Rule preview hook | `@proveanything/smartlinks-utils-ui/records-admin` → `useRulePreview` |
|
|
336
|
+
| Admin record CRUD (admin path) | `@proveanything/smartlinks` → `SL.app.records.{upsert, bulkUpsert, bulkDelete, restore, previewRule}` |
|
|
326
337
|
|
|
327
338
|
---
|
|
328
339
|
|