@happyvertical/smrt-content 0.44.0 → 0.45.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/agents/content-list.md +93 -14
- package/dist/chunks/{content-corrections-BxfA3tW1.js → content-corrections-B4mPd_th.js} +6 -3
- package/dist/chunks/content-corrections-B4mPd_th.js.map +1 -0
- package/dist/chunks/{content-query-B4cHfrig.js → content-query-BV41W2Dq.js} +6 -6
- package/dist/chunks/{content-query-B4cHfrig.js.map → content-query-BV41W2Dq.js.map} +1 -1
- package/dist/chunks/{content-reviews-BWrYEQc6.js → content-reviews-lBoqJY7Y.js} +6 -3
- package/dist/chunks/content-reviews-lBoqJY7Y.js.map +1 -0
- package/dist/chunks/{content-versions-OEYQVrUf.js → content-versions-dZSBU8UF.js} +6 -3
- package/dist/chunks/content-versions-dZSBU8UF.js.map +1 -0
- package/dist/chunks/{contents-BrGxWH3s.js → contents-Ba7JHu2K.js} +2 -2
- package/dist/chunks/{contents-BrGxWH3s.js.map → contents-Ba7JHu2K.js.map} +1 -1
- package/dist/content-contribution.d.ts +1 -1
- package/dist/content-contribution.d.ts.map +1 -1
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +2268 -4345
- package/dist/server/content-list-actions.d.ts +10 -3
- package/dist/server/content-list-actions.d.ts.map +1 -1
- package/dist/server/content-list-data-surface.d.ts +29 -0
- package/dist/server/content-list-data-surface.d.ts.map +1 -0
- package/dist/server/content-list-lifecycle.d.ts +20 -0
- package/dist/server/content-list-lifecycle.d.ts.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +247 -25
- package/dist/server.js.map +1 -1
- package/dist/smrt-knowledge.json +4291 -2510
- package/dist/svelte/components/ContentList.svelte +538 -40
- package/dist/svelte/components/ContentList.svelte.d.ts +6 -1
- package/dist/svelte/components/ContentList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentListLifecyclePanel.svelte +387 -0
- package/dist/svelte/components/ContentListLifecyclePanel.svelte.d.ts +17 -0
- package/dist/svelte/components/ContentListLifecyclePanel.svelte.d.ts.map +1 -0
- package/dist/svelte/content-list-controller.d.ts +10 -0
- package/dist/svelte/content-list-controller.d.ts.map +1 -1
- package/dist/svelte/content-list-controller.js +111 -26
- package/dist/svelte/content-list-data-surface.d.ts +45 -0
- package/dist/svelte/content-list-data-surface.d.ts.map +1 -0
- package/dist/svelte/content-list-data-surface.js +196 -0
- package/dist/svelte/content-list-lifecycle.d.ts +132 -0
- package/dist/svelte/content-list-lifecycle.d.ts.map +1 -0
- package/dist/svelte/content-list-lifecycle.js +439 -0
- package/dist/svelte/i18n.contribution.d.ts +27 -0
- package/dist/svelte/i18n.contribution.d.ts.map +1 -1
- package/dist/svelte/i18n.contribution.js +27 -0
- package/dist/svelte/index.d.ts +2 -0
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +2 -0
- package/package.json +15 -15
- package/dist/chunks/content-corrections-BxfA3tW1.js.map +0 -1
- package/dist/chunks/content-reviews-BWrYEQc6.js.map +0 -1
- package/dist/chunks/content-versions-OEYQVrUf.js.map +0 -1
package/agents/content-list.md
CHANGED
|
@@ -1,12 +1,67 @@
|
|
|
1
1
|
<!-- Module doc for packages/content/AGENTS.md. Linked from the Modules table there. -->
|
|
2
2
|
|
|
3
|
-
# ContentList: shared adapter,
|
|
3
|
+
# ContentList: shared adapter, query state, saved views, and lifecycle
|
|
4
4
|
|
|
5
5
|
`ContentList` reads every row, column, filter, and action through one shared
|
|
6
6
|
adapter (`src/svelte/content-list-controller.ts`) over a `DataTableController`,
|
|
7
7
|
and can source those rows either from a client array or from the bounded
|
|
8
8
|
content query endpoint. This doc covers both modes end to end.
|
|
9
9
|
|
|
10
|
+
## Trash, restore, and permanent deletion (#2454)
|
|
11
|
+
|
|
12
|
+
Lifecycle controls are an opt-in server-authoritative seam. Pass a
|
|
13
|
+
`ContentListLifecycleBinding` as `lifecycle`; set `lifecycleMode="trash"` for a
|
|
14
|
+
trash view. Trash mode locks the live status predicate to `deleted`, hides the
|
|
15
|
+
ordinary status control, removes legacy edit/delete buttons, and exposes
|
|
16
|
+
restore, permanent-delete, and empty-trash actions. Omit the binding and
|
|
17
|
+
ContentList keeps its existing `onDelete` behavior.
|
|
18
|
+
|
|
19
|
+
The browser never treats rendered rows as mutation authority. It sends a
|
|
20
|
+
selection reference, canonical query for `all-matching`, expected count, and
|
|
21
|
+
server revision through `createContentListLifecycleTransport()`. Preview,
|
|
22
|
+
initial apply, and every replay use distinct per-attempt request ids. Apply and
|
|
23
|
+
replay retain the opaque confirmation and idempotency authority envelope, while
|
|
24
|
+
the result's `auditReference` continues to identify the original execution.
|
|
25
|
+
Changing the query or selection invalidates the preview; expired, stale-revision,
|
|
26
|
+
row-revision, query-fingerprint, token, or matching-count failures require a
|
|
27
|
+
new preview.
|
|
28
|
+
|
|
29
|
+
Mount `createContentListLifecycleRoute()` from
|
|
30
|
+
`@happyvertical/smrt-content/server` at the transport's default
|
|
31
|
+
`POST /api/v1/contents/lifecycle` path. The host supplies a callback that
|
|
32
|
+
authenticates each native `Request` and returns its current principal/tenant
|
|
33
|
+
action context. The route accepts only the three lifecycle action ids and
|
|
34
|
+
delegates to the same `createContentListActionAdapter()` instance used by agent
|
|
35
|
+
and bulk-workflow callers; it never owns a second authorization or mutation
|
|
36
|
+
path. Invalid JSON, missing authentication, and internal failures return
|
|
37
|
+
bounded error envelopes without exposing private error text.
|
|
38
|
+
|
|
39
|
+
Lifecycle action ids and restore input are stable:
|
|
40
|
+
|
|
41
|
+
| action | eligible server state | input / consequence |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `move-to-trash` | not already `deleted` | soft-deletes content into trash |
|
|
44
|
+
| `restore` | `deleted` | `{ status: 'draft' \| 'review' \| 'published' }`; the server re-runs permission and publish-readiness checks |
|
|
45
|
+
| `permanent-delete` | `deleted` | irreversible deletion; the operator must type the exact server-resolved count |
|
|
46
|
+
|
|
47
|
+
Permanent deletion binds the row's `updated_at` revision into the final delete.
|
|
48
|
+
On PostgreSQL that comparison is part of the `DELETE` predicate and any cascade
|
|
49
|
+
shares its transaction; embedded adapters compare under the framework's shared
|
|
50
|
+
write queue before cascading. A writer racing preview/apply therefore produces
|
|
51
|
+
`row_revision_drifted` instead of deleting newer content.
|
|
52
|
+
|
|
53
|
+
The result details expose `count`, accepted/skipped/failed counts,
|
|
54
|
+
representative labels, canonical subtype-aware outcomes
|
|
55
|
+
(`resourceType`/`resourceId`), and `auditReference`. Applying a partial result
|
|
56
|
+
removes only accepted ids from selection, keeping skipped and failed rows
|
|
57
|
+
selected for inspection or retry. The exact query refreshes after success;
|
|
58
|
+
progress, partial exceptions, and the audit reference remain visible in a
|
|
59
|
+
polite live region. Empty trash is available only when an exact server count
|
|
60
|
+
and canonical query are present, so a page-sized guess cannot stand in for its
|
|
61
|
+
scope. `maxSelectionSize` defaults to 200; larger matching sets are announced
|
|
62
|
+
and fail closed until the operator narrows the query, matching the server's
|
|
63
|
+
bounded one-preview selection contract.
|
|
64
|
+
|
|
10
65
|
## Realtime, freshness, and background workflows (#2455)
|
|
11
66
|
|
|
12
67
|
A server-backed list consumes the complete reactive seam exposed by
|
|
@@ -142,6 +197,25 @@ Adapter exports (also re-exported from `./svelte`): `createContentListController
|
|
|
142
197
|
`resolveSelectedContentListRows`, `resolveSelectedContents`, plus the
|
|
143
198
|
`CONTENT_LIST_*` identity constants.
|
|
144
199
|
|
|
200
|
+
## Agent data-surface conformance (#2456)
|
|
201
|
+
|
|
202
|
+
`dataSurface` publishes the mounted list's readable columns, supported query
|
|
203
|
+
operators, visible state, selection scope, freshness, and only the actions its
|
|
204
|
+
mounted workflow/lifecycle bindings can execute. Visible commands run through
|
|
205
|
+
the registry's revision check; their acknowledgements describe the accepted
|
|
206
|
+
controller revision, while a disconnected registry refuses them.
|
|
207
|
+
|
|
208
|
+
For silent agent reads, register
|
|
209
|
+
`createContentListDataSurfaceDefinition({ collection, scope })` from
|
|
210
|
+
`@happyvertical/smrt-content/server` in the server-owned
|
|
211
|
+
`createDataSurfaceTools()` catalog. The factory resolves both the collection
|
|
212
|
+
and optional application scope from the live principal context, then delegates
|
|
213
|
+
rows, counts, facets, and offset continuations to `executeContentQuery()`.
|
|
214
|
+
Tenant, hidden, and sensitive fields remain outside discovery and projection;
|
|
215
|
+
the model request can only narrow the trusted scope. Durable actions continue
|
|
216
|
+
through `createContentListActionAdapter()` and its principal-bound
|
|
217
|
+
preview/apply contract rather than through the browser registry.
|
|
218
|
+
|
|
145
219
|
Notes:
|
|
146
220
|
|
|
147
221
|
- Controller modes are all `manual`: the adapter owns search, filters, sorting,
|
|
@@ -194,15 +268,19 @@ Notes:
|
|
|
194
268
|
— which owns both in compact mode — is not mounted there. A page size arriving
|
|
195
269
|
from a saved view or a surface command would otherwise strand the operator on
|
|
196
270
|
page one, and a refresh over retained rows would be silent.
|
|
197
|
-
- `dataSurface` registers the
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
271
|
+
- `dataSurface` registers at the `ContentList` boundary, independently of its
|
|
272
|
+
renderer. Grid, detailed, compact, loading, empty, and error presentations
|
|
273
|
+
therefore retain one stable surface identity. A `set-view` command updates
|
|
274
|
+
the published `viewMode` and revision before the renderer changes, so its
|
|
275
|
+
acknowledgement always describes the accepted presentation.
|
|
276
|
+
- The mounted snapshot publishes the controller state and normalized selection
|
|
277
|
+
together with the active query fingerprint, total, presentation, and
|
|
278
|
+
freshness (`stale`, `refreshing`, `offline`, last update, truncation, and
|
|
279
|
+
warnings). Context-only changes advance the same revision stream as visible
|
|
280
|
+
controller commands; stale command revisions are refused by the registry.
|
|
281
|
+
- Discovery publishes per-column search/filter/sort operators. A server-backed
|
|
282
|
+
list narrows the derived `site` column to read-only because the content query
|
|
283
|
+
translator cannot soundly project, filter, or sort that display value.
|
|
206
284
|
|
|
207
285
|
## ContentList server-backed mode (#2452)
|
|
208
286
|
|
|
@@ -965,10 +1043,11 @@ keeps the control from misstating the query; `readContentListFilter` stays
|
|
|
965
1043
|
value-only and must not drive a control. Choosing any real option replaces every
|
|
966
1044
|
filter on that column, so the operator is never stuck.
|
|
967
1045
|
|
|
968
|
-
`review` is now offered outright. `deleted` is deliberately not
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
list is a display vocabulary rather
|
|
1046
|
+
`review` is now offered outright. `deleted` is deliberately not part of the
|
|
1047
|
+
ordinary status vocabulary: the opt-in trash lifecycle locks that predicate
|
|
1048
|
+
and supplies the restore/purge affordances as one inseparable mode.
|
|
1049
|
+
`Content.type` is freeform, so its option list is a display vocabulary rather
|
|
1050
|
+
than the model's domain.
|
|
972
1051
|
|
|
973
1052
|
Everything a restore or a translation refused is reported in one dismissible
|
|
974
1053
|
notice rather than thrown — a stale link or an out-of-date saved view must still
|
|
@@ -52,8 +52,11 @@ var ContentCorrection = class extends SmrtObject {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
|
-
__decorateClass([foreignKey("Content", {
|
|
56
|
-
|
|
55
|
+
__decorateClass([foreignKey("Content", {
|
|
56
|
+
required: true,
|
|
57
|
+
onDelete: "CASCADE"
|
|
58
|
+
})], ContentCorrection.prototype, "contentId", 2);
|
|
59
|
+
__decorateClass([foreignKey("ContentVersion", { onDelete: "CASCADE" })], ContentCorrection.prototype, "contentVersionId", 2);
|
|
57
60
|
__decorateClass([crossPackageRef("@happyvertical/smrt-facts:Fact")], ContentCorrection.prototype, "factId", 2);
|
|
58
61
|
__decorateClass([crossPackageRef("@happyvertical/smrt-facts:Fact")], ContentCorrection.prototype, "replacementFactId", 2);
|
|
59
62
|
__decorateClass([tenantId({ nullable: true })], ContentCorrection.prototype, "tenantId", 2);
|
|
@@ -104,4 +107,4 @@ var ContentCorrectionCollection = class extends SmrtCollection {
|
|
|
104
107
|
//#endregion
|
|
105
108
|
export { content_corrections_exports as n, ContentCorrection as r, ContentCorrectionCollection as t };
|
|
106
109
|
|
|
107
|
-
//# sourceMappingURL=content-corrections-
|
|
110
|
+
//# sourceMappingURL=content-corrections-B4mPd_th.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-corrections-B4mPd_th.js","names":[],"sources":["../../src/content-correction.ts","../../src/content-corrections.ts"],"sourcesContent":["import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n ContentCorrectionStatus,\n ContentCorrectionType,\n} from './content-governance';\n\nexport interface ContentCorrectionOptions extends SmrtObjectOptions {\n contentId?: string;\n contentVersionId?: string;\n factId?: string;\n replacementFactId?: string;\n correctionType?: ContentCorrectionType;\n status?: ContentCorrectionStatus;\n summary?: string;\n incorrectText?: string;\n correctedText?: string;\n publicNote?: string;\n metadata?: string | Record<string, unknown>;\n tenantId?: string | null;\n publishedAt?: Date | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_corrections',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create', 'update'] },\n cli: true,\n})\nexport class ContentCorrection extends SmrtObject {\n @foreignKey('Content', { required: true, onDelete: 'CASCADE' })\n contentId = '';\n\n @foreignKey('ContentVersion', { onDelete: 'CASCADE' })\n contentVersionId = '';\n\n @crossPackageRef('@happyvertical/smrt-facts:Fact')\n factId = '';\n\n @crossPackageRef('@happyvertical/smrt-facts:Fact')\n replacementFactId = '';\n correctionType: ContentCorrectionType = 'fact';\n status: ContentCorrectionStatus = 'draft';\n summary = '';\n incorrectText = '';\n correctedText = '';\n publicNote = '';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n publishedAt: Date | null = null;\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentCorrectionOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.contentVersionId !== undefined)\n this.contentVersionId = options.contentVersionId;\n if (options.factId !== undefined) this.factId = options.factId;\n if (options.replacementFactId !== undefined)\n this.replacementFactId = options.replacementFactId;\n if (options.correctionType !== undefined)\n this.correctionType = options.correctionType;\n if (options.status !== undefined) this.status = options.status;\n if (options.summary !== undefined) this.summary = options.summary;\n if (options.incorrectText !== undefined)\n this.incorrectText = options.incorrectText;\n if (options.correctedText !== undefined)\n this.correctedText = options.correctedText;\n if (options.publicNote !== undefined) this.publicNote = options.publicNote;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.publishedAt !== undefined)\n this.publishedAt = options.publishedAt;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, unknown> {\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentCorrection } from './content-correction';\n\nexport class ContentCorrectionCollection extends SmrtCollection<ContentCorrection> {\n static readonly _itemClass = ContentCorrection;\n\n async listForContent(contentId: string): Promise<ContentCorrection[]> {\n return this.list({\n where: { contentId },\n orderBy: 'created_at DESC',\n });\n }\n\n async getPublishedForContent(\n contentId: string,\n ): Promise<ContentCorrection[]> {\n return this.list({\n where: { contentId, status: 'published' },\n orderBy: 'published_at DESC',\n });\n }\n\n async issue(\n options: ConstructorParameters<typeof ContentCorrection>[0],\n ): Promise<ContentCorrection> {\n if (!options) {\n return this.create({});\n }\n\n return this.create({\n ...options,\n metadata:\n typeof options.metadata === 'string'\n ? options.metadata\n : options.metadata\n ? JSON.stringify(options.metadata)\n : undefined,\n });\n }\n}\n"],"mappings":"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"}
|