@growth-labs/cms 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -6
- package/dist/engine/content-metadata.d.ts +13 -0
- package/dist/engine/content-metadata.d.ts.map +1 -0
- package/dist/engine/content-metadata.js +80 -0
- package/dist/engine/content-metadata.js.map +1 -0
- package/dist/engine/foundry-dispatch.d.ts +5 -1
- package/dist/engine/foundry-dispatch.d.ts.map +1 -1
- package/dist/engine/foundry-dispatch.js +19 -3
- package/dist/engine/foundry-dispatch.js.map +1 -1
- package/dist/engine/index.d.ts +4 -2
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +6 -2
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/publication.d.ts +29 -1
- package/dist/engine/publication.d.ts.map +1 -1
- package/dist/engine/publication.js +197 -15
- package/dist/engine/publication.js.map +1 -1
- package/dist/engine/published-content.d.ts +40 -0
- package/dist/engine/published-content.d.ts.map +1 -0
- package/dist/engine/published-content.js +388 -0
- package/dist/engine/published-content.js.map +1 -0
- package/dist/engine/publisher.d.ts +20 -1
- package/dist/engine/publisher.d.ts.map +1 -1
- package/dist/engine/publisher.js +264 -65
- package/dist/engine/publisher.js.map +1 -1
- package/dist/engine/revisions.d.ts.map +1 -1
- package/dist/engine/revisions.js +2 -0
- package/dist/engine/revisions.js.map +1 -1
- package/dist/providers/types.d.ts +1 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/routes/content.d.ts.map +1 -1
- package/dist/routes/content.js +76 -16
- package/dist/routes/content.js.map +1 -1
- package/dist/routes/context.d.ts +1 -0
- package/dist/routes/context.d.ts.map +1 -1
- package/dist/routes/context.js.map +1 -1
- package/dist/routes/media.d.ts.map +1 -1
- package/dist/routes/media.js +53 -31
- package/dist/routes/media.js.map +1 -1
- package/dist/schema/migrations.d.ts.map +1 -1
- package/dist/schema/migrations.js +24 -0
- package/dist/schema/migrations.js.map +1 -1
- package/dist/schema/types.d.ts +6 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js.map +1 -1
- package/dist/ui/editor/ContentForm.d.ts.map +1 -1
- package/dist/ui/editor/ContentForm.js +65 -10
- package/dist/ui/editor/ContentForm.js.map +1 -1
- package/dist/ui/editor/content-payload.d.ts +2 -0
- package/dist/ui/editor/content-payload.d.ts.map +1 -1
- package/dist/ui/editor/content-payload.js +15 -4
- package/dist/ui/editor/content-payload.js.map +1 -1
- package/dist/ui/editor/editor-media-duration.d.ts +24 -0
- package/dist/ui/editor/editor-media-duration.d.ts.map +1 -0
- package/dist/ui/editor/editor-media-duration.js +51 -0
- package/dist/ui/editor/editor-media-duration.js.map +1 -0
- package/dist/ui/screens/MediaScreen.d.ts.map +1 -1
- package/dist/ui/screens/MediaScreen.js +8 -1
- package/dist/ui/screens/MediaScreen.js.map +1 -1
- package/dist/ui/screens/media-upload.d.ts +9 -2
- package/dist/ui/screens/media-upload.d.ts.map +1 -1
- package/dist/ui/screens/media-upload.js +24 -0
- package/dist/ui/screens/media-upload.js.map +1 -1
- package/migrations/0020_content_metadata_read_model.sql +19 -0
- package/migrations/0021_published_revision_slug_index.sql +5 -0
- package/package.json +1 -1
- package/src/engine/content-metadata.ts +122 -0
- package/src/engine/foundry-dispatch.ts +32 -4
- package/src/engine/index.ts +27 -0
- package/src/engine/publication.ts +329 -18
- package/src/engine/published-content.ts +581 -0
- package/src/engine/publisher.ts +403 -107
- package/src/engine/revisions.ts +4 -0
- package/src/providers/types.ts +1 -0
- package/src/routes/content.ts +91 -16
- package/src/routes/context.ts +1 -0
- package/src/routes/media.ts +63 -41
- package/src/schema/migrations.ts +24 -0
- package/src/schema/types.ts +6 -0
- package/src/ui/editor/ContentForm.tsx +121 -4
- package/src/ui/editor/content-payload.ts +20 -2
- package/src/ui/editor/editor-media-duration.ts +75 -0
- package/src/ui/screens/MediaScreen.tsx +13 -2
- package/src/ui/screens/media-upload.ts +41 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaScreen.js","sourceRoot":"","sources":["../../../src/ui/screens/MediaScreen.tsx"],"names":[],"mappings":";AAAA,8DAA8D;AAC9D,EAAE;AACF,2DAA2D;AAC3D,4EAA4E;AAC5E,4EAA4E;AAC5E,2DAA2D;AAC3D,EAAE;AACF,+CAA+C;AAC/C,4CAA4C;AAC5C,6CAA6C;AAC7C,4DAA4D;AAC5D,EAAE;AACF,uBAAuB;AACvB,4CAA4C;AAC5C,gDAAgD;AAChD,iFAAiF;AACjF,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,oCAAoC;AACpC,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC5E,OAAO,EAAE,IAAI,EAAiB,MAAM,aAAa,CAAA;AACjD,OAAO,
|
|
1
|
+
{"version":3,"file":"MediaScreen.js","sourceRoot":"","sources":["../../../src/ui/screens/MediaScreen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -2,17 +2,24 @@ export type MediaUploadKind = 'image' | 'video' | 'podcast';
|
|
|
2
2
|
export interface MediaUploadResult {
|
|
3
3
|
id: string;
|
|
4
4
|
url: string | null;
|
|
5
|
+
durationSeconds?: number;
|
|
5
6
|
sourceKind?: string | null;
|
|
6
7
|
processingStatus?: string | null;
|
|
7
8
|
videoId?: string | null;
|
|
8
9
|
}
|
|
9
10
|
type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
10
|
-
interface
|
|
11
|
-
kind: MediaUploadKind;
|
|
11
|
+
interface BaseUploadMediaAssetInput {
|
|
12
12
|
file: File;
|
|
13
13
|
slug?: string;
|
|
14
14
|
fetchImpl?: FetchLike;
|
|
15
15
|
}
|
|
16
|
+
type UploadMediaAssetInput = (BaseUploadMediaAssetInput & {
|
|
17
|
+
kind: 'image';
|
|
18
|
+
durationSeconds?: never;
|
|
19
|
+
}) | (BaseUploadMediaAssetInput & {
|
|
20
|
+
kind: 'video' | 'podcast';
|
|
21
|
+
durationSeconds: number;
|
|
22
|
+
});
|
|
16
23
|
export declare function buildMediaUploadSlug(fileName: string): string;
|
|
17
24
|
export declare function uploadMediaAsset(input: UploadMediaAssetInput): Promise<MediaUploadResult>;
|
|
18
25
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-upload.d.ts","sourceRoot":"","sources":["../../../src/ui/screens/media-upload.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAA;AAE3D,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEzF,UAAU,
|
|
1
|
+
{"version":3,"file":"media-upload.d.ts","sourceRoot":"","sources":["../../../src/ui/screens/media-upload.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAA;AAE3D,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEzF,UAAU,yBAAyB;IAClC,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,KAAK,qBAAqB,GACvB,CAAC,yBAAyB,GAAG;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,eAAe,CAAC,EAAE,KAAK,CAAA;CACtB,CAAC,GACF,CAAC,yBAAyB,GAAG;IAC7B,IAAI,EAAE,OAAO,GAAG,SAAS,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;CACtB,CAAC,CAAA;AAwDL,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS7D;AAkCD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmM/F"}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
function requirePositiveIntegerDuration(input) {
|
|
2
|
+
const durationSeconds = input.durationSeconds;
|
|
3
|
+
if (typeof durationSeconds !== 'number' ||
|
|
4
|
+
!Number.isFinite(durationSeconds) ||
|
|
5
|
+
!Number.isInteger(durationSeconds) ||
|
|
6
|
+
durationSeconds <= 0) {
|
|
7
|
+
throw new Error('Media upload requires a positive integer duration');
|
|
8
|
+
}
|
|
9
|
+
return durationSeconds;
|
|
10
|
+
}
|
|
1
11
|
export function buildMediaUploadSlug(fileName) {
|
|
2
12
|
const basename = fileName.replace(/\.[^.]+$/, '');
|
|
3
13
|
const slug = basename
|
|
@@ -47,6 +57,7 @@ export async function uploadMediaAsset(input) {
|
|
|
47
57
|
};
|
|
48
58
|
}
|
|
49
59
|
if (input.kind === 'podcast') {
|
|
60
|
+
const durationSeconds = requirePositiveIntegerDuration(input);
|
|
50
61
|
if (input.file.size <= 0) {
|
|
51
62
|
throw new Error('Podcast audio file is empty');
|
|
52
63
|
}
|
|
@@ -61,6 +72,7 @@ export async function uploadMediaAsset(input) {
|
|
|
61
72
|
fileName: input.file.name,
|
|
62
73
|
contentType: input.file.type || null,
|
|
63
74
|
sizeBytes: input.file.size,
|
|
75
|
+
durationSeconds,
|
|
64
76
|
}),
|
|
65
77
|
});
|
|
66
78
|
const init = await assertOk(initResponse, 'Could not start podcast audio upload');
|
|
@@ -94,13 +106,18 @@ export async function uploadMediaAsset(input) {
|
|
|
94
106
|
fileName: input.file.name,
|
|
95
107
|
contentType: input.file.type || null,
|
|
96
108
|
sizeBytes: input.file.size,
|
|
109
|
+
durationSeconds,
|
|
97
110
|
parts,
|
|
98
111
|
}),
|
|
99
112
|
});
|
|
100
113
|
const complete = await assertOk(completeResponse, 'Could not complete podcast audio upload');
|
|
114
|
+
if (complete.durationSeconds !== durationSeconds) {
|
|
115
|
+
throw new Error('Podcast upload did not preserve the measured duration');
|
|
116
|
+
}
|
|
101
117
|
return {
|
|
102
118
|
id: complete.key || key,
|
|
103
119
|
url: complete.publicUrl || null,
|
|
120
|
+
durationSeconds,
|
|
104
121
|
};
|
|
105
122
|
}
|
|
106
123
|
catch (error) {
|
|
@@ -114,6 +131,7 @@ export async function uploadMediaAsset(input) {
|
|
|
114
131
|
throw error;
|
|
115
132
|
}
|
|
116
133
|
}
|
|
134
|
+
const durationSeconds = requirePositiveIntegerDuration(input);
|
|
117
135
|
if (input.file.size <= 0) {
|
|
118
136
|
throw new Error('Video file is empty');
|
|
119
137
|
}
|
|
@@ -128,6 +146,7 @@ export async function uploadMediaAsset(input) {
|
|
|
128
146
|
fileName: input.file.name,
|
|
129
147
|
contentType: input.file.type || null,
|
|
130
148
|
sizeBytes: input.file.size,
|
|
149
|
+
durationSeconds,
|
|
131
150
|
}),
|
|
132
151
|
});
|
|
133
152
|
const init = await assertOk(initResponse, 'Could not start video upload');
|
|
@@ -161,16 +180,21 @@ export async function uploadMediaAsset(input) {
|
|
|
161
180
|
fileName: input.file.name,
|
|
162
181
|
contentType: input.file.type || null,
|
|
163
182
|
sizeBytes: input.file.size,
|
|
183
|
+
durationSeconds,
|
|
164
184
|
parts,
|
|
165
185
|
}),
|
|
166
186
|
});
|
|
167
187
|
const complete = await assertOk(completeResponse, 'Could not complete video upload');
|
|
188
|
+
if (complete.durationSeconds !== durationSeconds) {
|
|
189
|
+
throw new Error('Video upload did not preserve the measured duration');
|
|
190
|
+
}
|
|
168
191
|
return {
|
|
169
192
|
id: complete.key || key,
|
|
170
193
|
url: complete.sourceUrl || null,
|
|
171
194
|
sourceKind: complete.sourceKind || 'http_url',
|
|
172
195
|
processingStatus: complete.processingStatus || 'processing',
|
|
173
196
|
videoId: complete.videoId || slug,
|
|
197
|
+
durationSeconds,
|
|
174
198
|
};
|
|
175
199
|
}
|
|
176
200
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-upload.js","sourceRoot":"","sources":["../../../src/ui/screens/media-upload.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"media-upload.js","sourceRoot":"","sources":["../../../src/ui/screens/media-upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- 0020_content_metadata_read_model: generic bounded site metadata and durable
|
|
2
|
+
-- historical publication time for pointer-move recovery.
|
|
3
|
+
|
|
4
|
+
ALTER TABLE content_items
|
|
5
|
+
ADD COLUMN metadata_json TEXT NOT NULL DEFAULT '{}';
|
|
6
|
+
|
|
7
|
+
ALTER TABLE content_items
|
|
8
|
+
ADD COLUMN source_id TEXT;
|
|
9
|
+
|
|
10
|
+
CREATE UNIQUE INDEX idx_content_items_source_id_unique
|
|
11
|
+
ON content_items(source_id)
|
|
12
|
+
WHERE source_id IS NOT NULL;
|
|
13
|
+
|
|
14
|
+
ALTER TABLE content_publication_attempts
|
|
15
|
+
ADD COLUMN target_published_at INTEGER;
|
|
16
|
+
|
|
17
|
+
UPDATE content_publication_attempts
|
|
18
|
+
SET target_published_at = created_at
|
|
19
|
+
WHERE operation = 'publish' AND target_published_at IS NULL;
|
package/package.json
CHANGED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export type ContentMetadataPrimitive = string | number | boolean | null
|
|
2
|
+
export type ContentMetadataValue =
|
|
3
|
+
| ContentMetadataPrimitive
|
|
4
|
+
| ContentMetadataValue[]
|
|
5
|
+
| { [key: string]: ContentMetadataValue }
|
|
6
|
+
export type ContentMetadata = Record<string, ContentMetadataValue>
|
|
7
|
+
|
|
8
|
+
export const MAX_CONTENT_METADATA_BYTES = 32 * 1024
|
|
9
|
+
const MAX_CONTENT_METADATA_DEPTH = 8
|
|
10
|
+
const MAX_CONTENT_METADATA_NODES = 1_024
|
|
11
|
+
const UNSAFE_METADATA_KEYS = new Set(['__proto__', 'constructor', 'prototype'])
|
|
12
|
+
|
|
13
|
+
export class ContentMetadataError extends Error {
|
|
14
|
+
constructor(
|
|
15
|
+
readonly code: 'content_metadata_invalid' | 'content_metadata_limit_exceeded',
|
|
16
|
+
message: string,
|
|
17
|
+
) {
|
|
18
|
+
super(message)
|
|
19
|
+
this.name = 'ContentMetadataError'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function byteLength(value: string): number {
|
|
24
|
+
return new TextEncoder().encode(value).byteLength
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function assertMetadataValue(value: unknown, depth: number, nodes: { count: number }): void {
|
|
28
|
+
nodes.count += 1
|
|
29
|
+
if (nodes.count > MAX_CONTENT_METADATA_NODES) {
|
|
30
|
+
throw new ContentMetadataError(
|
|
31
|
+
'content_metadata_limit_exceeded',
|
|
32
|
+
`content metadata exceeds ${MAX_CONTENT_METADATA_NODES} values`,
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
if (depth > MAX_CONTENT_METADATA_DEPTH) {
|
|
36
|
+
throw new ContentMetadataError(
|
|
37
|
+
'content_metadata_limit_exceeded',
|
|
38
|
+
`content metadata exceeds depth ${MAX_CONTENT_METADATA_DEPTH}`,
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean') return
|
|
42
|
+
if (typeof value === 'number') {
|
|
43
|
+
if (!Number.isFinite(value)) {
|
|
44
|
+
throw new ContentMetadataError(
|
|
45
|
+
'content_metadata_invalid',
|
|
46
|
+
'content metadata numbers must be finite',
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
if (Array.isArray(value)) {
|
|
52
|
+
for (const item of value) assertMetadataValue(item, depth + 1, nodes)
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
if (typeof value !== 'object') {
|
|
56
|
+
throw new ContentMetadataError(
|
|
57
|
+
'content_metadata_invalid',
|
|
58
|
+
'content metadata must contain only JSON values',
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
const prototype = Object.getPrototypeOf(value)
|
|
62
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
63
|
+
throw new ContentMetadataError(
|
|
64
|
+
'content_metadata_invalid',
|
|
65
|
+
'content metadata objects must use a plain object prototype',
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
for (const [key, child] of Object.entries(value)) {
|
|
69
|
+
if (!key || UNSAFE_METADATA_KEYS.has(key)) {
|
|
70
|
+
throw new ContentMetadataError(
|
|
71
|
+
'content_metadata_invalid',
|
|
72
|
+
'content metadata contains an unsafe key',
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
assertMetadataValue(child, depth + 1, nodes)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function serializeContentMetadata(value: ContentMetadata | undefined): string {
|
|
80
|
+
const metadata = value ?? {}
|
|
81
|
+
if (typeof metadata !== 'object' || metadata === null || Array.isArray(metadata)) {
|
|
82
|
+
throw new ContentMetadataError(
|
|
83
|
+
'content_metadata_invalid',
|
|
84
|
+
'content metadata must be a JSON object',
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
assertMetadataValue(metadata, 0, { count: 0 })
|
|
88
|
+
const encoded = JSON.stringify(metadata)
|
|
89
|
+
if (byteLength(encoded) > MAX_CONTENT_METADATA_BYTES) {
|
|
90
|
+
throw new ContentMetadataError(
|
|
91
|
+
'content_metadata_limit_exceeded',
|
|
92
|
+
`content metadata exceeds ${MAX_CONTENT_METADATA_BYTES} bytes`,
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
return encoded
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function parseContentMetadata(raw: unknown): ContentMetadata {
|
|
99
|
+
if (typeof raw !== 'string') {
|
|
100
|
+
throw new ContentMetadataError(
|
|
101
|
+
'content_metadata_invalid',
|
|
102
|
+
'stored content metadata must be JSON text',
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
if (byteLength(raw) > MAX_CONTENT_METADATA_BYTES) {
|
|
106
|
+
throw new ContentMetadataError(
|
|
107
|
+
'content_metadata_limit_exceeded',
|
|
108
|
+
`stored content metadata exceeds ${MAX_CONTENT_METADATA_BYTES} bytes`,
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
let parsed: unknown
|
|
112
|
+
try {
|
|
113
|
+
parsed = JSON.parse(raw)
|
|
114
|
+
} catch {
|
|
115
|
+
throw new ContentMetadataError(
|
|
116
|
+
'content_metadata_invalid',
|
|
117
|
+
'stored content metadata is not valid JSON',
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
serializeContentMetadata(parsed as ContentMetadata)
|
|
121
|
+
return parsed as ContentMetadata
|
|
122
|
+
}
|
|
@@ -28,6 +28,15 @@ export interface DispatchResult {
|
|
|
28
28
|
triggerToken: string
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export class FoundryDispatchPrerequisiteError extends Error {
|
|
32
|
+
readonly code = 'missing_duration' as const
|
|
33
|
+
|
|
34
|
+
constructor(contentId: string) {
|
|
35
|
+
super(`Content ${contentId} requires a positive finite duration before dispatch`)
|
|
36
|
+
this.name = 'FoundryDispatchPrerequisiteError'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
export interface CallbackInput {
|
|
32
41
|
eventId: string
|
|
33
42
|
eventKind: string
|
|
@@ -82,7 +91,7 @@ function inferVideoSourceKind(sourceUrl: string): string {
|
|
|
82
91
|
/**
|
|
83
92
|
* Dispatch a video or podcast content item to Foundry via the injected hook.
|
|
84
93
|
* Mints a fresh `processing_trigger_token` (UUID), calls
|
|
85
|
-
* `hook.dispatchVideo({ contentId, sourceUrl, kind })`, and writes
|
|
94
|
+
* `hook.dispatchVideo({ contentId, sourceUrl, kind, durationSeconds })`, and writes
|
|
86
95
|
* `processing_correlation_id` + advances to `'queued'` in either
|
|
87
96
|
* `video_content` or `podcast_content`.
|
|
88
97
|
*
|
|
@@ -110,12 +119,13 @@ export async function dispatchToFoundry(
|
|
|
110
119
|
// Determine which media table owns this content id.
|
|
111
120
|
const videoRow = await db
|
|
112
121
|
.prepare(
|
|
113
|
-
'SELECT content_id, video_id, processing_source_url, processing_source_kind FROM video_content WHERE content_id = ?',
|
|
122
|
+
'SELECT content_id, video_id, duration_seconds, processing_source_url, processing_source_kind FROM video_content WHERE content_id = ?',
|
|
114
123
|
)
|
|
115
124
|
.bind(contentId)
|
|
116
125
|
.first<{
|
|
117
126
|
content_id: string
|
|
118
127
|
video_id: string
|
|
128
|
+
duration_seconds: number | null
|
|
119
129
|
processing_source_url: string | null
|
|
120
130
|
processing_source_kind: string | null
|
|
121
131
|
}>()
|
|
@@ -125,6 +135,7 @@ export async function dispatchToFoundry(
|
|
|
125
135
|
let kind: string
|
|
126
136
|
let sourceKind: string | null = null
|
|
127
137
|
let videoId: string | null = null
|
|
138
|
+
let durationSeconds: number | null
|
|
128
139
|
|
|
129
140
|
if (videoRow) {
|
|
130
141
|
table = 'video_content'
|
|
@@ -135,11 +146,18 @@ export async function dispatchToFoundry(
|
|
|
135
146
|
kind = 'video'
|
|
136
147
|
sourceKind = videoRow.processing_source_kind || inferVideoSourceKind(sourceUrl)
|
|
137
148
|
videoId = normalizeVideoId(videoRow.video_id, content.slug)
|
|
149
|
+
durationSeconds = videoRow.duration_seconds
|
|
138
150
|
} else {
|
|
139
151
|
const podcastRow = await db
|
|
140
|
-
.prepare(
|
|
152
|
+
.prepare(
|
|
153
|
+
'SELECT content_id, audio_r2_key, duration_seconds FROM podcast_content WHERE content_id = ?',
|
|
154
|
+
)
|
|
141
155
|
.bind(contentId)
|
|
142
|
-
.first<{
|
|
156
|
+
.first<{
|
|
157
|
+
content_id: string
|
|
158
|
+
audio_r2_key: string | null
|
|
159
|
+
duration_seconds: number | null
|
|
160
|
+
}>()
|
|
143
161
|
|
|
144
162
|
if (!podcastRow) {
|
|
145
163
|
throw new Error(
|
|
@@ -154,6 +172,15 @@ export async function dispatchToFoundry(
|
|
|
154
172
|
kind = 'podcast'
|
|
155
173
|
sourceKind = 'r2_key'
|
|
156
174
|
videoId = normalizeVideoId(content.slug, content.slug)
|
|
175
|
+
durationSeconds = podcastRow.duration_seconds
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (
|
|
179
|
+
typeof durationSeconds !== 'number' ||
|
|
180
|
+
!Number.isFinite(durationSeconds) ||
|
|
181
|
+
durationSeconds <= 0
|
|
182
|
+
) {
|
|
183
|
+
throw new FoundryDispatchPrerequisiteError(contentId)
|
|
157
184
|
}
|
|
158
185
|
|
|
159
186
|
const triggerToken = crypto.randomUUID()
|
|
@@ -162,6 +189,7 @@ export async function dispatchToFoundry(
|
|
|
162
189
|
contentId,
|
|
163
190
|
sourceUrl,
|
|
164
191
|
kind,
|
|
192
|
+
durationSeconds,
|
|
165
193
|
...(sourceKind ? { sourceKind } : {}),
|
|
166
194
|
...(videoId ? { videoId } : {}),
|
|
167
195
|
title: content.title,
|
package/src/engine/index.ts
CHANGED
|
@@ -39,6 +39,16 @@ export {
|
|
|
39
39
|
type VerifyApiKeyResult,
|
|
40
40
|
verifyCmsApiKey,
|
|
41
41
|
} from './api-keys.js'
|
|
42
|
+
// Bounded site-specific metadata retained in immutable content revisions.
|
|
43
|
+
export {
|
|
44
|
+
type ContentMetadata,
|
|
45
|
+
ContentMetadataError,
|
|
46
|
+
type ContentMetadataPrimitive,
|
|
47
|
+
type ContentMetadataValue,
|
|
48
|
+
MAX_CONTENT_METADATA_BYTES,
|
|
49
|
+
parseContentMetadata,
|
|
50
|
+
serializeContentMetadata,
|
|
51
|
+
} from './content-metadata.js'
|
|
42
52
|
// content_contributors engine — list/replace co-authors (P3 Task 3).
|
|
43
53
|
export {
|
|
44
54
|
type ContributorInput,
|
|
@@ -121,6 +131,7 @@ export {
|
|
|
121
131
|
MAX_PUBLICATION_SURFACE_HOOK_TIMEOUT_MS,
|
|
122
132
|
type PublicationAttempt,
|
|
123
133
|
type PublicationAttemptState,
|
|
134
|
+
PublicationInputError,
|
|
124
135
|
PublicationNotFoundError,
|
|
125
136
|
type PublicationOperation,
|
|
126
137
|
PublicationPointerMoveError,
|
|
@@ -150,6 +161,21 @@ export {
|
|
|
150
161
|
type PublishGuardOutcome,
|
|
151
162
|
publishGuardResponseOrNull,
|
|
152
163
|
} from './publish-guard.js'
|
|
164
|
+
// Bounded, pointer-selected public content read model.
|
|
165
|
+
export {
|
|
166
|
+
getPublishedContentById,
|
|
167
|
+
getPublishedContentBySlug,
|
|
168
|
+
type ListPublishedContentOptions,
|
|
169
|
+
listPublishedContent,
|
|
170
|
+
MAX_PUBLISHED_CONTENT_PAGE_BYTES,
|
|
171
|
+
MAX_PUBLISHED_CONTENT_PAGE_SIZE,
|
|
172
|
+
MAX_PUBLISHED_CONTENT_PAYLOAD_BYTES,
|
|
173
|
+
type PublishedContent,
|
|
174
|
+
type PublishedContentCursor,
|
|
175
|
+
type PublishedContentPage,
|
|
176
|
+
PublishedContentReadError,
|
|
177
|
+
type PublishedContentReadErrorCode,
|
|
178
|
+
} from './published-content.js'
|
|
153
179
|
// The publishing engine — content data-access core.
|
|
154
180
|
export {
|
|
155
181
|
type ArticleInput,
|
|
@@ -178,6 +204,7 @@ export {
|
|
|
178
204
|
type UpdateContentInput,
|
|
179
205
|
unpublishContent,
|
|
180
206
|
updateContentItem,
|
|
207
|
+
VerifiedMediaDurationConflictError,
|
|
181
208
|
type VideoInput,
|
|
182
209
|
} from './publisher.js'
|
|
183
210
|
// Verified-user/site reader product state. Analytics remains observation-only.
|