@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/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export { dispatch as dispatchWebhook, createEndpoint as createWebhookEndpoint, l
|
|
|
16
16
|
export { buildLocaleFilter, buildLocaleFallbackQuery, getLocales, resolveLocale, } from './i18n/index.js';
|
|
17
17
|
// Cache
|
|
18
18
|
export { cached, revalidateTag, buildCacheKey, getDocumentCacheTags } from './cache/index.js';
|
|
19
|
+
export { ACTUATE_TAG_ROOT, actuateTag, invalidationTagsForDocumentWrite, invalidationTagsForGlobalWrite, publicReadCacheControl, } from './cache/http.js';
|
|
19
20
|
// Content
|
|
20
21
|
export { extractPlainText, extractExcerpt, hashContent, registerSchemaType, getSchemaType, generateJsonLd, renderJsonLdScript, buildContentGraph, serializeGraph, findIncomingReferences, handleContentApiRequest, sanitizeForPublicApi, } from './content/index.js';
|
|
21
22
|
// Codegen
|
|
@@ -50,6 +51,7 @@ export { advanceWorkflow, rejectWorkflowStep, getWorkflowState } from './workflo
|
|
|
50
51
|
export { canTransition, getAvailableTransitions, transitionDocument } from './workflow/index.js';
|
|
51
52
|
// Presence
|
|
52
53
|
export { createSSEPresenceAdapter } from './presence/index.js';
|
|
54
|
+
export { createPrismaDocumentPersistence, createRealtimeGateway } from './realtime/index.js';
|
|
53
55
|
// Scheduling
|
|
54
56
|
export { getScheduleCalendar, processScheduledPublish, processScheduledUnpublish, schedulingCronHandler, } from './scheduling/index.js';
|
|
55
57
|
// Templates
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA0BhD,cAAc;AACd,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAA;AAG/B,SAAS;AACT,OAAO,EACL,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,SAAS,EACT,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,SAAS,EACT,cAAc,EACd,SAAS,EACT,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAQ1B,OAAO;AACP,OAAO,EACL,aAAa,EACb,aAAa,EACb,aAAa,EACb,cAAc,EACd,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,cAAc,EACd,WAAW,EACX,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,mBAAmB,GACpB,MAAM,iBAAiB,CAAA;AAWxB,WAAW;AACX,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,QAAQ,EACR,WAAW,EACX,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAE5B,SAAS;AACT,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGnD,WAAW;AACX,OAAO,EACL,QAAQ,IAAI,eAAe,EAC3B,cAAc,IAAI,qBAAqB,EACvC,aAAa,IAAI,oBAAoB,EACrC,cAAc,IAAI,qBAAqB,EACvC,cAAc,IAAI,qBAAqB,EACvC,aAAa,IAAI,oBAAoB,EACrC,cAAc,IAAI,qBAAqB,EACvC,WAAW,EACX,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAG5B,OAAO;AACP,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,UAAU,EACV,aAAa,GACd,MAAM,iBAAiB,CAAA;AAExB,QAAQ;AACR,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,8 +26,8 @@ export declare const blockNodeSchema: z.ZodObject<{
|
|
|
26
26
|
data: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
27
27
|
}, "strip", z.ZodTypeAny, {
|
|
28
28
|
type: "block";
|
|
29
|
-
data: Record<string, unknown>;
|
|
30
29
|
id: string;
|
|
30
|
+
data: Record<string, unknown>;
|
|
31
31
|
settings: {
|
|
32
32
|
blockType: string;
|
|
33
33
|
variant?: string | undefined;
|
|
@@ -40,8 +40,8 @@ export declare const blockNodeSchema: z.ZodObject<{
|
|
|
40
40
|
} | undefined;
|
|
41
41
|
}, {
|
|
42
42
|
type: "block";
|
|
43
|
-
data: Record<string, unknown>;
|
|
44
43
|
id: string;
|
|
44
|
+
data: Record<string, unknown>;
|
|
45
45
|
settings: {
|
|
46
46
|
blockType: string;
|
|
47
47
|
variant?: string | undefined;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process pub/sub for live-preview update events.
|
|
3
|
+
*
|
|
4
|
+
* The admin emits `notifyPreviewUpdate(collection, id, payload)` whenever a
|
|
5
|
+
* draft document changes (today: the `PUT /collections/:slug/:id` route).
|
|
6
|
+
* Active SSE streams subscribe via `subscribePreviewUpdates(collection, id, listener)`
|
|
7
|
+
* and forward every payload through to their connected `EventSource`
|
|
8
|
+
* clients.
|
|
9
|
+
*
|
|
10
|
+
* The bus is intentionally single-instance and in-memory:
|
|
11
|
+
*
|
|
12
|
+
* - Self-hosted single-node deployments get push-to-iframe updates
|
|
13
|
+
* "for free" with zero extra infrastructure.
|
|
14
|
+
* - Multi-node deployments will see each node deliver only its own
|
|
15
|
+
* update events — fine for the Phase 2 finish-line. A future Slice
|
|
16
|
+
* can swap this for a Redis/postgres-listen backed bus without
|
|
17
|
+
* changing the public contract (`notifyPreviewUpdate` /
|
|
18
|
+
* `subscribePreviewUpdates`).
|
|
19
|
+
*
|
|
20
|
+
* The bus is keyed by `${collection}:${documentId}` so two simultaneously
|
|
21
|
+
* open previews for different docs don't see each other's traffic.
|
|
22
|
+
*/
|
|
23
|
+
export interface PreviewUpdateEvent {
|
|
24
|
+
collection: string;
|
|
25
|
+
documentId: string;
|
|
26
|
+
/** Free-form payload — the SSE handler stringifies it as the event data. */
|
|
27
|
+
payload: Record<string, unknown>;
|
|
28
|
+
/** Server-side emission timestamp; useful for clients to detect skew. */
|
|
29
|
+
at: number;
|
|
30
|
+
}
|
|
31
|
+
export type PreviewUpdateListener = (event: PreviewUpdateEvent) => void;
|
|
32
|
+
export declare function subscribePreviewUpdates(collection: string, documentId: string, listener: PreviewUpdateListener): () => void;
|
|
33
|
+
export declare function notifyPreviewUpdate(collection: string, documentId: string, payload: Record<string, unknown>): void;
|
|
34
|
+
export declare function previewSubscriberCount(collection: string, documentId: string): number;
|
|
35
|
+
/**
|
|
36
|
+
* Test helper. Drops every subscription. Production code never calls this.
|
|
37
|
+
*/
|
|
38
|
+
export declare function __resetPreviewEventBus(): void;
|
|
39
|
+
//# sourceMappingURL=event-bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/preview/event-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAA;AAQvE,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,qBAAqB,GAC9B,MAAM,IAAI,CAcZ;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,IAAI,CAiBN;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAErF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process pub/sub for live-preview update events.
|
|
3
|
+
*
|
|
4
|
+
* The admin emits `notifyPreviewUpdate(collection, id, payload)` whenever a
|
|
5
|
+
* draft document changes (today: the `PUT /collections/:slug/:id` route).
|
|
6
|
+
* Active SSE streams subscribe via `subscribePreviewUpdates(collection, id, listener)`
|
|
7
|
+
* and forward every payload through to their connected `EventSource`
|
|
8
|
+
* clients.
|
|
9
|
+
*
|
|
10
|
+
* The bus is intentionally single-instance and in-memory:
|
|
11
|
+
*
|
|
12
|
+
* - Self-hosted single-node deployments get push-to-iframe updates
|
|
13
|
+
* "for free" with zero extra infrastructure.
|
|
14
|
+
* - Multi-node deployments will see each node deliver only its own
|
|
15
|
+
* update events — fine for the Phase 2 finish-line. A future Slice
|
|
16
|
+
* can swap this for a Redis/postgres-listen backed bus without
|
|
17
|
+
* changing the public contract (`notifyPreviewUpdate` /
|
|
18
|
+
* `subscribePreviewUpdates`).
|
|
19
|
+
*
|
|
20
|
+
* The bus is keyed by `${collection}:${documentId}` so two simultaneously
|
|
21
|
+
* open previews for different docs don't see each other's traffic.
|
|
22
|
+
*/
|
|
23
|
+
const listenersByKey = new Map();
|
|
24
|
+
function keyOf(collection, documentId) {
|
|
25
|
+
return `${collection}:${documentId}`;
|
|
26
|
+
}
|
|
27
|
+
export function subscribePreviewUpdates(collection, documentId, listener) {
|
|
28
|
+
const key = keyOf(collection, documentId);
|
|
29
|
+
let set = listenersByKey.get(key);
|
|
30
|
+
if (!set) {
|
|
31
|
+
set = new Set();
|
|
32
|
+
listenersByKey.set(key, set);
|
|
33
|
+
}
|
|
34
|
+
set.add(listener);
|
|
35
|
+
return () => {
|
|
36
|
+
const current = listenersByKey.get(key);
|
|
37
|
+
if (!current)
|
|
38
|
+
return;
|
|
39
|
+
current.delete(listener);
|
|
40
|
+
if (current.size === 0)
|
|
41
|
+
listenersByKey.delete(key);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function notifyPreviewUpdate(collection, documentId, payload) {
|
|
45
|
+
const set = listenersByKey.get(keyOf(collection, documentId));
|
|
46
|
+
if (!set || set.size === 0)
|
|
47
|
+
return;
|
|
48
|
+
const event = {
|
|
49
|
+
collection,
|
|
50
|
+
documentId,
|
|
51
|
+
payload,
|
|
52
|
+
at: Date.now(),
|
|
53
|
+
};
|
|
54
|
+
for (const listener of [...set]) {
|
|
55
|
+
try {
|
|
56
|
+
listener(event);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// listener throws are isolated — one buggy stream must not take down
|
|
60
|
+
// every other subscriber for the same doc.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function previewSubscriberCount(collection, documentId) {
|
|
65
|
+
return listenersByKey.get(keyOf(collection, documentId))?.size ?? 0;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Test helper. Drops every subscription. Production code never calls this.
|
|
69
|
+
*/
|
|
70
|
+
export function __resetPreviewEventBus() {
|
|
71
|
+
listenersByKey.clear();
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=event-bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../src/preview/event-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAaH,MAAM,cAAc,GAAG,IAAI,GAAG,EAAsC,CAAA;AAEpE,SAAS,KAAK,CAAC,UAAkB,EAAE,UAAkB;IACnD,OAAO,GAAG,UAAU,IAAI,UAAU,EAAE,CAAA;AACtC,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,UAAkB,EAClB,UAAkB,EAClB,QAA+B;IAE/B,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;IACzC,IAAI,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAA;QACf,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAC9B,CAAC;IACD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACjB,OAAO,GAAG,EAAE;QACV,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACvC,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QACxB,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACpD,CAAC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,UAAkB,EAClB,OAAgC;IAEhC,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAA;IAC7D,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC;QAAE,OAAM;IAClC,MAAM,KAAK,GAAuB;QAChC,UAAU;QACV,UAAU;QACV,OAAO;QACP,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;KACf,CAAA;IACD,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,QAAQ,CAAC,KAAK,CAAC,CAAA;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;YACrE,2CAA2C;QAC7C,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,UAAkB;IAC3E,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,CAAA;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,cAAc,CAAC,KAAK,EAAE,CAAA;AACxB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { PreviewSession } from './index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default keepalive interval. 25 s sits safely under the most aggressive
|
|
4
|
+
* proxy/idle timeouts we've encountered in production (Cloudflare 30 s,
|
|
5
|
+
* Vercel Serverless 30 s, most reverse-proxies 60 s).
|
|
6
|
+
*/
|
|
7
|
+
export declare const PREVIEW_SSE_HEARTBEAT_MS = 25000;
|
|
8
|
+
/**
|
|
9
|
+
* Maximum stream lifetime in ms. After this, the server closes the stream
|
|
10
|
+
* cleanly so EventSource will reconnect — important because some platforms
|
|
11
|
+
* (Vercel Fluid Compute, Cloudflare Workers) cap any single response at a
|
|
12
|
+
* few minutes regardless of activity.
|
|
13
|
+
*/
|
|
14
|
+
export declare const PREVIEW_SSE_MAX_LIFETIME_MS: number;
|
|
15
|
+
export interface PreviewStreamOptions {
|
|
16
|
+
/** Override for tests so we don't have to wait 25 seconds. */
|
|
17
|
+
heartbeatMs?: number;
|
|
18
|
+
/** Override for tests so we don't tie up the suite for 4 minutes. */
|
|
19
|
+
maxLifetimeMs?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Encode a single SSE message. `event` is optional; when omitted the
|
|
23
|
+
* default `message` event is used.
|
|
24
|
+
*/
|
|
25
|
+
export declare function encodeSseEvent(data: unknown, event?: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Build a `ReadableStream` of Server-Sent Events for the given preview
|
|
28
|
+
* session. The stream:
|
|
29
|
+
*
|
|
30
|
+
* 1. Emits an `event: ready` frame with the session's collection/id.
|
|
31
|
+
* Lets the client confirm the server-side subscription is wired up
|
|
32
|
+
* before it starts treating the absence of events as "stale".
|
|
33
|
+
* 2. Forwards every `notifyPreviewUpdate(collection, id, payload)` to
|
|
34
|
+
* the client as `event: update` with `payload` as JSON data.
|
|
35
|
+
* 3. Sends `: heartbeat\n\n` keepalive comments on
|
|
36
|
+
* `PREVIEW_SSE_HEARTBEAT_MS` intervals.
|
|
37
|
+
* 4. Cleanly closes after `PREVIEW_SSE_MAX_LIFETIME_MS` and lets the
|
|
38
|
+
* browser reconnect, sidestepping platform idle/max-duration caps.
|
|
39
|
+
*
|
|
40
|
+
* The returned stream MUST be wrapped in a `Response` with the SSE
|
|
41
|
+
* headers — `createPreviewStreamResponse` does this for typical callers.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createPreviewStream(session: Pick<PreviewSession, 'collection' | 'documentId'>, opts?: PreviewStreamOptions): ReadableStream<Uint8Array>;
|
|
44
|
+
/**
|
|
45
|
+
* Standard SSE response headers. Exposed for callers (and tests) that want
|
|
46
|
+
* to wrap the stream themselves.
|
|
47
|
+
*/
|
|
48
|
+
export declare const PREVIEW_SSE_HEADERS: Record<string, string>;
|
|
49
|
+
export declare function createPreviewStreamResponse(session: Pick<PreviewSession, 'collection' | 'documentId'>, opts?: PreviewStreamOptions): Response;
|
|
50
|
+
//# sourceMappingURL=sse-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-stream.d.ts","sourceRoot":"","sources":["../../src/preview/sse-stream.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAUhD;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAAS,CAAA;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAAgB,CAAA;AAExD,MAAM,WAAW,oBAAoB;IACnC,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAUpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,GAAG,YAAY,CAAC,EAC1D,IAAI,GAAE,oBAAyB,GAC9B,cAAc,CAAC,UAAU,CAAC,CAwD5B;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAOtD,CAAA;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,GAAG,YAAY,CAAC,EAC1D,IAAI,CAAC,EAAE,oBAAoB,GAC1B,QAAQ,CAKV"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { subscribePreviewUpdates } from './event-bus.js';
|
|
2
|
+
/**
|
|
3
|
+
* SSE wire format helpers. We keep them small and pure so the route handler
|
|
4
|
+
* can build a `ReadableStream<Uint8Array>` without pulling in any extra
|
|
5
|
+
* dependencies (this also keeps the file edge-compatible).
|
|
6
|
+
*/
|
|
7
|
+
const encoder = new TextEncoder();
|
|
8
|
+
/**
|
|
9
|
+
* Default keepalive interval. 25 s sits safely under the most aggressive
|
|
10
|
+
* proxy/idle timeouts we've encountered in production (Cloudflare 30 s,
|
|
11
|
+
* Vercel Serverless 30 s, most reverse-proxies 60 s).
|
|
12
|
+
*/
|
|
13
|
+
export const PREVIEW_SSE_HEARTBEAT_MS = 25_000;
|
|
14
|
+
/**
|
|
15
|
+
* Maximum stream lifetime in ms. After this, the server closes the stream
|
|
16
|
+
* cleanly so EventSource will reconnect — important because some platforms
|
|
17
|
+
* (Vercel Fluid Compute, Cloudflare Workers) cap any single response at a
|
|
18
|
+
* few minutes regardless of activity.
|
|
19
|
+
*/
|
|
20
|
+
export const PREVIEW_SSE_MAX_LIFETIME_MS = 4 * 60 * 1000;
|
|
21
|
+
/**
|
|
22
|
+
* Encode a single SSE message. `event` is optional; when omitted the
|
|
23
|
+
* default `message` event is used.
|
|
24
|
+
*/
|
|
25
|
+
export function encodeSseEvent(data, event) {
|
|
26
|
+
const lines = [];
|
|
27
|
+
if (event)
|
|
28
|
+
lines.push(`event: ${event}`);
|
|
29
|
+
const serialized = typeof data === 'string' ? data : JSON.stringify(data);
|
|
30
|
+
for (const line of serialized.split('\n')) {
|
|
31
|
+
lines.push(`data: ${line}`);
|
|
32
|
+
}
|
|
33
|
+
lines.push('');
|
|
34
|
+
lines.push('');
|
|
35
|
+
return lines.join('\n');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build a `ReadableStream` of Server-Sent Events for the given preview
|
|
39
|
+
* session. The stream:
|
|
40
|
+
*
|
|
41
|
+
* 1. Emits an `event: ready` frame with the session's collection/id.
|
|
42
|
+
* Lets the client confirm the server-side subscription is wired up
|
|
43
|
+
* before it starts treating the absence of events as "stale".
|
|
44
|
+
* 2. Forwards every `notifyPreviewUpdate(collection, id, payload)` to
|
|
45
|
+
* the client as `event: update` with `payload` as JSON data.
|
|
46
|
+
* 3. Sends `: heartbeat\n\n` keepalive comments on
|
|
47
|
+
* `PREVIEW_SSE_HEARTBEAT_MS` intervals.
|
|
48
|
+
* 4. Cleanly closes after `PREVIEW_SSE_MAX_LIFETIME_MS` and lets the
|
|
49
|
+
* browser reconnect, sidestepping platform idle/max-duration caps.
|
|
50
|
+
*
|
|
51
|
+
* The returned stream MUST be wrapped in a `Response` with the SSE
|
|
52
|
+
* headers — `createPreviewStreamResponse` does this for typical callers.
|
|
53
|
+
*/
|
|
54
|
+
export function createPreviewStream(session, opts = {}) {
|
|
55
|
+
const heartbeatMs = opts.heartbeatMs ?? PREVIEW_SSE_HEARTBEAT_MS;
|
|
56
|
+
const maxLifetimeMs = opts.maxLifetimeMs ?? PREVIEW_SSE_MAX_LIFETIME_MS;
|
|
57
|
+
let heartbeat;
|
|
58
|
+
let lifetime;
|
|
59
|
+
let unsubscribe;
|
|
60
|
+
return new ReadableStream({
|
|
61
|
+
start(controller) {
|
|
62
|
+
const enqueue = (chunk) => {
|
|
63
|
+
try {
|
|
64
|
+
controller.enqueue(encoder.encode(chunk));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Controller can be closed mid-emit if the client disconnected
|
|
68
|
+
// between the `notifyPreviewUpdate` call and the enqueue. Swallow.
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
enqueue(encodeSseEvent({ collection: session.collection, documentId: session.documentId }, 'ready'));
|
|
72
|
+
unsubscribe = subscribePreviewUpdates(session.collection, session.documentId, (event) => {
|
|
73
|
+
enqueue(encodeSseEvent({
|
|
74
|
+
collection: event.collection,
|
|
75
|
+
documentId: event.documentId,
|
|
76
|
+
at: event.at,
|
|
77
|
+
...event.payload,
|
|
78
|
+
}, 'update'));
|
|
79
|
+
});
|
|
80
|
+
heartbeat = setInterval(() => {
|
|
81
|
+
enqueue(`: heartbeat\n\n`);
|
|
82
|
+
}, heartbeatMs);
|
|
83
|
+
lifetime = setTimeout(() => {
|
|
84
|
+
try {
|
|
85
|
+
controller.close();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Already closed; nothing to do.
|
|
89
|
+
}
|
|
90
|
+
}, maxLifetimeMs);
|
|
91
|
+
},
|
|
92
|
+
cancel() {
|
|
93
|
+
if (heartbeat)
|
|
94
|
+
clearInterval(heartbeat);
|
|
95
|
+
if (lifetime)
|
|
96
|
+
clearTimeout(lifetime);
|
|
97
|
+
if (unsubscribe)
|
|
98
|
+
unsubscribe();
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Standard SSE response headers. Exposed for callers (and tests) that want
|
|
104
|
+
* to wrap the stream themselves.
|
|
105
|
+
*/
|
|
106
|
+
export const PREVIEW_SSE_HEADERS = {
|
|
107
|
+
'Content-Type': 'text/event-stream; charset=utf-8',
|
|
108
|
+
'Cache-Control': 'no-cache, no-transform',
|
|
109
|
+
Connection: 'keep-alive',
|
|
110
|
+
// Discourage proxies/CDNs from buffering — without this nginx will hold
|
|
111
|
+
// events back until 4 KB of payload accumulates.
|
|
112
|
+
'X-Accel-Buffering': 'no',
|
|
113
|
+
};
|
|
114
|
+
export function createPreviewStreamResponse(session, opts) {
|
|
115
|
+
return new Response(createPreviewStream(session, opts), {
|
|
116
|
+
status: 200,
|
|
117
|
+
headers: PREVIEW_SSE_HEADERS,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=sse-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-stream.js","sourceRoot":"","sources":["../../src/preview/sse-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document comments — anchored, threaded discussion attached to documents.
|
|
3
|
+
*
|
|
4
|
+
* This module owns the *pure* comment logic: validation, normalization, and
|
|
5
|
+
* the storage-agnostic CRUD entry points. The HTTP layer in `api/handlers.ts`
|
|
6
|
+
* is a thin wrapper that handles auth + JSON envelope; everything else lives
|
|
7
|
+
* here so the unit tests don't need a Request loop.
|
|
8
|
+
*
|
|
9
|
+
* Storage shape — see `packages/cms-core/prisma/cms-schema.prisma`,
|
|
10
|
+
* model `DocumentComment`. We require only a minimal Prisma surface so the
|
|
11
|
+
* helpers can be tested against an in-memory fake.
|
|
12
|
+
*
|
|
13
|
+
* Anchors are Yjs *relative positions* serialised as Base64. Storing them in
|
|
14
|
+
* a JSON column (rather than Bytes) keeps the REST contract trivial: the
|
|
15
|
+
* client posts `{ from: "AQ...", to: "AQ..." }`, we round-trip the strings.
|
|
16
|
+
* Slice 5 reconstitutes them with `Y.createAbsolutePositionFromRelativePosition`
|
|
17
|
+
* to paint anchored highlights in the editor; nothing in the API layer needs
|
|
18
|
+
* to interpret the bytes.
|
|
19
|
+
*/
|
|
20
|
+
/** Maximum length we accept for a comment body (markdown source). */
|
|
21
|
+
export declare const MAX_COMMENT_BODY_LENGTH = 10000;
|
|
22
|
+
/** Cap on returned comments per `listComments` call. */
|
|
23
|
+
export declare const MAX_COMMENT_LIST_PAGE_SIZE = 200;
|
|
24
|
+
/** Default page size when the caller does not request one. */
|
|
25
|
+
export declare const DEFAULT_COMMENT_LIST_PAGE_SIZE = 100;
|
|
26
|
+
/**
|
|
27
|
+
* Yjs relative-position anchor. The two ends are Base64-encoded
|
|
28
|
+
* `Y.encodeRelativePosition` bytes; slice 5 turns them back into absolute
|
|
29
|
+
* positions for rendering.
|
|
30
|
+
*
|
|
31
|
+
* Slice 4 (this module) treats the anchor as opaque: we only validate that
|
|
32
|
+
* each side is a reasonably short string so we don't store arbitrary blobs.
|
|
33
|
+
*/
|
|
34
|
+
export interface CommentAnchor {
|
|
35
|
+
from: string;
|
|
36
|
+
to: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Public REST shape of a comment. Mirrors the Prisma row plus a derived
|
|
40
|
+
* `isResolved` flag so the client doesn't have to repeat the null check.
|
|
41
|
+
*/
|
|
42
|
+
export interface CommentDTO {
|
|
43
|
+
id: string;
|
|
44
|
+
documentId: string;
|
|
45
|
+
parentId: string | null;
|
|
46
|
+
userId: string | null;
|
|
47
|
+
body: string;
|
|
48
|
+
anchor: CommentAnchor | null;
|
|
49
|
+
resolvedAt: string | null;
|
|
50
|
+
resolvedById: string | null;
|
|
51
|
+
deletedAt: string | null;
|
|
52
|
+
createdAt: string;
|
|
53
|
+
updatedAt: string;
|
|
54
|
+
isResolved: boolean;
|
|
55
|
+
}
|
|
56
|
+
/** Input for creating a new comment. */
|
|
57
|
+
export interface CreateCommentInput {
|
|
58
|
+
documentId: string;
|
|
59
|
+
userId: string;
|
|
60
|
+
body: string;
|
|
61
|
+
anchor?: CommentAnchor | null;
|
|
62
|
+
parentId?: string | null;
|
|
63
|
+
}
|
|
64
|
+
/** Input for updating an existing comment. Only the body is editable. */
|
|
65
|
+
export interface UpdateCommentInput {
|
|
66
|
+
body: string;
|
|
67
|
+
}
|
|
68
|
+
/** Filter passed to `listComments`. */
|
|
69
|
+
export interface ListCommentsFilter {
|
|
70
|
+
documentId: string;
|
|
71
|
+
/** Include resolved threads. Default: `false`. */
|
|
72
|
+
includeResolved?: boolean;
|
|
73
|
+
/** Include soft-deleted comments. Default: `false`. */
|
|
74
|
+
includeDeleted?: boolean;
|
|
75
|
+
/** Page size (1..`MAX_COMMENT_LIST_PAGE_SIZE`). */
|
|
76
|
+
pageSize?: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Minimal Prisma surface we depend on. The real `PrismaClient` satisfies it,
|
|
80
|
+
* but tests inject a small in-memory fake.
|
|
81
|
+
*/
|
|
82
|
+
export interface CommentsDB {
|
|
83
|
+
documentComment: {
|
|
84
|
+
findUnique: (args: {
|
|
85
|
+
where: {
|
|
86
|
+
id: string;
|
|
87
|
+
};
|
|
88
|
+
[key: string]: unknown;
|
|
89
|
+
}) => Promise<DocumentCommentRow | null>;
|
|
90
|
+
findMany: (args: {
|
|
91
|
+
where: Record<string, unknown>;
|
|
92
|
+
orderBy?: Record<string, 'asc' | 'desc'>;
|
|
93
|
+
take?: number;
|
|
94
|
+
}) => Promise<DocumentCommentRow[]>;
|
|
95
|
+
create: (args: {
|
|
96
|
+
data: {
|
|
97
|
+
documentId: string;
|
|
98
|
+
userId: string | null;
|
|
99
|
+
body: string;
|
|
100
|
+
anchor: CommentAnchor | null;
|
|
101
|
+
parentId: string | null;
|
|
102
|
+
};
|
|
103
|
+
}) => Promise<DocumentCommentRow>;
|
|
104
|
+
update: (args: {
|
|
105
|
+
where: {
|
|
106
|
+
id: string;
|
|
107
|
+
};
|
|
108
|
+
data: Partial<{
|
|
109
|
+
body: string;
|
|
110
|
+
resolvedAt: Date | null;
|
|
111
|
+
resolvedById: string | null;
|
|
112
|
+
deletedAt: Date | null;
|
|
113
|
+
}>;
|
|
114
|
+
}) => Promise<DocumentCommentRow>;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Row shape returned by Prisma. We accept Date or ISO strings so fakes are cheap. */
|
|
118
|
+
export interface DocumentCommentRow {
|
|
119
|
+
id: string;
|
|
120
|
+
documentId: string;
|
|
121
|
+
parentId: string | null;
|
|
122
|
+
userId: string | null;
|
|
123
|
+
body: string;
|
|
124
|
+
anchor: CommentAnchor | null;
|
|
125
|
+
resolvedAt: Date | string | null;
|
|
126
|
+
resolvedById: string | null;
|
|
127
|
+
deletedAt: Date | string | null;
|
|
128
|
+
createdAt: Date | string;
|
|
129
|
+
updatedAt: Date | string;
|
|
130
|
+
}
|
|
131
|
+
/** Discriminated result type used by the service entry points. */
|
|
132
|
+
export type CommentsResult<T> = {
|
|
133
|
+
ok: true;
|
|
134
|
+
value: T;
|
|
135
|
+
} | {
|
|
136
|
+
ok: false;
|
|
137
|
+
error: CommentsError;
|
|
138
|
+
};
|
|
139
|
+
export interface CommentsError {
|
|
140
|
+
/**
|
|
141
|
+
* Stable machine-readable code. The HTTP layer maps each to a status:
|
|
142
|
+
* - validation → 400
|
|
143
|
+
* - not_found → 404
|
|
144
|
+
* - forbidden → 403
|
|
145
|
+
* - conflict → 409 (e.g. resolving an already-resolved thread)
|
|
146
|
+
*/
|
|
147
|
+
code: 'validation' | 'not_found' | 'forbidden' | 'conflict';
|
|
148
|
+
message: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Strip a comment row down to the public DTO. Centralised so the response
|
|
152
|
+
* shape stays consistent between create / list / update / resolve.
|
|
153
|
+
*/
|
|
154
|
+
export declare function toCommentDTO(row: DocumentCommentRow): CommentDTO;
|
|
155
|
+
/**
|
|
156
|
+
* Parse + validate an anchor blob coming from an untrusted client. Returns
|
|
157
|
+
* `null` when the caller did not provide one (document-level comments).
|
|
158
|
+
*/
|
|
159
|
+
export declare function parseAnchor(input: unknown): CommentsResult<CommentAnchor | null>;
|
|
160
|
+
/** Normalize whitespace + enforce length limits on a posted body. */
|
|
161
|
+
export declare function normaliseBody(input: unknown): CommentsResult<string>;
|
|
162
|
+
/**
|
|
163
|
+
* Create a comment. Enforces:
|
|
164
|
+
* - body validation (non-empty, length-capped)
|
|
165
|
+
* - anchor shape validation
|
|
166
|
+
* - single-level threading: a `parentId` must reference an existing,
|
|
167
|
+
* non-deleted, non-reply comment under the same document.
|
|
168
|
+
*
|
|
169
|
+
* The caller (HTTP handler) is responsible for auth — once we reach here we
|
|
170
|
+
* trust the supplied `userId`.
|
|
171
|
+
*/
|
|
172
|
+
export declare function createComment(db: CommentsDB, input: CreateCommentInput): Promise<CommentsResult<CommentDTO>>;
|
|
173
|
+
/**
|
|
174
|
+
* List comments for a document. Returns the rows ordered oldest-first so a
|
|
175
|
+
* naive client can render threads top-down. Pagination is "show the first
|
|
176
|
+
* N"; the higher-level UI in slice 5 will switch to cursor pagination once
|
|
177
|
+
* volume justifies it.
|
|
178
|
+
*/
|
|
179
|
+
export declare function listComments(db: CommentsDB, filter: ListCommentsFilter): Promise<CommentsResult<CommentDTO[]>>;
|
|
180
|
+
/**
|
|
181
|
+
* Edit a comment body. Only the author can edit, and only if the comment is
|
|
182
|
+
* not soft-deleted. Resolved threads remain editable so a moderator can
|
|
183
|
+
* append context.
|
|
184
|
+
*/
|
|
185
|
+
export declare function updateComment(db: CommentsDB, id: string, input: UpdateCommentInput, actor: {
|
|
186
|
+
userId: string;
|
|
187
|
+
isAdmin: boolean;
|
|
188
|
+
}): Promise<CommentsResult<CommentDTO>>;
|
|
189
|
+
/**
|
|
190
|
+
* Mark a comment thread as resolved. Either the comment's author or any
|
|
191
|
+
* admin / write-role caller can resolve. Resolving an already-resolved
|
|
192
|
+
* comment is a no-op (returns the existing row) so a duplicate click in the
|
|
193
|
+
* UI does not surface as an error.
|
|
194
|
+
*/
|
|
195
|
+
export declare function resolveComment(db: CommentsDB, id: string, actor: {
|
|
196
|
+
userId: string;
|
|
197
|
+
canResolve: boolean;
|
|
198
|
+
}): Promise<CommentsResult<CommentDTO>>;
|
|
199
|
+
/**
|
|
200
|
+
* Re-open a resolved thread. Same permission as `resolveComment`.
|
|
201
|
+
*/
|
|
202
|
+
export declare function reopenComment(db: CommentsDB, id: string, actor: {
|
|
203
|
+
userId: string;
|
|
204
|
+
canResolve: boolean;
|
|
205
|
+
}): Promise<CommentsResult<CommentDTO>>;
|
|
206
|
+
/**
|
|
207
|
+
* Soft-delete a comment. The row is preserved (so replies don't lose their
|
|
208
|
+
* thread root) but stops being returned by `listComments` unless explicitly
|
|
209
|
+
* requested with `includeDeleted: true`.
|
|
210
|
+
*
|
|
211
|
+
* Only the author or an admin may delete.
|
|
212
|
+
*/
|
|
213
|
+
export declare function deleteComment(db: CommentsDB, id: string, actor: {
|
|
214
|
+
userId: string;
|
|
215
|
+
isAdmin: boolean;
|
|
216
|
+
}): Promise<CommentsResult<CommentDTO>>;
|
|
217
|
+
//# sourceMappingURL=comments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/realtime/comments.ts"],"names":[],"mappings":"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"}
|