@growth-labs/cms 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,493 @@
1
+ export const READER_AUTOMATIC_COMPLETION_BPS = 9_000;
2
+ export const DEFAULT_READER_STATE_BATCH_SIZE = 50;
3
+ export const MAX_READER_STATE_BATCH_SIZE = 100;
4
+ const UUIDV4_PATTERN = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;
5
+ const ULID_PATTERN = /^[0-9A-HJKMNP-TV-Z]{26}$/;
6
+ const SITE_ID_PATTERN = /^[a-z][a-z0-9_-]{1,63}$/;
7
+ const CONTENT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,127}$/;
8
+ const MUTATION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,127}$/;
9
+ const PREFERENCE_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9._:-]{0,63}$/;
10
+ const CONTENT_TYPES = new Set(['article', 'video', 'podcast', 'newsletter', 'page']);
11
+ const MAX_PREFERENCE_KEYS = 50;
12
+ const MAX_PREFERENCES_JSON_BYTES = 8_192;
13
+ const MAX_EVENT_FUTURE_SKEW_MS = 5 * 60 * 1_000;
14
+ export class ReaderStateInputError extends Error {
15
+ constructor(message) {
16
+ super(message);
17
+ this.name = 'ReaderStateInputError';
18
+ }
19
+ }
20
+ export class ReaderStateConflictError extends Error {
21
+ expectedVersion;
22
+ actualVersion;
23
+ constructor(expectedVersion, actualVersion) {
24
+ super(`@growth-labs/cms reader state version conflict: expected ${expectedVersion}, actual ${actualVersion ?? 'missing'}`);
25
+ this.expectedVersion = expectedVersion;
26
+ this.actualVersion = actualVersion;
27
+ this.name = 'ReaderStateConflictError';
28
+ }
29
+ }
30
+ export class ReaderStateDurableStateError extends Error {
31
+ constructor(message) {
32
+ super(message);
33
+ this.name = 'ReaderStateDurableStateError';
34
+ }
35
+ }
36
+ export async function getReaderState(db, scope, key) {
37
+ const resolvedScope = resolveScope(scope);
38
+ const resolvedKey = resolveContentKey(key);
39
+ return loadReaderState(db, resolvedScope, resolvedKey);
40
+ }
41
+ /** Unlock is intentionally a read-only observation: it never creates or completes state. */
42
+ export async function recordReaderUnlock(db, scope, key) {
43
+ return getReaderState(db, scope, key);
44
+ }
45
+ export async function recordReaderOpen(db, scope, key, options) {
46
+ const resolvedScope = resolveScope(scope);
47
+ const resolvedKey = resolveContentKey(key);
48
+ if (resolveBehavioralConsent(options) === 'denied') {
49
+ return {
50
+ applied: false,
51
+ reason: 'consent_denied',
52
+ state: await loadReaderState(db, resolvedScope, resolvedKey),
53
+ };
54
+ }
55
+ const mutation = resolveMutation(options);
56
+ const { occurredAt, expectedVersion } = mutation;
57
+ return executeMutation(db, resolvedScope, resolvedKey, occurredAt, expectedVersion, db
58
+ .prepare(`UPDATE cms_reader_state
59
+ SET first_opened_at = CASE
60
+ WHEN first_opened_at IS NULL OR first_opened_at > ? THEN ?
61
+ ELSE first_opened_at END,
62
+ last_opened_at = CASE
63
+ WHEN last_opened_at IS NULL OR last_opened_at < ? THEN ?
64
+ ELSE last_opened_at END,
65
+ version = version + 1,
66
+ updated_at = CASE WHEN updated_at < ? THEN ? ELSE updated_at END
67
+ WHERE identity_user_id = ? AND site_id = ? AND content_type = ? AND content_id = ?
68
+ AND (? IS NULL OR version = ?)
69
+ AND (first_opened_at IS NULL OR first_opened_at > ?
70
+ OR last_opened_at IS NULL OR last_opened_at < ?)
71
+ RETURNING *`)
72
+ .bind(occurredAt, occurredAt, occurredAt, occurredAt, occurredAt, occurredAt, resolvedScope.identityUserId, resolvedScope.siteId, resolvedKey.contentType, resolvedKey.contentId, expectedVersion ?? null, expectedVersion ?? null, occurredAt, occurredAt));
73
+ }
74
+ export async function recordReaderProgress(db, scope, key, options) {
75
+ const resolvedScope = resolveScope(scope);
76
+ const resolvedKey = resolveContentKey(key);
77
+ if (resolveBehavioralConsent(options) === 'denied') {
78
+ return {
79
+ applied: false,
80
+ reason: 'consent_denied',
81
+ state: await loadReaderState(db, resolvedScope, resolvedKey),
82
+ };
83
+ }
84
+ const mutation = resolveMutation(options);
85
+ const progress = assertBasisPoints(options.progressBasisPoints);
86
+ const mediaPositionMs = optionalNonNegativeInteger(options.mediaPositionMs, 'mediaPositionMs');
87
+ const mediaDurationMs = optionalNonNegativeInteger(options.mediaDurationMs, 'mediaDurationMs');
88
+ if (mediaPositionMs !== undefined &&
89
+ mediaDurationMs !== undefined &&
90
+ mediaPositionMs > mediaDurationMs) {
91
+ throw new ReaderStateInputError('reader mediaPositionMs cannot exceed mediaDurationMs');
92
+ }
93
+ const { occurredAt, expectedVersion } = mutation;
94
+ return executeMutation(db, resolvedScope, resolvedKey, occurredAt, expectedVersion, db
95
+ .prepare(`UPDATE cms_reader_state
96
+ SET max_progress_bps = CASE
97
+ WHEN max_progress_bps < ? THEN ? ELSE max_progress_bps END,
98
+ media_position_ms = CASE
99
+ WHEN ? IS NOT NULL AND (progress_observed_at IS NULL OR progress_observed_at < ?)
100
+ THEN ? ELSE media_position_ms END,
101
+ media_duration_ms = CASE
102
+ WHEN ? IS NOT NULL AND (progress_observed_at IS NULL OR progress_observed_at < ?)
103
+ THEN ? ELSE media_duration_ms END,
104
+ progress_observed_at = CASE
105
+ WHEN progress_observed_at IS NULL OR progress_observed_at < ? THEN ?
106
+ ELSE progress_observed_at END,
107
+ automatic_completed_at = CASE
108
+ WHEN automatic_completed_at IS NULL
109
+ AND MAX(max_progress_bps, ?) >= ${READER_AUTOMATIC_COMPLETION_BPS}
110
+ THEN ? ELSE automatic_completed_at END,
111
+ version = version + 1,
112
+ updated_at = CASE WHEN updated_at < ? THEN ? ELSE updated_at END
113
+ WHERE identity_user_id = ? AND site_id = ? AND content_type = ? AND content_id = ?
114
+ AND (? IS NULL OR version = ?)
115
+ AND (max_progress_bps < ?
116
+ OR progress_observed_at IS NULL OR progress_observed_at < ?
117
+ OR (automatic_completed_at IS NULL AND ? >= ${READER_AUTOMATIC_COMPLETION_BPS}))
118
+ RETURNING *`)
119
+ .bind(progress, progress, mediaPositionMs ?? null, occurredAt, mediaPositionMs ?? null, mediaDurationMs ?? null, occurredAt, mediaDurationMs ?? null, occurredAt, occurredAt, progress, occurredAt, occurredAt, occurredAt, resolvedScope.identityUserId, resolvedScope.siteId, resolvedKey.contentType, resolvedKey.contentId, expectedVersion ?? null, expectedVersion ?? null, progress, occurredAt, progress));
120
+ }
121
+ export async function setManualReadState(db, scope, key, options) {
122
+ if (options?.state !== 'read' && options?.state !== 'unread') {
123
+ throw new ReaderStateInputError('manual reader state must be "read" or "unread"');
124
+ }
125
+ return writeManualState(db, scope, key, options.state, options);
126
+ }
127
+ export async function clearManualReadState(db, scope, key, options) {
128
+ return writeManualState(db, scope, key, null, options);
129
+ }
130
+ async function writeManualState(db, scope, key, state, options) {
131
+ const resolvedScope = resolveScope(scope);
132
+ const resolvedKey = resolveContentKey(key);
133
+ const mutation = resolveExplicitMutation(options);
134
+ return executeMutation(db, resolvedScope, resolvedKey, mutation.occurredAt, mutation.expectedVersion, db
135
+ .prepare(`UPDATE cms_reader_state
136
+ SET manual_read_state = ?, manual_state_at = ?, manual_mutation_id = ?,
137
+ version = version + 1,
138
+ updated_at = CASE WHEN updated_at < ? THEN ? ELSE updated_at END
139
+ WHERE identity_user_id = ? AND site_id = ? AND content_type = ? AND content_id = ?
140
+ AND (? IS NULL OR version = ?)
141
+ AND (manual_state_at IS NULL OR manual_state_at < ?
142
+ OR (manual_state_at = ? AND COALESCE(manual_mutation_id, '') < ?))
143
+ RETURNING *`)
144
+ .bind(state, mutation.occurredAt, options.mutationId, mutation.occurredAt, mutation.occurredAt, resolvedScope.identityUserId, resolvedScope.siteId, resolvedKey.contentType, resolvedKey.contentId, mutation.expectedVersion ?? null, mutation.expectedVersion ?? null, mutation.occurredAt, mutation.occurredAt, options.mutationId));
145
+ }
146
+ export async function setSavedState(db, scope, key, options) {
147
+ if (typeof options?.saved !== 'boolean') {
148
+ throw new ReaderStateInputError('saved reader state must be a boolean');
149
+ }
150
+ const resolvedScope = resolveScope(scope);
151
+ const resolvedKey = resolveContentKey(key);
152
+ const mutation = resolveExplicitMutation(options);
153
+ return executeMutation(db, resolvedScope, resolvedKey, mutation.occurredAt, mutation.expectedVersion, db
154
+ .prepare(`UPDATE cms_reader_state
155
+ SET saved = ?, saved_at = ?, saved_mutation_id = ?,
156
+ version = version + 1,
157
+ updated_at = CASE WHEN updated_at < ? THEN ? ELSE updated_at END
158
+ WHERE identity_user_id = ? AND site_id = ? AND content_type = ? AND content_id = ?
159
+ AND (? IS NULL OR version = ?)
160
+ AND (saved_at IS NULL OR saved_at < ?
161
+ OR (saved_at = ? AND COALESCE(saved_mutation_id, '') < ?))
162
+ RETURNING *`)
163
+ .bind(options.saved ? 1 : 0, mutation.occurredAt, options.mutationId, mutation.occurredAt, mutation.occurredAt, resolvedScope.identityUserId, resolvedScope.siteId, resolvedKey.contentType, resolvedKey.contentId, mutation.expectedVersion ?? null, mutation.expectedVersion ?? null, mutation.occurredAt, mutation.occurredAt, options.mutationId));
164
+ }
165
+ export async function setReaderPreferences(db, scope, key, options) {
166
+ const preferences = normalizePreferences(options?.preferences);
167
+ const resolvedScope = resolveScope(scope);
168
+ const resolvedKey = resolveContentKey(key);
169
+ const mutation = resolveExplicitMutation(options);
170
+ const preferencesJson = JSON.stringify(preferences);
171
+ return executeMutation(db, resolvedScope, resolvedKey, mutation.occurredAt, mutation.expectedVersion, db
172
+ .prepare(`UPDATE cms_reader_state
173
+ SET preferences_json = ?, preferences_at = ?, preferences_mutation_id = ?,
174
+ version = version + 1,
175
+ updated_at = CASE WHEN updated_at < ? THEN ? ELSE updated_at END
176
+ WHERE identity_user_id = ? AND site_id = ? AND content_type = ? AND content_id = ?
177
+ AND (? IS NULL OR version = ?)
178
+ AND (preferences_at IS NULL OR preferences_at < ?
179
+ OR (preferences_at = ? AND COALESCE(preferences_mutation_id, '') < ?))
180
+ RETURNING *`)
181
+ .bind(preferencesJson, mutation.occurredAt, options.mutationId, mutation.occurredAt, mutation.occurredAt, resolvedScope.identityUserId, resolvedScope.siteId, resolvedKey.contentType, resolvedKey.contentId, mutation.expectedVersion ?? null, mutation.expectedVersion ?? null, mutation.occurredAt, mutation.occurredAt, options.mutationId));
182
+ }
183
+ export async function getReaderStateBatch(db, scope, keys) {
184
+ const resolvedScope = resolveScope(scope);
185
+ if (!Array.isArray(keys)) {
186
+ throw new ReaderStateInputError('reader state batch keys must be an array');
187
+ }
188
+ if (keys.length > MAX_READER_STATE_BATCH_SIZE) {
189
+ throw new ReaderStateInputError(`reader state batches are limited to ${MAX_READER_STATE_BATCH_SIZE} declared content IDs`);
190
+ }
191
+ if (keys.length === 0)
192
+ return [];
193
+ const resolvedKeys = keys.map(resolveContentKey);
194
+ const declared = resolvedKeys.map(() => '(content_type = ? AND content_id = ?)').join(' OR ');
195
+ const statement = db.prepare(`SELECT * FROM cms_reader_state
196
+ WHERE identity_user_id = ? AND site_id = ? AND (${declared})
197
+ ORDER BY content_type, content_id`);
198
+ const bindings = [resolvedScope.identityUserId, resolvedScope.siteId];
199
+ for (const key of resolvedKeys)
200
+ bindings.push(key.contentType, key.contentId);
201
+ const result = await statement.bind(...bindings).all();
202
+ return (result.results ?? []).map(decodeReaderStateRow);
203
+ }
204
+ export async function listReaderState(db, scope, options = {}) {
205
+ const resolvedScope = resolveScope(scope);
206
+ return readReaderStatePage(db, resolvedScope, options, 'updated');
207
+ }
208
+ async function readReaderStatePage(db, scope, options, order) {
209
+ const limit = resolveLimit(options.limit);
210
+ const cursor = options.cursor ? decodeCursor(options.cursor, order) : null;
211
+ const orderColumn = order === 'updated' ? 'updated_at' : 'created_at';
212
+ let statement;
213
+ if (cursor) {
214
+ statement = db
215
+ .prepare(`SELECT * FROM cms_reader_state
216
+ WHERE identity_user_id = ? AND site_id = ?
217
+ AND (${orderColumn} < ?
218
+ OR (${orderColumn} = ? AND content_type > ?)
219
+ OR (${orderColumn} = ? AND content_type = ? AND content_id > ?))
220
+ ORDER BY ${orderColumn} DESC, content_type, content_id
221
+ LIMIT ?`)
222
+ .bind(scope.identityUserId, scope.siteId, cursor.orderedAt, cursor.orderedAt, cursor.contentType, cursor.orderedAt, cursor.contentType, cursor.contentId, limit + 1);
223
+ }
224
+ else {
225
+ statement = db
226
+ .prepare(`SELECT * FROM cms_reader_state
227
+ WHERE identity_user_id = ? AND site_id = ?
228
+ ORDER BY ${orderColumn} DESC, content_type, content_id
229
+ LIMIT ?`)
230
+ .bind(scope.identityUserId, scope.siteId, limit + 1);
231
+ }
232
+ const result = await statement.all();
233
+ const decoded = (result.results ?? []).map(decodeReaderStateRow);
234
+ const hasMore = decoded.length > limit;
235
+ const items = hasMore ? decoded.slice(0, limit) : decoded;
236
+ const last = items.at(-1);
237
+ return {
238
+ items,
239
+ nextCursor: hasMore && last ? encodeCursor(last, order) : null,
240
+ };
241
+ }
242
+ export async function exportReaderStatePage(db, scope, options = {}) {
243
+ const resolvedScope = resolveScope(scope);
244
+ const page = await readReaderStatePage(db, resolvedScope, options, 'created');
245
+ return {
246
+ ...page,
247
+ scope: resolvedScope,
248
+ exportedAt: Date.now(),
249
+ };
250
+ }
251
+ /**
252
+ * Consent-withdrawal/privacy clear: remove behavioral history while retaining
253
+ * explicit read/unread, save, and stated preference choices.
254
+ */
255
+ export async function clearReaderHistory(db, scope) {
256
+ const resolvedScope = resolveScope(scope);
257
+ const now = Date.now();
258
+ const result = await db
259
+ .prepare(`UPDATE cms_reader_state
260
+ SET first_opened_at = NULL, last_opened_at = NULL,
261
+ max_progress_bps = 0, media_position_ms = NULL, media_duration_ms = NULL,
262
+ progress_observed_at = NULL, automatic_completed_at = NULL,
263
+ version = version + 1, updated_at = ?
264
+ WHERE identity_user_id = ? AND site_id = ?
265
+ AND (first_opened_at IS NOT NULL OR last_opened_at IS NOT NULL
266
+ OR max_progress_bps <> 0 OR media_position_ms IS NOT NULL
267
+ OR media_duration_ms IS NOT NULL OR progress_observed_at IS NOT NULL
268
+ OR automatic_completed_at IS NOT NULL)`)
269
+ .bind(now, resolvedScope.identityUserId, resolvedScope.siteId)
270
+ .run();
271
+ return resultChanges(result);
272
+ }
273
+ /** Delete every row for exactly one verified user/site scope. */
274
+ export async function deleteReaderState(db, scope) {
275
+ const resolvedScope = resolveScope(scope);
276
+ const result = await db
277
+ .prepare('DELETE FROM cms_reader_state WHERE identity_user_id = ? AND site_id = ?')
278
+ .bind(resolvedScope.identityUserId, resolvedScope.siteId)
279
+ .run();
280
+ return resultChanges(result);
281
+ }
282
+ async function executeMutation(db, scope, key, occurredAt, expectedVersion, update) {
283
+ const expected = expectedVersion ?? null;
284
+ const ensure = db
285
+ .prepare(`INSERT OR IGNORE INTO cms_reader_state
286
+ (identity_user_id, site_id, content_type, content_id, created_at, updated_at)
287
+ SELECT ?, ?, ?, ?, ?, ?
288
+ WHERE ? IS NULL OR ? = 0`)
289
+ .bind(scope.identityUserId, scope.siteId, key.contentType, key.contentId, occurredAt, occurredAt, expected, expected);
290
+ const [, updateResult] = await db.batch([ensure, update]);
291
+ const returnedRow = updateResult?.results?.[0];
292
+ if (returnedRow) {
293
+ return { applied: true, reason: 'applied', state: decodeReaderStateRow(returnedRow) };
294
+ }
295
+ if (resultChanges(updateResult) > 0) {
296
+ throw new ReaderStateDurableStateError('reader state mutation changed a row without returning its atomic state');
297
+ }
298
+ const state = await loadReaderState(db, scope, key);
299
+ if (!state) {
300
+ if (expectedVersion !== undefined) {
301
+ throw new ReaderStateConflictError(expectedVersion, null);
302
+ }
303
+ throw new ReaderStateDurableStateError('reader state mutation did not produce a durable row');
304
+ }
305
+ if (expectedVersion !== undefined && state.version !== expectedVersion) {
306
+ throw new ReaderStateConflictError(expectedVersion, state.version);
307
+ }
308
+ return { applied: false, reason: 'stale', state };
309
+ }
310
+ async function loadReaderState(db, scope, key) {
311
+ const row = await db
312
+ .prepare(`SELECT * FROM cms_reader_state
313
+ WHERE identity_user_id = ? AND site_id = ? AND content_type = ? AND content_id = ?`)
314
+ .bind(scope.identityUserId, scope.siteId, key.contentType, key.contentId)
315
+ .first();
316
+ return row ? decodeReaderStateRow(row) : null;
317
+ }
318
+ function decodeReaderStateRow(row) {
319
+ let preferences;
320
+ try {
321
+ preferences = normalizePreferences(JSON.parse(row.preferences_json));
322
+ }
323
+ catch (error) {
324
+ const detail = error instanceof Error ? `: ${error.message}` : '';
325
+ throw new ReaderStateDurableStateError(`reader state contains unreadable preferences${detail}`);
326
+ }
327
+ return {
328
+ identityUserId: row.identity_user_id,
329
+ siteId: row.site_id,
330
+ contentType: row.content_type,
331
+ contentId: row.content_id,
332
+ firstOpenedAt: row.first_opened_at,
333
+ lastOpenedAt: row.last_opened_at,
334
+ maxProgressBasisPoints: row.max_progress_bps,
335
+ mediaPositionMs: row.media_position_ms,
336
+ mediaDurationMs: row.media_duration_ms,
337
+ progressObservedAt: row.progress_observed_at,
338
+ automaticCompletedAt: row.automatic_completed_at,
339
+ manualReadState: row.manual_read_state,
340
+ manualStateAt: row.manual_state_at,
341
+ saved: row.saved === 1,
342
+ savedAt: row.saved_at,
343
+ preferences,
344
+ preferencesAt: row.preferences_at,
345
+ version: row.version,
346
+ effectiveRead: row.manual_read_state === 'read' ||
347
+ (row.manual_read_state === null && row.automatic_completed_at !== null),
348
+ createdAt: row.created_at,
349
+ updatedAt: row.updated_at,
350
+ };
351
+ }
352
+ function resolveScope(scope) {
353
+ if (!scope || typeof scope !== 'object') {
354
+ throw new ReaderStateInputError('reader state requires a verified scope');
355
+ }
356
+ const identityUserId = scope.identityUserId;
357
+ if (typeof identityUserId !== 'string' ||
358
+ !(UUIDV4_PATTERN.test(identityUserId) || ULID_PATTERN.test(identityUserId))) {
359
+ throw new ReaderStateInputError('reader state requires a verified raw realm user id, never an analytics, local, email, or prefixed subject identifier');
360
+ }
361
+ if (typeof scope.siteId !== 'string' || !SITE_ID_PATTERN.test(scope.siteId)) {
362
+ throw new ReaderStateInputError('reader state requires a verified stable lowercase site id such as "fronts"');
363
+ }
364
+ return {
365
+ identityUserId: UUIDV4_PATTERN.test(identityUserId)
366
+ ? identityUserId.toLowerCase()
367
+ : identityUserId,
368
+ siteId: scope.siteId,
369
+ };
370
+ }
371
+ function resolveContentKey(key) {
372
+ if (!key || typeof key !== 'object' || !CONTENT_TYPES.has(key.contentType)) {
373
+ throw new ReaderStateInputError('reader state requires a supported CMS content type');
374
+ }
375
+ if (typeof key.contentId !== 'string' || !CONTENT_ID_PATTERN.test(key.contentId)) {
376
+ throw new ReaderStateInputError('reader state requires a stable CMS content id using URL-safe identifier characters');
377
+ }
378
+ return { contentType: key.contentType, contentId: key.contentId };
379
+ }
380
+ function resolveBehavioralConsent(options) {
381
+ if (!options || typeof options !== 'object') {
382
+ throw new ReaderStateInputError('reader behavioral writes require explicit consent state');
383
+ }
384
+ if (options.behavioralConsent !== 'granted' && options.behavioralConsent !== 'denied') {
385
+ throw new ReaderStateInputError('behavioralConsent must be "granted" or "denied"');
386
+ }
387
+ return options.behavioralConsent;
388
+ }
389
+ function resolveExplicitMutation(options) {
390
+ if (!options || typeof options !== 'object') {
391
+ throw new ReaderStateInputError('explicit reader state writes require mutation options');
392
+ }
393
+ if (typeof options.mutationId !== 'string' || !MUTATION_ID_PATTERN.test(options.mutationId)) {
394
+ throw new ReaderStateInputError('explicit reader state writes require a stable mutationId');
395
+ }
396
+ return resolveMutation(options);
397
+ }
398
+ function resolveMutation(options) {
399
+ const occurredAt = options.occurredAt ?? Date.now();
400
+ if (!Number.isSafeInteger(occurredAt) || occurredAt < 0) {
401
+ throw new ReaderStateInputError('reader state occurredAt must be a non-negative epoch millisecond');
402
+ }
403
+ if (occurredAt > Date.now() + MAX_EVENT_FUTURE_SKEW_MS) {
404
+ throw new ReaderStateInputError('reader state occurredAt exceeds the allowed five-minute clock skew');
405
+ }
406
+ if (options.expectedVersion !== undefined &&
407
+ (!Number.isSafeInteger(options.expectedVersion) || options.expectedVersion < 0)) {
408
+ throw new ReaderStateInputError('reader state expectedVersion must be a non-negative integer');
409
+ }
410
+ return { occurredAt, expectedVersion: options.expectedVersion };
411
+ }
412
+ function assertBasisPoints(value) {
413
+ if (!Number.isInteger(value) || value < 0 || value > 10_000) {
414
+ throw new ReaderStateInputError('reader progress must be an integer from 0 through 10000');
415
+ }
416
+ return value;
417
+ }
418
+ function optionalNonNegativeInteger(value, name) {
419
+ if (value === undefined)
420
+ return undefined;
421
+ if (!Number.isSafeInteger(value) || value < 0) {
422
+ throw new ReaderStateInputError(`reader ${name} must be a non-negative integer`);
423
+ }
424
+ return value;
425
+ }
426
+ function normalizePreferences(value) {
427
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
428
+ throw new ReaderStateInputError('reader preferences must be a plain object of stated values');
429
+ }
430
+ const prototype = Object.getPrototypeOf(value);
431
+ if (prototype !== Object.prototype && prototype !== null) {
432
+ throw new ReaderStateInputError('reader preferences must be a plain object');
433
+ }
434
+ const entries = Object.entries(value);
435
+ if (entries.length > MAX_PREFERENCE_KEYS) {
436
+ throw new ReaderStateInputError(`reader preferences are limited to ${MAX_PREFERENCE_KEYS} keys`);
437
+ }
438
+ const normalized = Object.create(null);
439
+ for (const [key, preference] of entries.sort(([a], [b]) => a.localeCompare(b))) {
440
+ if (!PREFERENCE_KEY_PATTERN.test(key) ||
441
+ ['__proto__', 'constructor', 'prototype'].includes(key)) {
442
+ throw new ReaderStateInputError('reader preference keys must use safe stable identifiers');
443
+ }
444
+ if (preference !== null &&
445
+ typeof preference !== 'string' &&
446
+ typeof preference !== 'boolean' &&
447
+ (typeof preference !== 'number' || !Number.isFinite(preference))) {
448
+ throw new ReaderStateInputError('reader preference values must be finite scalar values');
449
+ }
450
+ normalized[key] = preference;
451
+ }
452
+ if (new TextEncoder().encode(JSON.stringify(normalized)).byteLength > MAX_PREFERENCES_JSON_BYTES) {
453
+ throw new ReaderStateInputError(`reader preferences are limited to ${MAX_PREFERENCES_JSON_BYTES} encoded bytes`);
454
+ }
455
+ return normalized;
456
+ }
457
+ function resolveLimit(value) {
458
+ const limit = value ?? DEFAULT_READER_STATE_BATCH_SIZE;
459
+ if (!Number.isInteger(limit) || limit < 1 || limit > MAX_READER_STATE_BATCH_SIZE) {
460
+ throw new ReaderStateInputError(`reader state list limits must be from 1 through ${MAX_READER_STATE_BATCH_SIZE}`);
461
+ }
462
+ return limit;
463
+ }
464
+ function encodeCursor(record, order) {
465
+ const orderedAt = order === 'updated' ? record.updatedAt : record.createdAt;
466
+ return encodeURIComponent(JSON.stringify([order, orderedAt, record.contentType, record.contentId]));
467
+ }
468
+ function decodeCursor(cursor, expectedOrder) {
469
+ try {
470
+ const parsed = JSON.parse(decodeURIComponent(cursor));
471
+ if (!Array.isArray(parsed) ||
472
+ parsed.length !== 4 ||
473
+ parsed[0] !== expectedOrder ||
474
+ !Number.isSafeInteger(parsed[1])) {
475
+ throw new Error('shape');
476
+ }
477
+ const key = resolveContentKey({ contentType: parsed[2], contentId: parsed[3] });
478
+ return { order: expectedOrder, orderedAt: parsed[1], ...key };
479
+ }
480
+ catch (error) {
481
+ if (error instanceof ReaderStateInputError)
482
+ throw error;
483
+ throw new ReaderStateInputError('reader state cursor is invalid');
484
+ }
485
+ }
486
+ function resultChanges(result) {
487
+ const changes = result?.meta?.changes;
488
+ if (typeof changes !== 'number' || !Number.isFinite(changes)) {
489
+ throw new ReaderStateDurableStateError('reader state mutation returned no finite change count');
490
+ }
491
+ return changes;
492
+ }
493
+ //# sourceMappingURL=reader-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader-state.js","sourceRoot":"","sources":["../../src/engine/reader-state.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from './engine/index.js';
2
2
  export * from './providers/index.js';
3
3
  export type { CmsUser } from './routes/context.js';
4
- export { type ArticleContentRow, type AuthorRow, applyMigrations, CMS_MIGRATION_SQL, CMS_MIGRATIONS_0002_PLUS, CMS_TABLES, type CmsActivityLogRow, type CmsApiKeyRow, type CmsNotificationRow, type CmsRole, type CmsTableName, type CmsWebhookRow, type ContentContributorRow, type ContentImportRow, type ContentItemRow, type ContentPublicationAttemptRow, type ContentPublicationAttemptState, type ContentPublicationOperation, type ContentRelationRow, type ContentRevisionRow, type ContentSlugRedirectRow, type ContentStatus, type ContentTagLinkRow, type ContentTagRow, type ContentType, type ContentVisibility, type FoundryCallbackEventRow, type MastheadUserRow, type MediaAssetRow, NON_CMS_TABLES, type PodcastContentRow, splitStatements, type VideoContentRow, type VideoProcessingState, type WorkspaceInviteRow, type WorkspaceMembershipRow, type WorkspaceSettingsRow, } from './schema/index.js';
4
+ export { type ArticleContentRow, type AuthorRow, applyMigrations, CMS_MIGRATION_SQL, CMS_MIGRATIONS_0002_PLUS, CMS_TABLES, type CmsActivityLogRow, type CmsApiKeyRow, type CmsNotificationRow, type CmsReaderStateRow, type CmsRole, type CmsTableName, type CmsWebhookRow, type ContentContributorRow, type ContentImportRow, type ContentItemRow, type ContentPublicationAttemptRow, type ContentPublicationAttemptState, type ContentPublicationOperation, type ContentRelationRow, type ContentRevisionRow, type ContentSlugRedirectRow, type ContentStatus, type ContentTagLinkRow, type ContentTagRow, type ContentType, type ContentVisibility, type FoundryCallbackEventRow, type MastheadUserRow, type MediaAssetRow, NON_CMS_TABLES, type PodcastContentRow, type ReaderManualReadState, splitStatements, type VideoContentRow, type VideoProcessingState, type WorkspaceInviteRow, type WorkspaceMembershipRow, type WorkspaceSettingsRow, } from './schema/index.js';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgCA,cAAc,mBAAmB,CAAA;AAGjC,cAAc,sBAAsB,CAAA;AAGpC,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,eAAe,EAEf,iBAAiB,EACjB,wBAAwB,EAExB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,4BAA4B,EACjC,KAAK,8BAA8B,EACnC,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAElB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,cAAc,EACd,KAAK,iBAAiB,EACtB,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,GACzB,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgCA,cAAc,mBAAmB,CAAA;AAGjC,cAAc,sBAAsB,CAAA;AAGpC,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,eAAe,EAEf,iBAAiB,EACjB,wBAAwB,EAExB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,4BAA4B,EACjC,KAAK,8BAA8B,EACnC,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAElB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,GACzB,MAAM,mBAAmB,CAAA"}
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  // @growth-labs/cms — the reusable Fronts-proven publishing/admin engine, as a
2
2
  // package (NOT a shared engine). See docs/reference/cms-reuse-decision.md.
3
3
  //
4
- // This package ships the D1 schema contract (the 11-table
5
- // content/revision/media/authors/foundry-callback set) + its TypeScript row
4
+ // This package ships the D1 schema contract (the original 11-table
5
+ // content/revision/media/authors/foundry-callback set plus additive migrations) + its TypeScript row
6
6
  // types (WS7-04/06 foundation) AND the publishing engine — the content
7
7
  // data-access core (WS7-05):
8
8
  //
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,EAAE;AACF,0DAA0D;AAC1D,4EAA4E;AAC5E,uEAAuE;AACvE,6BAA6B;AAC7B,EAAE;AACF,qEAAqE;AACrE,iEAAiE;AACjE,qEAAqE;AACrE,iDAAiD;AACjD,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,+EAA+E;AAC/E,oEAAoE;AACpE,2EAA2E;AAC3E,+EAA+E;AAC/E,qBAAqB;AACrB,oEAAoE;AACpE,wEAAwE;AACxE,4EAA4E;AAC5E,yEAAyE;AACzE,8EAA8E;AAC9E,gFAAgF;AAChF,0EAA0E;AAC1E,6EAA6E;AAC7E,iDAAiD;AAEjD,sEAAsE;AACtE,sDAAsD;AACtD,cAAc,mBAAmB,CAAA;AAEjC,mEAAmE;AACnE,cAAc,sBAAsB,CAAA;AAKpC,OAAO,EAGN,eAAe;AACf,qBAAqB;AACrB,iBAAiB,EACjB,wBAAwB;AACxB,iBAAiB;AACjB,UAAU,EAyBV,cAAc,EAEd,eAAe,GAMf,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,EAAE;AACF,mEAAmE;AACnE,qGAAqG;AACrG,uEAAuE;AACvE,6BAA6B;AAC7B,EAAE;AACF,qEAAqE;AACrE,iEAAiE;AACjE,qEAAqE;AACrE,iDAAiD;AACjD,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,+EAA+E;AAC/E,oEAAoE;AACpE,2EAA2E;AAC3E,+EAA+E;AAC/E,qBAAqB;AACrB,oEAAoE;AACpE,wEAAwE;AACxE,4EAA4E;AAC5E,yEAAyE;AACzE,8EAA8E;AAC9E,gFAAgF;AAChF,0EAA0E;AAC1E,6EAA6E;AAC7E,iDAAiD;AAEjD,sEAAsE;AACtE,sDAAsD;AACtD,cAAc,mBAAmB,CAAA;AAEjC,mEAAmE;AACnE,cAAc,sBAAsB,CAAA;AAKpC,OAAO,EAGN,eAAe;AACf,qBAAqB;AACrB,iBAAiB,EACjB,wBAAwB;AACxB,iBAAiB;AACjB,UAAU,EA0BV,cAAc,EAGd,eAAe,GAMf,MAAM,mBAAmB,CAAA"}
@@ -1,4 +1,4 @@
1
1
  export { applyMigrations, CMS_MIGRATION_SQL, CMS_MIGRATIONS_0002_PLUS, splitStatements, } from './migrations.js';
2
2
  export { CMS_TABLES, type CmsTableName, NON_CMS_TABLES, } from './tables.js';
3
- export type { ArticleContentRow, AuthorRow, CmsActivityLogRow, CmsApiKeyRow, CmsNotificationRow, CmsRole, CmsWebhookRow, ContentContributorRow, ContentImportRow, ContentItemRow, ContentPublicationAttemptRow, ContentPublicationAttemptState, ContentPublicationOperation, ContentRelationRow, ContentRevisionRow, ContentSlugRedirectRow, ContentStatus, ContentTagLinkRow, ContentTagRow, ContentType, ContentVisibility, FoundryCallbackEventRow, MastheadUserRow, MediaAssetRow, PodcastContentRow, VideoContentRow, VideoProcessingState, WorkspaceInviteRow, WorkspaceMembershipRow, WorkspaceSettingsRow, } from './types.js';
3
+ export type { ArticleContentRow, AuthorRow, CmsActivityLogRow, CmsApiKeyRow, CmsNotificationRow, CmsReaderStateRow, CmsRole, CmsWebhookRow, ContentContributorRow, ContentImportRow, ContentItemRow, ContentPublicationAttemptRow, ContentPublicationAttemptState, ContentPublicationOperation, ContentRelationRow, ContentRevisionRow, ContentSlugRedirectRow, ContentStatus, ContentTagLinkRow, ContentTagRow, ContentType, ContentVisibility, FoundryCallbackEventRow, MastheadUserRow, MediaAssetRow, PodcastContentRow, ReaderManualReadState, VideoContentRow, VideoProcessingState, WorkspaceInviteRow, WorkspaceMembershipRow, WorkspaceSettingsRow, } from './types.js';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,GACf,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACN,UAAU,EACV,KAAK,YAAY,EACjB,cAAc,GACd,MAAM,aAAa,CAAA;AAEpB,YAAY,EACX,iBAAiB,EACjB,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,4BAA4B,EAC5B,8BAA8B,EAC9B,2BAA2B,EAC3B,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACpB,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,GACf,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACN,UAAU,EACV,KAAK,YAAY,EACjB,cAAc,GACd,MAAM,aAAa,CAAA;AAEpB,YAAY,EACX,iBAAiB,EACjB,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,OAAO,EACP,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,4BAA4B,EAC5B,8BAA8B,EAC9B,2BAA2B,EAC3B,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACpB,MAAM,YAAY,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/schema/migrations.ts"],"names":[],"mappings":"AAYA;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,mzKAyJ7B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAKrD;AAED,iFAAiF;AACjF,UAAU,MAAM;IACf,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,wBAAwB,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EA0gBjE,CAAA;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/D;AAED,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG/C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/schema/migrations.ts"],"names":[],"mappings":"AAYA;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,mzKAyJ7B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAKrD;AAED,iFAAiF;AACjF,UAAU,MAAM;IACf,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,wBAAwB,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EA+iBjE,CAAA;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/D;AAED,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG/C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA"}
@@ -733,6 +733,43 @@ CREATE INDEX idx_content_publication_attempts_recovery
733
733
  ON content_publication_attempts(state, updated_at);
734
734
  CREATE INDEX idx_content_publication_attempts_content
735
735
  ON content_publication_attempts(content_id, created_at DESC);
736
+ `,
737
+ },
738
+ {
739
+ id: '0019_reader_state',
740
+ sql: `
741
+ CREATE TABLE cms_reader_state (
742
+ identity_user_id TEXT NOT NULL,
743
+ site_id TEXT NOT NULL,
744
+ content_type TEXT NOT NULL CHECK (content_type IN ('article','video','podcast','newsletter','page')),
745
+ content_id TEXT NOT NULL,
746
+ first_opened_at INTEGER,
747
+ last_opened_at INTEGER,
748
+ max_progress_bps INTEGER NOT NULL DEFAULT 0 CHECK (max_progress_bps BETWEEN 0 AND 10000),
749
+ media_position_ms INTEGER CHECK (media_position_ms IS NULL OR media_position_ms >= 0),
750
+ media_duration_ms INTEGER CHECK (media_duration_ms IS NULL OR media_duration_ms >= 0),
751
+ progress_observed_at INTEGER,
752
+ automatic_completed_at INTEGER,
753
+ manual_read_state TEXT CHECK (manual_read_state IS NULL OR manual_read_state IN ('read','unread')),
754
+ manual_state_at INTEGER,
755
+ manual_mutation_id TEXT,
756
+ saved INTEGER NOT NULL DEFAULT 0 CHECK (saved IN (0,1)),
757
+ saved_at INTEGER,
758
+ saved_mutation_id TEXT,
759
+ preferences_json TEXT NOT NULL DEFAULT '{}',
760
+ preferences_at INTEGER,
761
+ preferences_mutation_id TEXT,
762
+ version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
763
+ created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
764
+ updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
765
+ PRIMARY KEY (identity_user_id, site_id, content_type, content_id)
766
+ );
767
+ CREATE INDEX idx_cms_reader_state_library
768
+ ON cms_reader_state(identity_user_id, site_id, updated_at DESC, content_type, content_id);
769
+ CREATE INDEX idx_cms_reader_state_export
770
+ ON cms_reader_state(identity_user_id, site_id, created_at DESC, content_type, content_id);
771
+ CREATE INDEX idx_cms_reader_state_saved
772
+ ON cms_reader_state(identity_user_id, site_id, saved, updated_at DESC);
736
773
  `,
737
774
  },
738
775
  ];