@openrails/contentkit-ui 0.104.0-rc.1 → 0.104.0-rc.2
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/README.md +6 -6
- package/dist/client/beacons.js +4 -1
- package/dist/client/beacons.js.map +1 -1
- package/dist/client/contents.d.ts +7 -1
- package/dist/client/contents.js +8 -0
- package/dist/client/contents.js.map +1 -1
- package/dist/client/discovery.d.ts +6 -2
- package/dist/client/discovery.js +1 -1
- package/dist/client/discovery.js.map +1 -1
- package/dist/client/generated/routes.d.ts +41 -28
- package/dist/client/generated/routes.js +63 -61
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +36 -74
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/media/windows.d.ts +2 -0
- package/dist/client/media/windows.js +4 -1
- package/dist/client/media/windows.js.map +1 -1
- package/dist/client/stats.d.ts +4 -20
- package/dist/client/stats.js +0 -11
- package/dist/client/stats.js.map +1 -1
- package/dist/client/versions.d.ts +8 -6
- package/dist/client/versions.js +15 -10
- package/dist/client/versions.js.map +1 -1
- package/dist/components/admin/bulk-drafts.d.ts +17 -0
- package/dist/components/admin/bulk-drafts.js +41 -0
- package/dist/components/admin/bulk-drafts.js.map +1 -0
- package/dist/components/admin/content-admin.d.ts +1 -1
- package/dist/components/admin/content-admin.js.map +1 -1
- package/dist/components/admin/content-manager.d.ts +11 -3
- package/dist/components/admin/content-manager.js +739 -380
- package/dist/components/admin/content-manager.js.map +1 -1
- package/dist/components/admin/group-manager.d.ts +8 -3
- package/dist/components/admin/group-manager.js +218 -146
- package/dist/components/admin/group-manager.js.map +1 -1
- package/dist/components/admin/page-notices.d.ts +16 -0
- package/dist/components/admin/page-notices.js +113 -0
- package/dist/components/admin/page-notices.js.map +1 -0
- package/dist/components/admin/page-picker.d.ts +38 -0
- package/dist/components/admin/page-picker.js +159 -0
- package/dist/components/admin/page-picker.js.map +1 -0
- package/dist/components/admin/reader-content-editor.js +537 -500
- package/dist/components/admin/reader-content-editor.js.map +1 -1
- package/dist/components/admin/reader-manifest.js +181 -179
- package/dist/components/admin/reader-manifest.js.map +1 -1
- package/dist/components/admin/shell.d.ts +10 -2
- package/dist/components/admin/shell.js +114 -42
- package/dist/components/admin/shell.js.map +1 -1
- package/dist/components/admin/stats-dashboard.d.ts +4 -9
- package/dist/components/admin/stats-dashboard.js +300 -202
- package/dist/components/admin/stats-dashboard.js.map +1 -1
- package/dist/components/admin/upload-queue.d.ts +14 -0
- package/dist/components/admin/upload-queue.js +115 -98
- package/dist/components/admin/upload-queue.js.map +1 -1
- package/dist/components/content/card.d.ts +31 -3
- package/dist/components/content/card.js +324 -158
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/daily-releases.js +14 -12
- package/dist/components/content/daily-releases.js.map +1 -1
- package/dist/components/content/editor-save.js +27 -25
- package/dist/components/content/editor-save.js.map +1 -1
- package/dist/components/content/editors.js +274 -253
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/favorites.d.ts +1 -1
- package/dist/components/content/favorites.js +36 -22
- package/dist/components/content/favorites.js.map +1 -1
- package/dist/components/content/grid.d.ts +11 -4
- package/dist/components/content/grid.js +52 -43
- package/dist/components/content/grid.js.map +1 -1
- package/dist/components/content/history.js +83 -63
- package/dist/components/content/history.js.map +1 -1
- package/dist/components/content/index.d.ts +5 -3
- package/dist/components/content/listing.d.ts +14 -3
- package/dist/components/content/listing.js +65 -56
- package/dist/components/content/listing.js.map +1 -1
- package/dist/components/content/offer-fields.js +6 -6
- package/dist/components/content/paged-grid.d.ts +10 -0
- package/dist/components/content/paged-grid.js +116 -0
- package/dist/components/content/paged-grid.js.map +1 -0
- package/dist/components/content/pagination.d.ts +19 -0
- package/dist/components/content/pagination.js +97 -0
- package/dist/components/content/pagination.js.map +1 -0
- package/dist/components/content/paywall.d.ts +9 -0
- package/dist/components/content/paywall.js +27 -3
- package/dist/components/content/paywall.js.map +1 -1
- package/dist/components/content/post-list.d.ts +37 -0
- package/dist/components/content/post-list.js +203 -0
- package/dist/components/content/post-list.js.map +1 -0
- package/dist/components/content/reader-settings.d.ts +2 -0
- package/dist/components/content/reader-settings.js +1 -1
- package/dist/components/content/reader-settings.js.map +1 -1
- package/dist/components/groups/banner.d.ts +6 -2
- package/dist/components/groups/banner.js +79 -61
- package/dist/components/groups/banner.js.map +1 -1
- package/dist/components/groups/directory.d.ts +12 -2
- package/dist/components/groups/directory.js +168 -105
- package/dist/components/groups/directory.js.map +1 -1
- package/dist/components/groups/editor.js +10 -10
- package/dist/components/groups/editor.js.map +1 -1
- package/dist/components/groups/entity-chips.d.ts +61 -0
- package/dist/components/groups/entity-chips.js +382 -0
- package/dist/components/groups/entity-chips.js.map +1 -0
- package/dist/components/groups/group-members.d.ts +29 -0
- package/dist/components/groups/group-members.js +474 -0
- package/dist/components/groups/group-members.js.map +1 -0
- package/dist/components/groups/header.js +53 -45
- package/dist/components/groups/header.js.map +1 -1
- package/dist/components/groups/index.d.ts +3 -1
- package/dist/components/groups/memberships.d.ts +3 -36
- package/dist/components/groups/memberships.js +105 -480
- package/dist/components/groups/memberships.js.map +1 -1
- package/dist/components/groups/scoped.d.ts +23 -0
- package/dist/components/groups/scoped.js +92 -0
- package/dist/components/groups/scoped.js.map +1 -0
- package/dist/components/media-folder-editor.d.ts +5 -0
- package/dist/components/media-folder-editor.js +418 -230
- package/dist/components/media-folder-editor.js.map +1 -1
- package/dist/components/sortable-list.d.ts +5 -1
- package/dist/components/sortable-list.js +97 -81
- package/dist/components/sortable-list.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +41 -37
- package/dist/locales/admin/de.js +78 -45
- package/dist/locales/admin/de.js.map +1 -1
- package/dist/locales/admin/en.d.ts +74 -41
- package/dist/locales/admin/en.js +78 -45
- package/dist/locales/admin/en.js.map +1 -1
- package/dist/locales/admin/es.js +78 -45
- package/dist/locales/admin/es.js.map +1 -1
- package/dist/locales/admin/ja.js +78 -45
- package/dist/locales/admin/ja.js.map +1 -1
- package/dist/locales/admin/ko.js +78 -45
- package/dist/locales/admin/ko.js.map +1 -1
- package/dist/locales/admin/zh.js +78 -45
- package/dist/locales/admin/zh.js.map +1 -1
- package/dist/locales/de.js +1 -0
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/discovery/de.js +25 -1
- package/dist/locales/discovery/de.js.map +1 -1
- package/dist/locales/discovery/en.d.ts +24 -0
- package/dist/locales/discovery/en.js +25 -1
- package/dist/locales/discovery/en.js.map +1 -1
- package/dist/locales/discovery/es.js +25 -1
- package/dist/locales/discovery/es.js.map +1 -1
- package/dist/locales/discovery/ja.js +25 -1
- package/dist/locales/discovery/ja.js.map +1 -1
- package/dist/locales/discovery/ko.js +25 -1
- package/dist/locales/discovery/ko.js.map +1 -1
- package/dist/locales/discovery/zh.js +25 -1
- package/dist/locales/discovery/zh.js.map +1 -1
- package/dist/locales/en.d.ts +119 -43
- package/dist/locales/en.js +1 -0
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +1 -0
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/groups/de.js +22 -4
- package/dist/locales/groups/de.js.map +1 -1
- package/dist/locales/groups/en.d.ts +20 -2
- package/dist/locales/groups/en.js +22 -4
- package/dist/locales/groups/en.js.map +1 -1
- package/dist/locales/groups/es.js +22 -4
- package/dist/locales/groups/es.js.map +1 -1
- package/dist/locales/groups/ja.js +22 -4
- package/dist/locales/groups/ja.js.map +1 -1
- package/dist/locales/groups/ko.js +22 -4
- package/dist/locales/groups/ko.js.map +1 -1
- package/dist/locales/groups/zh.js +22 -4
- package/dist/locales/groups/zh.js.map +1 -1
- package/dist/locales/ja.js +1 -0
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +1 -0
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +1 -0
- package/dist/locales/zh.js.map +1 -1
- package/dist/react/discovery.d.ts +16 -0
- package/dist/react/discovery.js +69 -37
- package/dist/react/discovery.js.map +1 -1
- package/dist/react/groups.d.ts +19 -3
- package/dist/react/groups.js +49 -22
- package/dist/react/groups.js.map +1 -1
- package/dist/react/index.d.ts +6 -4
- package/dist/react/page-notices.d.ts +13 -0
- package/dist/react/page-notices.js +38 -0
- package/dist/react/page-notices.js.map +1 -0
- package/dist/react/post-reads.d.ts +23 -0
- package/dist/react/post-reads.js +90 -0
- package/dist/react/post-reads.js.map +1 -0
- package/dist/react/remembered-sort.d.ts +5 -0
- package/dist/react/remembered-sort.js +29 -0
- package/dist/react/remembered-sort.js.map +1 -0
- package/dist/react/resources.js +2 -2
- package/dist/react/resources.js.map +1 -1
- package/dist/react/stats.d.ts +3 -7
- package/dist/react/stats.js +2 -6
- package/dist/react/stats.js.map +1 -1
- package/dist/react/use-engagement.d.ts +2 -0
- package/dist/react/use-engagement.js +8 -3
- package/dist/react/use-engagement.js.map +1 -1
- package/dist/react.js +29 -27
- package/dist/styles.css +1 -1
- package/dist/urls/index.d.ts +1 -1
- package/dist/urls.js +2 -2
- package/dist/urls.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/admin/page-review.d.ts +0 -13
- package/dist/components/admin/page-review.js +0 -225
- package/dist/components/admin/page-review.js.map +0 -1
- package/dist/react/page-review.d.ts +0 -14
- package/dist/react/page-review.js +0 -37
- package/dist/react/page-review.js.map +0 -1
package/README.md
CHANGED
|
@@ -755,12 +755,12 @@ const nav = useMemo(() => ({ pathname: location.pathname, search: location.searc
|
|
|
755
755
|
Management authorization remains enforced by the server. Set
|
|
756
756
|
`presentation="header"` for the shared centered-header dropdown.
|
|
757
757
|
|
|
758
|
-
- **`
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
versions
|
|
763
|
-
|
|
758
|
+
- **`PageNotices`**: quiet, collapsed notes about automatic page changes:
|
|
759
|
+
pages removed as blank, duplicate or covered by a spread (one-click Restore)
|
|
760
|
+
and archives put in name order (Dismiss). It renders nothing without notices
|
|
761
|
+
and never blocks saving or publishing. `ContentManager` includes it for reader
|
|
762
|
+
versions; `usePageNotices()` exposes the same API. Page tiles are named by
|
|
763
|
+
their place and reordered by dragging the whole tile.
|
|
764
764
|
|
|
765
765
|
- **`ReaderManifestEditor`**: a reader version's manifest over its published
|
|
766
766
|
pages and audio: scroll anchors, audio cues (matched to pages or anchors by
|
package/dist/client/beacons.js
CHANGED
|
@@ -158,7 +158,10 @@ var p = class {
|
|
|
158
158
|
async contexts(e, n, r) {
|
|
159
159
|
if (this.paused() || !await this.recording()) return n === this.generation && this.pause(), null;
|
|
160
160
|
if (n !== this.generation) return null;
|
|
161
|
-
let i = [...new Map(e.map((e) => [m(e),
|
|
161
|
+
let i = [...new Map(e.map((e) => [m(e), {
|
|
162
|
+
content_id: e.content_id,
|
|
163
|
+
version_id: e.version_id
|
|
164
|
+
}])).values()], a = [], o = this.session();
|
|
162
165
|
for (let e = 0; e < i.length; e += t) a.push(this.client.discovery.activityContexts(i.slice(e, e + t), o, r));
|
|
163
166
|
let s = await Promise.all(a);
|
|
164
167
|
if (n !== this.generation) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"beacons.js","names":[],"sources":["../../src/client/beacons.ts"],"sourcesContent":["import type { ContentKitClient } from \"./client.js\";\nimport { toContentKitError } from \"./errors.js\";\nimport type { ActivityContext, ActivityTarget, ExposureInput, SignalInput } from \"./generated/wire.js\";\n\nexport interface BeaconOptions {\n /** A signed-out visitor identity, persistent across this browser's tabs. */\n session?: () => string | undefined;\n /** How long events gather before they are sent, ms. Default 2000. */\n delay?: number;\n /** How long beacons stay off after the site records no signals, ms, before the content model is read again. Default 60000. */\n recheck?: number;\n}\n\n/** Where a click came from: the list render it was shown in. */\nexport interface Attribution {\n /** Language of the displayed content; defaults to the client's request language. */\n language?: string;\n render_id?: string;\n surface?: string;\n /** 1-based position in that render. */\n position?: number;\n}\n\n\nconst MAX = 100;\n// Fetch's keepalive limit includes all in-flight bodies in the fetch group.\n// Leave headroom and serialize this module's keepalive requests across clients.\nconst KEEPALIVE_BYTES = 60 * 1024;\nconst FLUSH_BYTES = 48 * 1024;\nlet keepaliveTail: Promise<void> = Promise.resolve();\nconst encoder = new TextEncoder();\nconst bytes = (field: \"signals\" | \"exposures\", rows: readonly unknown[], session?: string) => encoder.encode(JSON.stringify({ session, [field]: rows })).length;\n\nfunction packets<T>(items: readonly T[], field: \"signals\" | \"exposures\", session?: string): { items: T[]; bytes: number }[] {\n const out: { items: T[]; bytes: number }[] = [];\n let current: T[] = [];\n for (const item of items) {\n if (current.length && (current.length === MAX || bytes(field, [...current, item], session) > KEEPALIVE_BYTES)) {\n out.push({ items: current, bytes: bytes(field, current, session) });\n current = [];\n }\n current.push(item);\n }\n if (current.length) out.push({ items: current, bytes: bytes(field, current, session) });\n return out;\n}\n\nfunction serializeKeepalive(send: () => Promise<void>): Promise<void> {\n const pending = keepaliveTail.then(send, send);\n keepaliveTail = pending.then(() => {}, () => {});\n return pending;\n}\nconst SESSION_KEY = \"contentkit.visitor.v1\";\nexport const eventId = () => (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto ? crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`);\n\nlet unstored: string | undefined;\n\n/** A random signed-out browser identity shared across tabs/reloads, never an account credential. */\nexport function readerSession(): string {\n try {\n const kept = localStorage.getItem(SESSION_KEY);\n if (kept) return kept;\n const made = eventId();\n localStorage.setItem(SESSION_KEY, made);\n return made;\n } catch {\n return (unstored ??= eventId());\n }\n}\n\n/**\n * Batched, best-effort signals and exposures: gathered for `delay`, sent in\n * one request each, flushed with keepalive when the page hides. While the\n * content model says the site records no signals (or a send is refused as\n * not_configured or unavailable) events are dropped; after `recheck` the\n * next event reads the model again, so signals resume when the site's\n * signal plane is back.\n */\nexport class Beacons {\n private signals: SignalInput[] = [];\n private exposures: ExposureInput[] = [];\n private timer: ReturnType<typeof setTimeout> | undefined;\n private offUntil = 0;\n private recorded: Promise<boolean> | undefined;\n private generation = 0;\n private hidden = false;\n private readonly pending = new Set<Promise<void>>();\n private readonly exposureContexts = new Map<string, { active: boolean; releaseRevision: number; occurredAt?: string; contexts: Map<string, Promise<Receipt | null>> }>();\n private readonly session: () => string | undefined;\n private readonly delay: number;\n private readonly recheck: number;\n\n constructor(\n private readonly client: Pick<ContentKitClient, \"discovery\" | \"kinds\"> & Partial<Pick<ContentKitClient, \"preferences\">>,\n o: BeaconOptions = {},\n ) {\n this.session = o.session ?? readerSession;\n this.delay = o.delay ?? 2000;\n this.recheck = o.recheck ?? 60_000;\n client.preferences?.subscribeIdentity(() => {\n // The old credentials can no longer be assumed available for a flush.\n this.generation++;\n clearTimeout(this.timer);\n this.timer = undefined;\n this.signals = [];\n this.exposures = [];\n this.pending.clear();\n for (const state of this.exposureContexts.values()) state.active = false;\n this.exposureContexts.clear();\n this.recorded = undefined;\n });\n if (typeof addEventListener === \"function\") {\n addEventListener(\"pagehide\", () => { this.hidden = true; void this.flush(true); });\n addEventListener(\"pageshow\", () => { this.hidden = false; });\n addEventListener(\"visibilitychange\", () => {\n this.hidden = typeof document !== \"undefined\" && document.visibilityState === \"hidden\";\n if (this.hidden) void this.flush(true);\n });\n }\n }\n\n /** A click on a listed card. Acquire its access snapshot at observation time. */\n click(content: string, a: Attribution & { version_id?: string } = {}): void {\n if (this.paused()) return;\n const generation = this.generation;\n const event = eventId(), at = new Date().toISOString();\n const { language, ...attribution } = a;\n const target = { content_id: content, version_id: a.version_id };\n this.track(this.contexts([target], generation, language).then((receipts) => {\n const receipt = receipts?.get(targetKey(target));\n if (!receipt || generation !== this.generation) return;\n this.signal({ content_id: content, type: \"click\", event_id: event, ...attribution,\n occurred_at: receipt.context?.occurred_at ?? at, activity_token: receipt.context?.token });\n }), generation);\n }\n\n /** A cumulative result-list stage; each newly observed target gets one receipt. */\n exposure(e: ExposureInput): void {\n if (this.paused() || !e.shown.length) return;\n const generation = this.generation;\n const key = `${e.render_id}\\u0000${e.stage}`;\n let state = this.exposureContexts.get(key);\n if (!state) {\n state = { active: true, releaseRevision: 0, contexts: new Map() };\n this.exposureContexts.set(key, state);\n }\n state.releaseRevision++;\n const captured = state;\n const unseen = e.shown.filter((p) => !captured.contexts.has(targetKey(p)));\n if (unseen.length) {\n const contexts = this.contexts(unseen, generation, e.language);\n for (const target of unseen) {\n const key = targetKey(target);\n const pending: Promise<Receipt | null> = contexts.then((values) => {\n const receipt = values?.get(key) ?? null;\n if (!receipt && captured.contexts.get(key) === pending) captured.contexts.delete(key);\n return receipt;\n }, (error: unknown) => {\n if (captured.contexts.get(key) === pending) captured.contexts.delete(key);\n throw error;\n });\n captured.contexts.set(key, pending);\n }\n }\n this.track(Promise.all(e.shown.map((p) => captured.contexts.get(targetKey(p))!)).then((receipts) => {\n if (generation !== this.generation || !captured.active || receipts.some((r) => !r)) return;\n const valid = receipts as Receipt[];\n if (new Set(valid.map((r) => r.enabled)).size !== 1) return;\n captured.occurredAt ??= valid.find((r) => r.context)?.context?.occurred_at ?? e.occurred_at ?? new Date().toISOString();\n const enriched = { ...e, occurred_at: captured.occurredAt,\n shown: e.shown.map((p, i) => ({ ...p, activity_token: valid[i]?.context?.token })) };\n // A later cumulative revision supersedes a queued earlier snapshot.\n const previous = this.exposures.find((x) => x.render_id === e.render_id && x.stage === e.stage);\n if (previous && (previous.revision ?? 0) > (e.revision ?? 0)) return;\n this.exposures = this.exposures.filter((x) => x.render_id !== e.render_id || x.stage !== e.stage);\n this.exposures.push(enriched);\n this.schedule();\n }), generation);\n }\n\n /** Keep receipt state when a mounted list resumes (including StrictMode replay). */\n beginExposure(render: string): void {\n for (const stage of [\"served\", \"rendered\", \"visible\"]) {\n const state = this.exposureContexts.get(`${render}\\u0000${stage}`);\n if (state) state.releaseRevision++;\n }\n }\n\n /** Retire receipt state after a list unmounts without cancelling observations. */\n endExposure(render: string): void {\n for (const stage of [\"served\", \"rendered\", \"visible\"]) {\n const key = `${render}\\u0000${stage}`, state = this.exposureContexts.get(key);\n if (!state) continue;\n const release = ++state.releaseRevision;\n queueMicrotask(() => {\n if (this.exposureContexts.get(key) === state && state.releaseRevision === release) this.exposureContexts.delete(key);\n });\n }\n }\n\n /** Sends ready observations; receipts are never acquired for the first time here. */\n async flush(keepalive = false): Promise<void> {\n clearTimeout(this.timer);\n this.timer = undefined;\n const generation = this.generation;\n await Promise.allSettled([...this.pending]);\n if (generation !== this.generation) return;\n clearTimeout(this.timer);\n this.timer = undefined;\n const signals = this.signals.splice(0), exposures = this.exposures.splice(0);\n if (this.paused() || (!signals.length && !exposures.length)) return;\n const session = this.session();\n const jobs = [\n ...packets(signals, \"signals\", session).map((packet) => ({ ...packet, send: (persist: boolean) => this.client.discovery.signals(packet.items, session, { keepalive: persist }) })),\n ...packets(exposures, \"exposures\", session).map((packet) => ({ ...packet, send: (persist: boolean) => this.client.discovery.exposures(packet.items, session, { keepalive: persist }) })),\n ];\n const done = await Promise.allSettled(jobs.map((job) => {\n const persist = keepalive && job.bytes <= KEEPALIVE_BYTES;\n const send = () => generation === this.generation ? job.send(persist) : Promise.resolve();\n // A single oversized cumulative exposure cannot be split without losing\n // history. Normal fetch is the best effort available during pagehide.\n return persist ? serializeKeepalive(send) : send();\n }));\n if (generation === this.generation && done.some((r) => r.status === \"rejected\" && unavailable(r.reason))) this.pause();\n }\n\n private async contexts(targets: readonly ActivityTarget[], generation: number, language?: string): Promise<Map<string, Receipt> | null> {\n if (this.paused() || !(await this.recording())) {\n if (generation === this.generation) this.pause();\n return null;\n }\n if (generation !== this.generation) return null;\n const unique = [...new Map(targets.map((target) => [targetKey(target), target])).values()];\n const batches = [];\n const session = this.session();\n for (let i = 0; i < unique.length; i += MAX) batches.push(this.client.discovery.activityContexts(unique.slice(i, i + MAX), session, language));\n const responses = await Promise.all(batches);\n if (generation !== this.generation) return null;\n const out = new Map<string, Receipt>();\n for (let i = 0; i < responses.length; i++) {\n const response = responses[i]!;\n if (typeof response?.enabled !== \"boolean\" || (response.enabled && !Array.isArray(response.contexts))) throw new Error(\"contentkit: invalid activity context response\");\n const contexts = new Map((response.contexts ?? []).map((context) => [targetKey(context), context]));\n for (const target of unique.slice(i * MAX, (i + 1) * MAX)) {\n const context = contexts.get(targetKey(target));\n if (response.enabled && (!context?.token || !Number.isFinite(Date.parse(context.occurred_at)))) throw new Error(\"contentkit: invalid activity context\");\n out.set(targetKey(target), { enabled: response.enabled, context: response.enabled ? context : undefined });\n }\n }\n return out;\n }\n\n private track(task: Promise<void>, generation: number): void {\n const pending = task.catch((error) => { if (generation === this.generation && unavailable(error)) this.pause(); }).finally(() => { this.pending.delete(pending); });\n this.pending.add(pending);\n }\n\n private signal(s: SignalInput): void {\n if (this.paused()) return;\n this.signals.push(s);\n this.schedule();\n }\n private paused(): boolean {\n if (this.offUntil > Date.now()) return true;\n this.offUntil = 0;\n return false;\n }\n private pause(): void { this.offUntil = Date.now() + this.recheck; this.recorded = undefined; }\n private recording(): Promise<boolean> {\n return (this.recorded ??= this.client.kinds().then((m) => m.signals, () => true));\n }\n private schedule(): void {\n const queued = bytes(\"signals\", this.signals, this.session()) + bytes(\"exposures\", this.exposures, this.session());\n if (this.signals.length + this.exposures.length >= MAX || queued >= FLUSH_BYTES) return void this.flush(this.hidden);\n this.timer ??= setTimeout(() => void this.flush(), this.delay);\n }\n}\n\ntype Receipt = { enabled: boolean; context?: ActivityContext };\nconst targetKey = (target: ActivityTarget) => `${target.content_id}\\u0000${target.version_id ?? \"\"}`;\nconst unavailable = (error: unknown) => [\"not_configured\", \"unavailable\", \"server_unavailable\"].includes(toContentKitError(error).code);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"beacons.js","names":[],"sources":["../../src/client/beacons.ts"],"sourcesContent":["import type { ContentKitClient } from \"./client.js\";\nimport { toContentKitError } from \"./errors.js\";\nimport type { ActivityContext, ActivityTarget, ExposureInput, SignalInput } from \"./generated/wire.js\";\n\nexport interface BeaconOptions {\n /** A signed-out visitor identity, persistent across this browser's tabs. */\n session?: () => string | undefined;\n /** How long events gather before they are sent, ms. Default 2000. */\n delay?: number;\n /** How long beacons stay off after the site records no signals, ms, before the content model is read again. Default 60000. */\n recheck?: number;\n}\n\n/** Where a click came from: the list render it was shown in. */\nexport interface Attribution {\n /** Language of the displayed content; defaults to the client's request language. */\n language?: string;\n render_id?: string;\n surface?: string;\n /** 1-based position in that render. */\n position?: number;\n}\n\n\nconst MAX = 100;\n// Fetch's keepalive limit includes all in-flight bodies in the fetch group.\n// Leave headroom and serialize this module's keepalive requests across clients.\nconst KEEPALIVE_BYTES = 60 * 1024;\nconst FLUSH_BYTES = 48 * 1024;\nlet keepaliveTail: Promise<void> = Promise.resolve();\nconst encoder = new TextEncoder();\nconst bytes = (field: \"signals\" | \"exposures\", rows: readonly unknown[], session?: string) => encoder.encode(JSON.stringify({ session, [field]: rows })).length;\n\nfunction packets<T>(items: readonly T[], field: \"signals\" | \"exposures\", session?: string): { items: T[]; bytes: number }[] {\n const out: { items: T[]; bytes: number }[] = [];\n let current: T[] = [];\n for (const item of items) {\n if (current.length && (current.length === MAX || bytes(field, [...current, item], session) > KEEPALIVE_BYTES)) {\n out.push({ items: current, bytes: bytes(field, current, session) });\n current = [];\n }\n current.push(item);\n }\n if (current.length) out.push({ items: current, bytes: bytes(field, current, session) });\n return out;\n}\n\nfunction serializeKeepalive(send: () => Promise<void>): Promise<void> {\n const pending = keepaliveTail.then(send, send);\n keepaliveTail = pending.then(() => {}, () => {});\n return pending;\n}\nconst SESSION_KEY = \"contentkit.visitor.v1\";\nexport const eventId = () => (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto ? crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`);\n\nlet unstored: string | undefined;\n\n/** A random signed-out browser identity shared across tabs/reloads, never an account credential. */\nexport function readerSession(): string {\n try {\n const kept = localStorage.getItem(SESSION_KEY);\n if (kept) return kept;\n const made = eventId();\n localStorage.setItem(SESSION_KEY, made);\n return made;\n } catch {\n return (unstored ??= eventId());\n }\n}\n\n/**\n * Batched, best-effort signals and exposures: gathered for `delay`, sent in\n * one request each, flushed with keepalive when the page hides. While the\n * content model says the site records no signals (or a send is refused as\n * not_configured or unavailable) events are dropped; after `recheck` the\n * next event reads the model again, so signals resume when the site's\n * signal plane is back.\n */\nexport class Beacons {\n private signals: SignalInput[] = [];\n private exposures: ExposureInput[] = [];\n private timer: ReturnType<typeof setTimeout> | undefined;\n private offUntil = 0;\n private recorded: Promise<boolean> | undefined;\n private generation = 0;\n private hidden = false;\n private readonly pending = new Set<Promise<void>>();\n private readonly exposureContexts = new Map<string, { active: boolean; releaseRevision: number; occurredAt?: string; contexts: Map<string, Promise<Receipt | null>> }>();\n private readonly session: () => string | undefined;\n private readonly delay: number;\n private readonly recheck: number;\n\n constructor(\n private readonly client: Pick<ContentKitClient, \"discovery\" | \"kinds\"> & Partial<Pick<ContentKitClient, \"preferences\">>,\n o: BeaconOptions = {},\n ) {\n this.session = o.session ?? readerSession;\n this.delay = o.delay ?? 2000;\n this.recheck = o.recheck ?? 60_000;\n client.preferences?.subscribeIdentity(() => {\n // The old credentials can no longer be assumed available for a flush.\n this.generation++;\n clearTimeout(this.timer);\n this.timer = undefined;\n this.signals = [];\n this.exposures = [];\n this.pending.clear();\n for (const state of this.exposureContexts.values()) state.active = false;\n this.exposureContexts.clear();\n this.recorded = undefined;\n });\n if (typeof addEventListener === \"function\") {\n addEventListener(\"pagehide\", () => { this.hidden = true; void this.flush(true); });\n addEventListener(\"pageshow\", () => { this.hidden = false; });\n addEventListener(\"visibilitychange\", () => {\n this.hidden = typeof document !== \"undefined\" && document.visibilityState === \"hidden\";\n if (this.hidden) void this.flush(true);\n });\n }\n }\n\n /** A click on a listed card. Acquire its access snapshot at observation time. */\n click(content: string, a: Attribution & { version_id?: string } = {}): void {\n if (this.paused()) return;\n const generation = this.generation;\n const event = eventId(), at = new Date().toISOString();\n const { language, ...attribution } = a;\n const target = { content_id: content, version_id: a.version_id };\n this.track(this.contexts([target], generation, language).then((receipts) => {\n const receipt = receipts?.get(targetKey(target));\n if (!receipt || generation !== this.generation) return;\n this.signal({ content_id: content, type: \"click\", event_id: event, ...attribution,\n occurred_at: receipt.context?.occurred_at ?? at, activity_token: receipt.context?.token });\n }), generation);\n }\n\n /** A cumulative result-list stage; each newly observed target gets one receipt. */\n exposure(e: ExposureInput): void {\n if (this.paused() || !e.shown.length) return;\n const generation = this.generation;\n const key = `${e.render_id}\\u0000${e.stage}`;\n let state = this.exposureContexts.get(key);\n if (!state) {\n state = { active: true, releaseRevision: 0, contexts: new Map() };\n this.exposureContexts.set(key, state);\n }\n state.releaseRevision++;\n const captured = state;\n const unseen = e.shown.filter((p) => !captured.contexts.has(targetKey(p)));\n if (unseen.length) {\n const contexts = this.contexts(unseen, generation, e.language);\n for (const target of unseen) {\n const key = targetKey(target);\n const pending: Promise<Receipt | null> = contexts.then((values) => {\n const receipt = values?.get(key) ?? null;\n if (!receipt && captured.contexts.get(key) === pending) captured.contexts.delete(key);\n return receipt;\n }, (error: unknown) => {\n if (captured.contexts.get(key) === pending) captured.contexts.delete(key);\n throw error;\n });\n captured.contexts.set(key, pending);\n }\n }\n this.track(Promise.all(e.shown.map((p) => captured.contexts.get(targetKey(p))!)).then((receipts) => {\n if (generation !== this.generation || !captured.active || receipts.some((r) => !r)) return;\n const valid = receipts as Receipt[];\n if (new Set(valid.map((r) => r.enabled)).size !== 1) return;\n captured.occurredAt ??= valid.find((r) => r.context)?.context?.occurred_at ?? e.occurred_at ?? new Date().toISOString();\n const enriched = { ...e, occurred_at: captured.occurredAt,\n shown: e.shown.map((p, i) => ({ ...p, activity_token: valid[i]?.context?.token })) };\n // A later cumulative revision supersedes a queued earlier snapshot.\n const previous = this.exposures.find((x) => x.render_id === e.render_id && x.stage === e.stage);\n if (previous && (previous.revision ?? 0) > (e.revision ?? 0)) return;\n this.exposures = this.exposures.filter((x) => x.render_id !== e.render_id || x.stage !== e.stage);\n this.exposures.push(enriched);\n this.schedule();\n }), generation);\n }\n\n /** Keep receipt state when a mounted list resumes (including StrictMode replay). */\n beginExposure(render: string): void {\n for (const stage of [\"served\", \"rendered\", \"visible\"]) {\n const state = this.exposureContexts.get(`${render}\\u0000${stage}`);\n if (state) state.releaseRevision++;\n }\n }\n\n /** Retire receipt state after a list unmounts without cancelling observations. */\n endExposure(render: string): void {\n for (const stage of [\"served\", \"rendered\", \"visible\"]) {\n const key = `${render}\\u0000${stage}`, state = this.exposureContexts.get(key);\n if (!state) continue;\n const release = ++state.releaseRevision;\n queueMicrotask(() => {\n if (this.exposureContexts.get(key) === state && state.releaseRevision === release) this.exposureContexts.delete(key);\n });\n }\n }\n\n /** Sends ready observations; receipts are never acquired for the first time here. */\n async flush(keepalive = false): Promise<void> {\n clearTimeout(this.timer);\n this.timer = undefined;\n const generation = this.generation;\n await Promise.allSettled([...this.pending]);\n if (generation !== this.generation) return;\n clearTimeout(this.timer);\n this.timer = undefined;\n const signals = this.signals.splice(0), exposures = this.exposures.splice(0);\n if (this.paused() || (!signals.length && !exposures.length)) return;\n const session = this.session();\n const jobs = [\n ...packets(signals, \"signals\", session).map((packet) => ({ ...packet, send: (persist: boolean) => this.client.discovery.signals(packet.items, session, { keepalive: persist }) })),\n ...packets(exposures, \"exposures\", session).map((packet) => ({ ...packet, send: (persist: boolean) => this.client.discovery.exposures(packet.items, session, { keepalive: persist }) })),\n ];\n const done = await Promise.allSettled(jobs.map((job) => {\n const persist = keepalive && job.bytes <= KEEPALIVE_BYTES;\n const send = () => generation === this.generation ? job.send(persist) : Promise.resolve();\n // A single oversized cumulative exposure cannot be split without losing\n // history. Normal fetch is the best effort available during pagehide.\n return persist ? serializeKeepalive(send) : send();\n }));\n if (generation === this.generation && done.some((r) => r.status === \"rejected\" && unavailable(r.reason))) this.pause();\n }\n\n private async contexts(targets: readonly ActivityTarget[], generation: number, language?: string): Promise<Map<string, Receipt> | null> {\n if (this.paused() || !(await this.recording())) {\n if (generation === this.generation) this.pause();\n return null;\n }\n if (generation !== this.generation) return null;\n // Exposure rows carry list fields (position); the strict endpoint takes only the target.\n const unique = [...new Map(targets.map((t) => [targetKey(t), { content_id: t.content_id, version_id: t.version_id }])).values()];\n const batches = [];\n const session = this.session();\n for (let i = 0; i < unique.length; i += MAX) batches.push(this.client.discovery.activityContexts(unique.slice(i, i + MAX), session, language));\n const responses = await Promise.all(batches);\n if (generation !== this.generation) return null;\n const out = new Map<string, Receipt>();\n for (let i = 0; i < responses.length; i++) {\n const response = responses[i]!;\n if (typeof response?.enabled !== \"boolean\" || (response.enabled && !Array.isArray(response.contexts))) throw new Error(\"contentkit: invalid activity context response\");\n const contexts = new Map((response.contexts ?? []).map((context) => [targetKey(context), context]));\n for (const target of unique.slice(i * MAX, (i + 1) * MAX)) {\n const context = contexts.get(targetKey(target));\n if (response.enabled && (!context?.token || !Number.isFinite(Date.parse(context.occurred_at)))) throw new Error(\"contentkit: invalid activity context\");\n out.set(targetKey(target), { enabled: response.enabled, context: response.enabled ? context : undefined });\n }\n }\n return out;\n }\n\n private track(task: Promise<void>, generation: number): void {\n const pending = task.catch((error) => { if (generation === this.generation && unavailable(error)) this.pause(); }).finally(() => { this.pending.delete(pending); });\n this.pending.add(pending);\n }\n\n private signal(s: SignalInput): void {\n if (this.paused()) return;\n this.signals.push(s);\n this.schedule();\n }\n private paused(): boolean {\n if (this.offUntil > Date.now()) return true;\n this.offUntil = 0;\n return false;\n }\n private pause(): void { this.offUntil = Date.now() + this.recheck; this.recorded = undefined; }\n private recording(): Promise<boolean> {\n return (this.recorded ??= this.client.kinds().then((m) => m.signals, () => true));\n }\n private schedule(): void {\n const queued = bytes(\"signals\", this.signals, this.session()) + bytes(\"exposures\", this.exposures, this.session());\n if (this.signals.length + this.exposures.length >= MAX || queued >= FLUSH_BYTES) return void this.flush(this.hidden);\n this.timer ??= setTimeout(() => void this.flush(), this.delay);\n }\n}\n\ntype Receipt = { enabled: boolean; context?: ActivityContext };\nconst targetKey = (target: ActivityTarget) => `${target.content_id}\\u0000${target.version_id ?? \"\"}`;\nconst unavailable = (error: unknown) => [\"not_configured\", \"unavailable\", \"server_unavailable\"].includes(toContentKitError(error).code);\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CatalogText, Content, ContentInput, ContentPatch, Creator, InlineImage, Segment, Version, VersionInput } from './generated/wire.js';
|
|
1
|
+
import { CatalogText, Content, ContentInput, ContentPatch, Creator, InlineImage, ManageCount, Segment, Version, VersionInput } from './generated/wire.js';
|
|
2
2
|
import { Http } from './http.js';
|
|
3
3
|
import { RouteQuery } from './route.js';
|
|
4
4
|
/** The URL scheme of an image reference in a content body. */
|
|
@@ -15,6 +15,10 @@ export declare const imageRefs: () => RegExp;
|
|
|
15
15
|
export type ManageQuery = RouteQuery<"GET", "/manage"> & {
|
|
16
16
|
kind?: string;
|
|
17
17
|
};
|
|
18
|
+
/** The /manage/{kind} filters a count takes. */
|
|
19
|
+
export type ManageCountQuery = RouteQuery<"GET", "/manage/{kind}/count"> & {
|
|
20
|
+
kind: string;
|
|
21
|
+
};
|
|
18
22
|
/**
|
|
19
23
|
* Content items: a viewer's reads, and the writes of their creators, their
|
|
20
24
|
* owner group's editors and root:content:write holders.
|
|
@@ -27,6 +31,8 @@ export declare class ContentsClient {
|
|
|
27
31
|
version(id: string, vid: string, language?: string, signal?: AbortSignal): Promise<Version>;
|
|
28
32
|
/** Items the caller manages, newest first: all for root:content:write holders, else theirs or an owner group's. */
|
|
29
33
|
manage(q?: ManageQuery, signal?: AbortSignal): Promise<Content[]>;
|
|
34
|
+
/** How many items of a kind the caller manages under these filters: exact up to 10,000, then truncated. */
|
|
35
|
+
manageCount(q: ManageCountQuery, signal?: AbortSignal): Promise<ManageCount>;
|
|
30
36
|
/** Creates a draft. */
|
|
31
37
|
create(input: ContentInput): Promise<Content>;
|
|
32
38
|
update(id: string, patch: ContentPatch): Promise<Content>;
|
package/dist/client/contents.js
CHANGED
|
@@ -33,6 +33,14 @@ var t = "contentkit:", n = (e) => t + e, r = () => /contentkit:(i-[0-9a-f]{8}-[0
|
|
|
33
33
|
signal: n
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
+
manageCount(t, n) {
|
|
37
|
+
let { kind: r, ...i } = t;
|
|
38
|
+
return e(this.http, "GET", "/manage/{kind}/count", {
|
|
39
|
+
params: { kind: r },
|
|
40
|
+
query: i,
|
|
41
|
+
signal: n
|
|
42
|
+
});
|
|
43
|
+
}
|
|
36
44
|
create(t) {
|
|
37
45
|
return this.write(e(this.http, "POST", "/contents", { body: t }));
|
|
38
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contents.js","names":[],"sources":["../../src/client/contents.ts"],"sourcesContent":["import type {\n CatalogText,\n Content,\n ContentInput,\n ContentPatch,\n Creator,\n InlineImage,\n Segment,\n Version,\n VersionInput,\n} from \"./generated/wire.js\";\nimport type { Http } from \"./http.js\";\nimport { call, type RouteQuery } from \"./route.js\";\n\n/** The URL scheme of an image reference in a content body. */\nexport const IMAGE_SCHEME = \"contentkit:\";\n\n/**\n * The reference a body stores for one of its images, by name\n * (\"contentkit:i-{uuid}\"), where the image's URL would go: reads resolve it to\n * the image's current public file (`Content.images`).\n */\nexport const imageRef = (name: string) => IMAGE_SCHEME + name;\n\n/** Matches every image reference; the name is group 1. */\nexport const imageRefs = () => /contentkit:(i-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/g;\n\n/** Management filters; kind selects /manage/{kind}, otherwise /manage. */\nexport type ManageQuery = RouteQuery<\"GET\", \"/manage\"> & { kind?: string };\n\n/**\n * Content items: a viewer's reads, and the writes of their creators, their\n * owner group's editors and root:content:write holders.\n */\nexport class ContentsClient {\n constructor(private readonly http: Http) {}\n\n /** The item as the caller sees it; text in language, else the site's first, else any. */\n get(id: string, language?: string, signal?: AbortSignal): Promise<Content> {\n return call(this.http, \"GET\", \"/contents/{id}\", { params: { id }, query: { language }, signal });\n }\n version(id: string, vid: string, language?: string, signal?: AbortSignal): Promise<Version> {\n return call(this.http, \"GET\", \"/contents/{id}/versions/{vid}\", { params: { id, vid }, query: { language }, signal });\n }\n /** Items the caller manages, newest first: all for root:content:write holders, else theirs or an owner group's. */\n manage(q: ManageQuery = {}, signal?: AbortSignal): Promise<Content[]> {\n const { kind, ...query } = q;\n return kind\n ? call(this.http, \"GET\", \"/manage/{kind}\", { params: { kind }, query, signal })\n : call(this.http, \"GET\", \"/manage\", { query, signal });\n }\n /** Creates a draft. */\n create(input: ContentInput): Promise<Content> {\n return this.write(call(this.http, \"POST\", \"/contents\", { body: input }));\n }\n update(id: string, patch: ContentPatch): Promise<Content> {\n return this.write(call(this.http, \"PATCH\", \"/contents/{id}\", { params: { id }, body: patch }));\n }\n /** Sets the text in one language; moderation \"held\" when the moderator holds the edit. */\n putText(id: string, language: string, text: CatalogText): Promise<Content> {\n return this.write(call(this.http, \"PUT\", \"/contents/{id}/text/{language}\", { params: { id, language }, body: text }));\n }\n deleteText(id: string, language: string): Promise<Content> {\n return this.write(call(this.http, \"DELETE\", \"/contents/{id}/text/{language}\", { params: { id, language } }));\n }\n setCreators(id: string, creators: Creator[]): Promise<Content> {\n return this.write(call(this.http, \"PUT\", \"/contents/{id}/creators\", { params: { id }, body: { creators } }));\n }\n /** Publishes now, or schedules for at; moderation \"held\" when the moderator holds it. */\n publish(id: string, at?: string): Promise<Content> {\n return this.write(call(this.http, \"POST\", \"/contents/{id}/publish\", { params: { id }, body: { publish_at: at } }));\n }\n unpublish(id: string): Promise<Content> {\n return this.write(call(this.http, \"POST\", \"/contents/{id}/unpublish\", { params: { id } }));\n }\n async remove(id: string): Promise<void> {\n const emit = this.http.captureChanges();\n await call(this.http, \"DELETE\", \"/contents/{id}\", { params: { id } });\n emit({ type: \"content.deleted\", id });\n }\n restore(id: string): Promise<Content> {\n return this.write(call(this.http, \"POST\", \"/contents/{id}/restore\", { params: { id } }));\n }\n /** Selects a version's cover by the name (\"i-{uuid}\") of one of its cover uploads; null returns to its first. */\n setCover(id: string, vid: string, image: string | null): Promise<Version> {\n return this.updateVersion(id, vid, { cover: image ?? \"\" });\n }\n /**\n * A body image uploaded to version vid (its private files), copied into\n * every other version: the reference to store in the body and a URL that shows\n * it to the editor now (null while none exists).\n */\n inlineImage(id: string, vid: string, image: string, signal?: AbortSignal): Promise<InlineImage> {\n return call(this.http, \"POST\", \"/contents/{id}/images\", { params: { id }, body: { image, version: vid }, signal });\n }\n addVersion(id: string, input: VersionInput): Promise<Version> {\n return this.writeVersion(id, call(this.http, \"POST\", \"/contents/{id}/versions\", { params: { id }, body: input }));\n }\n updateVersion(id: string, vid: string, input: VersionInput): Promise<Version> {\n return this.writeVersion(id, call(this.http, \"PATCH\", \"/contents/{id}/versions/{vid}\", { params: { id, vid }, body: input }));\n }\n async removeVersion(id: string, vid: string): Promise<void> {\n await this.writeVersion(id, call(this.http, \"DELETE\", \"/contents/{id}/versions/{vid}\", { params: { id, vid } }));\n }\n /** Orders the versions: ids lists each version that is not deleted, first first. */\n orderVersions(id: string, ids: string[]): Promise<Content> {\n return this.write(call(this.http, \"PUT\", \"/contents/{id}/versions/order\", { params: { id }, body: { ids } }));\n }\n /** Replaces a version's segments (chapters). */\n setSegments(id: string, vid: string, segments: Segment[]): Promise<Version> {\n return this.writeVersion(id, call(this.http, \"PUT\", \"/contents/{id}/versions/{vid}/segments\", { params: { id, vid }, body: { segments } }));\n }\n\n private async write(p: Promise<Content>): Promise<Content> {\n const emit = this.http.captureChanges();\n const content = await p;\n emit({ type: \"content.saved\", content });\n return content;\n }\n\n private async writeVersion<T>(id: string, p: Promise<T>): Promise<T> {\n const emit = this.http.captureChanges();\n const out = await p;\n emit({ type: \"content.changed\", id });\n return out;\n }\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"contents.js","names":[],"sources":["../../src/client/contents.ts"],"sourcesContent":["import type {\n CatalogText,\n Content,\n ContentInput,\n ContentPatch,\n Creator,\n InlineImage,\n ManageCount,\n Segment,\n Version,\n VersionInput,\n} from \"./generated/wire.js\";\nimport type { Http } from \"./http.js\";\nimport { call, type RouteQuery } from \"./route.js\";\n\n/** The URL scheme of an image reference in a content body. */\nexport const IMAGE_SCHEME = \"contentkit:\";\n\n/**\n * The reference a body stores for one of its images, by name\n * (\"contentkit:i-{uuid}\"), where the image's URL would go: reads resolve it to\n * the image's current public file (`Content.images`).\n */\nexport const imageRef = (name: string) => IMAGE_SCHEME + name;\n\n/** Matches every image reference; the name is group 1. */\nexport const imageRefs = () => /contentkit:(i-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/g;\n\n/** Management filters; kind selects /manage/{kind}, otherwise /manage. */\nexport type ManageQuery = RouteQuery<\"GET\", \"/manage\"> & { kind?: string };\n\n/** The /manage/{kind} filters a count takes. */\nexport type ManageCountQuery = RouteQuery<\"GET\", \"/manage/{kind}/count\"> & { kind: string };\n\n/**\n * Content items: a viewer's reads, and the writes of their creators, their\n * owner group's editors and root:content:write holders.\n */\nexport class ContentsClient {\n constructor(private readonly http: Http) {}\n\n /** The item as the caller sees it; text in language, else the site's first, else any. */\n get(id: string, language?: string, signal?: AbortSignal): Promise<Content> {\n return call(this.http, \"GET\", \"/contents/{id}\", { params: { id }, query: { language }, signal });\n }\n version(id: string, vid: string, language?: string, signal?: AbortSignal): Promise<Version> {\n return call(this.http, \"GET\", \"/contents/{id}/versions/{vid}\", { params: { id, vid }, query: { language }, signal });\n }\n /** Items the caller manages, newest first: all for root:content:write holders, else theirs or an owner group's. */\n manage(q: ManageQuery = {}, signal?: AbortSignal): Promise<Content[]> {\n const { kind, ...query } = q;\n return kind\n ? call(this.http, \"GET\", \"/manage/{kind}\", { params: { kind }, query, signal })\n : call(this.http, \"GET\", \"/manage\", { query, signal });\n }\n /** How many items of a kind the caller manages under these filters: exact up to 10,000, then truncated. */\n manageCount(q: ManageCountQuery, signal?: AbortSignal): Promise<ManageCount> {\n const { kind, ...query } = q;\n return call(this.http, \"GET\", \"/manage/{kind}/count\", { params: { kind }, query, signal });\n }\n /** Creates a draft. */\n create(input: ContentInput): Promise<Content> {\n return this.write(call(this.http, \"POST\", \"/contents\", { body: input }));\n }\n update(id: string, patch: ContentPatch): Promise<Content> {\n return this.write(call(this.http, \"PATCH\", \"/contents/{id}\", { params: { id }, body: patch }));\n }\n /** Sets the text in one language; moderation \"held\" when the moderator holds the edit. */\n putText(id: string, language: string, text: CatalogText): Promise<Content> {\n return this.write(call(this.http, \"PUT\", \"/contents/{id}/text/{language}\", { params: { id, language }, body: text }));\n }\n deleteText(id: string, language: string): Promise<Content> {\n return this.write(call(this.http, \"DELETE\", \"/contents/{id}/text/{language}\", { params: { id, language } }));\n }\n setCreators(id: string, creators: Creator[]): Promise<Content> {\n return this.write(call(this.http, \"PUT\", \"/contents/{id}/creators\", { params: { id }, body: { creators } }));\n }\n /** Publishes now, or schedules for at; moderation \"held\" when the moderator holds it. */\n publish(id: string, at?: string): Promise<Content> {\n return this.write(call(this.http, \"POST\", \"/contents/{id}/publish\", { params: { id }, body: { publish_at: at } }));\n }\n unpublish(id: string): Promise<Content> {\n return this.write(call(this.http, \"POST\", \"/contents/{id}/unpublish\", { params: { id } }));\n }\n async remove(id: string): Promise<void> {\n const emit = this.http.captureChanges();\n await call(this.http, \"DELETE\", \"/contents/{id}\", { params: { id } });\n emit({ type: \"content.deleted\", id });\n }\n restore(id: string): Promise<Content> {\n return this.write(call(this.http, \"POST\", \"/contents/{id}/restore\", { params: { id } }));\n }\n /** Selects a version's cover by the name (\"i-{uuid}\") of one of its cover uploads; null returns to its first. */\n setCover(id: string, vid: string, image: string | null): Promise<Version> {\n return this.updateVersion(id, vid, { cover: image ?? \"\" });\n }\n /**\n * A body image uploaded to version vid (its private files), copied into\n * every other version: the reference to store in the body and a URL that shows\n * it to the editor now (null while none exists).\n */\n inlineImage(id: string, vid: string, image: string, signal?: AbortSignal): Promise<InlineImage> {\n return call(this.http, \"POST\", \"/contents/{id}/images\", { params: { id }, body: { image, version: vid }, signal });\n }\n addVersion(id: string, input: VersionInput): Promise<Version> {\n return this.writeVersion(id, call(this.http, \"POST\", \"/contents/{id}/versions\", { params: { id }, body: input }));\n }\n updateVersion(id: string, vid: string, input: VersionInput): Promise<Version> {\n return this.writeVersion(id, call(this.http, \"PATCH\", \"/contents/{id}/versions/{vid}\", { params: { id, vid }, body: input }));\n }\n async removeVersion(id: string, vid: string): Promise<void> {\n await this.writeVersion(id, call(this.http, \"DELETE\", \"/contents/{id}/versions/{vid}\", { params: { id, vid } }));\n }\n /** Orders the versions: ids lists each version that is not deleted, first first. */\n orderVersions(id: string, ids: string[]): Promise<Content> {\n return this.write(call(this.http, \"PUT\", \"/contents/{id}/versions/order\", { params: { id }, body: { ids } }));\n }\n /** Replaces a version's segments (chapters). */\n setSegments(id: string, vid: string, segments: Segment[]): Promise<Version> {\n return this.writeVersion(id, call(this.http, \"PUT\", \"/contents/{id}/versions/{vid}/segments\", { params: { id, vid }, body: { segments } }));\n }\n\n private async write(p: Promise<Content>): Promise<Content> {\n const emit = this.http.captureChanges();\n const content = await p;\n emit({ type: \"content.saved\", content });\n return content;\n }\n\n private async writeVersion<T>(id: string, p: Promise<T>): Promise<T> {\n const emit = this.http.captureChanges();\n const out = await p;\n emit({ type: \"content.changed\", id });\n return out;\n }\n}\n"],"mappings":"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"}
|
|
@@ -53,7 +53,11 @@ export interface PageQuery {
|
|
|
53
53
|
cursor?: string;
|
|
54
54
|
limit?: number;
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
/** A numbered page from 1 instead of cursor; its summary then comes with every page. */
|
|
57
|
+
export interface NumberedPageQuery {
|
|
58
|
+
page?: number;
|
|
59
|
+
}
|
|
60
|
+
export type ContentQuery = ContentFilterQuery & ReaderQuery & CardQuery & PageQuery & NumberedPageQuery & {
|
|
57
61
|
/** Selection-wide metadata; requested only on the first page. */
|
|
58
62
|
summary?: boolean;
|
|
59
63
|
sort?: ListSort;
|
|
@@ -75,7 +79,7 @@ export declare function popularQuery(period?: PopularPeriod | PopularDateRange,
|
|
|
75
79
|
export declare function popularBetween(from: string, until: string, filters: PopularQuery & {
|
|
76
80
|
kind: string;
|
|
77
81
|
}): ContentQuery;
|
|
78
|
-
export type SearchQuery = ContentFilterQuery & ReaderQuery & CardQuery & PageQuery & {
|
|
82
|
+
export type SearchQuery = ContentFilterQuery & ReaderQuery & CardQuery & PageQuery & NumberedPageQuery & {
|
|
79
83
|
q: string;
|
|
80
84
|
sort?: "relevance" | ListSort;
|
|
81
85
|
personalize?: boolean;
|
package/dist/client/discovery.js
CHANGED
|
@@ -48,7 +48,7 @@ var s = class {
|
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
async search(t, n) {
|
|
51
|
-
let r = t.cursor ? null : this.http.captureChanges(), i = await e(this.http, "GET", "/search", {
|
|
51
|
+
let r = t.cursor || (t.page ?? 1) > 1 ? null : this.http.captureChanges(), i = await e(this.http, "GET", "/search", {
|
|
52
52
|
query: o(t),
|
|
53
53
|
signal: n
|
|
54
54
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.js","names":[],"sources":["../../src/client/discovery.ts"],"sourcesContent":["import type {\n ActivityContexts,\n ActivityContextsInput,\n ActivityTarget,\n ContentFilters,\n ContentFiltersUpdate,\n ContentPage,\n DailyReleases,\n EngagementBatch,\n EngagementSnapshot,\n ExposureInput,\n Exposures,\n RecentSearches,\n ReleaseDates,\n SignalInput,\n Signals,\n Typeahead,\n} from \"./generated/wire.js\";\nimport type { Http } from \"./http.js\";\nimport { call, routeURL } from \"./route.js\";\nimport { browserSearchHistory, type BrowserSearchHistory } from \"./browser-search-history.js\";\n\n/** A popularity period. */\nexport type Period = \"7d\" | \"30d\" | \"90d\" | \"365d\" | \"all\";\n/** A list's order; position orders by the first of `groups` (an ordered group). */\nexport type ListSort = \"newest\" | \"oldest\" | \"title\" | \"popular\" | `popular:${Period}` | \"top_rated\" | `top_rated:${Period}` | \"most_favorited\" | \"position\" | \"random\";\n/** How locked contents list: marked (lock, the default) or left out (hide). */\nexport type AccessMode = \"lock\" | \"hide\";\n\n/** Which contents a list holds. */\nexport interface ContentFilterQuery {\n kind?: string;\n /** Public card hydration under current domain/access/preferences; at most 100. */\n ids?: readonly string[];\n /** Group ids every listed version is in. */\n groups?: readonly string[];\n /** Group ids no listed version is in. */\n exclude_groups?: readonly string[];\n /** Only contents this group owns: a channel's feed. */\n owner_group?: string;\n /** User ids: only contents one of them is credited on. */\n creators?: readonly string[];\n /** public (anyone opens it now) or the level it stays locked at. */\n access?: readonly (\"public\" | \"tier\" | \"group\" | \"ppv\" | \"group_ppv\")[];\n /** Only contents locked behind one of these tiers. */\n tiers?: readonly string[];\n /** Version traits every listed version has. */\n traits?: readonly string[];\n /** \"name:value\" of the kind's filterable attributes. */\n attribute?: readonly string[];\n /** Published on this day (YYYY-MM-DD) or month (YYYY-MM). */\n released_on?: string;\n /** Only contents published within this age window; independent of the popularity score window. */\n published_within?: Period;\n /** IANA time zone of released_on and release dates; UTC by default. */\n tz?: string;\n /** The signed-in reader's unseen, in-progress or completed contents. */\n view_status?: \"unseen\" | \"in_progress\" | \"completed\";\n}\n\n/** How a list reads to its reader. */\nexport interface ReaderQuery {\n /** Only content with a live version in this language. */\n language?: string;\n /** Titles, names and paths in this language, and each card's preferred version's; language by default. */\n display_language?: string;\n mode?: AccessMode;\n}\n\n/** The group kinds cards name; every kind with a page by default. */\nexport interface CardQuery {\n card_entities?: readonly string[];\n}\n\nexport interface PageQuery {\n cursor?: string;\n limit?: number;\n}\n\nexport type ContentQuery = ContentFilterQuery & ReaderQuery & CardQuery & PageQuery & {\n /** Selection-wide metadata; requested only on the first page. */\n summary?: boolean;\n sort?: ListSort;\n /** Inclusive UTC date (YYYY-MM-DD); requires activity_until, kind and sort=popular. */\n activity_from?: string;\n /** Exclusive UTC date (YYYY-MM-DD); requires activity_from, kind and sort=popular. */\n activity_until?: string;\n};\nexport type PopularPeriod = \"7d\" | \"90d\" | \"365d\" | \"all\";\n/** Whole UTC dates: from inclusive, until exclusive. */\nexport interface PopularDateRange {\n from: string;\n until: string;\n}\nexport type PopularQuery = Omit<ContentQuery, \"sort\" | \"activity_from\" | \"activity_until\">;\n\n/** Rank activity in the selected window; publication age is an optional separate filter. */\nexport function popularQuery(period: PopularPeriod | PopularDateRange = \"7d\", filters: PopularQuery = {}): ContentQuery {\n return typeof period === \"string\"\n ? { ...filters, sort: `popular:${period}` }\n : { ...filters, sort: \"popular\", activity_from: period.from, activity_until: period.until };\n}\n\n/** Rank activity between two UTC dates: from inclusive, until exclusive. */\nexport function popularBetween(from: string, until: string, filters: PopularQuery & { kind: string }): ContentQuery {\n return popularQuery({ from, until }, filters);\n}\n\nexport type SearchQuery = ContentFilterQuery &\n ReaderQuery &\n CardQuery &\n PageQuery & {\n q: string;\n sort?: \"relevance\" | ListSort;\n personalize?: boolean;\n summary?: boolean;\n /** Explicit legacy server-side anonymous history. Omit for public search without server history. */\n session?: string;\n };\nexport interface RecentSearchesQuery {\n /** Explicit legacy server-side anonymous history; no anonymous session is created by default. */\n session?: string;\n /** 10 by default, at most 100. */\n limit?: number;\n}\nexport type RailQuery = ContentFilterQuery & ReaderQuery & CardQuery & { limit?: number; summary?: boolean };\nexport type ReleaseDatesQuery = ContentFilterQuery & ReaderQuery & PageQuery & { by?: \"month\" | \"day\" };\n/** Complete daily metadata for one calendar window, without pagination. */\nexport type DailyReleasesQuery = Omit<ContentFilterQuery, \"released_on\" | \"tz\"> & ReaderQuery & CardQuery & {\n days?: number;\n /** Inclusive YYYY-MM-DD in time_zone; today by default. Future dates are rejected. */\n end_date?: string;\n time_zone?: string;\n};\nexport type HistoryQuery = ReaderQuery & CardQuery & PageQuery & { kind?: string; status?: \"seen\" | \"in_progress\" | \"completed\"; summary?: boolean };\nexport interface TypeaheadQuery extends ReaderQuery {\n q: string;\n /** Only contents of this kind. */\n kind?: string;\n /** The group kinds suggested; every kind with a page by default. */\n entity_kinds?: readonly string[];\n /** Per section: 8 by default, at most 20. */\n limit?: number;\n}\n\n/** Private editor navigation. Each requested section must be chosen explicitly. */\nexport interface AdminSuggestionsQuery {\n q: string;\n display_language?: string;\n content_kinds?: readonly string[];\n entity_kinds?: readonly string[];\n include_contents: boolean;\n include_entities: boolean;\n /** Per section: 8 by default, at most 20. */\n limit?: number;\n}\n\n// Comma-joined list parameters; `attribute` repeats instead.\nconst LISTS = new Set([\"ids\", \"groups\", \"exclude_groups\", \"creators\", \"access\", \"tiers\", \"traits\", \"card_entities\", \"entity_kinds\", \"content_kinds\"]);\n\n/** A query with its list parameters comma-joined, as discovery routes read them. */\nexport function query(q: object): Record<string, string | number | boolean | readonly string[] | undefined> {\n const out: Record<string, string | number | boolean | readonly string[] | undefined> = {};\n for (const [k, v] of Object.entries(q)) out[k] = LISTS.has(k) && Array.isArray(v) ? (v.length ? v.join(\",\") : undefined) : v;\n return out;\n}\n\n/**\n * Discovery: lists, search, typeahead, similar and recommended contents,\n * release dates, the reader's content filters and history, signals and exposures.\n */\nexport class DiscoveryClient {\n /** Local anonymous history, isolated from authenticated server history. */\n readonly browserSearches: BrowserSearchHistory;\n\n constructor(private readonly http: Http) {\n this.browserSearches = browserSearchHistory(http.mount(\"discovery\"));\n }\n\n /** Contents as cards, one per content item with the version that fits the reader. */\n list(q: ContentQuery = {}, signal?: AbortSignal): Promise<ContentPage> {\n return call(this.http, \"GET\", \"/contents\", { query: query(q) as never, signal });\n }\n /** A first page is kept among the reader's recent searches. */\n async search(q: SearchQuery, signal?: AbortSignal): Promise<ContentPage> {\n const emit = q.cursor ? null : this.http.captureChanges();\n const out: ContentPage = await call(this.http, \"GET\", \"/search\", { query: query(q) as never, signal });\n emit?.({ type: \"searches.changed\" });\n return out;\n }\n /** The reader's recent searches, newest first, since they last cleared them. */\n recentSearches(q: RecentSearchesQuery = {}, signal?: AbortSignal): Promise<RecentSearches> {\n return call(this.http, \"GET\", \"/me/searches\", { query: q, signal });\n }\n /** Clears one recent search, or all of them. */\n async clearSearches(o: { query?: string; session?: string } = {}): Promise<void> {\n const emit = this.http.captureChanges();\n await call(this.http, \"DELETE\", \"/me/searches\", { query: o });\n emit({ type: \"searches.changed\" });\n }\n /** Contents and groups while the reader types. */\n typeahead(q: TypeaheadQuery, signal?: AbortSignal): Promise<Typeahead> {\n return call(this.http, \"GET\", \"/typeahead\", { query: query(q) as never, signal });\n }\n /** Current names of authorized draft/hidden content and entities; no public search fallback. */\n adminSuggestions(q: AdminSuggestionsQuery, signal?: AbortSignal): Promise<Typeahead> {\n return call(this.http, \"GET\", \"/manage/search-suggestions\", { query: query(q) as never, signal });\n }\n /** Contents like one, of its kind unless q.kind names another. */\n similar(id: string, q: RailQuery = {}, signal?: AbortSignal): Promise<ContentPage> {\n return call(this.http, \"GET\", \"/contents/{id}/similar\", { params: { id }, query: query(q) as never, signal });\n }\n /** For the signed-in reader. */\n recommendations(q: RailQuery = {}, signal?: AbortSignal): Promise<ContentPage> {\n return call(this.http, \"GET\", \"/recommendations\", { query: query(q) as never, signal });\n }\n /** Per month or day, newest first: how many contents the reader's listing shows released then, and how many are free. */\n releaseDates(q: ReleaseDatesQuery = {}, signal?: AbortSignal): Promise<ReleaseDates> {\n return call(this.http, \"GET\", \"/release-dates\", { query: query(q) as never, signal });\n }\n /** Every visible card in each day; opening or expanding a day needs no further request. */\n releases(q: DailyReleasesQuery = {}, signal?: AbortSignal): Promise<DailyReleases> {\n return call(this.http, \"GET\", \"/releases\", { query: query(q) as never, signal });\n }\n /** Only the current domain's reader-toggleable entities, named in the requested language. */\n async contentFilters(language?: string, signal?: AbortSignal): Promise<ContentFilters> {\n const result = await this.http.request<ContentFilters>(routeURL(this.http, \"GET\", \"/content-filters\", { query: { language } }), { signal, guestPreferences: false });\n this.http.acceptGuestFilters(result.filters);\n return result;\n }\n /** Atomically changes submitted shared choices; omitted settings remain intact. */\n async setContentFilters(update: ContentFiltersUpdate, language?: string): Promise<ContentFilters> {\n const emit = this.http.captureChanges();\n const out: ContentFilters = await call(this.http, \"PATCH\", \"/me/content-filters\", { query: { language }, body: update });\n emit({ type: \"contentFilters.changed\" });\n return out;\n }\n /** What the reader engaged with, most recent first. */\n history(q: HistoryQuery = {}, signal?: AbortSignal): Promise<ContentPage> {\n return call(this.http, \"GET\", \"/me/history\", { query: query(q) as never, signal });\n }\n /** Erases the reader's history: of one content item, one kind or everything. */\n async forgetHistory(o: { kind?: string; content_id?: string } = {}): Promise<void> {\n const emit = this.http.captureChanges();\n await call(this.http, \"DELETE\", \"/me/history\", { query: o });\n emit({ type: \"history.changed\" });\n }\n /** Capture server-owned access and eligibility at an observation's start. */\n activityContexts(targets: readonly ActivityTarget[], session?: string, language = this.http.language()): Promise<ActivityContexts> {\n const body: ActivityContextsInput = { targets: [...targets], session, language };\n return call(this.http, \"POST\", \"/activity-contexts\", { body });\n }\n /** Cumulative measured attention. Successful checkpoints refresh history/progress caches. */\n async engagement(snapshots: EngagementSnapshot[], o: { session?: string; keepalive?: boolean } = {}): Promise<void> {\n const emit = this.http.captureChanges();\n const body: EngagementBatch = { session: o.session, snapshots };\n await call(this.http, \"POST\", \"/engagement\", { body, keepalive: o.keepalive });\n emit({ type: \"engagement.changed\", ids: [...new Set(snapshots.map(s => s.content_id))] });\n }\n /** Clicks and explicit feedback; signed out, of the visitor named. */\n signals(signals: SignalInput[], session?: string, o: { keepalive?: boolean } = {}): Promise<void> {\n const body: Signals = { session, signals };\n return call(this.http, \"POST\", \"/signals\", { body, keepalive: o.keepalive });\n }\n /** Result lists served, rendered or shown, for click attribution. */\n exposures(exposures: ExposureInput[], session?: string, o: { keepalive?: boolean } = {}): Promise<void> {\n const body: Exposures = { session, exposures };\n return call(this.http, \"POST\", \"/exposures\", { body, keepalive: o.keepalive });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"discovery.js","names":[],"sources":["../../src/client/discovery.ts"],"sourcesContent":["import type {\n ActivityContexts,\n ActivityContextsInput,\n ActivityTarget,\n ContentFilters,\n ContentFiltersUpdate,\n ContentPage,\n DailyReleases,\n EngagementBatch,\n EngagementSnapshot,\n ExposureInput,\n Exposures,\n RecentSearches,\n ReleaseDates,\n SignalInput,\n Signals,\n Typeahead,\n} from \"./generated/wire.js\";\nimport type { Http } from \"./http.js\";\nimport { call, routeURL } from \"./route.js\";\nimport { browserSearchHistory, type BrowserSearchHistory } from \"./browser-search-history.js\";\n\n/** A popularity period. */\nexport type Period = \"7d\" | \"30d\" | \"90d\" | \"365d\" | \"all\";\n/** A list's order; position orders by the first of `groups` (an ordered group). */\nexport type ListSort = \"newest\" | \"oldest\" | \"title\" | \"popular\" | `popular:${Period}` | \"top_rated\" | `top_rated:${Period}` | \"most_favorited\" | \"position\" | \"random\";\n/** How locked contents list: marked (lock, the default) or left out (hide). */\nexport type AccessMode = \"lock\" | \"hide\";\n\n/** Which contents a list holds. */\nexport interface ContentFilterQuery {\n kind?: string;\n /** Public card hydration under current domain/access/preferences; at most 100. */\n ids?: readonly string[];\n /** Group ids every listed version is in. */\n groups?: readonly string[];\n /** Group ids no listed version is in. */\n exclude_groups?: readonly string[];\n /** Only contents this group owns: a channel's feed. */\n owner_group?: string;\n /** User ids: only contents one of them is credited on. */\n creators?: readonly string[];\n /** public (anyone opens it now) or the level it stays locked at. */\n access?: readonly (\"public\" | \"tier\" | \"group\" | \"ppv\" | \"group_ppv\")[];\n /** Only contents locked behind one of these tiers. */\n tiers?: readonly string[];\n /** Version traits every listed version has. */\n traits?: readonly string[];\n /** \"name:value\" of the kind's filterable attributes. */\n attribute?: readonly string[];\n /** Published on this day (YYYY-MM-DD) or month (YYYY-MM). */\n released_on?: string;\n /** Only contents published within this age window; independent of the popularity score window. */\n published_within?: Period;\n /** IANA time zone of released_on and release dates; UTC by default. */\n tz?: string;\n /** The signed-in reader's unseen, in-progress or completed contents. */\n view_status?: \"unseen\" | \"in_progress\" | \"completed\";\n}\n\n/** How a list reads to its reader. */\nexport interface ReaderQuery {\n /** Only content with a live version in this language. */\n language?: string;\n /** Titles, names and paths in this language, and each card's preferred version's; language by default. */\n display_language?: string;\n mode?: AccessMode;\n}\n\n/** The group kinds cards name; every kind with a page by default. */\nexport interface CardQuery {\n card_entities?: readonly string[];\n}\n\nexport interface PageQuery {\n cursor?: string;\n limit?: number;\n}\n\n/** A numbered page from 1 instead of cursor; its summary then comes with every page. */\nexport interface NumberedPageQuery {\n page?: number;\n}\n\nexport type ContentQuery = ContentFilterQuery & ReaderQuery & CardQuery & PageQuery & NumberedPageQuery & {\n /** Selection-wide metadata; requested only on the first page. */\n summary?: boolean;\n sort?: ListSort;\n /** Inclusive UTC date (YYYY-MM-DD); requires activity_until, kind and sort=popular. */\n activity_from?: string;\n /** Exclusive UTC date (YYYY-MM-DD); requires activity_from, kind and sort=popular. */\n activity_until?: string;\n};\nexport type PopularPeriod = \"7d\" | \"90d\" | \"365d\" | \"all\";\n/** Whole UTC dates: from inclusive, until exclusive. */\nexport interface PopularDateRange {\n from: string;\n until: string;\n}\nexport type PopularQuery = Omit<ContentQuery, \"sort\" | \"activity_from\" | \"activity_until\">;\n\n/** Rank activity in the selected window; publication age is an optional separate filter. */\nexport function popularQuery(period: PopularPeriod | PopularDateRange = \"7d\", filters: PopularQuery = {}): ContentQuery {\n return typeof period === \"string\"\n ? { ...filters, sort: `popular:${period}` }\n : { ...filters, sort: \"popular\", activity_from: period.from, activity_until: period.until };\n}\n\n/** Rank activity between two UTC dates: from inclusive, until exclusive. */\nexport function popularBetween(from: string, until: string, filters: PopularQuery & { kind: string }): ContentQuery {\n return popularQuery({ from, until }, filters);\n}\n\nexport type SearchQuery = ContentFilterQuery &\n ReaderQuery &\n CardQuery &\n PageQuery &\n NumberedPageQuery & {\n q: string;\n sort?: \"relevance\" | ListSort;\n personalize?: boolean;\n summary?: boolean;\n /** Explicit legacy server-side anonymous history. Omit for public search without server history. */\n session?: string;\n };\nexport interface RecentSearchesQuery {\n /** Explicit legacy server-side anonymous history; no anonymous session is created by default. */\n session?: string;\n /** 10 by default, at most 100. */\n limit?: number;\n}\nexport type RailQuery = ContentFilterQuery & ReaderQuery & CardQuery & { limit?: number; summary?: boolean };\nexport type ReleaseDatesQuery = ContentFilterQuery & ReaderQuery & PageQuery & { by?: \"month\" | \"day\" };\n/** Complete daily metadata for one calendar window, without pagination. */\nexport type DailyReleasesQuery = Omit<ContentFilterQuery, \"released_on\" | \"tz\"> & ReaderQuery & CardQuery & {\n days?: number;\n /** Inclusive YYYY-MM-DD in time_zone; today by default. Future dates are rejected. */\n end_date?: string;\n time_zone?: string;\n};\nexport type HistoryQuery = ReaderQuery & CardQuery & PageQuery & { kind?: string; status?: \"seen\" | \"in_progress\" | \"completed\"; summary?: boolean };\nexport interface TypeaheadQuery extends ReaderQuery {\n q: string;\n /** Only contents of this kind. */\n kind?: string;\n /** The group kinds suggested; every kind with a page by default. */\n entity_kinds?: readonly string[];\n /** Per section: 8 by default, at most 20. */\n limit?: number;\n}\n\n/** Private editor navigation. Each requested section must be chosen explicitly. */\nexport interface AdminSuggestionsQuery {\n q: string;\n display_language?: string;\n content_kinds?: readonly string[];\n entity_kinds?: readonly string[];\n include_contents: boolean;\n include_entities: boolean;\n /** Per section: 8 by default, at most 20. */\n limit?: number;\n}\n\n// Comma-joined list parameters; `attribute` repeats instead.\nconst LISTS = new Set([\"ids\", \"groups\", \"exclude_groups\", \"creators\", \"access\", \"tiers\", \"traits\", \"card_entities\", \"entity_kinds\", \"content_kinds\"]);\n\n/** A query with its list parameters comma-joined, as discovery routes read them. */\nexport function query(q: object): Record<string, string | number | boolean | readonly string[] | undefined> {\n const out: Record<string, string | number | boolean | readonly string[] | undefined> = {};\n for (const [k, v] of Object.entries(q)) out[k] = LISTS.has(k) && Array.isArray(v) ? (v.length ? v.join(\",\") : undefined) : v;\n return out;\n}\n\n/**\n * Discovery: lists, search, typeahead, similar and recommended contents,\n * release dates, the reader's content filters and history, signals and exposures.\n */\nexport class DiscoveryClient {\n /** Local anonymous history, isolated from authenticated server history. */\n readonly browserSearches: BrowserSearchHistory;\n\n constructor(private readonly http: Http) {\n this.browserSearches = browserSearchHistory(http.mount(\"discovery\"));\n }\n\n /** Contents as cards, one per content item with the version that fits the reader. */\n list(q: ContentQuery = {}, signal?: AbortSignal): Promise<ContentPage> {\n return call(this.http, \"GET\", \"/contents\", { query: query(q) as never, signal });\n }\n /** A first page is kept among the reader's recent searches. */\n async search(q: SearchQuery, signal?: AbortSignal): Promise<ContentPage> {\n const emit = q.cursor || (q.page ?? 1) > 1 ? null : this.http.captureChanges();\n const out: ContentPage = await call(this.http, \"GET\", \"/search\", { query: query(q) as never, signal });\n emit?.({ type: \"searches.changed\" });\n return out;\n }\n /** The reader's recent searches, newest first, since they last cleared them. */\n recentSearches(q: RecentSearchesQuery = {}, signal?: AbortSignal): Promise<RecentSearches> {\n return call(this.http, \"GET\", \"/me/searches\", { query: q, signal });\n }\n /** Clears one recent search, or all of them. */\n async clearSearches(o: { query?: string; session?: string } = {}): Promise<void> {\n const emit = this.http.captureChanges();\n await call(this.http, \"DELETE\", \"/me/searches\", { query: o });\n emit({ type: \"searches.changed\" });\n }\n /** Contents and groups while the reader types. */\n typeahead(q: TypeaheadQuery, signal?: AbortSignal): Promise<Typeahead> {\n return call(this.http, \"GET\", \"/typeahead\", { query: query(q) as never, signal });\n }\n /** Current names of authorized draft/hidden content and entities; no public search fallback. */\n adminSuggestions(q: AdminSuggestionsQuery, signal?: AbortSignal): Promise<Typeahead> {\n return call(this.http, \"GET\", \"/manage/search-suggestions\", { query: query(q) as never, signal });\n }\n /** Contents like one, of its kind unless q.kind names another. */\n similar(id: string, q: RailQuery = {}, signal?: AbortSignal): Promise<ContentPage> {\n return call(this.http, \"GET\", \"/contents/{id}/similar\", { params: { id }, query: query(q) as never, signal });\n }\n /** For the signed-in reader. */\n recommendations(q: RailQuery = {}, signal?: AbortSignal): Promise<ContentPage> {\n return call(this.http, \"GET\", \"/recommendations\", { query: query(q) as never, signal });\n }\n /** Per month or day, newest first: how many contents the reader's listing shows released then, and how many are free. */\n releaseDates(q: ReleaseDatesQuery = {}, signal?: AbortSignal): Promise<ReleaseDates> {\n return call(this.http, \"GET\", \"/release-dates\", { query: query(q) as never, signal });\n }\n /** Every visible card in each day; opening or expanding a day needs no further request. */\n releases(q: DailyReleasesQuery = {}, signal?: AbortSignal): Promise<DailyReleases> {\n return call(this.http, \"GET\", \"/releases\", { query: query(q) as never, signal });\n }\n /** Only the current domain's reader-toggleable entities, named in the requested language. */\n async contentFilters(language?: string, signal?: AbortSignal): Promise<ContentFilters> {\n const result = await this.http.request<ContentFilters>(routeURL(this.http, \"GET\", \"/content-filters\", { query: { language } }), { signal, guestPreferences: false });\n this.http.acceptGuestFilters(result.filters);\n return result;\n }\n /** Atomically changes submitted shared choices; omitted settings remain intact. */\n async setContentFilters(update: ContentFiltersUpdate, language?: string): Promise<ContentFilters> {\n const emit = this.http.captureChanges();\n const out: ContentFilters = await call(this.http, \"PATCH\", \"/me/content-filters\", { query: { language }, body: update });\n emit({ type: \"contentFilters.changed\" });\n return out;\n }\n /** What the reader engaged with, most recent first. */\n history(q: HistoryQuery = {}, signal?: AbortSignal): Promise<ContentPage> {\n return call(this.http, \"GET\", \"/me/history\", { query: query(q) as never, signal });\n }\n /** Erases the reader's history: of one content item, one kind or everything. */\n async forgetHistory(o: { kind?: string; content_id?: string } = {}): Promise<void> {\n const emit = this.http.captureChanges();\n await call(this.http, \"DELETE\", \"/me/history\", { query: o });\n emit({ type: \"history.changed\" });\n }\n /** Capture server-owned access and eligibility at an observation's start. */\n activityContexts(targets: readonly ActivityTarget[], session?: string, language = this.http.language()): Promise<ActivityContexts> {\n const body: ActivityContextsInput = { targets: [...targets], session, language };\n return call(this.http, \"POST\", \"/activity-contexts\", { body });\n }\n /** Cumulative measured attention. Successful checkpoints refresh history/progress caches. */\n async engagement(snapshots: EngagementSnapshot[], o: { session?: string; keepalive?: boolean } = {}): Promise<void> {\n const emit = this.http.captureChanges();\n const body: EngagementBatch = { session: o.session, snapshots };\n await call(this.http, \"POST\", \"/engagement\", { body, keepalive: o.keepalive });\n emit({ type: \"engagement.changed\", ids: [...new Set(snapshots.map(s => s.content_id))] });\n }\n /** Clicks and explicit feedback; signed out, of the visitor named. */\n signals(signals: SignalInput[], session?: string, o: { keepalive?: boolean } = {}): Promise<void> {\n const body: Signals = { session, signals };\n return call(this.http, \"POST\", \"/signals\", { body, keepalive: o.keepalive });\n }\n /** Result lists served, rendered or shown, for click attribution. */\n exposures(exposures: ExposureInput[], session?: string, o: { keepalive?: boolean } = {}): Promise<void> {\n const body: Exposures = { session, exposures };\n return call(this.http, \"POST\", \"/exposures\", { body, keepalive: o.keepalive });\n }\n}\n"],"mappings":"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"}
|
|
@@ -905,7 +905,7 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
905
905
|
readonly path: "/manage";
|
|
906
906
|
readonly auth: "public";
|
|
907
907
|
readonly permission: null;
|
|
908
|
-
readonly query: readonly ["state", "owner_group", "q", "language", "limit", "offset"];
|
|
908
|
+
readonly query: readonly ["state", "owner_group", "access", "tier", "q", "code", "ids", "language", "limit", "offset"];
|
|
909
909
|
readonly request: null;
|
|
910
910
|
readonly responses: {
|
|
911
911
|
readonly 200: "Content[]";
|
|
@@ -918,13 +918,26 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
918
918
|
readonly path: "/manage/{kind}";
|
|
919
919
|
readonly auth: "public";
|
|
920
920
|
readonly permission: null;
|
|
921
|
-
readonly query: readonly ["state", "owner_group", "q", "language", "limit", "offset"];
|
|
921
|
+
readonly query: readonly ["state", "owner_group", "access", "tier", "q", "code", "ids", "language", "limit", "offset"];
|
|
922
922
|
readonly request: null;
|
|
923
923
|
readonly responses: {
|
|
924
924
|
readonly 200: "Content[]";
|
|
925
925
|
};
|
|
926
926
|
readonly errors: readonly ["not_found"];
|
|
927
927
|
readonly errorSets: readonly ["module:contents", "auth", "request"];
|
|
928
|
+
}, {
|
|
929
|
+
readonly method: "GET";
|
|
930
|
+
readonly module: "contents";
|
|
931
|
+
readonly path: "/manage/{kind}/count";
|
|
932
|
+
readonly auth: "public";
|
|
933
|
+
readonly permission: null;
|
|
934
|
+
readonly query: readonly ["state", "owner_group", "access", "tier", "q"];
|
|
935
|
+
readonly request: null;
|
|
936
|
+
readonly responses: {
|
|
937
|
+
readonly 200: "ManageCount";
|
|
938
|
+
};
|
|
939
|
+
readonly errors: readonly ["not_found"];
|
|
940
|
+
readonly errorSets: readonly ["module:contents", "auth", "request"];
|
|
928
941
|
}, {
|
|
929
942
|
readonly method: "POST";
|
|
930
943
|
readonly module: "contents";
|
|
@@ -1295,7 +1308,7 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
1295
1308
|
readonly method: "GET";
|
|
1296
1309
|
readonly module: "codes";
|
|
1297
1310
|
readonly path: "/{code}";
|
|
1298
|
-
readonly auth: "
|
|
1311
|
+
readonly auth: "public";
|
|
1299
1312
|
readonly permission: null;
|
|
1300
1313
|
readonly query: readonly ["lang", "v"];
|
|
1301
1314
|
readonly request: null;
|
|
@@ -1303,7 +1316,7 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
1303
1316
|
readonly 200: "Resolved";
|
|
1304
1317
|
};
|
|
1305
1318
|
readonly errors: readonly ["gone", "not_found"];
|
|
1306
|
-
readonly errorSets: readonly ["module:codes", "request"];
|
|
1319
|
+
readonly errorSets: readonly ["module:codes", "auth", "request"];
|
|
1307
1320
|
}, {
|
|
1308
1321
|
readonly method: "POST";
|
|
1309
1322
|
readonly module: "codes";
|
|
@@ -1323,7 +1336,7 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
1323
1336
|
readonly path: "/entities";
|
|
1324
1337
|
readonly auth: "public";
|
|
1325
1338
|
readonly permission: null;
|
|
1326
|
-
readonly query: readonly ["kind", "parent", "scope", "slug", "letter", "language", "content_kind", "sort", "cursor", "limit"];
|
|
1339
|
+
readonly query: readonly ["kind", "parent", "scope", "slug", "letter", "language", "content_kind", "sort", "cursor", "page", "limit"];
|
|
1327
1340
|
readonly request: null;
|
|
1328
1341
|
readonly responses: {
|
|
1329
1342
|
readonly 200: "GroupPage";
|
|
@@ -1349,7 +1362,7 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
1349
1362
|
readonly path: "/manage/entities";
|
|
1350
1363
|
readonly auth: "staff";
|
|
1351
1364
|
readonly permission: "root:entities:write";
|
|
1352
|
-
readonly query: readonly ["kind", "parent", "scope", "slug", "q", "letter", "language", "content_kind", "sort", "cursor", "limit"];
|
|
1365
|
+
readonly query: readonly ["state", "kind", "parent", "scope", "slug", "q", "letter", "language", "content_kind", "sort", "cursor", "limit"];
|
|
1353
1366
|
readonly request: null;
|
|
1354
1367
|
readonly responses: {
|
|
1355
1368
|
readonly 200: "GroupPage";
|
|
@@ -1658,28 +1671,41 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
1658
1671
|
}, {
|
|
1659
1672
|
readonly method: "GET";
|
|
1660
1673
|
readonly module: "versions";
|
|
1661
|
-
readonly path: "/contents/{id}/versions/{version}/
|
|
1674
|
+
readonly path: "/contents/{id}/versions/{version}/page-notices";
|
|
1662
1675
|
readonly auth: "editor";
|
|
1663
1676
|
readonly permission: "root:content:write";
|
|
1664
1677
|
readonly query: readonly [];
|
|
1665
1678
|
readonly request: null;
|
|
1666
1679
|
readonly responses: {
|
|
1667
|
-
readonly 200: "
|
|
1680
|
+
readonly 200: "PageNotices";
|
|
1668
1681
|
};
|
|
1669
1682
|
readonly errors: readonly ["not_found", "forbidden"];
|
|
1670
1683
|
readonly errorSets: readonly ["module:versions", "auth", "request"];
|
|
1671
1684
|
}, {
|
|
1672
|
-
readonly method: "
|
|
1685
|
+
readonly method: "POST";
|
|
1686
|
+
readonly module: "versions";
|
|
1687
|
+
readonly path: "/contents/{id}/versions/{version}/page-notices/{notice}/dismiss";
|
|
1688
|
+
readonly auth: "editor";
|
|
1689
|
+
readonly permission: "root:content:write";
|
|
1690
|
+
readonly query: readonly [];
|
|
1691
|
+
readonly request: null;
|
|
1692
|
+
readonly responses: {
|
|
1693
|
+
readonly 204: null;
|
|
1694
|
+
};
|
|
1695
|
+
readonly errors: readonly ["not_found", "forbidden"];
|
|
1696
|
+
readonly errorSets: readonly ["module:versions", "auth", "request"];
|
|
1697
|
+
}, {
|
|
1698
|
+
readonly method: "POST";
|
|
1673
1699
|
readonly module: "versions";
|
|
1674
|
-
readonly path: "/contents/{id}/versions/{version}/
|
|
1700
|
+
readonly path: "/contents/{id}/versions/{version}/page-notices/{notice}/restore";
|
|
1675
1701
|
readonly auth: "editor";
|
|
1676
1702
|
readonly permission: "root:content:write";
|
|
1677
1703
|
readonly query: readonly [];
|
|
1678
|
-
readonly request:
|
|
1704
|
+
readonly request: null;
|
|
1679
1705
|
readonly responses: {
|
|
1680
|
-
readonly 200: "
|
|
1706
|
+
readonly 200: "PageNotices";
|
|
1681
1707
|
};
|
|
1682
|
-
readonly errors: readonly ["
|
|
1708
|
+
readonly errors: readonly ["invalid_request", "not_found", "forbidden"];
|
|
1683
1709
|
readonly errorSets: readonly ["module:versions", "auth", "request"];
|
|
1684
1710
|
}, {
|
|
1685
1711
|
readonly method: "GET";
|
|
@@ -1923,7 +1949,7 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
1923
1949
|
readonly path: "/contents";
|
|
1924
1950
|
readonly auth: "public";
|
|
1925
1951
|
readonly permission: null;
|
|
1926
|
-
readonly query: readonly ["kind", "ids", "groups", "exclude_groups", "owner_group", "creators", "access", "tiers", "traits", "attribute", "released_on", "published_within", "tz", "view_status", "language", "display_language", "mode", "sort", "card_entities", "summary", "activity_from", "activity_until", "cursor", "limit"];
|
|
1952
|
+
readonly query: readonly ["kind", "ids", "groups", "exclude_groups", "owner_group", "creators", "access", "tiers", "traits", "attribute", "released_on", "published_within", "tz", "view_status", "language", "display_language", "mode", "sort", "card_entities", "summary", "activity_from", "activity_until", "cursor", "limit", "page"];
|
|
1927
1953
|
readonly request: null;
|
|
1928
1954
|
readonly responses: {
|
|
1929
1955
|
readonly 200: "ContentPage";
|
|
@@ -1936,7 +1962,7 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
1936
1962
|
readonly path: "/search";
|
|
1937
1963
|
readonly auth: "public";
|
|
1938
1964
|
readonly permission: null;
|
|
1939
|
-
readonly query: readonly ["q", "kind", "ids", "groups", "exclude_groups", "owner_group", "creators", "access", "tiers", "traits", "attribute", "released_on", "published_within", "tz", "view_status", "language", "display_language", "mode", "sort", "card_entities", "summary", "personalize", "session", "cursor", "limit"];
|
|
1965
|
+
readonly query: readonly ["q", "kind", "ids", "groups", "exclude_groups", "owner_group", "creators", "access", "tiers", "traits", "attribute", "released_on", "published_within", "tz", "view_status", "language", "display_language", "mode", "sort", "card_entities", "summary", "personalize", "session", "cursor", "limit", "page"];
|
|
1940
1966
|
readonly request: null;
|
|
1941
1967
|
readonly responses: {
|
|
1942
1968
|
readonly 200: "ContentPage";
|
|
@@ -2177,19 +2203,6 @@ export declare const CONTENTKIT_ROUTES: readonly [{
|
|
|
2177
2203
|
};
|
|
2178
2204
|
readonly errors: readonly ["not_configured"];
|
|
2179
2205
|
readonly errorSets: readonly ["module:discovery", "auth", "request"];
|
|
2180
|
-
}, {
|
|
2181
|
-
readonly method: "GET";
|
|
2182
|
-
readonly module: "discovery";
|
|
2183
|
-
readonly path: "/stats/top";
|
|
2184
|
-
readonly auth: "staff";
|
|
2185
|
-
readonly permission: "root:content:view-restricted";
|
|
2186
|
-
readonly query: readonly ["kind", "metric", "period", "access", "tiers", "language", "limit"];
|
|
2187
|
-
readonly request: null;
|
|
2188
|
-
readonly responses: {
|
|
2189
|
-
readonly 200: "TopContents";
|
|
2190
|
-
};
|
|
2191
|
-
readonly errors: readonly ["not_configured"];
|
|
2192
|
-
readonly errorSets: readonly ["module:discovery", "auth", "request"];
|
|
2193
2206
|
}, {
|
|
2194
2207
|
readonly method: "GET";
|
|
2195
2208
|
readonly module: "discovery";
|