@actuate-media/cms-core 0.20.0 → 0.22.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/LICENSE +21 -21
- package/dist/__tests__/actions/document-crud.test.js +74 -2
- package/dist/__tests__/actions/document-crud.test.js.map +1 -1
- package/dist/__tests__/api/cache-headers.test.d.ts +2 -0
- package/dist/__tests__/api/cache-headers.test.d.ts.map +1 -0
- package/dist/__tests__/api/cache-headers.test.js +135 -0
- package/dist/__tests__/api/cache-headers.test.js.map +1 -0
- package/dist/__tests__/api/comments-routes.test.d.ts +2 -0
- package/dist/__tests__/api/comments-routes.test.d.ts.map +1 -0
- package/dist/__tests__/api/comments-routes.test.js +266 -0
- package/dist/__tests__/api/comments-routes.test.js.map +1 -0
- package/dist/__tests__/api/notifications-routes.test.d.ts +2 -0
- package/dist/__tests__/api/notifications-routes.test.d.ts.map +1 -0
- package/dist/__tests__/api/notifications-routes.test.js +225 -0
- package/dist/__tests__/api/notifications-routes.test.js.map +1 -0
- package/dist/__tests__/api/preview-and-scheduling.test.js +53 -0
- package/dist/__tests__/api/preview-and-scheduling.test.js.map +1 -1
- package/dist/__tests__/fields/component-block.test.d.ts +2 -0
- package/dist/__tests__/fields/component-block.test.d.ts.map +1 -0
- package/dist/__tests__/fields/component-block.test.js +129 -0
- package/dist/__tests__/fields/component-block.test.js.map +1 -0
- package/dist/__tests__/fields/relations.test.js +62 -8
- package/dist/__tests__/fields/relations.test.js.map +1 -1
- package/dist/__tests__/preview-event-bus.test.d.ts +2 -0
- package/dist/__tests__/preview-event-bus.test.d.ts.map +1 -0
- package/dist/__tests__/preview-event-bus.test.js +89 -0
- package/dist/__tests__/preview-event-bus.test.js.map +1 -0
- package/dist/__tests__/preview-sse-stream.test.d.ts +2 -0
- package/dist/__tests__/preview-sse-stream.test.d.ts.map +1 -0
- package/dist/__tests__/preview-sse-stream.test.js +117 -0
- package/dist/__tests__/preview-sse-stream.test.js.map +1 -0
- package/dist/__tests__/realtime/comments.test.d.ts +2 -0
- package/dist/__tests__/realtime/comments.test.d.ts.map +1 -0
- package/dist/__tests__/realtime/comments.test.js +508 -0
- package/dist/__tests__/realtime/comments.test.js.map +1 -0
- package/dist/__tests__/realtime/gateway-ws-integration.test.d.ts +2 -0
- package/dist/__tests__/realtime/gateway-ws-integration.test.d.ts.map +1 -0
- package/dist/__tests__/realtime/gateway-ws-integration.test.js +170 -0
- package/dist/__tests__/realtime/gateway-ws-integration.test.js.map +1 -0
- package/dist/__tests__/realtime/gateway.test.d.ts +2 -0
- package/dist/__tests__/realtime/gateway.test.d.ts.map +1 -0
- package/dist/__tests__/realtime/gateway.test.js +402 -0
- package/dist/__tests__/realtime/gateway.test.js.map +1 -0
- package/dist/__tests__/realtime/notifications.test.d.ts +2 -0
- package/dist/__tests__/realtime/notifications.test.d.ts.map +1 -0
- package/dist/__tests__/realtime/notifications.test.js +317 -0
- package/dist/__tests__/realtime/notifications.test.js.map +1 -0
- package/dist/__tests__/realtime/persistence.test.d.ts +2 -0
- package/dist/__tests__/realtime/persistence.test.d.ts.map +1 -0
- package/dist/__tests__/realtime/persistence.test.js +124 -0
- package/dist/__tests__/realtime/persistence.test.js.map +1 -0
- package/dist/__tests__/schema-preview-features.test.d.ts +2 -0
- package/dist/__tests__/schema-preview-features.test.d.ts.map +1 -0
- package/dist/__tests__/schema-preview-features.test.js +42 -0
- package/dist/__tests__/schema-preview-features.test.js.map +1 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +71 -26
- package/dist/actions.js.map +1 -1
- package/dist/api/handlers.d.ts.map +1 -1
- package/dist/api/handlers.js +734 -188
- package/dist/api/handlers.js.map +1 -1
- package/dist/cache/__tests__/http.test.d.ts +2 -0
- package/dist/cache/__tests__/http.test.d.ts.map +1 -0
- package/dist/cache/__tests__/http.test.js +285 -0
- package/dist/cache/__tests__/http.test.js.map +1 -0
- package/dist/cache/http.d.ts +119 -0
- package/dist/cache/http.d.ts.map +1 -0
- package/dist/cache/http.js +188 -0
- package/dist/cache/http.js.map +1 -0
- package/dist/config/types.d.ts +153 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/fields/component-block.d.ts +23 -0
- package/dist/fields/component-block.d.ts.map +1 -0
- package/dist/fields/component-block.js +137 -0
- package/dist/fields/component-block.js.map +1 -0
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.js +2 -0
- package/dist/fields/index.js.map +1 -1
- package/dist/fields/relations.d.ts.map +1 -1
- package/dist/fields/relations.js +43 -11
- package/dist/fields/relations.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/page-builder/schema.d.ts +2 -2
- package/dist/preview/event-bus.d.ts +39 -0
- package/dist/preview/event-bus.d.ts.map +1 -0
- package/dist/preview/event-bus.js +73 -0
- package/dist/preview/event-bus.js.map +1 -0
- package/dist/preview/sse-stream.d.ts +50 -0
- package/dist/preview/sse-stream.d.ts.map +1 -0
- package/dist/preview/sse-stream.js +120 -0
- package/dist/preview/sse-stream.js.map +1 -0
- package/dist/realtime/comments.d.ts +217 -0
- package/dist/realtime/comments.d.ts.map +1 -0
- package/dist/realtime/comments.js +282 -0
- package/dist/realtime/comments.js.map +1 -0
- package/dist/realtime/gateway.d.ts +107 -0
- package/dist/realtime/gateway.d.ts.map +1 -0
- package/dist/realtime/gateway.js +215 -0
- package/dist/realtime/gateway.js.map +1 -0
- package/dist/realtime/index.d.ts +18 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/index.js +18 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/notifications.d.ts +209 -0
- package/dist/realtime/notifications.d.ts.map +1 -0
- package/dist/realtime/notifications.js +209 -0
- package/dist/realtime/notifications.js.map +1 -0
- package/dist/realtime/persistence.d.ts +72 -0
- package/dist/realtime/persistence.d.ts.map +1 -0
- package/dist/realtime/persistence.js +53 -0
- package/dist/realtime/persistence.js.map +1 -0
- package/package.json +13 -4
- package/prisma/cms-schema.prisma +437 -306
- package/prisma/migrations/0001_init/migration.sql +384 -384
- package/prisma/migrations/0002_folders/migration.sql +39 -39
- package/prisma/migrations/0003_search_and_webhooks/migration.sql +50 -50
- package/prisma/migrations/0004_script_tags/migration.sql +21 -21
- package/prisma/migrations/0005_password_reset_tokens/migration.sql +20 -20
- package/prisma/migrations/0006_page_builder/migration.sql +38 -38
- package/prisma/migrations/migration_lock.toml +3 -3
- package/prisma/schema.prisma +563 -549
- package/generated/browser.ts +0 -109
- package/generated/client.ts +0 -133
- package/generated/commonInputTypes.ts +0 -709
- package/generated/enums.ts +0 -125
- package/generated/internal/class.ts +0 -376
- package/generated/internal/prismaNamespace.ts +0 -2617
- package/generated/internal/prismaNamespaceBrowser.ts +0 -611
- package/generated/models/ApiKey.ts +0 -1550
- package/generated/models/AuditLog.ts +0 -1206
- package/generated/models/BackupRecord.ts +0 -1250
- package/generated/models/ContentLock.ts +0 -1472
- package/generated/models/ContentTemplate.ts +0 -1416
- package/generated/models/Document.ts +0 -3005
- package/generated/models/Folder.ts +0 -1904
- package/generated/models/FormSubmission.ts +0 -1200
- package/generated/models/InAppNotification.ts +0 -1457
- package/generated/models/Media.ts +0 -2340
- package/generated/models/MediaUsage.ts +0 -1472
- package/generated/models/OAuthAccount.ts +0 -1463
- package/generated/models/Redirect.ts +0 -1284
- package/generated/models/Session.ts +0 -1492
- package/generated/models/Site.ts +0 -1206
- package/generated/models/User.ts +0 -3513
- package/generated/models/Version.ts +0 -1511
- package/generated/models/WorkflowState.ts +0 -1514
- package/generated/models.ts +0 -29
package/prisma/cms-schema.prisma
CHANGED
|
@@ -1,306 +1,437 @@
|
|
|
1
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
2
|
-
// Actuate CMS — Prisma schema fragment
|
|
3
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
4
|
-
//
|
|
5
|
-
// This file defines the database models expected by `@actuatecms/cms-core` API
|
|
6
|
-
// handlers and server actions. It is a **fragment**: it does not include a
|
|
7
|
-
// `datasource` or `generator` block.
|
|
8
|
-
//
|
|
9
|
-
// ── How to merge into your project ─────────────────────────────────────────────
|
|
10
|
-
//
|
|
11
|
-
// 1. Ensure your root `schema.prisma` uses PostgreSQL, for example:
|
|
12
|
-
// datasource db {
|
|
13
|
-
// provider = "postgresql"
|
|
14
|
-
// url = env("DATABASE_URL")
|
|
15
|
-
// }
|
|
16
|
-
// generator client {
|
|
17
|
-
// provider = "prisma-client-js"
|
|
18
|
-
// output = "../node_modules/.prisma/client"
|
|
19
|
-
// }
|
|
20
|
-
//
|
|
21
|
-
// 2. Copy the `enum` and `model` blocks below into your `schema.prisma` (or use
|
|
22
|
-
// Prisma’s multi-file schema preview: put this file in `prisma/schema/` and
|
|
23
|
-
// include it per Prisma’s multi-file docs).
|
|
24
|
-
//
|
|
25
|
-
// 3. Resolve naming clashes: if you already have a `User` or `Document` model,
|
|
26
|
-
// rename these models and update your Actuate integration to use a custom
|
|
27
|
-
// Prisma client, or map tables with `@@map("…")` and align delegate names.
|
|
28
|
-
//
|
|
29
|
-
// 4. Run migrations:
|
|
30
|
-
// npx prisma migrate dev --name actuate-cms
|
|
31
|
-
//
|
|
32
|
-
// Models mirror `packages/cms-core/src/api/handlers.ts` and `actions.ts`
|
|
33
|
-
// (including `contentHash`, `changeType` on versions, scheduling fields, etc.).
|
|
34
|
-
//
|
|
35
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
36
|
-
|
|
37
|
-
enum DocumentStatus {
|
|
38
|
-
DRAFT
|
|
39
|
-
PUBLISHED
|
|
40
|
-
ARCHIVED
|
|
41
|
-
SCHEDULED
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
model User {
|
|
45
|
-
id String @id @default(cuid())
|
|
46
|
-
email String @unique
|
|
47
|
-
name String @default("")
|
|
48
|
-
role String @default("EDITOR")
|
|
49
|
-
passwordHash String?
|
|
50
|
-
isActive Boolean @default(true)
|
|
51
|
-
isApproved Boolean @default(false)
|
|
52
|
-
emailVerified Boolean @default(false)
|
|
53
|
-
totpEnabled Boolean @default(false)
|
|
54
|
-
totpSecret String?
|
|
55
|
-
/// JSON array of one-time backup codes (e.g. `["abcd-1234", …]`).
|
|
56
|
-
backupCodes Json?
|
|
57
|
-
oauthProvider String?
|
|
58
|
-
oauthId String?
|
|
59
|
-
createdAt DateTime @default(now())
|
|
60
|
-
updatedAt DateTime @updatedAt
|
|
61
|
-
|
|
62
|
-
sessions Session[]
|
|
63
|
-
documentsCreated Document[]
|
|
64
|
-
documentsUpdated Document[]
|
|
65
|
-
documentsReviewed Document[]
|
|
66
|
-
versions Version[]
|
|
67
|
-
mediaUploaded Media[]
|
|
68
|
-
auditLogs AuditLog[]
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
@@
|
|
126
|
-
@@index([
|
|
127
|
-
@@index([
|
|
128
|
-
@@index([
|
|
129
|
-
@@index([
|
|
130
|
-
@@index([
|
|
131
|
-
@@index([
|
|
132
|
-
@@index([
|
|
133
|
-
@@index([
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
@@index([
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
@@index([scope
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
@@index([
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
@@index([
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
@@
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
2
|
+
// Actuate CMS — Prisma schema fragment
|
|
3
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// This file defines the database models expected by `@actuatecms/cms-core` API
|
|
6
|
+
// handlers and server actions. It is a **fragment**: it does not include a
|
|
7
|
+
// `datasource` or `generator` block.
|
|
8
|
+
//
|
|
9
|
+
// ── How to merge into your project ─────────────────────────────────────────────
|
|
10
|
+
//
|
|
11
|
+
// 1. Ensure your root `schema.prisma` uses PostgreSQL, for example:
|
|
12
|
+
// datasource db {
|
|
13
|
+
// provider = "postgresql"
|
|
14
|
+
// url = env("DATABASE_URL")
|
|
15
|
+
// }
|
|
16
|
+
// generator client {
|
|
17
|
+
// provider = "prisma-client-js"
|
|
18
|
+
// output = "../node_modules/.prisma/client"
|
|
19
|
+
// }
|
|
20
|
+
//
|
|
21
|
+
// 2. Copy the `enum` and `model` blocks below into your `schema.prisma` (or use
|
|
22
|
+
// Prisma’s multi-file schema preview: put this file in `prisma/schema/` and
|
|
23
|
+
// include it per Prisma’s multi-file docs).
|
|
24
|
+
//
|
|
25
|
+
// 3. Resolve naming clashes: if you already have a `User` or `Document` model,
|
|
26
|
+
// rename these models and update your Actuate integration to use a custom
|
|
27
|
+
// Prisma client, or map tables with `@@map("…")` and align delegate names.
|
|
28
|
+
//
|
|
29
|
+
// 4. Run migrations:
|
|
30
|
+
// npx prisma migrate dev --name actuate-cms
|
|
31
|
+
//
|
|
32
|
+
// Models mirror `packages/cms-core/src/api/handlers.ts` and `actions.ts`
|
|
33
|
+
// (including `contentHash`, `changeType` on versions, scheduling fields, etc.).
|
|
34
|
+
//
|
|
35
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
36
|
+
|
|
37
|
+
enum DocumentStatus {
|
|
38
|
+
DRAFT
|
|
39
|
+
PUBLISHED
|
|
40
|
+
ARCHIVED
|
|
41
|
+
SCHEDULED
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
model User {
|
|
45
|
+
id String @id @default(cuid())
|
|
46
|
+
email String @unique
|
|
47
|
+
name String @default("")
|
|
48
|
+
role String @default("EDITOR")
|
|
49
|
+
passwordHash String?
|
|
50
|
+
isActive Boolean @default(true)
|
|
51
|
+
isApproved Boolean @default(false)
|
|
52
|
+
emailVerified Boolean @default(false)
|
|
53
|
+
totpEnabled Boolean @default(false)
|
|
54
|
+
totpSecret String?
|
|
55
|
+
/// JSON array of one-time backup codes (e.g. `["abcd-1234", …]`).
|
|
56
|
+
backupCodes Json?
|
|
57
|
+
oauthProvider String?
|
|
58
|
+
oauthId String?
|
|
59
|
+
createdAt DateTime @default(now())
|
|
60
|
+
updatedAt DateTime @updatedAt
|
|
61
|
+
|
|
62
|
+
sessions Session[]
|
|
63
|
+
documentsCreated Document[] @relation("DocumentCreatedBy")
|
|
64
|
+
documentsUpdated Document[] @relation("DocumentUpdatedBy")
|
|
65
|
+
documentsReviewed Document[] @relation("DocumentReviewer")
|
|
66
|
+
versions Version[]
|
|
67
|
+
mediaUploaded Media[] @relation("MediaUploadedBy")
|
|
68
|
+
auditLogs AuditLog[]
|
|
69
|
+
comments DocumentComment[]
|
|
70
|
+
notifications DocumentNotification[]
|
|
71
|
+
|
|
72
|
+
@@index([role])
|
|
73
|
+
@@index([isActive])
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
model Session {
|
|
77
|
+
id String @id @default(cuid())
|
|
78
|
+
userId String
|
|
79
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
80
|
+
/// JWT or opaque session token; optional until first persisted login (e.g. OAuth).
|
|
81
|
+
token String? @unique
|
|
82
|
+
expiresAt DateTime
|
|
83
|
+
revokedAt DateTime?
|
|
84
|
+
ipAddress String?
|
|
85
|
+
userAgent String?
|
|
86
|
+
createdAt DateTime @default(now())
|
|
87
|
+
|
|
88
|
+
@@index([userId])
|
|
89
|
+
@@index([expiresAt])
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
model Document {
|
|
93
|
+
id String @id @default(cuid())
|
|
94
|
+
collection String
|
|
95
|
+
slug String?
|
|
96
|
+
title String?
|
|
97
|
+
data Json
|
|
98
|
+
status DocumentStatus @default(DRAFT)
|
|
99
|
+
plainText String? @db.Text
|
|
100
|
+
locale String?
|
|
101
|
+
folderId String?
|
|
102
|
+
structuredData Json?
|
|
103
|
+
workflowStage String?
|
|
104
|
+
reviewerId String?
|
|
105
|
+
reviewNote String? @db.Text
|
|
106
|
+
publishedAt DateTime?
|
|
107
|
+
scheduledAt DateTime?
|
|
108
|
+
scheduledUnpublishAt DateTime?
|
|
109
|
+
deletedAt DateTime?
|
|
110
|
+
contentHash String?
|
|
111
|
+
siteId String?
|
|
112
|
+
templateId String?
|
|
113
|
+
createdById String
|
|
114
|
+
updatedById String
|
|
115
|
+
createdAt DateTime @default(now())
|
|
116
|
+
updatedAt DateTime @updatedAt
|
|
117
|
+
|
|
118
|
+
createdBy User @relation("DocumentCreatedBy", fields: [createdById], references: [id], onDelete: Restrict)
|
|
119
|
+
updatedBy User @relation("DocumentUpdatedBy", fields: [updatedById], references: [id], onDelete: Restrict)
|
|
120
|
+
reviewer User? @relation("DocumentReviewer", fields: [reviewerId], references: [id], onDelete: SetNull)
|
|
121
|
+
folder Folder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
|
|
122
|
+
versions Version[]
|
|
123
|
+
formSubmissions FormSubmission[]
|
|
124
|
+
|
|
125
|
+
@@unique([collection, slug], name: "collection_slug")
|
|
126
|
+
@@index([collection])
|
|
127
|
+
@@index([status])
|
|
128
|
+
@@index([deletedAt])
|
|
129
|
+
@@index([publishedAt])
|
|
130
|
+
@@index([folderId])
|
|
131
|
+
@@index([locale])
|
|
132
|
+
@@index([scheduledAt])
|
|
133
|
+
@@index([scheduledUnpublishAt])
|
|
134
|
+
@@index([createdById])
|
|
135
|
+
@@index([updatedById])
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
model Media {
|
|
139
|
+
id String @id @default(cuid())
|
|
140
|
+
filename String
|
|
141
|
+
storageKey String @unique
|
|
142
|
+
mimeType String
|
|
143
|
+
fileSize Int
|
|
144
|
+
width Int?
|
|
145
|
+
height Int?
|
|
146
|
+
altText String?
|
|
147
|
+
title String?
|
|
148
|
+
blurHash String?
|
|
149
|
+
focalPointX Float?
|
|
150
|
+
focalPointY Float?
|
|
151
|
+
folderId String?
|
|
152
|
+
uploadedById String
|
|
153
|
+
createdAt DateTime @default(now())
|
|
154
|
+
updatedAt DateTime @updatedAt
|
|
155
|
+
|
|
156
|
+
uploadedBy User @relation("MediaUploadedBy", fields: [uploadedById], references: [id], onDelete: Restrict)
|
|
157
|
+
folder Folder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
|
|
158
|
+
|
|
159
|
+
@@index([folderId])
|
|
160
|
+
@@index([mimeType])
|
|
161
|
+
@@index([createdAt])
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
model Version {
|
|
165
|
+
id String @id @default(cuid())
|
|
166
|
+
documentId String
|
|
167
|
+
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
|
|
168
|
+
data Json
|
|
169
|
+
changedById String
|
|
170
|
+
changedBy User @relation(fields: [changedById], references: [id], onDelete: Restrict)
|
|
171
|
+
/// CREATE | UPDATE | DELETE (see `actions.ts` / workflow).
|
|
172
|
+
changeType String @default("UPDATE")
|
|
173
|
+
createdAt DateTime @default(now())
|
|
174
|
+
|
|
175
|
+
@@index([documentId])
|
|
176
|
+
@@index([createdAt])
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
model Folder {
|
|
180
|
+
id String @id @default(cuid())
|
|
181
|
+
name String
|
|
182
|
+
/// Discriminator for folder trees (e.g. `documents`, `media`).
|
|
183
|
+
scope String
|
|
184
|
+
parentId String?
|
|
185
|
+
position Int @default(0)
|
|
186
|
+
createdAt DateTime @default(now())
|
|
187
|
+
|
|
188
|
+
parent Folder? @relation("FolderTree", fields: [parentId], references: [id], onDelete: Cascade)
|
|
189
|
+
children Folder[] @relation("FolderTree")
|
|
190
|
+
documents Document[]
|
|
191
|
+
media Media[]
|
|
192
|
+
|
|
193
|
+
@@index([scope])
|
|
194
|
+
@@index([parentId])
|
|
195
|
+
@@index([scope, parentId, position])
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
model Redirect {
|
|
199
|
+
id String @id @default(cuid())
|
|
200
|
+
source String
|
|
201
|
+
destination String
|
|
202
|
+
statusCode Int @default(301)
|
|
203
|
+
isRegex Boolean @default(false)
|
|
204
|
+
notes String?
|
|
205
|
+
createdAt DateTime @default(now())
|
|
206
|
+
updatedAt DateTime @updatedAt
|
|
207
|
+
|
|
208
|
+
@@unique([source])
|
|
209
|
+
@@index([createdAt])
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
model FormSubmission {
|
|
213
|
+
id String @id @default(cuid())
|
|
214
|
+
formId String
|
|
215
|
+
form Document @relation(fields: [formId], references: [id], onDelete: Cascade)
|
|
216
|
+
data Json
|
|
217
|
+
attribution Json?
|
|
218
|
+
submittedAt DateTime @default(now())
|
|
219
|
+
createdAt DateTime @default(now())
|
|
220
|
+
|
|
221
|
+
@@index([formId])
|
|
222
|
+
@@index([submittedAt])
|
|
223
|
+
@@index([createdAt])
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
model AuditLog {
|
|
227
|
+
id String @id @default(cuid())
|
|
228
|
+
event String
|
|
229
|
+
userId String?
|
|
230
|
+
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
231
|
+
details Json?
|
|
232
|
+
ipAddress String?
|
|
233
|
+
userAgent String?
|
|
234
|
+
createdAt DateTime @default(now())
|
|
235
|
+
|
|
236
|
+
@@index([event])
|
|
237
|
+
@@index([userId])
|
|
238
|
+
@@index([createdAt])
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
model PasswordResetToken {
|
|
242
|
+
id String @id @default(cuid())
|
|
243
|
+
userId String
|
|
244
|
+
tokenHash String
|
|
245
|
+
expiresAt DateTime
|
|
246
|
+
usedAt DateTime?
|
|
247
|
+
createdAt DateTime @default(now())
|
|
248
|
+
|
|
249
|
+
@@index([tokenHash])
|
|
250
|
+
@@index([userId])
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
model MediaUsage {
|
|
254
|
+
id String @id @default(cuid())
|
|
255
|
+
mediaId String
|
|
256
|
+
documentId String
|
|
257
|
+
fieldPath String?
|
|
258
|
+
createdAt DateTime @default(now())
|
|
259
|
+
|
|
260
|
+
@@unique([mediaId, documentId, fieldPath])
|
|
261
|
+
@@index([mediaId])
|
|
262
|
+
@@index([documentId])
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
model ScriptTag {
|
|
266
|
+
id String @id @default(cuid())
|
|
267
|
+
name String
|
|
268
|
+
code String @db.Text
|
|
269
|
+
placement String
|
|
270
|
+
scope String
|
|
271
|
+
targetPaths String[]
|
|
272
|
+
priority Int @default(100)
|
|
273
|
+
enabled Boolean @default(true)
|
|
274
|
+
createdAt DateTime @default(now())
|
|
275
|
+
updatedAt DateTime @updatedAt
|
|
276
|
+
|
|
277
|
+
@@index([enabled])
|
|
278
|
+
@@index([placement])
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
model PageTemplate {
|
|
282
|
+
id String @id @default(cuid())
|
|
283
|
+
name String
|
|
284
|
+
description String?
|
|
285
|
+
category String @default("content")
|
|
286
|
+
tree Json
|
|
287
|
+
thumbnail String?
|
|
288
|
+
builtIn Boolean @default(false)
|
|
289
|
+
createdAt DateTime @default(now())
|
|
290
|
+
updatedAt DateTime @updatedAt
|
|
291
|
+
|
|
292
|
+
@@index([category])
|
|
293
|
+
@@index([builtIn])
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
model SavedSection {
|
|
297
|
+
id String @id @default(cuid())
|
|
298
|
+
name String
|
|
299
|
+
description String?
|
|
300
|
+
category String @default("content")
|
|
301
|
+
tree Json
|
|
302
|
+
thumbnail String?
|
|
303
|
+
usageCount Int @default(0)
|
|
304
|
+
createdAt DateTime @default(now())
|
|
305
|
+
updatedAt DateTime @updatedAt
|
|
306
|
+
|
|
307
|
+
@@index([category])
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/// Persisted Yjs state for a document, used by `@actuate-media/realtime`.
|
|
311
|
+
///
|
|
312
|
+
/// Each row holds the encoded Yjs document (`Y.encodeStateAsUpdate`) plus a
|
|
313
|
+
/// version vector so consumers can serve incremental sync to late joiners
|
|
314
|
+
/// without replaying full history. There is at most one row per `documentId`;
|
|
315
|
+
/// it is upserted on every persistence flush from a live collaboration room.
|
|
316
|
+
///
|
|
317
|
+
/// The model is *optional*: an Actuate deployment that does not use the
|
|
318
|
+
/// realtime collaboration features can leave this table empty. Cms-core only
|
|
319
|
+
/// touches it when the `/realtime/sync` endpoint is hit.
|
|
320
|
+
model DocumentCRDT {
|
|
321
|
+
/// References `Document.id`. We don't declare a Prisma relation here so
|
|
322
|
+
/// the realtime stack stays decoupled from the `Document` schema; the
|
|
323
|
+
/// constraint is enforced at the application layer.
|
|
324
|
+
documentId String @id
|
|
325
|
+
/// Yjs `encodeStateAsUpdate` bytes. Use bytea on Postgres.
|
|
326
|
+
state Bytes
|
|
327
|
+
/// Yjs `encodeStateVector` bytes — lets us reply to a `SyncStep1` without
|
|
328
|
+
/// decoding the full doc when persistence is hot but the room is cold.
|
|
329
|
+
stateVector Bytes
|
|
330
|
+
/// Monotonic counter for optimistic locking (incremented on every save).
|
|
331
|
+
version Int @default(0)
|
|
332
|
+
/// Wall-clock of the most recent flush.
|
|
333
|
+
lastUpdatedAt DateTime @default(now()) @updatedAt
|
|
334
|
+
/// User id of the most recent editor, if known.
|
|
335
|
+
lastUpdatedById String?
|
|
336
|
+
createdAt DateTime @default(now())
|
|
337
|
+
|
|
338
|
+
@@index([lastUpdatedAt])
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/// Threaded inline comment anchored to a Yjs document range.
|
|
342
|
+
///
|
|
343
|
+
/// Comments survive concurrent edits because the `anchor` field stores Yjs
|
|
344
|
+
/// *relative positions* (the binary blob you get from
|
|
345
|
+
/// `Y.createRelativePositionFromTypeIndex` followed by
|
|
346
|
+
/// `Y.encodeRelativePosition`) rather than absolute offsets. Slice 5 binds
|
|
347
|
+
/// these back to live ranges in the TipTap document.
|
|
348
|
+
///
|
|
349
|
+
/// Threading is single-level: a top-level comment has `parentId == null`,
|
|
350
|
+
/// replies set `parentId` to the root comment's id. Deletes cascade so a
|
|
351
|
+
/// resolved or removed thread cleans up its replies.
|
|
352
|
+
///
|
|
353
|
+
/// The model is *optional*. Deployments that don't enable Phase 3 simply
|
|
354
|
+
/// leave the table empty; the cms-core API stays serviceable without it.
|
|
355
|
+
model DocumentComment {
|
|
356
|
+
id String @id @default(cuid())
|
|
357
|
+
/// References `Document.id`. Like `DocumentCRDT`, we keep the foreign
|
|
358
|
+
/// constraint at the application layer so the realtime stack stays
|
|
359
|
+
/// decoupled from the core `Document` schema.
|
|
360
|
+
documentId String
|
|
361
|
+
/// `null` for top-level comments; the root comment's id for replies.
|
|
362
|
+
/// Replies cannot themselves be parents — slice 5 enforces this in the
|
|
363
|
+
/// API handler.
|
|
364
|
+
parentId String?
|
|
365
|
+
parent DocumentComment? @relation("CommentThread", fields: [parentId], references: [id], onDelete: Cascade)
|
|
366
|
+
replies DocumentComment[] @relation("CommentThread")
|
|
367
|
+
/// Author of the comment. We don't cascade on user deletion so an
|
|
368
|
+
/// orphaned comment is preserved with a null `userId`; the UI can then
|
|
369
|
+
/// render "deleted user" without losing thread history.
|
|
370
|
+
userId String?
|
|
371
|
+
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
372
|
+
/// Markdown body (sanitized server-side before render).
|
|
373
|
+
body String @db.Text
|
|
374
|
+
/// Yjs relative-position JSON: `{ from: number[]; to: number[] }` where
|
|
375
|
+
/// each entry is the Base64-encoded `encodeRelativePosition` bytes.
|
|
376
|
+
/// Stored as JSON (not Bytes) so the API can return it without an
|
|
377
|
+
/// extra encoding hop. May be null for document-level (un-anchored)
|
|
378
|
+
/// comments.
|
|
379
|
+
anchor Json?
|
|
380
|
+
/// When set, the thread is resolved. UI hides resolved threads by
|
|
381
|
+
/// default but they remain in the table for audit.
|
|
382
|
+
resolvedAt DateTime?
|
|
383
|
+
/// User that resolved the thread, if any.
|
|
384
|
+
resolvedById String?
|
|
385
|
+
/// Soft delete for moderation; row is preserved so replies don't lose
|
|
386
|
+
/// their parent.
|
|
387
|
+
deletedAt DateTime?
|
|
388
|
+
createdAt DateTime @default(now())
|
|
389
|
+
updatedAt DateTime @updatedAt
|
|
390
|
+
|
|
391
|
+
@@index([documentId])
|
|
392
|
+
@@index([documentId, resolvedAt])
|
|
393
|
+
@@index([parentId])
|
|
394
|
+
@@index([userId])
|
|
395
|
+
@@index([createdAt])
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ─── Notifications (slice 6 — Phase 3) ─────────────────────────────────────────
|
|
399
|
+
//
|
|
400
|
+
// Per-user notification feed driven by collaboration events. Slice 6 wires
|
|
401
|
+
// the comment lifecycle (reply, resolve, mention) into this table so editors
|
|
402
|
+
// see "someone replied to your thread" without polling the comments API.
|
|
403
|
+
//
|
|
404
|
+
// The model is intentionally generic — the `kind` discriminator + `payload`
|
|
405
|
+
// JSON blob keeps the schema stable while future slices add new notification
|
|
406
|
+
// types (e.g. publish workflow transitions, document share invites).
|
|
407
|
+
|
|
408
|
+
model DocumentNotification {
|
|
409
|
+
id String @id @default(cuid())
|
|
410
|
+
/// Recipient. Cascade-deletes on user removal — we don't want orphan
|
|
411
|
+
/// notifications pointing at gone-users in the dropdown.
|
|
412
|
+
userId String
|
|
413
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
414
|
+
/// Discriminator. Slice 6 ships:
|
|
415
|
+
/// - "comment_reply" — someone replied to a thread you authored
|
|
416
|
+
/// - "comment_resolved" — your thread was resolved by another user
|
|
417
|
+
/// - "comment_mention" — your @handle was mentioned in a comment body
|
|
418
|
+
/// Future slices can extend this without a migration.
|
|
419
|
+
kind String
|
|
420
|
+
/// Optional document scope so the bell can group / link notifications.
|
|
421
|
+
documentId String?
|
|
422
|
+
/// Optional comment scope (the comment that triggered the notification).
|
|
423
|
+
commentId String?
|
|
424
|
+
/// `{ actorId, actorName, excerpt?, ... }`. Shape depends on `kind`;
|
|
425
|
+
/// the service module documents each variant.
|
|
426
|
+
payload Json
|
|
427
|
+
/// `null` until the user marks the notification read. We keep read rows
|
|
428
|
+
/// in the table so the dropdown can show recent activity, but the bell
|
|
429
|
+
/// counts only `readAt = null` rows.
|
|
430
|
+
readAt DateTime?
|
|
431
|
+
createdAt DateTime @default(now())
|
|
432
|
+
|
|
433
|
+
@@index([userId, readAt])
|
|
434
|
+
@@index([userId, createdAt])
|
|
435
|
+
@@index([documentId])
|
|
436
|
+
@@index([commentId])
|
|
437
|
+
}
|