@growth-labs/cms 0.2.0 → 0.3.1
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 +106 -2
- package/dist/cli/migrations.d.ts +3 -0
- package/dist/cli/migrations.d.ts.map +1 -0
- package/dist/cli/migrations.js +73 -0
- package/dist/cli/migrations.js.map +1 -0
- package/dist/engine/index.d.ts +1 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +2 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/reader-state.d.ts +127 -0
- package/dist/engine/reader-state.d.ts.map +1 -0
- package/dist/engine/reader-state.js +493 -0
- package/dist/engine/reader-state.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/migration-vendor-files.d.ts +17 -0
- package/dist/migration-vendor-files.d.ts.map +1 -0
- package/dist/migration-vendor-files.js +67 -0
- package/dist/migration-vendor-files.js.map +1 -0
- package/dist/migration-vendor.d.ts +26 -0
- package/dist/migration-vendor.d.ts.map +1 -0
- package/dist/migration-vendor.js +321 -0
- package/dist/migration-vendor.js.map +1 -0
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/migrations.d.ts.map +1 -1
- package/dist/schema/migrations.js +37 -0
- package/dist/schema/migrations.js.map +1 -1
- package/dist/schema/tables.d.ts +1 -1
- package/dist/schema/tables.d.ts.map +1 -1
- package/dist/schema/tables.js +5 -2
- package/dist/schema/tables.js.map +1 -1
- package/dist/schema/types.d.ts +27 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js.map +1 -1
- package/migrations/0019_reader_state.sql +34 -0
- package/package.json +8 -1
- package/src/cli/migrations.ts +85 -0
- package/src/engine/index.ts +38 -0
- package/src/engine/reader-state.ts +918 -0
- package/src/index.ts +4 -2
- package/src/migration-vendor-files.ts +100 -0
- package/src/migration-vendor.ts +450 -0
- package/src/schema/index.ts +2 -0
- package/src/schema/migrations.ts +37 -0
- package/src/schema/tables.ts +5 -2
- package/src/schema/types.ts +29 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
-- Package-owned reader product state. Raw verified realm identity is the only
|
|
2
|
+
-- principal; analytics identifiers never enter this table.
|
|
3
|
+
CREATE TABLE cms_reader_state (
|
|
4
|
+
identity_user_id TEXT NOT NULL,
|
|
5
|
+
site_id TEXT NOT NULL,
|
|
6
|
+
content_type TEXT NOT NULL CHECK (content_type IN ('article','video','podcast','newsletter','page')),
|
|
7
|
+
content_id TEXT NOT NULL,
|
|
8
|
+
first_opened_at INTEGER,
|
|
9
|
+
last_opened_at INTEGER,
|
|
10
|
+
max_progress_bps INTEGER NOT NULL DEFAULT 0 CHECK (max_progress_bps BETWEEN 0 AND 10000),
|
|
11
|
+
media_position_ms INTEGER CHECK (media_position_ms IS NULL OR media_position_ms >= 0),
|
|
12
|
+
media_duration_ms INTEGER CHECK (media_duration_ms IS NULL OR media_duration_ms >= 0),
|
|
13
|
+
progress_observed_at INTEGER,
|
|
14
|
+
automatic_completed_at INTEGER,
|
|
15
|
+
manual_read_state TEXT CHECK (manual_read_state IS NULL OR manual_read_state IN ('read','unread')),
|
|
16
|
+
manual_state_at INTEGER,
|
|
17
|
+
manual_mutation_id TEXT,
|
|
18
|
+
saved INTEGER NOT NULL DEFAULT 0 CHECK (saved IN (0,1)),
|
|
19
|
+
saved_at INTEGER,
|
|
20
|
+
saved_mutation_id TEXT,
|
|
21
|
+
preferences_json TEXT NOT NULL DEFAULT '{}',
|
|
22
|
+
preferences_at INTEGER,
|
|
23
|
+
preferences_mutation_id TEXT,
|
|
24
|
+
version INTEGER NOT NULL DEFAULT 0 CHECK (version >= 0),
|
|
25
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
26
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
27
|
+
PRIMARY KEY (identity_user_id, site_id, content_type, content_id)
|
|
28
|
+
);
|
|
29
|
+
CREATE INDEX idx_cms_reader_state_library
|
|
30
|
+
ON cms_reader_state(identity_user_id, site_id, updated_at DESC, content_type, content_id);
|
|
31
|
+
CREATE INDEX idx_cms_reader_state_export
|
|
32
|
+
ON cms_reader_state(identity_user_id, site_id, created_at DESC, content_type, content_id);
|
|
33
|
+
CREATE INDEX idx_cms_reader_state_saved
|
|
34
|
+
ON cms_reader_state(identity_user_id, site_id, saved, updated_at DESC);
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@growth-labs/cms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"growth-labs-cms-migrations": "./dist/cli/migrations.js"
|
|
7
|
+
},
|
|
5
8
|
"types": "./dist/index.d.ts",
|
|
6
9
|
"exports": {
|
|
7
10
|
".": {
|
|
@@ -24,6 +27,10 @@
|
|
|
24
27
|
"types": "./dist/integration/index.d.ts",
|
|
25
28
|
"import": "./dist/integration/index.js"
|
|
26
29
|
},
|
|
30
|
+
"./migration-vendor": {
|
|
31
|
+
"types": "./dist/migration-vendor.d.ts",
|
|
32
|
+
"import": "./dist/migration-vendor.js"
|
|
33
|
+
},
|
|
27
34
|
"./ui": {
|
|
28
35
|
"types": "./dist/ui/components/CmsApp.d.ts",
|
|
29
36
|
"import": "./dist/ui/components/CmsApp.js"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { syncCmsMigrations, verifyCmsMigrations } from '../migration-vendor.js'
|
|
4
|
+
|
|
5
|
+
interface ParsedArgs {
|
|
6
|
+
command: 'sync' | 'verify'
|
|
7
|
+
migrationsDir: string
|
|
8
|
+
startSequence?: number
|
|
9
|
+
manifestPath?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function usage(): string {
|
|
13
|
+
return [
|
|
14
|
+
'Usage:',
|
|
15
|
+
' growth-labs-cms-migrations sync --dir <migrations-dir> --start <positive-integer>',
|
|
16
|
+
' growth-labs-cms-migrations verify --dir <migrations-dir>',
|
|
17
|
+
'',
|
|
18
|
+
'Optional for both commands: --manifest <receipt-path>',
|
|
19
|
+
].join('\n')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function requireValue(argv: string[], index: number, flag: string): string {
|
|
23
|
+
const value = argv[index + 1]
|
|
24
|
+
if (!value || value.startsWith('--')) throw new Error(`${flag} requires a value`)
|
|
25
|
+
return value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function parseArgs(argv: string[]): ParsedArgs {
|
|
29
|
+
const command = argv[0]
|
|
30
|
+
if (command !== 'sync' && command !== 'verify') throw new Error(usage())
|
|
31
|
+
let migrationsDir: string | undefined
|
|
32
|
+
let startSequence: number | undefined
|
|
33
|
+
let manifestPath: string | undefined
|
|
34
|
+
|
|
35
|
+
for (let index = 1; index < argv.length; index += 1) {
|
|
36
|
+
const flag = argv[index]
|
|
37
|
+
if (flag === '--dir') {
|
|
38
|
+
migrationsDir = requireValue(argv, index, flag)
|
|
39
|
+
index += 1
|
|
40
|
+
continue
|
|
41
|
+
}
|
|
42
|
+
if (flag === '--start') {
|
|
43
|
+
startSequence = Number(requireValue(argv, index, flag))
|
|
44
|
+
index += 1
|
|
45
|
+
continue
|
|
46
|
+
}
|
|
47
|
+
if (flag === '--manifest') {
|
|
48
|
+
manifestPath = requireValue(argv, index, flag)
|
|
49
|
+
index += 1
|
|
50
|
+
continue
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`unknown argument: ${flag}\n\n${usage()}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!migrationsDir) throw new Error(`--dir is required\n\n${usage()}`)
|
|
56
|
+
if (command === 'sync' && startSequence === undefined) {
|
|
57
|
+
throw new Error(`--start is required for sync\n\n${usage()}`)
|
|
58
|
+
}
|
|
59
|
+
if (command === 'verify' && startSequence !== undefined) {
|
|
60
|
+
throw new Error('--start is read from the committed manifest during verify')
|
|
61
|
+
}
|
|
62
|
+
return { command, migrationsDir, startSequence, manifestPath }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function main(): Promise<void> {
|
|
66
|
+
const args = parseArgs(process.argv.slice(2))
|
|
67
|
+
const result =
|
|
68
|
+
args.command === 'sync'
|
|
69
|
+
? await syncCmsMigrations({
|
|
70
|
+
migrationsDir: args.migrationsDir,
|
|
71
|
+
startSequence: args.startSequence as number,
|
|
72
|
+
manifestPath: args.manifestPath,
|
|
73
|
+
})
|
|
74
|
+
: await verifyCmsMigrations({
|
|
75
|
+
migrationsDir: args.migrationsDir,
|
|
76
|
+
manifestPath: args.manifestPath,
|
|
77
|
+
})
|
|
78
|
+
process.stdout.write(`${JSON.stringify({ ok: true, command: args.command, ...result })}\n`)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
main().catch((error: unknown) => {
|
|
82
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
83
|
+
process.stderr.write(`growth-labs-cms-migrations: ${message}\n`)
|
|
84
|
+
process.exitCode = 1
|
|
85
|
+
})
|
package/src/engine/index.ts
CHANGED
|
@@ -180,6 +180,44 @@ export {
|
|
|
180
180
|
updateContentItem,
|
|
181
181
|
type VideoInput,
|
|
182
182
|
} from './publisher.js'
|
|
183
|
+
// Verified-user/site reader product state. Analytics remains observation-only.
|
|
184
|
+
export {
|
|
185
|
+
type ClearManualReadStateOptions,
|
|
186
|
+
type ContentStateKey,
|
|
187
|
+
clearManualReadState,
|
|
188
|
+
clearReaderHistory,
|
|
189
|
+
DEFAULT_READER_STATE_BATCH_SIZE,
|
|
190
|
+
deleteReaderState,
|
|
191
|
+
exportReaderStatePage,
|
|
192
|
+
getReaderState,
|
|
193
|
+
getReaderStateBatch,
|
|
194
|
+
listReaderState,
|
|
195
|
+
MAX_READER_STATE_BATCH_SIZE,
|
|
196
|
+
READER_AUTOMATIC_COMPLETION_BPS,
|
|
197
|
+
type ReaderBehavioralConsent,
|
|
198
|
+
type ReaderPreferences,
|
|
199
|
+
type ReaderPreferenceValue,
|
|
200
|
+
ReaderStateConflictError,
|
|
201
|
+
ReaderStateDurableStateError,
|
|
202
|
+
type ReaderStateExportPage,
|
|
203
|
+
ReaderStateInputError,
|
|
204
|
+
type ReaderStateListOptions,
|
|
205
|
+
type ReaderStateMutationResult,
|
|
206
|
+
type ReaderStatePage,
|
|
207
|
+
type ReaderStateRecord,
|
|
208
|
+
type ReaderStateScope,
|
|
209
|
+
type RecordReaderOpenOptions,
|
|
210
|
+
type RecordReaderProgressOptions,
|
|
211
|
+
recordReaderOpen,
|
|
212
|
+
recordReaderProgress,
|
|
213
|
+
recordReaderUnlock,
|
|
214
|
+
type SetManualReadStateOptions,
|
|
215
|
+
type SetReaderPreferencesOptions,
|
|
216
|
+
type SetSavedStateOptions,
|
|
217
|
+
setManualReadState,
|
|
218
|
+
setReaderPreferences,
|
|
219
|
+
setSavedState,
|
|
220
|
+
} from './reader-state.js'
|
|
183
221
|
// Revision engine — snapshot + word-delta history + restore.
|
|
184
222
|
export {
|
|
185
223
|
type ContentRevisionPayload,
|