@sudobility/screenwriter_types 0.1.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/CLAUDE.md +50 -0
- package/README.md +34 -0
- package/dist/account/index.d.ts +440 -0
- package/dist/account/index.js +274 -0
- package/dist/admin/index.d.ts +95 -0
- package/dist/admin/index.js +20 -0
- package/dist/ai/index.d.ts +564 -0
- package/dist/ai/index.js +179 -0
- package/dist/api/envelope.d.ts +33 -0
- package/dist/api/envelope.js +140 -0
- package/dist/api/pagination.d.ts +7 -0
- package/dist/api/pagination.js +9 -0
- package/dist/api/routes.d.ts +273 -0
- package/dist/api/routes.js +306 -0
- package/dist/assets/index.d.ts +722 -0
- package/dist/assets/index.js +452 -0
- package/dist/collab/index.d.ts +214 -0
- package/dist/collab/index.js +211 -0
- package/dist/commands/index.d.ts +92 -0
- package/dist/commands/index.js +20 -0
- package/dist/credits/index.d.ts +26 -0
- package/dist/credits/index.js +7 -0
- package/dist/formats/index.d.ts +87 -0
- package/dist/formats/index.js +26 -0
- package/dist/ids/index.d.ts +2 -0
- package/dist/ids/index.js +2 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +33 -0
- package/dist/io/index.d.ts +395 -0
- package/dist/io/index.js +161 -0
- package/dist/jobs/index.d.ts +278 -0
- package/dist/jobs/index.js +138 -0
- package/dist/keys/index.d.ts +53 -0
- package/dist/keys/index.js +22 -0
- package/dist/lifecycle/index.d.ts +263 -0
- package/dist/lifecycle/index.js +148 -0
- package/dist/me/index.d.ts +35 -0
- package/dist/me/index.js +18 -0
- package/dist/packets/index.d.ts +887 -0
- package/dist/packets/index.js +312 -0
- package/dist/projects/index.d.ts +201 -0
- package/dist/projects/index.js +75 -0
- package/dist/public/index.d.ts +95 -0
- package/dist/public/index.js +25 -0
- package/dist/reads/index.d.ts +387 -0
- package/dist/reads/index.js +118 -0
- package/dist/reports/index.d.ts +168 -0
- package/dist/reports/index.js +466 -0
- package/dist/sharing/index.d.ts +256 -0
- package/dist/sharing/index.js +91 -0
- package/dist/sync/codec.d.ts +7 -0
- package/dist/sync/codec.js +91 -0
- package/dist/sync/index.d.ts +382 -0
- package/dist/sync/index.js +262 -0
- package/dist/sync/permissions.d.ts +22 -0
- package/dist/sync/permissions.js +11 -0
- package/dist/templates/index.d.ts +1699 -0
- package/dist/templates/index.js +70 -0
- package/dist/tenancy/index.d.ts +116 -0
- package/dist/tenancy/index.js +102 -0
- package/dist/test/index.d.ts +8 -0
- package/dist/test/index.js +88 -0
- package/dist/versions/index.d.ts +335 -0
- package/dist/versions/index.js +107 -0
- package/package.json +62 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { cursorQuerySchema } from '../api/pagination.js';
|
|
3
|
+
/**
|
|
4
|
+
* The asset library (slice B11; spec 05 §6.13, §8.6, §14.1, spec 11 §3 and §4.5). Assets are workspace files with metadata;
|
|
5
|
+
* bytes never pass through the API (presigned multipart PUT to R2). This file holds the vocabularies, the DTOs and the
|
|
6
|
+
* role-to-target table the server enforces (`ROLE_NOT_ALLOWED_FOR_TARGET`).
|
|
7
|
+
*/
|
|
8
|
+
// ─── vocabularies ────────────────────────────────────────────────────────────
|
|
9
|
+
export const ASSET_KINDS = [
|
|
10
|
+
'image',
|
|
11
|
+
'video',
|
|
12
|
+
'audio',
|
|
13
|
+
'model3d',
|
|
14
|
+
'document',
|
|
15
|
+
'archive',
|
|
16
|
+
'data',
|
|
17
|
+
];
|
|
18
|
+
export const assetKindSchema = z.enum(ASSET_KINDS);
|
|
19
|
+
export const ASSET_ROLES = [
|
|
20
|
+
// launch
|
|
21
|
+
'reference',
|
|
22
|
+
'headshot',
|
|
23
|
+
'photo',
|
|
24
|
+
'logo',
|
|
25
|
+
'beat_image',
|
|
26
|
+
'inline_image',
|
|
27
|
+
'panel_reference',
|
|
28
|
+
'location_scout',
|
|
29
|
+
'mood_board',
|
|
30
|
+
'attachment',
|
|
31
|
+
// future production (valid now, unused by launch UI)
|
|
32
|
+
'turnaround',
|
|
33
|
+
'expression_sheet',
|
|
34
|
+
'costume_design',
|
|
35
|
+
'set_concept',
|
|
36
|
+
'set_plan',
|
|
37
|
+
'storyboard_frame',
|
|
38
|
+
'animatic',
|
|
39
|
+
'previz',
|
|
40
|
+
'rendered_video',
|
|
41
|
+
'rendered_shot',
|
|
42
|
+
'dialogue_audio',
|
|
43
|
+
'voice_sample',
|
|
44
|
+
'voice_profile',
|
|
45
|
+
'music_cue',
|
|
46
|
+
'sound_effect',
|
|
47
|
+
'lip_sync',
|
|
48
|
+
'captions',
|
|
49
|
+
'model3d',
|
|
50
|
+
'model3d_rig',
|
|
51
|
+
'texture',
|
|
52
|
+
'lora',
|
|
53
|
+
'timeline',
|
|
54
|
+
];
|
|
55
|
+
export const assetRoleSchema = z.enum(ASSET_ROLES);
|
|
56
|
+
export const ASSET_ROLE_GROUPS = {
|
|
57
|
+
reference: 'reference',
|
|
58
|
+
headshot: 'reference',
|
|
59
|
+
photo: 'reference',
|
|
60
|
+
logo: 'other',
|
|
61
|
+
beat_image: 'other',
|
|
62
|
+
inline_image: 'other',
|
|
63
|
+
panel_reference: 'storyboard',
|
|
64
|
+
location_scout: 'reference',
|
|
65
|
+
mood_board: 'reference',
|
|
66
|
+
attachment: 'other',
|
|
67
|
+
turnaround: 'design',
|
|
68
|
+
expression_sheet: 'design',
|
|
69
|
+
costume_design: 'design',
|
|
70
|
+
set_concept: 'design',
|
|
71
|
+
set_plan: 'design',
|
|
72
|
+
storyboard_frame: 'storyboard',
|
|
73
|
+
animatic: 'video',
|
|
74
|
+
previz: 'video',
|
|
75
|
+
rendered_video: 'video',
|
|
76
|
+
rendered_shot: 'video',
|
|
77
|
+
dialogue_audio: 'audio',
|
|
78
|
+
voice_sample: 'audio',
|
|
79
|
+
voice_profile: 'audio',
|
|
80
|
+
music_cue: 'audio',
|
|
81
|
+
sound_effect: 'audio',
|
|
82
|
+
lip_sync: 'video',
|
|
83
|
+
captions: 'other',
|
|
84
|
+
model3d: '3d',
|
|
85
|
+
model3d_rig: '3d',
|
|
86
|
+
texture: '3d',
|
|
87
|
+
lora: 'other',
|
|
88
|
+
timeline: 'other',
|
|
89
|
+
};
|
|
90
|
+
export const ASSET_TARGET_KINDS = [
|
|
91
|
+
'document',
|
|
92
|
+
'scene',
|
|
93
|
+
'element',
|
|
94
|
+
'shot',
|
|
95
|
+
'entity',
|
|
96
|
+
'beat',
|
|
97
|
+
'title_page',
|
|
98
|
+
'snapshot',
|
|
99
|
+
];
|
|
100
|
+
export const assetTargetKindSchema = z.enum(ASSET_TARGET_KINDS);
|
|
101
|
+
/**
|
|
102
|
+
* Which target kinds a role may sit on (spec 05 §6.13: "enforces spec 11's role-to-target table"; spec 11 §3.7 lists the
|
|
103
|
+
* roles but not the table, so this is the decision made in B11). A role not listed here may go on any target.
|
|
104
|
+
*/
|
|
105
|
+
export const ASSET_ROLE_TARGETS = {
|
|
106
|
+
headshot: ['entity'],
|
|
107
|
+
turnaround: ['entity'],
|
|
108
|
+
expression_sheet: ['entity'],
|
|
109
|
+
costume_design: ['entity'],
|
|
110
|
+
voice_sample: ['entity'],
|
|
111
|
+
voice_profile: ['entity'],
|
|
112
|
+
set_concept: ['entity', 'scene'],
|
|
113
|
+
set_plan: ['entity', 'scene'],
|
|
114
|
+
location_scout: ['entity', 'scene'],
|
|
115
|
+
beat_image: ['beat'],
|
|
116
|
+
inline_image: ['element'],
|
|
117
|
+
panel_reference: ['element', 'scene', 'shot'],
|
|
118
|
+
logo: ['title_page', 'document'],
|
|
119
|
+
storyboard_frame: ['shot', 'scene'],
|
|
120
|
+
animatic: ['shot', 'scene', 'document'],
|
|
121
|
+
previz: ['shot', 'scene', 'document'],
|
|
122
|
+
rendered_video: ['shot', 'scene', 'document'],
|
|
123
|
+
rendered_shot: ['shot'],
|
|
124
|
+
dialogue_audio: ['element', 'shot', 'scene'],
|
|
125
|
+
music_cue: ['scene', 'shot', 'document'],
|
|
126
|
+
sound_effect: ['scene', 'shot', 'element'],
|
|
127
|
+
lip_sync: ['shot', 'element'],
|
|
128
|
+
captions: ['scene', 'shot', 'document'],
|
|
129
|
+
timeline: ['document', 'scene'],
|
|
130
|
+
};
|
|
131
|
+
/** Roles that only fit an entity of one kind (checked against `proj_entities.kind`). */
|
|
132
|
+
export const ASSET_ROLE_ENTITY_KINDS = {
|
|
133
|
+
headshot: ['character'],
|
|
134
|
+
turnaround: ['character'],
|
|
135
|
+
expression_sheet: ['character'],
|
|
136
|
+
costume_design: ['character'],
|
|
137
|
+
voice_sample: ['character'],
|
|
138
|
+
voice_profile: ['character'],
|
|
139
|
+
set_concept: ['location'],
|
|
140
|
+
set_plan: ['location'],
|
|
141
|
+
location_scout: ['location'],
|
|
142
|
+
};
|
|
143
|
+
export const ASSET_ORIGINS = [
|
|
144
|
+
'upload',
|
|
145
|
+
'import',
|
|
146
|
+
'generated',
|
|
147
|
+
'external_tool',
|
|
148
|
+
];
|
|
149
|
+
export const ASSET_VERSION_STATUSES = [
|
|
150
|
+
'uploading',
|
|
151
|
+
'processing',
|
|
152
|
+
'ready',
|
|
153
|
+
'failed',
|
|
154
|
+
];
|
|
155
|
+
export const STALENESS_VALUES = [
|
|
156
|
+
'fresh',
|
|
157
|
+
'stale',
|
|
158
|
+
'target_deleted',
|
|
159
|
+
'unknown',
|
|
160
|
+
];
|
|
161
|
+
/** Multipart parts are this big (the last one smaller); an upload of at most one part is a single presigned PUT. */
|
|
162
|
+
export const ASSET_PART_SIZE_BYTES = 8 * 1024 * 1024;
|
|
163
|
+
/** How many part PUTs the client helper runs at once. */
|
|
164
|
+
export const ASSET_UPLOAD_CONCURRENCY = 3;
|
|
165
|
+
/** Presigned part URLs and the upload itself live this long (seconds); a resume re-signs. */
|
|
166
|
+
export const ASSET_UPLOAD_TTL_S = 3600;
|
|
167
|
+
/** Presigned GET lifetime for `GET /assets/:aid/versions/:vid/url` (seconds). */
|
|
168
|
+
export const ASSET_URL_TTL_S = 300;
|
|
169
|
+
/** Largest original per kind (spec 11 §3.2). */
|
|
170
|
+
export const ASSET_MAX_BYTES = {
|
|
171
|
+
image: 100 * 1024 ** 2,
|
|
172
|
+
video: 10 * 1024 ** 3,
|
|
173
|
+
audio: 2 * 1024 ** 3,
|
|
174
|
+
model3d: 5 * 1024 ** 3,
|
|
175
|
+
document: 200 * 1024 ** 2,
|
|
176
|
+
archive: 10 * 1024 ** 3,
|
|
177
|
+
data: 50 * 1024 ** 2,
|
|
178
|
+
};
|
|
179
|
+
/** Extension -> kind and the MIME types accepted for it (spec 11 §3.2). The extension must be listed and the magic bytes must agree. */
|
|
180
|
+
export const ASSET_EXTENSIONS = {
|
|
181
|
+
'.png': { kind: 'image', mimes: ['image/png'] },
|
|
182
|
+
'.jpg': { kind: 'image', mimes: ['image/jpeg'] },
|
|
183
|
+
'.jpeg': { kind: 'image', mimes: ['image/jpeg'] },
|
|
184
|
+
'.webp': { kind: 'image', mimes: ['image/webp'] },
|
|
185
|
+
'.avif': { kind: 'image', mimes: ['image/avif'] },
|
|
186
|
+
'.gif': { kind: 'image', mimes: ['image/gif'] },
|
|
187
|
+
'.heic': { kind: 'image', mimes: ['image/heic'] },
|
|
188
|
+
'.heif': { kind: 'image', mimes: ['image/heif'] },
|
|
189
|
+
'.svg': { kind: 'image', mimes: ['image/svg+xml'] },
|
|
190
|
+
'.tif': { kind: 'image', mimes: ['image/tiff'] },
|
|
191
|
+
'.tiff': { kind: 'image', mimes: ['image/tiff'] },
|
|
192
|
+
'.exr': { kind: 'image', mimes: ['image/x-exr'] },
|
|
193
|
+
'.psd': { kind: 'image', mimes: ['image/vnd.adobe.photoshop'] },
|
|
194
|
+
'.mp4': { kind: 'video', mimes: ['video/mp4'] },
|
|
195
|
+
'.mov': { kind: 'video', mimes: ['video/quicktime'] },
|
|
196
|
+
'.webm': { kind: 'video', mimes: ['video/webm'] },
|
|
197
|
+
'.mkv': { kind: 'video', mimes: ['video/x-matroska'] },
|
|
198
|
+
'.wav': { kind: 'audio', mimes: ['audio/wav', 'audio/x-wav', 'audio/wave'] },
|
|
199
|
+
'.aif': { kind: 'audio', mimes: ['audio/x-aiff', 'audio/aiff'] },
|
|
200
|
+
'.aiff': { kind: 'audio', mimes: ['audio/x-aiff', 'audio/aiff'] },
|
|
201
|
+
'.flac': { kind: 'audio', mimes: ['audio/flac'] },
|
|
202
|
+
'.mp3': { kind: 'audio', mimes: ['audio/mpeg'] },
|
|
203
|
+
'.aac': { kind: 'audio', mimes: ['audio/aac'] },
|
|
204
|
+
'.m4a': { kind: 'audio', mimes: ['audio/mp4', 'audio/x-m4a'] },
|
|
205
|
+
'.ogg': { kind: 'audio', mimes: ['audio/ogg'] },
|
|
206
|
+
'.opus': { kind: 'audio', mimes: ['audio/ogg', 'audio/opus'] },
|
|
207
|
+
'.glb': { kind: 'model3d', mimes: ['model/gltf-binary'] },
|
|
208
|
+
'.gltf': { kind: 'model3d', mimes: ['model/gltf+json'] },
|
|
209
|
+
'.usdz': { kind: 'model3d', mimes: ['model/vnd.usdz+zip'] },
|
|
210
|
+
'.blend': {
|
|
211
|
+
kind: 'model3d',
|
|
212
|
+
mimes: ['application/x-blender', 'application/octet-stream'],
|
|
213
|
+
},
|
|
214
|
+
'.fbx': {
|
|
215
|
+
kind: 'model3d',
|
|
216
|
+
mimes: ['model/vnd.fbx', 'application/octet-stream'],
|
|
217
|
+
},
|
|
218
|
+
'.obj': { kind: 'model3d', mimes: ['model/obj', 'text/plain'] },
|
|
219
|
+
'.stl': {
|
|
220
|
+
kind: 'model3d',
|
|
221
|
+
mimes: ['model/stl', 'application/sla', 'application/octet-stream'],
|
|
222
|
+
},
|
|
223
|
+
'.usda': { kind: 'model3d', mimes: ['model/vnd.usda', 'text/plain'] },
|
|
224
|
+
'.usdc': {
|
|
225
|
+
kind: 'model3d',
|
|
226
|
+
mimes: ['model/vnd.usda', 'application/octet-stream'],
|
|
227
|
+
},
|
|
228
|
+
'.pdf': { kind: 'document', mimes: ['application/pdf'] },
|
|
229
|
+
'.txt': { kind: 'document', mimes: ['text/plain'] },
|
|
230
|
+
'.md': { kind: 'document', mimes: ['text/markdown'] },
|
|
231
|
+
'.docx': {
|
|
232
|
+
kind: 'document',
|
|
233
|
+
mimes: [
|
|
234
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
'.zip': {
|
|
238
|
+
kind: 'archive',
|
|
239
|
+
mimes: ['application/zip', 'application/x-zip-compressed'],
|
|
240
|
+
},
|
|
241
|
+
'.json': { kind: 'data', mimes: ['application/json'] },
|
|
242
|
+
'.csv': { kind: 'data', mimes: ['text/csv'] },
|
|
243
|
+
'.srt': { kind: 'data', mimes: ['application/x-subrip', 'text/plain'] },
|
|
244
|
+
'.vtt': { kind: 'data', mimes: ['text/vtt'] },
|
|
245
|
+
'.otio': {
|
|
246
|
+
kind: 'data',
|
|
247
|
+
mimes: ['application/otio+json', 'application/json'],
|
|
248
|
+
},
|
|
249
|
+
'.fcpxml': {
|
|
250
|
+
kind: 'data',
|
|
251
|
+
mimes: ['application/x-fcpxml', 'application/xml', 'text/xml'],
|
|
252
|
+
},
|
|
253
|
+
'.edl': { kind: 'data', mimes: ['application/edl', 'text/plain'] },
|
|
254
|
+
};
|
|
255
|
+
/** `.ext` of a file name, lower-cased ('' when it has none). */
|
|
256
|
+
export const assetExtension = (filename) => {
|
|
257
|
+
const m = /(\.[A-Za-z0-9]{1,10})$/.exec(filename);
|
|
258
|
+
return m ? m[1].toLowerCase() : '';
|
|
259
|
+
};
|
|
260
|
+
/** Client-side pre-check that mirrors the server's: null when the file could be accepted, else why not. */
|
|
261
|
+
export function checkAssetFile(filename, mimeType, sizeBytes, kind) {
|
|
262
|
+
const spec = ASSET_EXTENSIONS[assetExtension(filename)];
|
|
263
|
+
if (!spec)
|
|
264
|
+
return 'type';
|
|
265
|
+
if (spec.kind !== kind)
|
|
266
|
+
return 'kind';
|
|
267
|
+
if (!spec.mimes.includes(mimeType.toLowerCase().split(';')[0].trim()))
|
|
268
|
+
return 'mime';
|
|
269
|
+
if (sizeBytes > ASSET_MAX_BYTES[kind])
|
|
270
|
+
return 'size';
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
// ─── rights and provenance (spec 11 §3.6, §3.8) ──────────────────────────────
|
|
274
|
+
export const assetRightsSchema = z.object({
|
|
275
|
+
ownership: z
|
|
276
|
+
.enum(['owned', 'licensed', 'public_domain', 'generated', 'unknown'])
|
|
277
|
+
.default('unknown'),
|
|
278
|
+
license: z.string().max(500).optional(),
|
|
279
|
+
attribution: z.string().max(500).optional(),
|
|
280
|
+
sourceUrl: z.string().max(2000).optional(),
|
|
281
|
+
restrictions: z.string().max(1000).optional(),
|
|
282
|
+
expiresAt: z.string().optional(),
|
|
283
|
+
containsLikenessOf: z.array(z.string().max(200)).max(50).optional(),
|
|
284
|
+
consentAssetId: z.string().optional(),
|
|
285
|
+
aiTrainingAllowed: z.boolean().default(false),
|
|
286
|
+
});
|
|
287
|
+
export const assetSourceRefSchema = z.object({
|
|
288
|
+
documentId: z.string(),
|
|
289
|
+
snapshotId: z.string().optional(),
|
|
290
|
+
targetKind: z.enum([
|
|
291
|
+
'document',
|
|
292
|
+
'scene',
|
|
293
|
+
'element',
|
|
294
|
+
'shot',
|
|
295
|
+
'entity',
|
|
296
|
+
'beat',
|
|
297
|
+
'title_page',
|
|
298
|
+
]),
|
|
299
|
+
targetId: z.string(),
|
|
300
|
+
sourceHash: z.string(),
|
|
301
|
+
});
|
|
302
|
+
/** What a caller may send as `provenance` (the server fills `upload` and `import` itself). */
|
|
303
|
+
export const assetProvenanceInputSchema = z.discriminatedUnion('origin', [
|
|
304
|
+
z.object({
|
|
305
|
+
origin: z.literal('external_tool'),
|
|
306
|
+
tool: z.string().min(1).max(100),
|
|
307
|
+
toolVersion: z.string().max(100).optional(),
|
|
308
|
+
description: z.string().max(2000).optional(),
|
|
309
|
+
sourceRefs: z.array(assetSourceRefSchema).max(100).default([]),
|
|
310
|
+
createdVia: z.enum(['mcp', 'api', 'app']).default('api'),
|
|
311
|
+
}),
|
|
312
|
+
z.object({
|
|
313
|
+
origin: z.literal('generated'),
|
|
314
|
+
jobId: z.string().optional(),
|
|
315
|
+
adapter: z.string().min(1).max(100),
|
|
316
|
+
provider: z.string().min(1).max(100),
|
|
317
|
+
model: z.string().max(200).optional(),
|
|
318
|
+
prompt: z.string().max(20000).optional(),
|
|
319
|
+
negativePrompt: z.string().max(20000).optional(),
|
|
320
|
+
parameters: z.record(z.string(), z.unknown()).default({}),
|
|
321
|
+
inputs: z
|
|
322
|
+
.array(z.object({
|
|
323
|
+
assetVersionId: z.string().optional(),
|
|
324
|
+
packetHash: z.string().optional(),
|
|
325
|
+
role: z.string(),
|
|
326
|
+
}))
|
|
327
|
+
.max(100)
|
|
328
|
+
.default([]),
|
|
329
|
+
sourceRefs: z.array(assetSourceRefSchema).max(100).default([]),
|
|
330
|
+
costCredits: z.number().optional(),
|
|
331
|
+
providerJobId: z.string().optional(),
|
|
332
|
+
createdVia: z.enum(['mcp', 'api', 'app']).default('api'),
|
|
333
|
+
}),
|
|
334
|
+
]);
|
|
335
|
+
// ─── upload flow (spec 05 §6.13) ─────────────────────────────────────────────
|
|
336
|
+
const sha256HexSchema = z
|
|
337
|
+
.string()
|
|
338
|
+
.regex(/^[0-9a-fA-F]{64}$/, 'sha256Hex must be 64 hex characters');
|
|
339
|
+
export const assetUploadRequestSchema = z.object({
|
|
340
|
+
/** Client-minted `asset_...` id for offline staging; accepted when unused (`ID_CONFLICT` otherwise). */
|
|
341
|
+
assetId: z
|
|
342
|
+
.string()
|
|
343
|
+
.regex(/^asset_[0-9A-Za-z]{10,40}$/)
|
|
344
|
+
.optional(),
|
|
345
|
+
filename: z.string().min(1).max(500),
|
|
346
|
+
mimeType: z.string().min(1).max(200),
|
|
347
|
+
sizeBytes: z.number().int().min(1),
|
|
348
|
+
sha256Hex: sha256HexSchema.optional(),
|
|
349
|
+
kind: assetKindSchema,
|
|
350
|
+
title: z.string().trim().min(1).max(200).optional(),
|
|
351
|
+
/** A new version of an existing asset: the version it derives from. */
|
|
352
|
+
parentVersionId: z.string().min(1).optional(),
|
|
353
|
+
provenance: assetProvenanceInputSchema.optional(),
|
|
354
|
+
rights: assetRightsSchema.partial().optional(),
|
|
355
|
+
});
|
|
356
|
+
export const assetPartsRequestSchema = z.object({
|
|
357
|
+
partNumbers: z.array(z.number().int().min(1).max(10000)).min(1).max(100),
|
|
358
|
+
});
|
|
359
|
+
export const assetCompleteSchema = z.object({
|
|
360
|
+
parts: z
|
|
361
|
+
.array(z.object({
|
|
362
|
+
partNumber: z.number().int().min(1),
|
|
363
|
+
etag: z.string().min(1).max(200),
|
|
364
|
+
}))
|
|
365
|
+
.max(10000),
|
|
366
|
+
sha256Hex: sha256HexSchema.optional(),
|
|
367
|
+
});
|
|
368
|
+
// ─── library routes ──────────────────────────────────────────────────────────
|
|
369
|
+
const linkedToSchema = z
|
|
370
|
+
.string()
|
|
371
|
+
.regex(/^(entity|scene|shot|element):[A-Za-z0-9_-]+$/, 'linkedTo is <entity|scene|shot|element>:<id>');
|
|
372
|
+
export const assetListQuerySchema = cursorQuerySchema.extend({
|
|
373
|
+
workspaceId: z.string().min(1).optional(),
|
|
374
|
+
documentId: z.string().min(1).optional(),
|
|
375
|
+
linkedTo: linkedToSchema.optional(),
|
|
376
|
+
role: assetRoleSchema.optional(),
|
|
377
|
+
kind: assetKindSchema.optional(),
|
|
378
|
+
q: z.string().trim().min(1).max(200).optional(),
|
|
379
|
+
origin: z.enum(ASSET_ORIGINS).optional(),
|
|
380
|
+
});
|
|
381
|
+
export const assetUpdateSchema = z
|
|
382
|
+
.object({
|
|
383
|
+
title: z.string().trim().min(1).max(200).optional(),
|
|
384
|
+
description: z.string().max(5000).optional(),
|
|
385
|
+
rights: assetRightsSchema.partial().optional(),
|
|
386
|
+
})
|
|
387
|
+
.refine((v) => Object.keys(v).length > 0, 'Nothing to update');
|
|
388
|
+
export const ASSET_URL_VARIANTS = [
|
|
389
|
+
'original',
|
|
390
|
+
'thumb_256',
|
|
391
|
+
'thumb_512',
|
|
392
|
+
'preview_1600',
|
|
393
|
+
'poster',
|
|
394
|
+
'proxy_720p',
|
|
395
|
+
'proxy_1080p',
|
|
396
|
+
'preview',
|
|
397
|
+
'waveform',
|
|
398
|
+
'sprite',
|
|
399
|
+
];
|
|
400
|
+
export const assetUrlQuerySchema = z.object({
|
|
401
|
+
variant: z
|
|
402
|
+
.string()
|
|
403
|
+
.regex(/^[a-z0-9_]{1,40}$/)
|
|
404
|
+
.default('original'),
|
|
405
|
+
});
|
|
406
|
+
// ─── links ───────────────────────────────────────────────────────────────────
|
|
407
|
+
export const assetLinkCreateSchema = z.object({
|
|
408
|
+
assetId: z.string().min(1),
|
|
409
|
+
pinnedVersionId: z.string().min(1).optional(),
|
|
410
|
+
/** Null/omitted = a workspace-level link: the target must then be `{kind: 'document', id: <the workspace id>}`. */
|
|
411
|
+
documentId: z.string().min(1).nullable().optional(),
|
|
412
|
+
target: z.object({
|
|
413
|
+
kind: assetTargetKindSchema,
|
|
414
|
+
id: z.string().min(1).max(200),
|
|
415
|
+
}),
|
|
416
|
+
role: assetRoleSchema,
|
|
417
|
+
sortOrder: z.number().int().min(0).max(1_000_000).optional(),
|
|
418
|
+
/** Version-prefixed content hash of the target when the asset was derived from it (spec 11 §4.2). */
|
|
419
|
+
sourceHash: z.string().min(1).max(200).optional(),
|
|
420
|
+
sourceSnapshotId: z.string().min(1).optional(),
|
|
421
|
+
note: z.string().max(2000).optional(),
|
|
422
|
+
});
|
|
423
|
+
export const assetLinkUpdateSchema = z
|
|
424
|
+
.object({
|
|
425
|
+
role: assetRoleSchema.optional(),
|
|
426
|
+
sortOrder: z.number().int().min(0).max(1_000_000).optional(),
|
|
427
|
+
/** `null` unpins (follow the current version). */
|
|
428
|
+
pinnedVersionId: z.string().min(1).nullable().optional(),
|
|
429
|
+
note: z.string().max(2000).optional(),
|
|
430
|
+
})
|
|
431
|
+
.refine((v) => Object.keys(v).length > 0, 'Nothing to update');
|
|
432
|
+
const boolQuery = z.enum(['true', 'false']).transform((v) => v === 'true');
|
|
433
|
+
export const documentAssetLinksQuerySchema = z.object({
|
|
434
|
+
targetKind: assetTargetKindSchema.optional(),
|
|
435
|
+
targetId: z.string().min(1).optional(),
|
|
436
|
+
role: assetRoleSchema.optional(),
|
|
437
|
+
withStaleness: boolQuery.optional(),
|
|
438
|
+
});
|
|
439
|
+
// ─── staleness (spec 11 §4.5) ────────────────────────────────────────────────
|
|
440
|
+
export const STALENESS_TARGET_KINDS = [
|
|
441
|
+
'scene',
|
|
442
|
+
'element',
|
|
443
|
+
'shot',
|
|
444
|
+
'entity',
|
|
445
|
+
];
|
|
446
|
+
export const documentStalenessQuerySchema = z.object({
|
|
447
|
+
targetKind: z.enum(STALENESS_TARGET_KINDS).optional(),
|
|
448
|
+
});
|
|
449
|
+
// ─── the `asset.derive` job (a documented stub: see the API's CLAUDE.md) ─────
|
|
450
|
+
export const assetDeriveInputSchema = z.object({
|
|
451
|
+
assetVersionId: z.string().min(1),
|
|
452
|
+
});
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collaboration DTOs (spec 05 §6.15 notes/mentions/chat/activity, §6.16 notifications, §6.24 devices/push,
|
|
3
|
+
* §6.26 `writingReminder` prefs; slice B12). Tables: `note_mentions`, `document_chat_messages`, `activity_events`,
|
|
4
|
+
* `notifications`, `devices`.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
export declare const NOTIFICATION_KINDS: readonly ["mention", "note_reply", "note_on_my_document", "snapshot_comment", "chat_mention", "invitation", "share_granted", "snapshot_opened_by_collaborator", "job_finished", "job_failed", "ai_suggestions_ready", "ai_refunded", "export_ready", "watermark_batch_sent", "writing_reminder", "credits_low", "purchase_completed", "account_deletion_scheduled"];
|
|
8
|
+
export type NotificationKind = (typeof NOTIFICATION_KINDS)[number];
|
|
9
|
+
export declare const NOTIFICATION_EMAIL_MODES: readonly ["immediate", "digest", "off"];
|
|
10
|
+
export type NotificationEmailMode = (typeof NOTIFICATION_EMAIL_MODES)[number];
|
|
11
|
+
export interface NotificationKindPrefs {
|
|
12
|
+
inApp: boolean;
|
|
13
|
+
push: boolean;
|
|
14
|
+
email: NotificationEmailMode;
|
|
15
|
+
}
|
|
16
|
+
/** Every kind gets a sane default; a person may override any of `inApp`/`push`/`email` per kind. */
|
|
17
|
+
export declare function defaultNotificationKindPrefs(kind: NotificationKind): NotificationKindPrefs;
|
|
18
|
+
export interface NotificationPrefs {
|
|
19
|
+
kinds: Record<NotificationKind, NotificationKindPrefs>;
|
|
20
|
+
/** `HH:MM` local time (§6.26 `system.writingReminder`); `null` = the reminder job never fires for this user. */
|
|
21
|
+
writingReminderTime: string | null;
|
|
22
|
+
}
|
|
23
|
+
export declare function defaultNotificationPrefs(): NotificationPrefs;
|
|
24
|
+
/** `PUT /me/notification-prefs`: a sparse per-kind patch (only the kinds/fields given change) plus the reminder time. */
|
|
25
|
+
export declare const notificationPrefsSchema: z.ZodObject<{
|
|
26
|
+
kinds: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
27
|
+
inApp: z.ZodOptional<z.ZodBoolean>;
|
|
28
|
+
push: z.ZodOptional<z.ZodBoolean>;
|
|
29
|
+
email: z.ZodOptional<z.ZodEnum<{
|
|
30
|
+
off: "off";
|
|
31
|
+
immediate: "immediate";
|
|
32
|
+
digest: "digest";
|
|
33
|
+
}>>;
|
|
34
|
+
}, z.core.$strip>>>;
|
|
35
|
+
writingReminderTime: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
export type NotificationPrefsUpdate = z.infer<typeof notificationPrefsSchema>;
|
|
38
|
+
/** `{...current, ...update}` per kind (a patch's fields win); `writingReminderTime` replaces whole. */
|
|
39
|
+
export declare function mergeNotificationPrefs(current: NotificationPrefs, update: NotificationPrefsUpdate): NotificationPrefs;
|
|
40
|
+
export interface Notification {
|
|
41
|
+
id: string;
|
|
42
|
+
kind: NotificationKind;
|
|
43
|
+
/** Ids and display strings only; never document/script content (spec 05 §8.7). */
|
|
44
|
+
payload: Record<string, unknown>;
|
|
45
|
+
workspaceId: string | null;
|
|
46
|
+
documentId: string | null;
|
|
47
|
+
readAt: string | null;
|
|
48
|
+
createdAt: string;
|
|
49
|
+
}
|
|
50
|
+
export declare const notificationsQuerySchema: z.ZodObject<{
|
|
51
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
52
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
53
|
+
unread: z.ZodOptional<z.ZodPipe<z.ZodEnum<{
|
|
54
|
+
true: "true";
|
|
55
|
+
false: "false";
|
|
56
|
+
}>, z.ZodTransform<boolean, "true" | "false">>>;
|
|
57
|
+
}, z.core.$strip>;
|
|
58
|
+
export type NotificationsQuery = z.infer<typeof notificationsQuerySchema>;
|
|
59
|
+
export declare const notificationsReadSchema: z.ZodObject<{
|
|
60
|
+
ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
61
|
+
all: z.ZodOptional<z.ZodLiteral<true>>;
|
|
62
|
+
before: z.ZodOptional<z.ZodISODateTime>;
|
|
63
|
+
}, z.core.$strip>;
|
|
64
|
+
export type NotificationsReadRequest = z.infer<typeof notificationsReadSchema>;
|
|
65
|
+
export interface NotificationsReadResponse {
|
|
66
|
+
updated: number;
|
|
67
|
+
}
|
|
68
|
+
export interface NotificationDeleteResponse {
|
|
69
|
+
deleted: true;
|
|
70
|
+
}
|
|
71
|
+
export interface MentionWithoutAccess {
|
|
72
|
+
noteId: string;
|
|
73
|
+
replyId?: string;
|
|
74
|
+
userId: string;
|
|
75
|
+
email: string | null;
|
|
76
|
+
createdAt: string;
|
|
77
|
+
}
|
|
78
|
+
export declare const CHAT_BODY_MAX = 4000;
|
|
79
|
+
export declare const CHAT_EDIT_WINDOW_MINUTES = 15;
|
|
80
|
+
/** Y.Doc notes use plain `mentions: string[]` (user ids, no offset/length: writing_core's simplification); chat mirrors it in the DTO for consistency with the spec's shape, offset/length optional. */
|
|
81
|
+
export declare const mentionRefSchema: z.ZodObject<{
|
|
82
|
+
userId: z.ZodString;
|
|
83
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
84
|
+
length: z.ZodOptional<z.ZodNumber>;
|
|
85
|
+
}, z.core.$strip>;
|
|
86
|
+
export type MentionRef = z.infer<typeof mentionRefSchema>;
|
|
87
|
+
export interface ChatMessage {
|
|
88
|
+
id: string;
|
|
89
|
+
documentId: string;
|
|
90
|
+
authorId: string | null;
|
|
91
|
+
body: string;
|
|
92
|
+
mentions: MentionRef[];
|
|
93
|
+
createdAt: string;
|
|
94
|
+
editedAt: string | null;
|
|
95
|
+
deletedAt: string | null;
|
|
96
|
+
}
|
|
97
|
+
export declare const chatMessageCreateSchema: z.ZodObject<{
|
|
98
|
+
clientMessageId: z.ZodString;
|
|
99
|
+
body: z.ZodString;
|
|
100
|
+
mentions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
101
|
+
userId: z.ZodString;
|
|
102
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
103
|
+
length: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
}, z.core.$strip>>>;
|
|
105
|
+
}, z.core.$strip>;
|
|
106
|
+
export type ChatMessageCreateRequest = z.infer<typeof chatMessageCreateSchema>;
|
|
107
|
+
export declare const chatMessageUpdateSchema: z.ZodObject<{
|
|
108
|
+
body: z.ZodString;
|
|
109
|
+
}, z.core.$strip>;
|
|
110
|
+
export type ChatMessageUpdateRequest = z.infer<typeof chatMessageUpdateSchema>;
|
|
111
|
+
export declare const chatQuerySchema: z.ZodObject<{
|
|
112
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
113
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
114
|
+
before: z.ZodOptional<z.ZodISODateTime>;
|
|
115
|
+
}, z.core.$strip>;
|
|
116
|
+
export type ChatQuery = z.infer<typeof chatQuerySchema>;
|
|
117
|
+
export interface ChatMessageDeleteResponse {
|
|
118
|
+
deletedAt: string;
|
|
119
|
+
}
|
|
120
|
+
export declare const ACTIVITY_KINDS: readonly ["document.created", "document.renamed", "document.moved", "document.trashed", "document.restored", "session.edited", "snapshot.created", "snapshot.opened", "snapshot.forked", "version.restored", "template.applied", "import.over", "revision.setCreated", "locks.changed", "changes.decided", "ai.jobCompleted", "ai.suggestionsDecided", "share.granted", "share.linkCreated", "member.joined", "member.left", "mcp.commandsApplied"];
|
|
121
|
+
export type ActivityKind = (typeof ACTIVITY_KINDS)[number];
|
|
122
|
+
export declare const ACTOR_KINDS: readonly ["user", "mcp", "api", "ai", "system"];
|
|
123
|
+
export type ActorKind = (typeof ACTOR_KINDS)[number];
|
|
124
|
+
export interface ActivitySummary {
|
|
125
|
+
i18nKey: string;
|
|
126
|
+
params?: Record<string, unknown>;
|
|
127
|
+
}
|
|
128
|
+
export interface ActivityEvent {
|
|
129
|
+
id: string;
|
|
130
|
+
kind: ActivityKind;
|
|
131
|
+
actorId: string | null;
|
|
132
|
+
actorKind: ActorKind;
|
|
133
|
+
summary: ActivitySummary;
|
|
134
|
+
targetIds: string[];
|
|
135
|
+
createdAt: string;
|
|
136
|
+
}
|
|
137
|
+
/** `GET /workspaces/:wid/activity` items also carry the document they happened on. */
|
|
138
|
+
export interface WorkspaceActivityEvent extends ActivityEvent {
|
|
139
|
+
documentId: string | null;
|
|
140
|
+
}
|
|
141
|
+
export declare const activityQuerySchema: z.ZodObject<{
|
|
142
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
143
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
144
|
+
kinds: z.ZodOptional<z.ZodPreprocess<z.ZodArray<z.ZodString>, unknown>>;
|
|
145
|
+
}, z.core.$strip>;
|
|
146
|
+
export type ActivityQuery = z.infer<typeof activityQuerySchema>;
|
|
147
|
+
export declare const workspaceActivityQuerySchema: z.ZodObject<{
|
|
148
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
149
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
150
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
151
|
+
}, z.core.$strip>;
|
|
152
|
+
export type WorkspaceActivityQuery = z.infer<typeof workspaceActivityQuerySchema>;
|
|
153
|
+
export declare const DEVICE_PLATFORMS: readonly ["web", "ios", "ipados", "android", "macos", "windows"];
|
|
154
|
+
export type DevicePlatform = (typeof DEVICE_PLATFORMS)[number];
|
|
155
|
+
export declare const PUSH_PLATFORMS: readonly ["apns", "fcm", "wns", "webpush"];
|
|
156
|
+
export type PushPlatform = (typeof PUSH_PLATFORMS)[number];
|
|
157
|
+
export interface Device {
|
|
158
|
+
id: string;
|
|
159
|
+
displayName: string;
|
|
160
|
+
platform: DevicePlatform;
|
|
161
|
+
appVersion: string;
|
|
162
|
+
lastSeenAt: string;
|
|
163
|
+
revokedAt: string | null;
|
|
164
|
+
/** True for the device making the current request (matched by id). */
|
|
165
|
+
current: boolean;
|
|
166
|
+
/** Per-device: offline availability (F-SAFE-004), local-backup status; never per-user data. */
|
|
167
|
+
settings: Record<string, unknown>;
|
|
168
|
+
}
|
|
169
|
+
export declare const deviceCreateSchema: z.ZodObject<{
|
|
170
|
+
id: z.ZodString;
|
|
171
|
+
installId: z.ZodString;
|
|
172
|
+
displayName: z.ZodString;
|
|
173
|
+
platform: z.ZodEnum<{
|
|
174
|
+
web: "web";
|
|
175
|
+
ios: "ios";
|
|
176
|
+
ipados: "ipados";
|
|
177
|
+
android: "android";
|
|
178
|
+
macos: "macos";
|
|
179
|
+
windows: "windows";
|
|
180
|
+
}>;
|
|
181
|
+
appVersion: z.ZodString;
|
|
182
|
+
}, z.core.$strip>;
|
|
183
|
+
export type DeviceCreateRequest = z.infer<typeof deviceCreateSchema>;
|
|
184
|
+
export interface DeviceCreateResponse extends Device {
|
|
185
|
+
/** A second live install presenting the same `id` gets a fresh one (spec 03 §12.8); this is that fresh id. */
|
|
186
|
+
reassignedId?: string;
|
|
187
|
+
}
|
|
188
|
+
export declare const deviceUpdateSchema: z.ZodObject<{
|
|
189
|
+
displayName: z.ZodString;
|
|
190
|
+
}, z.core.$strip>;
|
|
191
|
+
export type DeviceUpdateRequest = z.infer<typeof deviceUpdateSchema>;
|
|
192
|
+
export interface DeviceRevokeResponse {
|
|
193
|
+
revokedAt: string;
|
|
194
|
+
}
|
|
195
|
+
export declare const pushTokenSetSchema: z.ZodObject<{
|
|
196
|
+
platform: z.ZodEnum<{
|
|
197
|
+
apns: "apns";
|
|
198
|
+
fcm: "fcm";
|
|
199
|
+
wns: "wns";
|
|
200
|
+
webpush: "webpush";
|
|
201
|
+
}>;
|
|
202
|
+
token: z.ZodString;
|
|
203
|
+
environment: z.ZodOptional<z.ZodEnum<{
|
|
204
|
+
production: "production";
|
|
205
|
+
sandbox: "sandbox";
|
|
206
|
+
}>>;
|
|
207
|
+
}, z.core.$strip>;
|
|
208
|
+
export type PushTokenSetRequest = z.infer<typeof pushTokenSetSchema>;
|
|
209
|
+
export interface PushTokenSetResponse {
|
|
210
|
+
registeredAt: string;
|
|
211
|
+
}
|
|
212
|
+
export interface PushTokenDeleteResponse {
|
|
213
|
+
deleted: true;
|
|
214
|
+
}
|