@seedprotocol/mapping 0.5.3 → 0.6.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 +29 -0
- package/README.md +202 -36
- package/dist/adapters/rss.d.ts +2 -1
- package/dist/adapters/rss.d.ts.map +1 -1
- package/dist/applyMapping.d.ts +14 -1
- package/dist/applyMapping.d.ts.map +1 -1
- package/dist/autoMap-PTFd4l-9.js +534 -0
- package/dist/autoMap-PTFd4l-9.js.map +1 -0
- package/dist/autoMap.d.ts +3 -3
- package/dist/autoMap.d.ts.map +1 -1
- package/dist/classifyUrl.d.ts +14 -0
- package/dist/classifyUrl.d.ts.map +1 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -402
- package/dist/index.js.map +1 -1
- package/dist/react/FieldMapper.d.ts +65 -5
- package/dist/react/FieldMapper.d.ts.map +1 -1
- package/dist/react/FieldMapperWires.d.ts +19 -0
- package/dist/react/FieldMapperWires.d.ts.map +1 -0
- package/dist/react/LookupEditor.d.ts +24 -0
- package/dist/react/LookupEditor.d.ts.map +1 -0
- package/dist/react/PropertyRows.d.ts +19 -0
- package/dist/react/PropertyRows.d.ts.map +1 -0
- package/dist/react/SourceRows.d.ts +18 -0
- package/dist/react/SourceRows.d.ts.map +1 -0
- package/dist/react/fieldMapperControls.d.ts +9 -0
- package/dist/react/fieldMapperControls.d.ts.map +1 -0
- package/dist/react/fieldMapperCore.d.ts +79 -0
- package/dist/react/fieldMapperCore.d.ts.map +1 -0
- package/dist/react/fieldMapperSlots.d.ts +69 -0
- package/dist/react/fieldMapperSlots.d.ts.map +1 -0
- package/dist/react/fieldMapperTheme.d.ts +34 -0
- package/dist/react/fieldMapperTheme.d.ts.map +1 -0
- package/dist/react/fieldMapperTypes.d.ts +63 -0
- package/dist/react/fieldMapperTypes.d.ts.map +1 -0
- package/dist/react/useFieldMapper.d.ts +8 -0
- package/dist/react/useFieldMapper.d.ts.map +1 -0
- package/dist/react.d.ts +10 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +1617 -0
- package/dist/react.js.map +1 -0
- package/dist/relationLookup.d.ts +14 -0
- package/dist/relationLookup.d.ts.map +1 -0
- package/dist/resolvedSources.d.ts +32 -0
- package/dist/resolvedSources.d.ts.map +1 -0
- package/dist/types.d.ts +57 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +19 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
- `FieldMapper` `renderRowAccessory?: (row: FieldMapperRow) => ReactNode` — host chrome slot on each rows-layout row (`.fm-row-accessory` / `classNames.rowAccessory`), after the transform control and before remove. Package does not fetch or preview; hosts return `null` when idle (e.g. show **Preview** only for `resolve: 'extract' | 'file'`).
|
|
6
|
+
- Optional `SourceNode.subtitle` for a secondary display line (inspector, wires card, source option labels). Prefer this over stuffing origin into `label`. Display-only — not part of `MappingDocument`.
|
|
7
|
+
|
|
8
|
+
## 0.6.0
|
|
9
|
+
|
|
10
|
+
- `FieldMapper` Phase 5: `layout` defaults to `'rows'`; `'wires'` is deprecated but still supported.
|
|
11
|
+
- `FieldMapper` Phase 4: per-row lookup editors (`slots.lookups: 'row'`), row/JSON preview parity with sync `applyMapping` (+ `_pendingResolve`), JSON behind a `<details>` disclosure. Rows layout defaults `lookups` to `'row'`; wires keep `'section'`.
|
|
12
|
+
- Shared `LookupEditor` + `buildSyncPreviewBag` / upgraded `previewForEdge` (lookup table hits, coerced copy values).
|
|
13
|
+
- `FieldMapper` Phase 3 theming contract: `--sfm-*` tokens (with `--fm-*` aliases), `theme="default" | "structural" | "none"` (`unstyled` shim), `classNames` / `components` / `slots`, `@layer seed-field-mapper`, document-once CSS injection, row `data-source-kind`.
|
|
14
|
+
- Deprecated (still work): `layout="wires"`, `theme="unstyled"`, `showPreview`, `connectionColors` — prefer `layout="rows"`, `theme="none"`, `slots.preview`, and CSS map tokens.
|
|
15
|
+
- `FieldMapper` row layout (Phase 1–2 of the redesign): `layout="rows" | "wires"`, `rowKey="property" | "source"`, `defaultRows`, optional `TargetProperty.required` for coverage.
|
|
16
|
+
- Headless `useFieldMapper` hook + shared core (`setSource` / `setTransform` / coverage / conflicts); wires UI refactored to consume the hook.
|
|
17
|
+
- Rows UI: transform control on the edge (no `buildResolvedSourceNodes` in the rows path), coverage toolbar, mapped+required filter, add-mapping flow, source inspector; source mode conflict + coverage banners.
|
|
18
|
+
- **Breaking:** `FieldMapper` and related UI exports moved to `@seedprotocol/mapping/react`. The default entry is headless-only (no React import or required peer) so Node sidecars can load without React. Install `react` / `react-dom` only when using `/react`.
|
|
19
|
+
- **Breaking:** `FieldMapper` `layout` default flipped from `'wires'` to `'rows'`. Pass `layout="wires"` explicitly if you still need the two-pane connector UI. For rows, pass origin sources only (not `buildResolvedSourceNodes`).
|
|
20
|
+
- `resolve: 'lookup'` for Relation / List-of-Relation targets: persistable `MappingDocument.lookups` (string → seed uid), `applyMappingAsync` table hit + optional host callback on miss; sync apply skips lookup edges.
|
|
21
|
+
- `TargetProperty.ref` / `refValueType`; `isRelationLookupTarget` helper; `autoMap` never plain-copies onto lookup-capable targets (author → authors no longer writes a string into a relation list).
|
|
22
|
+
- `FieldMapper`: connecting to a lookup-capable target sets `resolve: 'lookup'`; optional `lookups` / `onLookupsChange` panel edits string → uid maps (comma-separated for multi).
|
|
23
|
+
- `FieldMapper`: `theme="default" | "unstyled"`, CSS-var connector strokes (`--fm-map-1…8` / `--map-1…8`), optional `connectionColors`, `data-mapping-index` / `data-pair` on wells and paths; pending `.active` only on the selected source.
|
|
24
|
+
- `FieldMapping.resolve?: 'extract' | 'file' | 'lookup'`; sync `applyMapping` skips resolve edges; new `applyMappingAsync` with host callback.
|
|
25
|
+
- `classifyUrl`, `buildResolvedSourceNodes`, `normalizeMappingFromSourceId` for package-owned extract/file candidates.
|
|
26
|
+
- RSS adapter exposes enclosure / media:content as `url` + `contentType` in `meta` (stable `rss-enclosure-N` ids).
|
|
27
|
+
- `autoMap` never maps a raw URL onto html/Image/File without `resolve`; prefers full-text → html, then extract, then file jobs.
|
|
28
|
+
- Allow one source to map to multiple properties (edge-list fan-out); each property remains exclusive.
|
|
29
|
+
- `autoMap` fans `link` / `url` sources out to matching URL-ish targets (`importUrl`, `canonicalUrl`, `url`, `link`, `permalink`).
|
|
30
|
+
- `FieldMapper` supports attaching multiple properties from an active source without clearing prior edges; normalizes `@extract`/`@file` nodes to `resolve` on persist.
|
|
31
|
+
|
|
3
32
|
## 0.5.1
|
|
4
33
|
|
|
5
34
|
- Initial Phase 1 release: headless mapping core, markdown + RSS adapters, `FieldMapper` UI.
|
package/README.md
CHANGED
|
@@ -5,8 +5,15 @@ Source → Seed model property mapping helpers and a props-driven React UI.
|
|
|
5
5
|
Use this package to:
|
|
6
6
|
|
|
7
7
|
1. Parse markdown or RSS/Atom into `SourceNode[]`
|
|
8
|
-
2.
|
|
9
|
-
3. `
|
|
8
|
+
2. Optionally expand URL sources with `buildResolvedSourceNodes` (extract / file candidates)
|
|
9
|
+
3. Author `FieldMapping` edges (manually, via `autoMap`, or via `FieldMapper`)
|
|
10
|
+
4. `applyMapping` (sync copy) or `applyMappingAsync` (host resolve callback) → property bag
|
|
11
|
+
|
|
12
|
+
Mappings are an edge list: one source may fan out to multiple properties (e.g. RSS
|
|
13
|
+
`link` → `importUrl` and `canonicalUrl`). Each property is exclusive — at most one
|
|
14
|
+
source may map to it. Optional `resolve: 'extract' | 'file' | 'lookup'` marks
|
|
15
|
+
transforms the **host** (or a persisted value map) performs; the package never
|
|
16
|
+
fetches, runs Readability, or loads Seed Identity items.
|
|
10
17
|
|
|
11
18
|
## Install
|
|
12
19
|
|
|
@@ -14,7 +21,11 @@ Use this package to:
|
|
|
14
21
|
bun add @seedprotocol/mapping
|
|
15
22
|
```
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
The default entry (`@seedprotocol/mapping`) is headless — no React peer required.
|
|
25
|
+
For `FieldMapper`, also install React peers and import from `@seedprotocol/mapping/react`.
|
|
26
|
+
|
|
27
|
+
RSS parsing uses `rss-parser` with the same custom fields as `@seedprotocol/feed`
|
|
28
|
+
`parseRssString` (aligned, no hard dependency on the feed package barrel).
|
|
18
29
|
|
|
19
30
|
## Headless API
|
|
20
31
|
|
|
@@ -24,6 +35,9 @@ import {
|
|
|
24
35
|
rssXmlToSources,
|
|
25
36
|
autoMap,
|
|
26
37
|
applyMapping,
|
|
38
|
+
applyMappingAsync,
|
|
39
|
+
buildResolvedSourceNodes,
|
|
40
|
+
classifyUrl,
|
|
27
41
|
type TargetProperty,
|
|
28
42
|
type MappingDocument,
|
|
29
43
|
} from '@seedprotocol/mapping'
|
|
@@ -43,63 +57,215 @@ const doc: MappingDocument = {
|
|
|
43
57
|
}
|
|
44
58
|
```
|
|
45
59
|
|
|
46
|
-
RSS:
|
|
60
|
+
RSS with resolve jobs:
|
|
47
61
|
|
|
48
62
|
```ts
|
|
49
|
-
const {
|
|
63
|
+
const { items } = await rssXmlToSources(xml)
|
|
50
64
|
const itemSources = items[0]!
|
|
65
|
+
const expanded = buildResolvedSourceNodes(itemSources)
|
|
66
|
+
const postTargets: TargetProperty[] = [
|
|
67
|
+
{ name: 'importUrl', dataType: 'String' },
|
|
68
|
+
{ name: 'canonicalUrl', dataType: 'String' },
|
|
69
|
+
{ name: 'html', dataType: 'Html' },
|
|
70
|
+
{ name: 'featureImage', dataType: 'Image' },
|
|
71
|
+
{ name: 'title', dataType: 'String' },
|
|
72
|
+
]
|
|
51
73
|
const mappings = autoMap(itemSources, postTargets)
|
|
52
|
-
|
|
74
|
+
// link → importUrl/canonicalUrl (copy); missing body → link extract→html;
|
|
75
|
+
// image URLs → featureImage with resolve:'file'
|
|
76
|
+
|
|
77
|
+
// Sync preview skips resolve edges:
|
|
78
|
+
const preview = applyMapping(itemSources, mappings, postTargets)
|
|
79
|
+
|
|
80
|
+
// Publish path — host owns HTTP / extract / store:
|
|
81
|
+
const { properties, errors } = await applyMappingAsync(
|
|
82
|
+
itemSources,
|
|
83
|
+
mappings,
|
|
84
|
+
postTargets,
|
|
85
|
+
{
|
|
86
|
+
resolve: async ({ job, url, contentType, rawValue }) => {
|
|
87
|
+
if (job === 'extract') return await hostExtractHtml(url!)
|
|
88
|
+
if (job === 'lookup') return await hostLookupIdentity(rawValue!)
|
|
89
|
+
return await hostFetchAndStoreFile(url!, contentType)
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Relation lookup (`resolve: 'lookup'`)
|
|
96
|
+
|
|
97
|
+
Map a string source (e.g. RSS `author`) onto a Relation or List-of-Relation
|
|
98
|
+
target (e.g. `authors` → Identity) via a persisted dictionary and/or host callback:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const postTargets: TargetProperty[] = [
|
|
102
|
+
{
|
|
103
|
+
name: 'authors',
|
|
104
|
+
dataType: 'List',
|
|
105
|
+
refValueType: 'Relation',
|
|
106
|
+
ref: 'Identity',
|
|
107
|
+
},
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
const mappings = [
|
|
111
|
+
{ sourceId: 'rss-author', propertyName: 'authors', resolve: 'lookup' as const },
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
const doc: MappingDocument = {
|
|
115
|
+
version: 1,
|
|
116
|
+
sourceKind: 'rss',
|
|
117
|
+
mappings,
|
|
118
|
+
lookups: {
|
|
119
|
+
authors: { 'Jane Doe': 'identity-seed-uid' },
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const { properties, errors } = await applyMappingAsync(
|
|
124
|
+
itemSources,
|
|
125
|
+
mappings,
|
|
126
|
+
postTargets,
|
|
127
|
+
{
|
|
128
|
+
lookups: doc.lookups,
|
|
129
|
+
// Optional: called only when the table has no entry for the trimmed source value
|
|
130
|
+
resolve: async ({ job, rawValue }) => {
|
|
131
|
+
if (job === 'lookup') return await findOrCreateIdentity(rawValue!)
|
|
132
|
+
throw new Error(`unexpected job ${job}`)
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
// properties.authors === ['identity-seed-uid']
|
|
53
137
|
```
|
|
54
138
|
|
|
139
|
+
`autoMap` never wires a plain string onto Relation / List-of-Relation targets —
|
|
140
|
+
author those edges in FieldMapper or programmatically.
|
|
141
|
+
|
|
142
|
+
`classifyUrl({ url, contentType? })` is a pure MIME/extension classifier
|
|
143
|
+
(`html` | `image` | `audio` | `video` | `unknown`). Enclosure nodes expose
|
|
144
|
+
`meta.url`, `meta.contentType`, and `meta.class` (not a stringified object).
|
|
145
|
+
|
|
55
146
|
## FieldMapper UI
|
|
56
147
|
|
|
57
|
-
Props-driven only — no Seed hooks or routing.
|
|
148
|
+
Props-driven only — no Seed hooks or routing. Import from `@seedprotocol/mapping/react`.
|
|
149
|
+
|
|
150
|
+
Two layouts share the same persisted `FieldMapping[]`. **`layout` defaults to `"rows"`.**
|
|
151
|
+
|
|
152
|
+
| `layout` | Behavior |
|
|
153
|
+
|----------|----------|
|
|
154
|
+
| `"rows"` (default) | Row-based authoring. Pass **origin** sources only — transforms are chosen per row (no `@extract`/`@file` cards). |
|
|
155
|
+
| `"wires"` (**deprecated**) | Two-pane click-to-connect with SVG connectors. Pass `buildResolvedSourceNodes(sources)` so extract/file candidates appear as source cards. Still supported for one minor. |
|
|
156
|
+
|
|
157
|
+
When `layout="rows"`, `rowKey` picks orientation:
|
|
158
|
+
|
|
159
|
+
| `rowKey` | Behavior |
|
|
160
|
+
|----------|----------|
|
|
161
|
+
| `"property"` (default) | One row per target property; source + transform inside the row. Structurally property-exclusive. |
|
|
162
|
+
| `"source"` | One row per edge (insertion order); conflict banner when two rows claim one property; coverage banner for missing `required` targets. |
|
|
163
|
+
|
|
164
|
+
Mark targets with `required: true` so coverage / default filters surface missing fields. Default visible set for property mode is mapped + required (`defaultRows="requiredAndMapped"`).
|
|
58
165
|
|
|
59
166
|
```tsx
|
|
60
167
|
import { useState } from 'react'
|
|
61
168
|
import {
|
|
62
|
-
|
|
169
|
+
buildResolvedSourceNodes,
|
|
63
170
|
markdownToSources,
|
|
64
|
-
|
|
171
|
+
rssItemToSources,
|
|
172
|
+
applyMappingAsync,
|
|
65
173
|
type FieldMapping,
|
|
174
|
+
type MappingLookups,
|
|
66
175
|
} from '@seedprotocol/mapping'
|
|
176
|
+
import { FieldMapper, useFieldMapper } from '@seedprotocol/mapping/react'
|
|
67
177
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
178
|
+
// Rows — property-keyed (default layout; recommended)
|
|
179
|
+
<FieldMapper
|
|
180
|
+
rowKey="property"
|
|
181
|
+
sources={rssItemToSources(item)} // origin sources; no buildResolvedSourceNodes
|
|
182
|
+
targets={postTargets} // e.g. { name: 'html', dataType: 'Html', required: true }
|
|
183
|
+
mappings={mappings}
|
|
184
|
+
onChange={setMappings}
|
|
185
|
+
lookups={lookups}
|
|
186
|
+
onLookupsChange={setLookups}
|
|
187
|
+
renderRowAccessory={(row) =>
|
|
188
|
+
row.mapping?.resolve === 'extract' || row.mapping?.resolve === 'file'
|
|
189
|
+
? <button type="button">Preview</button>
|
|
190
|
+
: null
|
|
191
|
+
}
|
|
192
|
+
/>
|
|
193
|
+
|
|
194
|
+
// Rows — source-keyed
|
|
195
|
+
<FieldMapper rowKey="source" sources={itemSources} targets={targets} mappings={mappings} onChange={setMappings} />
|
|
196
|
+
|
|
197
|
+
// Wires (deprecated — opt in explicitly)
|
|
198
|
+
<FieldMapper
|
|
199
|
+
layout="wires"
|
|
200
|
+
sources={buildResolvedSourceNodes(markdownToSources(markdown))}
|
|
201
|
+
targets={targets}
|
|
202
|
+
mappings={mappings}
|
|
203
|
+
onChange={setMappings}
|
|
204
|
+
theme="none"
|
|
205
|
+
/>
|
|
88
206
|
```
|
|
89
207
|
|
|
208
|
+
Headless mechanics (same package):
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
const mapper = useFieldMapper({
|
|
212
|
+
sources,
|
|
213
|
+
targets,
|
|
214
|
+
mappings,
|
|
215
|
+
onChange: setMappings,
|
|
216
|
+
rowKey: 'property',
|
|
217
|
+
})
|
|
218
|
+
// mapper.rows, mapper.coverage, mapper.setSource, mapper.setTransform, …
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Connecting a source to a Relation / List-of-Relation target sets `resolve: 'lookup'`
|
|
222
|
+
and (when `onLookupsChange` is provided) shows a string → seed uid editor — per-row
|
|
223
|
+
when `layout="rows"` (default `slots.lookups: 'row'`), or as a section when
|
|
224
|
+
`layout="wires"` / `slots.lookups: 'section'`.
|
|
225
|
+
|
|
226
|
+
Row and JSON previews match sync `applyMapping` output (pending resolve edges listed
|
|
227
|
+
under `_pendingResolve`; JSON sits behind a disclosure).
|
|
228
|
+
|
|
229
|
+
**Theming**
|
|
230
|
+
|
|
231
|
+
| Prop | Behavior |
|
|
232
|
+
|------|----------|
|
|
233
|
+
| `theme="default"` (default) | Injects structural + paint CSS once into `document.head` (`@layer seed-field-mapper`) with `--sfm-*` tokens (`--fm-*` aliases kept for one minor) |
|
|
234
|
+
| `theme="structural"` | Layout / spacing only — no color paint; inherits host colors |
|
|
235
|
+
| `theme="none"` | No injection — structural classes only (`fm-card`, `fm-row`, `fm-grid`, …); keeps `seed-field-mapper--unstyled` |
|
|
236
|
+
| `theme="unstyled"` | **Deprecated** shim for `none` |
|
|
237
|
+
| `classNames` | Per-slot host classes merged with package classes (`root`, `toolbar`, `row`, `rowAccessory`, …) |
|
|
238
|
+
| `components` | Optional host `Select` / `Button` / `Pill` (defaults are native controls) |
|
|
239
|
+
| `slots` | Toggle chrome: `autoMap`, `filter`, `inspector`, `preview` (`'row' \| 'json' \| 'both' \| false`), `lookups` (`'row' \| 'section' \| false`; rows layout defaults to `'row'`, wires to `'section'`) |
|
|
240
|
+
| `renderRowAccessory` | Optional `(row: FieldMapperRow) => ReactNode` for host chrome (e.g. extract/file **Preview**) in `.fm-row-accessory`. Unrelated to `slots.preview`. Package does not fetch. |
|
|
241
|
+
| `showPreview` | **Deprecated** — prefer `slots.preview` |
|
|
242
|
+
| `connectionColors` | **Deprecated** optional stroke palette for wires; prefer `--sfm-map-*` / `--fm-map-*` / `--map-*` |
|
|
243
|
+
| `layout="wires"` | **Deprecated** — prefer `layout="rows"` (now the default) |
|
|
244
|
+
|
|
245
|
+
`SourceNode` may include optional `subtitle` (display-only). Prefer `subtitle` over stuffing a secondary fact into `label` (e.g. origin field name on a resolved well).
|
|
246
|
+
|
|
247
|
+
**DOM hooks for host CSS**
|
|
248
|
+
|
|
249
|
+
- Wires: mapped wells expose `data-mapping-index` / `data-pair={index % 8}` (kept for host CSS); pending `.active` only on the selected source.
|
|
250
|
+
- Rows: `data-state="empty|mapped|needsResolve|conflict"`, `data-property-name`, `data-resolve`, `data-required`, `data-source-kind`.
|
|
251
|
+
|
|
252
|
+
Sync `applyMapping` preview lists pending resolve edges under `_pendingResolve`.
|
|
253
|
+
|
|
254
|
+
See [FIELD_MAPPER_REDESIGN.md](../../docs/FIELD_MAPPER_REDESIGN.md) for the row-layout design study (Phases 1–5 shipped). PermaPress: [FIELD_MAPPER_PERMAPRESS_HANDOFF.md](../../docs/FIELD_MAPPER_PERMAPRESS_HANDOFF.md).
|
|
255
|
+
|
|
90
256
|
## Relationship to `FeedFieldManifest`
|
|
91
257
|
|
|
92
258
|
| Type | Package | Meaning |
|
|
93
259
|
|------|---------|---------|
|
|
94
|
-
| `FieldMapping` / `MappingDocument` | `@seedprotocol/mapping` | Source id → **model property name** |
|
|
95
|
-
| `FeedFieldManifest` | `@seedprotocol/sdk` | Property/key → **role** (`image` / `html` / `text`) for
|
|
260
|
+
| `FieldMapping` / `MappingDocument` | `@seedprotocol/mapping` | Source id → **model property name** (1→N edges; optional `resolve`; optional `lookups`) |
|
|
261
|
+
| `FeedFieldManifest` | `@seedprotocol/sdk` | Property/key → **role** (`image` / `audio` / `video` / `file` / `html` / `text`) for display |
|
|
96
262
|
|
|
97
|
-
Compose them: map
|
|
263
|
+
Compose them: map + resolve into a plain item, then optionally normalize roles for media/HTML display. Storage stays `Image` / `File` schema types — no separate Audio/Video dataTypes.
|
|
98
264
|
|
|
99
|
-
##
|
|
265
|
+
## Limits
|
|
100
266
|
|
|
101
267
|
- Markdown: flat YAML frontmatter; `#` / `##` sections only
|
|
102
|
-
- RSS: top-level item fields via `parseRssString` (no general XPath)
|
|
103
|
-
- UI: self-contained dark theme; no desktop/Tailwind coupling
|
|
268
|
+
- RSS: top-level item fields via `parseRssString` (no general XPath); structured enclosure / media:content
|
|
269
|
+
- UI: self-contained dark theme (or `theme="none"` / `"structural"` for host paint); `layout` defaults to `rows` (`wires` deprecated); no desktop/Tailwind coupling; no media preview player
|
|
104
270
|
|
|
105
|
-
See [MAPPING_PHASE2.md](../../docs/MAPPING_PHASE2.md) for consumer migration and
|
|
271
|
+
See [MAPPING_PHASE2.md](../../docs/MAPPING_PHASE2.md) for remaining consumer work (desktop migration, npm publish), [FIELD_MAPPER_REDESIGN.md](../../docs/FIELD_MAPPER_REDESIGN.md) for the row-layout study, and [FIELD_MAPPER_PERMAPRESS_HANDOFF.md](../../docs/FIELD_MAPPER_PERMAPRESS_HANDOFF.md) for PermaPress.
|
package/dist/adapters/rss.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ export type ParsedRssChannel = {
|
|
|
8
8
|
};
|
|
9
9
|
/**
|
|
10
10
|
* Flatten a parsed RSS/Atom item into SourceNodes (one per string-coercible key).
|
|
11
|
-
*
|
|
11
|
+
* Enclosure / media:content become url + type in `meta` (not stringified objects).
|
|
12
|
+
* Stable ids: `rss-{key}`, `rss-enclosure-0`, …
|
|
12
13
|
*/
|
|
13
14
|
export declare function rssItemToSources(item: Record<string, unknown>): SourceNode[];
|
|
14
15
|
export type RssXmlSourcesResult = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rss.d.ts","sourceRoot":"","sources":["../../src/adapters/rss.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rss.d.ts","sourceRoot":"","sources":["../../src/adapters/rss.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;CACjC,CAAA;AA8JD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,EAAE,CAoD5E;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,0DAA0D;IAC1D,KAAK,EAAE,UAAU,EAAE,EAAE,CAAA;CACtB,CAAA;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,mBAAmB,CAAC,CAU9B"}
|
package/dist/applyMapping.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FieldMapping, PropertyBag, SourceNode, TargetProperty } from './types';
|
|
1
|
+
import type { ApplyMappingAsyncResult, FieldMapping, MappingLookups, PropertyBag, ResolveCallback, SourceNode, TargetProperty } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Coerce a raw string value to the Seed model property dataType.
|
|
4
4
|
*/
|
|
@@ -6,6 +6,19 @@ export declare function coerceValue(rawValue: string, dataType: string): unknown
|
|
|
6
6
|
/**
|
|
7
7
|
* Apply field mappings to produce a property bag for createItem / publish.
|
|
8
8
|
* Missing sources or unknown target properties are skipped (no throw).
|
|
9
|
+
* Mappings with `resolve` are skipped — use `applyMappingAsync` with a host callback.
|
|
9
10
|
*/
|
|
10
11
|
export declare function applyMapping(sources: SourceNode[], mappings: FieldMapping[], targets: TargetProperty[]): PropertyBag;
|
|
12
|
+
export type ApplyMappingAsyncOptions = {
|
|
13
|
+
/** Required for extract/file edges and lookup misses. */
|
|
14
|
+
resolve?: ResolveCallback;
|
|
15
|
+
/** String → seed uid dictionaries keyed by property name. */
|
|
16
|
+
lookups?: MappingLookups;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Async apply: copy+coerce plain edges; for `resolve` edges call the host
|
|
20
|
+
* callback (or apply lookups for `lookup`) then coerce. Partial success —
|
|
21
|
+
* failed resolve edges are listed in `errors` and omitted from `properties`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function applyMappingAsync(sources: SourceNode[], mappings: FieldMapping[], targets: TargetProperty[], options?: ApplyMappingAsyncOptions): Promise<ApplyMappingAsyncResult>;
|
|
11
24
|
//# sourceMappingURL=applyMapping.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applyMapping.d.ts","sourceRoot":"","sources":["../src/applyMapping.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"applyMapping.d.ts","sourceRoot":"","sources":["../src/applyMapping.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,uBAAuB,EACvB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,eAAe,EAEf,UAAU,EACV,cAAc,EAEf,MAAM,SAAS,CAAA;AAEhB;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAuBvE;AA8DD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,UAAU,EAAE,EACrB,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,cAAc,EAAE,GACxB,WAAW,CAmBb;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,yDAAyD;IACzD,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,cAAc,CAAA;CACzB,CAAA;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,UAAU,EAAE,EACrB,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,cAAc,EAAE,EACzB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CAwIlC"}
|