@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,70 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** `GET /templates` query: user templates always; `workspaceId` adds that workspace's; `scope` narrows. */
|
|
3
|
+
export const templateListQuerySchema = z.object({
|
|
4
|
+
category: z.string().optional(),
|
|
5
|
+
workspaceId: z.string().optional(),
|
|
6
|
+
scope: z.enum(['builtin', 'user', 'workspace']).optional(),
|
|
7
|
+
});
|
|
8
|
+
/** `GET /templates/:tid?version=`: an older version of a user/workspace template (immutable). */
|
|
9
|
+
export const templateGetQuerySchema = z.object({
|
|
10
|
+
version: z.coerce.number().int().min(1).optional(),
|
|
11
|
+
});
|
|
12
|
+
// ─── B14: template lifecycle (spec 05 §6.8) ─────────────────────────────────
|
|
13
|
+
/** The body is validated server-side with writing_core's `TemplateJSON` schema (`TEMPLATE_INVALID` with the issues). */
|
|
14
|
+
const templateBody = z.custom((v) => typeof v === 'object' && v !== null && !Array.isArray(v), {
|
|
15
|
+
message: 'template must be an object',
|
|
16
|
+
});
|
|
17
|
+
export const templateCreateSchema = z
|
|
18
|
+
.object({
|
|
19
|
+
scope: z.enum(['user', 'workspace']),
|
|
20
|
+
workspaceId: z.string().min(1).optional(),
|
|
21
|
+
template: templateBody,
|
|
22
|
+
})
|
|
23
|
+
.refine((v) => v.scope !== 'workspace' || !!v.workspaceId, {
|
|
24
|
+
message: 'workspaceId is required for a workspace template',
|
|
25
|
+
path: ['workspaceId'],
|
|
26
|
+
});
|
|
27
|
+
export const templateVersionCreateSchema = z.object({ template: templateBody });
|
|
28
|
+
export const templateUpdateSchema = z.object({
|
|
29
|
+
name: z.string().trim().min(1).max(120).optional(),
|
|
30
|
+
description: z.string().max(2000).nullable().optional(),
|
|
31
|
+
category: z.string().min(1).max(40).optional(),
|
|
32
|
+
});
|
|
33
|
+
/** Template file formats: Fadewright's own JSON and the two foreign ones spec 04 §4.3 names. */
|
|
34
|
+
export const TEMPLATE_FILE_FORMATS = [
|
|
35
|
+
'fwtemplate',
|
|
36
|
+
'fadein-template',
|
|
37
|
+
'fdxt',
|
|
38
|
+
];
|
|
39
|
+
/** `{ "format": "fadewright-template", "formatVersion": 1, "template": <TemplateJSON> }` (spec 04 §4.3.1). */
|
|
40
|
+
export const FWTEMPLATE_FORMAT = 'fadewright-template';
|
|
41
|
+
export const FWTEMPLATE_FORMAT_VERSION = 1;
|
|
42
|
+
/**
|
|
43
|
+
* `POST /templates/import`. Spec 05's `importId` flow is `templateImportByIdSchema` (B16); this body form (the file inline, like
|
|
44
|
+
* `documents/import`) keeps working. The result is the created template.
|
|
45
|
+
*/
|
|
46
|
+
export const templateImportSchema = z
|
|
47
|
+
.object({
|
|
48
|
+
scope: z.enum(['user', 'workspace']),
|
|
49
|
+
workspaceId: z.string().min(1).optional(),
|
|
50
|
+
filename: z.string().min(1).max(255),
|
|
51
|
+
contentB64: z.string().min(1),
|
|
52
|
+
})
|
|
53
|
+
.refine((v) => v.scope !== 'workspace' || !!v.workspaceId, {
|
|
54
|
+
message: 'workspaceId is required for a workspace template',
|
|
55
|
+
path: ['workspaceId'],
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* The upload flow (B16): `POST /imports {templateTarget, filename, sizeBytes, sha256Hex}`, PUT the file, then
|
|
59
|
+
* `POST /templates/import {importId}`. Scope and workspace come from the upload, never from this request.
|
|
60
|
+
*/
|
|
61
|
+
export const templateImportByIdSchema = z.object({
|
|
62
|
+
importId: z.string().min(1),
|
|
63
|
+
});
|
|
64
|
+
/** `GET /templates/:tid/export?format=` (only `fwtemplate` is built). */
|
|
65
|
+
export const templateExportQuerySchema = z.object({
|
|
66
|
+
format: z
|
|
67
|
+
.enum(['fwtemplate', 'json', 'fadein-template', 'fdxt'])
|
|
68
|
+
.default('fwtemplate'),
|
|
69
|
+
version: z.coerce.number().int().min(1).optional(),
|
|
70
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const WORKSPACE_KINDS: readonly ["personal", "team"];
|
|
3
|
+
export type WorkspaceKind = (typeof WORKSPACE_KINDS)[number];
|
|
4
|
+
/** Ordered by authority (spec 05 §5.2). */
|
|
5
|
+
export declare const ROLES: readonly ["owner", "admin", "writer", "commenter", "viewer"];
|
|
6
|
+
export type Role = (typeof ROLES)[number];
|
|
7
|
+
export declare const workspaceKindSchema: z.ZodEnum<{
|
|
8
|
+
personal: "personal";
|
|
9
|
+
team: "team";
|
|
10
|
+
}>;
|
|
11
|
+
export declare const roleSchema: z.ZodEnum<{
|
|
12
|
+
owner: "owner";
|
|
13
|
+
admin: "admin";
|
|
14
|
+
writer: "writer";
|
|
15
|
+
commenter: "commenter";
|
|
16
|
+
viewer: "viewer";
|
|
17
|
+
}>;
|
|
18
|
+
export interface WorkspaceSummary {
|
|
19
|
+
id: string;
|
|
20
|
+
kind: WorkspaceKind;
|
|
21
|
+
name: string;
|
|
22
|
+
avatarAssetId: string | null;
|
|
23
|
+
}
|
|
24
|
+
export interface Workspace extends WorkspaceSummary {
|
|
25
|
+
defaultTemplateId: string | null;
|
|
26
|
+
defaultLanguage: string;
|
|
27
|
+
aiEnabled: boolean;
|
|
28
|
+
/** F-SET-009: false disables every existing `anyone with the link` share link of the workspace and refuses new ones. */
|
|
29
|
+
allowPublicLinks: boolean;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
updatedAt: string;
|
|
32
|
+
}
|
|
33
|
+
/** `GET /workspaces` item: summary plus the caller's role. */
|
|
34
|
+
export type WorkspaceListItem = WorkspaceSummary & {
|
|
35
|
+
role: Role;
|
|
36
|
+
};
|
|
37
|
+
/** `GET /workspaces/:wid` */
|
|
38
|
+
export type WorkspaceDetail = Workspace & {
|
|
39
|
+
role: Role;
|
|
40
|
+
memberCount: number;
|
|
41
|
+
storageBytes: number;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Every permission with the LOWEST role that holds it. The matrix is monotonic (a higher role has
|
|
45
|
+
* everything a lower one has), so `ROLE_PERMISSIONS` is derived from this table.
|
|
46
|
+
* Notes on the two permissions with a condition beyond the role:
|
|
47
|
+
* - `share.manage` for a writer only applies to documents/projects they created (checked by the API).
|
|
48
|
+
* - `project.trash` / `project.restore` for a writer only applies to projects they created.
|
|
49
|
+
*/
|
|
50
|
+
export declare const PERMISSION_MIN_ROLE: {
|
|
51
|
+
readonly 'workspace.read': "viewer";
|
|
52
|
+
readonly 'workspace.update': "admin";
|
|
53
|
+
readonly 'workspace.aiToggle': "owner";
|
|
54
|
+
readonly 'workspace.audit': "admin";
|
|
55
|
+
readonly 'workspace.delete': "owner";
|
|
56
|
+
readonly 'workspace.transfer': "owner";
|
|
57
|
+
readonly 'workspace.leave': "viewer";
|
|
58
|
+
readonly 'members.read': "viewer";
|
|
59
|
+
readonly 'members.invite': "admin";
|
|
60
|
+
readonly 'members.updateRole': "admin";
|
|
61
|
+
readonly 'members.remove': "admin";
|
|
62
|
+
readonly 'project.create': "writer";
|
|
63
|
+
readonly 'project.read': "viewer";
|
|
64
|
+
readonly 'project.update': "writer";
|
|
65
|
+
readonly 'project.trash': "writer";
|
|
66
|
+
readonly 'project.restore': "writer";
|
|
67
|
+
readonly 'project.purge': "admin";
|
|
68
|
+
readonly 'document.create': "writer";
|
|
69
|
+
readonly 'document.read': "viewer";
|
|
70
|
+
readonly 'document.export': "viewer";
|
|
71
|
+
readonly 'document.edit': "writer";
|
|
72
|
+
readonly 'document.comment': "commenter";
|
|
73
|
+
readonly 'document.chat': "commenter";
|
|
74
|
+
readonly 'document.activity': "viewer";
|
|
75
|
+
readonly 'document.trash': "writer";
|
|
76
|
+
readonly 'document.restore': "writer";
|
|
77
|
+
readonly 'document.move': "writer";
|
|
78
|
+
readonly 'document.lock': "writer";
|
|
79
|
+
readonly 'document.aiExclude': "writer";
|
|
80
|
+
readonly 'snapshot.create': "writer";
|
|
81
|
+
readonly 'snapshot.open': "writer";
|
|
82
|
+
readonly 'snapshot.fork': "writer";
|
|
83
|
+
readonly 'snapshot.cherryPick': "writer";
|
|
84
|
+
readonly 'snapshot.appendNote': "writer";
|
|
85
|
+
readonly 'snapshot.read': "viewer";
|
|
86
|
+
readonly 'snapshot.compare': "viewer";
|
|
87
|
+
readonly 'snapshot.hideForSelf': "viewer";
|
|
88
|
+
readonly 'version.restore': "writer";
|
|
89
|
+
readonly 'version.restoreAsCopy': "writer";
|
|
90
|
+
readonly 'share.manage': "writer";
|
|
91
|
+
readonly 'assets.upload': "writer";
|
|
92
|
+
readonly 'assets.link': "writer";
|
|
93
|
+
readonly 'assets.read': "viewer";
|
|
94
|
+
readonly 'ai.run': "writer";
|
|
95
|
+
readonly 'ai.review': "commenter";
|
|
96
|
+
readonly 'jobs.media': "writer";
|
|
97
|
+
readonly 'templates.manage': "writer";
|
|
98
|
+
readonly 'reports.run': "viewer";
|
|
99
|
+
readonly 'apiKeys.use': "viewer";
|
|
100
|
+
};
|
|
101
|
+
export type Permission = keyof typeof PERMISSION_MIN_ROLE;
|
|
102
|
+
export declare const PERMISSIONS: Permission[];
|
|
103
|
+
/** True when `a` has at least the authority of `b`. */
|
|
104
|
+
export declare const roleAtLeast: (a: Role, b: Role) => boolean;
|
|
105
|
+
/** The higher-authority of the given roles (nulls ignored); null when there are none. */
|
|
106
|
+
export declare function maxRole(...roles: (Role | null | undefined)[]): Role | null;
|
|
107
|
+
/** The lower-authority of two roles (used to cap an API key by its scope). */
|
|
108
|
+
export declare const minRole: (a: Role, b: Role) => Role;
|
|
109
|
+
export declare const ROLE_PERMISSIONS: Record<Role, readonly Permission[]>;
|
|
110
|
+
/** The only check routes call. */
|
|
111
|
+
export declare const hasPermission: (role: Role, permission: Permission) => boolean;
|
|
112
|
+
/** Lowest role that holds `permission` (goes in a 403's `details.requiredRole`). */
|
|
113
|
+
export declare const requiredRoleFor: (permission: Permission) => Role;
|
|
114
|
+
/** Roles a share grant or a project/document invitation may carry: `owner` is never granted by share. */
|
|
115
|
+
export declare const SHARE_ROLES: readonly ["admin", "writer", "commenter", "viewer"];
|
|
116
|
+
export type ShareRole = (typeof SHARE_ROLES)[number];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const WORKSPACE_KINDS = ['personal', 'team'];
|
|
3
|
+
/** Ordered by authority (spec 05 §5.2). */
|
|
4
|
+
export const ROLES = [
|
|
5
|
+
'owner',
|
|
6
|
+
'admin',
|
|
7
|
+
'writer',
|
|
8
|
+
'commenter',
|
|
9
|
+
'viewer',
|
|
10
|
+
];
|
|
11
|
+
export const workspaceKindSchema = z.enum(WORKSPACE_KINDS);
|
|
12
|
+
export const roleSchema = z.enum(ROLES);
|
|
13
|
+
// ─── Permissions (spec 05 §5.2) ─────────────────────────────────────────────
|
|
14
|
+
/**
|
|
15
|
+
* Every permission with the LOWEST role that holds it. The matrix is monotonic (a higher role has
|
|
16
|
+
* everything a lower one has), so `ROLE_PERMISSIONS` is derived from this table.
|
|
17
|
+
* Notes on the two permissions with a condition beyond the role:
|
|
18
|
+
* - `share.manage` for a writer only applies to documents/projects they created (checked by the API).
|
|
19
|
+
* - `project.trash` / `project.restore` for a writer only applies to projects they created.
|
|
20
|
+
*/
|
|
21
|
+
export const PERMISSION_MIN_ROLE = {
|
|
22
|
+
'workspace.read': 'viewer',
|
|
23
|
+
'workspace.update': 'admin',
|
|
24
|
+
'workspace.aiToggle': 'owner',
|
|
25
|
+
'workspace.audit': 'admin',
|
|
26
|
+
'workspace.delete': 'owner',
|
|
27
|
+
'workspace.transfer': 'owner',
|
|
28
|
+
'workspace.leave': 'viewer',
|
|
29
|
+
'members.read': 'viewer',
|
|
30
|
+
'members.invite': 'admin',
|
|
31
|
+
'members.updateRole': 'admin',
|
|
32
|
+
'members.remove': 'admin',
|
|
33
|
+
'project.create': 'writer',
|
|
34
|
+
'project.read': 'viewer',
|
|
35
|
+
'project.update': 'writer',
|
|
36
|
+
'project.trash': 'writer',
|
|
37
|
+
'project.restore': 'writer',
|
|
38
|
+
'project.purge': 'admin',
|
|
39
|
+
'document.create': 'writer',
|
|
40
|
+
'document.read': 'viewer',
|
|
41
|
+
'document.export': 'viewer',
|
|
42
|
+
'document.edit': 'writer',
|
|
43
|
+
'document.comment': 'commenter',
|
|
44
|
+
'document.chat': 'commenter',
|
|
45
|
+
'document.activity': 'viewer',
|
|
46
|
+
'document.trash': 'writer',
|
|
47
|
+
'document.restore': 'writer',
|
|
48
|
+
'document.move': 'writer',
|
|
49
|
+
'document.lock': 'writer',
|
|
50
|
+
'document.aiExclude': 'writer',
|
|
51
|
+
'snapshot.create': 'writer',
|
|
52
|
+
'snapshot.open': 'writer',
|
|
53
|
+
'snapshot.fork': 'writer',
|
|
54
|
+
'snapshot.cherryPick': 'writer',
|
|
55
|
+
'snapshot.appendNote': 'writer',
|
|
56
|
+
'snapshot.read': 'viewer',
|
|
57
|
+
'snapshot.compare': 'viewer',
|
|
58
|
+
'snapshot.hideForSelf': 'viewer',
|
|
59
|
+
'version.restore': 'writer',
|
|
60
|
+
'version.restoreAsCopy': 'writer',
|
|
61
|
+
'share.manage': 'writer',
|
|
62
|
+
'assets.upload': 'writer',
|
|
63
|
+
'assets.link': 'writer',
|
|
64
|
+
'assets.read': 'viewer',
|
|
65
|
+
'ai.run': 'writer',
|
|
66
|
+
'ai.review': 'commenter',
|
|
67
|
+
'jobs.media': 'writer',
|
|
68
|
+
'templates.manage': 'writer',
|
|
69
|
+
'reports.run': 'viewer',
|
|
70
|
+
'apiKeys.use': 'viewer',
|
|
71
|
+
};
|
|
72
|
+
export const PERMISSIONS = Object.keys(PERMISSION_MIN_ROLE);
|
|
73
|
+
/** 0 = owner ... 4 = viewer; a smaller number is more authority. */
|
|
74
|
+
const RANK = {
|
|
75
|
+
owner: 0,
|
|
76
|
+
admin: 1,
|
|
77
|
+
writer: 2,
|
|
78
|
+
commenter: 3,
|
|
79
|
+
viewer: 4,
|
|
80
|
+
};
|
|
81
|
+
/** True when `a` has at least the authority of `b`. */
|
|
82
|
+
export const roleAtLeast = (a, b) => RANK[a] <= RANK[b];
|
|
83
|
+
/** The higher-authority of the given roles (nulls ignored); null when there are none. */
|
|
84
|
+
export function maxRole(...roles) {
|
|
85
|
+
let best = null;
|
|
86
|
+
for (const r of roles)
|
|
87
|
+
if (r && (best === null || RANK[r] < RANK[best]))
|
|
88
|
+
best = r;
|
|
89
|
+
return best;
|
|
90
|
+
}
|
|
91
|
+
/** The lower-authority of two roles (used to cap an API key by its scope). */
|
|
92
|
+
export const minRole = (a, b) => (RANK[a] >= RANK[b] ? a : b);
|
|
93
|
+
export const ROLE_PERMISSIONS = Object.fromEntries(ROLES.map((role) => [
|
|
94
|
+
role,
|
|
95
|
+
PERMISSIONS.filter((p) => roleAtLeast(role, PERMISSION_MIN_ROLE[p])),
|
|
96
|
+
]));
|
|
97
|
+
/** The only check routes call. */
|
|
98
|
+
export const hasPermission = (role, permission) => roleAtLeast(role, PERMISSION_MIN_ROLE[permission]);
|
|
99
|
+
/** Lowest role that holds `permission` (goes in a 403's `details.requiredRole`). */
|
|
100
|
+
export const requiredRoleFor = (permission) => PERMISSION_MIN_ROLE[permission];
|
|
101
|
+
/** Roles a share grant or a project/document invitation may carry: `owner` is never granted by share. */
|
|
102
|
+
export const SHARE_ROLES = ['admin', 'writer', 'commenter', 'viewer'];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Fixture factories for consumers' tests (`@sudobility/screenwriter_types/test`). */
|
|
2
|
+
import type { Workspace } from '../tenancy/index.js';
|
|
3
|
+
import type { Project, DocumentMeta } from '../projects/index.js';
|
|
4
|
+
import type { SnapshotSummary } from '../versions/index.js';
|
|
5
|
+
export declare function makeWorkspace(over?: Partial<Workspace>): Workspace;
|
|
6
|
+
export declare function makeProject(over?: Partial<Project>): Project;
|
|
7
|
+
export declare function makeDocumentMeta(over?: Partial<DocumentMeta>): DocumentMeta;
|
|
8
|
+
export declare function makeSnapshotSummary(over?: Partial<SnapshotSummary>): SnapshotSummary;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const T = '2026-01-01T00:00:00.000Z';
|
|
2
|
+
export function makeWorkspace(over = {}) {
|
|
3
|
+
return {
|
|
4
|
+
id: 'ws_test',
|
|
5
|
+
kind: 'personal',
|
|
6
|
+
name: 'Personal',
|
|
7
|
+
avatarAssetId: null,
|
|
8
|
+
defaultTemplateId: null,
|
|
9
|
+
defaultLanguage: 'en',
|
|
10
|
+
aiEnabled: true,
|
|
11
|
+
allowPublicLinks: true,
|
|
12
|
+
createdAt: T,
|
|
13
|
+
updatedAt: T,
|
|
14
|
+
...over,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function makeProject(over = {}) {
|
|
18
|
+
return {
|
|
19
|
+
id: 'prj_test',
|
|
20
|
+
workspaceId: 'ws_test',
|
|
21
|
+
name: 'Untitled Project',
|
|
22
|
+
description: null,
|
|
23
|
+
color: null,
|
|
24
|
+
coverAssetId: null,
|
|
25
|
+
kind: 'feature',
|
|
26
|
+
logline: null,
|
|
27
|
+
documentCount: 0,
|
|
28
|
+
createdAt: T,
|
|
29
|
+
updatedAt: T,
|
|
30
|
+
trashedAt: null,
|
|
31
|
+
role: 'owner',
|
|
32
|
+
folders: [],
|
|
33
|
+
documents: [],
|
|
34
|
+
...over,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function makeDocumentMeta(over = {}) {
|
|
38
|
+
return {
|
|
39
|
+
id: 'doc_test',
|
|
40
|
+
projectId: 'prj_test',
|
|
41
|
+
workspaceId: 'ws_test',
|
|
42
|
+
folderId: null,
|
|
43
|
+
kind: 'script',
|
|
44
|
+
title: 'Untitled Screenplay',
|
|
45
|
+
logline: null,
|
|
46
|
+
color: null,
|
|
47
|
+
labels: [],
|
|
48
|
+
season: null,
|
|
49
|
+
episode: null,
|
|
50
|
+
position: 0,
|
|
51
|
+
language: 'en',
|
|
52
|
+
templateId: null,
|
|
53
|
+
templateVersion: null,
|
|
54
|
+
epoch: 0,
|
|
55
|
+
excludeFromAi: false,
|
|
56
|
+
locked: false,
|
|
57
|
+
pageCount: 0,
|
|
58
|
+
sceneCount: 0,
|
|
59
|
+
wordCount: 0,
|
|
60
|
+
parentSnapshotId: null,
|
|
61
|
+
createdBy: null,
|
|
62
|
+
createdAt: T,
|
|
63
|
+
updatedAt: T,
|
|
64
|
+
lastEditedAt: null,
|
|
65
|
+
trashedAt: null,
|
|
66
|
+
...over,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function makeSnapshotSummary(over = {}) {
|
|
70
|
+
return {
|
|
71
|
+
id: 'snap_test',
|
|
72
|
+
documentId: 'doc_test',
|
|
73
|
+
parentId: null,
|
|
74
|
+
name: 'First draft',
|
|
75
|
+
note: null,
|
|
76
|
+
kind: 'manual',
|
|
77
|
+
autoReason: null,
|
|
78
|
+
stats: { pages: 0, scenes: 0, words: 0 },
|
|
79
|
+
createdBy: null,
|
|
80
|
+
createdOnDevice: null,
|
|
81
|
+
createdAt: T,
|
|
82
|
+
receivedAt: T,
|
|
83
|
+
forkedDocumentIds: [],
|
|
84
|
+
hiddenForMe: false,
|
|
85
|
+
noteCount: 0,
|
|
86
|
+
...over,
|
|
87
|
+
};
|
|
88
|
+
}
|