@phtngyn/cms 0.1.0-beta.4 → 0.2.0-beta.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.
Files changed (93) hide show
  1. package/README.md +85 -5
  2. package/package.json +12 -1
  3. package/src/ApplicationTypes.d.ts +82 -0
  4. package/src/ApplicationTypes.js +1 -0
  5. package/src/{Configuration-CDMYfTre.js → Configuration-CjVUBBwa.js} +3 -3
  6. package/src/{Configuration-CDMYfTre.js.map → Configuration-CjVUBBwa.js.map} +1 -1
  7. package/src/Configuration.d.ts +9 -4
  8. package/src/Configuration.js.map +1 -1
  9. package/src/Content.d.ts +67 -0
  10. package/src/Content.js +291 -0
  11. package/src/Content.js.map +1 -0
  12. package/src/ContentTransfer-CRQet3QJ.d.ts +48 -0
  13. package/src/{ContentTransfer-C3Av9sWz.js → ContentTransfer-CTzGGKFV.js} +8 -4
  14. package/src/ContentTransfer-CTzGGKFV.js.map +1 -0
  15. package/src/{DocumentEngine-J7g-emdf.js → DocumentEngine-BbhfnTAc.js} +4 -4
  16. package/src/{DocumentEngine-J7g-emdf.js.map → DocumentEngine-BbhfnTAc.js.map} +1 -1
  17. package/src/DocumentModel.d.ts +8 -1
  18. package/src/DocumentModel.js +29 -2
  19. package/src/DocumentModel.js.map +1 -1
  20. package/src/{Forms-Dj6NuW66.js → Forms-02-p8qEw.js} +2 -2
  21. package/src/{Forms-Dj6NuW66.js.map → Forms-02-p8qEw.js.map} +1 -1
  22. package/src/{Forms-BsJMev5_.d.ts → Forms-BorTcIlp.d.ts} +2 -5
  23. package/src/Forms.d.ts +25 -14
  24. package/src/Forms.js.map +1 -1
  25. package/src/I18n-BXlVunfa.d.ts +27 -0
  26. package/src/I18n.d.ts +2 -20
  27. package/src/Module.js +14 -5
  28. package/src/Module.js.map +1 -1
  29. package/src/{S3MediaObjects-CpPSzJto.js → S3MediaObjects-DC0c8sYC.js} +54 -35
  30. package/src/{S3MediaObjects-CpPSzJto.js.map → S3MediaObjects-DC0c8sYC.js.map} +1 -1
  31. package/src/cli/content.js +63 -221
  32. package/src/cli/content.js.map +1 -1
  33. package/src/cli.js +93 -4
  34. package/src/cli.js.map +1 -1
  35. package/src/{connection-CBAy2qGy.js → connection-BPf4BQUZ.js} +2 -2
  36. package/src/{connection-CBAy2qGy.js.map → connection-BPf4BQUZ.js.map} +1 -1
  37. package/src/dev-lifecycle-vQLxwCFq.js +428 -0
  38. package/src/dev-lifecycle-vQLxwCFq.js.map +1 -0
  39. package/src/{installation-CNfIriVm.js → installation-DsGst1BH.js} +578 -457
  40. package/src/installation-DsGst1BH.js.map +1 -0
  41. package/src/internal/application-types.js +43 -0
  42. package/src/internal/application-types.js.map +1 -0
  43. package/src/internal/authoring-catalog.js +9 -4
  44. package/src/internal/authoring-catalog.js.map +1 -1
  45. package/src/internal/authoring-metadata.js +1 -1
  46. package/src/internal/configuration.js +10 -6
  47. package/src/internal/configuration.js.map +1 -1
  48. package/src/internal/dev-lifecycle.js +3 -0
  49. package/src/internal/document-model.js +2 -2
  50. package/src/internal/document-model.js.map +1 -1
  51. package/src/internal/i18n.js +21 -0
  52. package/src/internal/i18n.js.map +1 -1
  53. package/src/{location-BTqdfIzX.js → location-BgYhXEZp.js} +2 -2
  54. package/src/{location-BTqdfIzX.js.map → location-BgYhXEZp.js.map} +1 -1
  55. package/src/{models-Bah5B3bT.js → models-DgkGTFus.js} +6 -1
  56. package/src/models-DgkGTFus.js.map +1 -0
  57. package/src/{models-B4IoTmp7.js → models-k2nXyD6q.js} +2 -2
  58. package/src/{models-B4IoTmp7.js.map → models-k2nXyD6q.js.map} +1 -1
  59. package/src/runtime/delivery/context.js +1 -1
  60. package/src/runtime/delivery/plugin.js +27 -5
  61. package/src/runtime/delivery/plugin.js.map +1 -1
  62. package/src/runtime/delivery/preview.d.ts +1 -1
  63. package/src/runtime/delivery/types.d.ts +2 -85
  64. package/src/runtime/delivery/useCmsDocumentSeo.d.ts +8 -1
  65. package/src/runtime/delivery/useCmsDocumentSeo.js +19 -7
  66. package/src/runtime/delivery/useCmsDocumentSeo.js.map +1 -1
  67. package/src/runtime/delivery/useDocument.d.ts +2 -2
  68. package/src/runtime/delivery/useDocument.js.map +1 -1
  69. package/src/runtime/delivery/useDocumentQuery.d.ts +3 -3
  70. package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
  71. package/src/runtime/forms/document.js +1 -1
  72. package/src/runtime/forms/useCmsForm.js +81 -41
  73. package/src/runtime/forms/useCmsForm.js.map +1 -1
  74. package/src/runtime/i18n/useCmsI18n.d.ts +9 -7
  75. package/src/runtime/i18n/useCmsI18n.js +5 -4
  76. package/src/runtime/i18n/useCmsI18n.js.map +1 -1
  77. package/src/runtime/installation.js +2 -2
  78. package/src/runtime/plugin.js +1 -1
  79. package/src/runtime/preview/connection.js +1 -1
  80. package/src/runtime/preview/controller.js +2 -2
  81. package/src/runtime/preview/plugin.client.js +3 -3
  82. package/src/runtime/preview/store.js +1 -1
  83. package/src/runtime/sitemap.js +1 -1
  84. package/src/scalars-CA6kyipS.d.ts +7 -0
  85. package/src/{store-b2CSXgMt.js → store-BYgSt7E3.js} +3 -3
  86. package/src/{store-b2CSXgMt.js.map → store-BYgSt7E3.js.map} +1 -1
  87. package/src/types-DutFRtaG.d.ts +90 -0
  88. package/studio/{CreateDocumentDialog-GGey1uBc.js → CreateDocumentDialog-BdiM77bb.js} +1 -1
  89. package/studio/{documentPlanning-DRErYmBU.js → documentPlanning-B7fyUj9r.js} +7072 -7065
  90. package/studio/host.js +2 -2
  91. package/src/ContentTransfer-C3Av9sWz.js.map +0 -1
  92. package/src/installation-CNfIriVm.js.map +0 -1
  93. package/src/models-Bah5B3bT.js.map +0 -1
@@ -1,42 +1,548 @@
1
1
  import { a as EditorNodeId, c as RevisionId, d as SourcePath, i as DocumentVersion, r as DocumentId, t as DocumentGeneration } from "./scalars-B2lgGUnj.js";
2
- import { i as FormResult, n as FORM_SUBMISSION_MAX_BYTES } from "./Forms-CfcI3tPU.js";
3
- import { a as encodeCmsEditorComponentAttributes, d as createCmsComarkRenderData, i as validateFormValues, t as documentForms } from "./Forms-Dj6NuW66.js";
4
- import { $ as StudioActor, A as UnpublishDocumentInput, B as SeoMediaUnavailable, D as RemoveDocumentInput, Et as RequestId, H as SeoRevision, J as AccessDenied, K as SeoVersionConflict, O as RestoreDocumentInput, Q as Role, S as PublishDocumentInput, Y as AuthenticationRequired, _t as MediaReference, a as DOCUMENT_REVISION_ACTIONS, at as MediaCleanupReport, b as MarkdownNode, bt as MediaTooLarge, ct as MediaFolder, dt as MediaInvalid, et as StudioEntryDenied, ft as MediaName, ht as MediaPage, it as MediaByteSize, j as UpdateDocumentInput, k as UndeleteDocumentInput, l as DocumentMutationResult, lt as MediaId, m as DocumentSource, mt as MediaObjectKey, n as CmsMarkdownDocument, nt as ImageMimeType, o as DeletedDocument, ot as MediaConflict, p as DocumentRevisionAction, pt as MediaNotFound, rt as MediaAsset, st as MediaCursor, tt as StudioRequestContext, ut as MediaIntegrityReport, vt as MediaReferenced, x as MoveDocumentInput, xt as MediaUpload, y as DuplicateDocumentInput, yt as MediaStatus, z as SeoConfirmationRequired } from "./models-Bah5B3bT.js";
5
- import { $ as DocumentRevision, A as StudioBadRequest, B as User, C as DocumentStore, D as CurrentStudioRequest, E as defaultAccessControlLayer, F as studioInternalError, G as UserSelfRemovalDenied, H as UserAlreadyExists, I as InitializationAlreadyCompleted, J as CollaborationServerMessage, K as UserSelfRoleChangeDenied, L as InitializationProofInvalid, M as StudioRequestConflict, N as StudioSchemaError, O as StudioApi, P as StudioInternalError, Q as DocumentHistoryInvalidCursor, R as InitializationState, S as DocumentPersistenceError, T as AccessControl, U as UserNotFound, V as UserAdministrationDenied, W as UserPage, X as StateVector, Y as CollaborationTicket, Z as DocumentHistoryComparisonTooLarge, _ as Documents, a as mediaObjectPrefix, at as ActivityEntry, b as cursorCodec, c as Seo, ct as ActivityPage, d as seoDeliveryLayer, dt as DocumentMediaUnavailable, et as ACTIVITY_ACTIONS, f as seoLayer, ft as DocumentNotFound, g as DocumentPreviews, gt as PublishedDocumentNotFound, h as DocumentMaintenance, ht as DocumentVersionConflict, i as MediaObjectStore, it as ActivityCursorInvalid, k as StudioAuthentication, l as SeoDelivery, lt as ActivityTarget, m as SeoStore, mt as DocumentValidationFailed, n as s3MediaObjectStoreLayer, nt as ActivityContext, o as PreviewSeo, ot as ActivityEntryDraft, p as SeoPersistenceError, pt as DocumentPathConflict, q as CollaborationClientMessage, r as MediaPersistenceError, rt as ActivityCursor, s as PublishedSeo, st as ActivityId, tt as ActivityAction, u as makeDefaultSeoOptions, ut as ActivityTargetKind, v as PublishedDocuments, w as renderEditorMarkdown, x as DocumentGenerationConflict, y as documentsLayer, z as CreateUserInput } from "./S3MediaObjects-CpPSzJto.js";
2
+ import { $ as StudioActor, A as UnpublishDocumentInput, B as SeoMediaUnavailable, D as RemoveDocumentInput, Et as RequestId, H as SeoRevision, J as AccessDenied, K as SeoVersionConflict, O as RestoreDocumentInput, Q as Role, S as PublishDocumentInput, Y as AuthenticationRequired, _t as MediaReference, a as DOCUMENT_REVISION_ACTIONS, at as MediaCleanupReport, b as MarkdownNode, bt as MediaTooLarge, ct as MediaFolder, dt as MediaInvalid, et as StudioEntryDenied, ft as MediaName, ht as MediaPage, it as MediaByteSize, j as UpdateDocumentInput, k as UndeleteDocumentInput, l as DocumentMutationResult, lt as MediaId, m as DocumentSource, mt as MediaObjectKey, n as CmsMarkdownDocument, nt as ImageMimeType, o as DeletedDocument, ot as MediaConflict, p as DocumentRevisionAction, pt as MediaNotFound, rt as MediaAsset, st as MediaCursor, tt as StudioRequestContext, ut as MediaIntegrityReport, vt as MediaReferenced, x as MoveDocumentInput, xt as MediaUpload, y as DuplicateDocumentInput, yt as MediaStatus, z as SeoConfirmationRequired } from "./models-DgkGTFus.js";
3
+ import { $ as DocumentRevision, A as StudioBadRequest, B as User, C as DocumentStore, D as CurrentStudioRequest, E as defaultAccessControlLayer, F as studioInternalError, G as UserSelfRemovalDenied, H as UserAlreadyExists, I as InitializationAlreadyCompleted, J as CollaborationServerMessage, K as UserSelfRoleChangeDenied, L as InitializationProofInvalid, M as StudioRequestConflict, N as StudioSchemaError, O as StudioApi, P as StudioInternalError, Q as DocumentHistoryInvalidCursor, R as InitializationState, S as DocumentPersistenceError, T as AccessControl, U as UserNotFound, V as UserAdministrationDenied, W as UserPage, X as StateVector, Y as CollaborationTicket, Z as DocumentHistoryComparisonTooLarge, _ as Documents, a as mediaObjectPrefix, at as ActivityEntry, b as cursorCodec, c as Seo, ct as ActivityPage, d as seoDeliveryLayer, dt as DocumentMediaUnavailable, et as ACTIVITY_ACTIONS, f as seoLayer, ft as DocumentNotFound, g as DocumentPreviews, gt as PublishedDocumentNotFound, h as DocumentMaintenance, ht as DocumentVersionConflict, i as MediaObjectStore, it as ActivityCursorInvalid, k as StudioAuthentication, l as SeoDelivery, lt as ActivityTarget, m as SeoStore, mt as DocumentValidationFailed, n as s3MediaObjectStoreLayer, nt as ActivityContext, o as PreviewSeo, ot as ActivityEntryDraft, p as SeoPersistenceError, pt as DocumentPathConflict, q as CollaborationClientMessage, r as MediaPersistenceError, rt as ActivityCursor, s as PublishedSeo, st as ActivityId, tt as ActivityAction, u as makeDefaultSeoOptions, ut as ActivityTargetKind, v as PublishedDocuments, w as renderEditorMarkdown, x as DocumentGenerationConflict, y as documentsLayer, z as CreateUserInput } from "./S3MediaObjects-DC0c8sYC.js";
4
+ import { o as ContentTransferConflict } from "./ContentTransfer-CTzGGKFV.js";
6
5
  import { a as CMS_FORM_SUBMIT_PATH, l as CMS_READINESS_PATH, o as CMS_LIVENESS_PATH, p as STUDIO_COLLABORATION_PATH, t as CMS_AUTHENTICATION_PATH, u as STUDIO_API_PATH } from "./HttpPaths-c9nLZ9H2.js";
6
+ import { i as FormResult, n as FORM_SUBMISSION_MAX_BYTES } from "./Forms-CfcI3tPU.js";
7
+ import { a as encodeCmsEditorComponentAttributes, d as createCmsComarkRenderData, i as validateFormValues, t as documentForms } from "./Forms-02-p8qEw.js";
7
8
  import { a as createEditorNodeId, o as editorNodeId, r as identifiedAttributes, t as assertCanonicalEditorContent } from "./metadata-BEZPWh-3.js";
8
- import { C as finiteNumberAttribute, S as compactJsonAttributes, _ as comarkTagForEditorMark, b as encodeEditorImageAttributes, g as EDITOR_MARK_TYPES, h as comarkToEditor, u as EditorDocumentInvalid, v as isEditorMark, w as nonEmptyStringAttribute, x as normalizeEditorImageLayout, y as EDITOR_IMAGE_LAYOUT_ATTRIBUTE } from "./Configuration-CDMYfTre.js";
9
- import { o as ContentTransferConflict } from "./ContentTransfer-C3Av9sWz.js";
9
+ import { C as finiteNumberAttribute, S as compactJsonAttributes, _ as comarkTagForEditorMark, b as encodeEditorImageAttributes, g as EDITOR_MARK_TYPES, h as comarkToEditor, u as EditorDocumentInvalid, v as isEditorMark, w as nonEmptyStringAttribute, x as normalizeEditorImageLayout, y as EDITOR_IMAGE_LAYOUT_ATTRIBUTE } from "./Configuration-CjVUBBwa.js";
10
10
  import { Cause, Clock, Context, Crypto, Data, DateTime, Deferred, Effect, Encoding, Exit, Fiber, Layer, Option, Predicate, PubSub, Pull, Queue, Redacted, Ref, Result, Schedule, Schema, Scope, Semaphore, Stream, flow } from "effect";
11
11
  import { Extension, Node, getSchema, mergeAttributes } from "@tiptap/core";
12
12
  import { prosemirrorJSONToYDoc, ySyncPluginKey, yXmlFragmentToProseMirrorRootNode } from "@tiptap/y-tiptap";
13
13
  import { FindMyWay, HttpEffect, HttpMiddleware, HttpRouter, HttpServer, HttpServerRequest, HttpServerResponse, Multipart } from "effect/unstable/http";
14
14
  import { HttpApiBuilder, HttpApiMiddleware } from "effect/unstable/httpapi";
15
- import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto";
16
- import { createAuthMiddleware, getSessionFromCtx, isAPIError } from "better-auth/api";
15
+ import { Pool } from "pg";
16
+ import { PgClient, PgPool } from "@effect/sql-pg";
17
+ import * as PgDrizzle from "drizzle-orm/effect-postgres";
18
+ import { migrate } from "drizzle-orm/pg-core/effect/session";
19
+ import { and, asc, count, desc, eq, gt, inArray, lt, lte, ne, or, sql } from "drizzle-orm";
20
+ import { alias, bigint, boolean, bytea, check, foreignKey, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique, uniqueIndex, uuid } from "drizzle-orm/pg-core";
21
+ import * as Client from "effect/unstable/sql/SqlClient";
22
+ import * as Statement from "effect/unstable/sql/Statement";
17
23
  import { betterAuth } from "better-auth";
18
24
  import { createAccessControl } from "better-auth/plugins/access";
19
25
  import { admin } from "better-auth/plugins/admin";
20
26
  import { defaultStatements } from "better-auth/plugins/admin/access";
27
+ import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto";
28
+ import { createAuthMiddleware, getSessionFromCtx, isAPIError } from "better-auth/api";
21
29
  import { Hocuspocus, IncomingMessage, MessageType, shouldSkipStoreHooks } from "@hocuspocus/server";
22
30
  import StarterKit from "@tiptap/starter-kit";
23
31
  import * as Y from "yjs";
24
32
  import { Doc, applyUpdate, encodeStateAsUpdate, encodeStateVector } from "yjs";
25
33
  import { RateLimiter } from "effect/unstable/persistence";
26
- import { PgClient } from "@effect/sql-pg";
27
34
  import { isDeepStrictEqual } from "node:util";
28
- import { and, asc, count, desc, eq, gt, inArray, lt, lte, ne, or, sql } from "drizzle-orm";
29
- import * as PgDrizzle from "drizzle-orm/effect-postgres";
30
35
  import { createInsertSchema, createSelectSchema } from "drizzle-orm/effect-schema";
31
- import { alias, bigint, boolean, bytea, check, foreignKey, index, integer, jsonb, pgTable, primaryKey, text, timestamp, unique, uniqueIndex, uuid } from "drizzle-orm/pg-core";
32
- import { migrate } from "drizzle-orm/pg-core/effect/session";
33
36
  import { EffectDrizzleQueryError } from "drizzle-orm/effect-core";
34
37
  import * as Cause$1 from "effect/Cause";
35
38
  import * as Option$1 from "effect/Option";
36
39
  import * as SqlError from "effect/unstable/sql/SqlError";
37
40
  import { Buffer } from "node:buffer";
38
- import { Pool } from "pg";
39
41
 
42
+ //#region ../sql-pg/src/internal/database/embedded-migrations.generated.ts
43
+ const embeddedMigrations = [
44
+ {
45
+ sql: [
46
+ "CREATE TABLE \"activity_entries\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"action\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"target_kind\" text NOT NULL,\n \"target_id\" text,\n \"details\" jsonb DEFAULT '{}' NOT NULL,\n \"occurred_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset')),\n CONSTRAINT \"activity_entries_target_kind_check\" CHECK (\"target_kind\" in ('document', 'media', 'media-library', 'user')),\n CONSTRAINT \"activity_entries_target_check\" CHECK ((\"target_kind\" = 'media-library' AND \"target_id\" IS NULL)\n OR (\"target_kind\" <> 'media-library' AND \"target_id\" IS NOT NULL)),\n CONSTRAINT \"activity_entries_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"activity_entries_details_check\" CHECK (jsonb_typeof(\"details\") = 'object')\n);\n",
47
+ "\nCREATE TABLE \"auth_accounts\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"issuer\" text NOT NULL,\n \"account_id\" text NOT NULL,\n \"provider_id\" text NOT NULL,\n \"user_id\" uuid NOT NULL,\n \"access_token\" text,\n \"refresh_token\" text,\n \"id_token\" text,\n \"access_token_expires_at\" timestamp with time zone,\n \"refresh_token_expires_at\" timestamp with time zone,\n \"scope\" text,\n \"password\" text,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL\n);\n",
48
+ "\nCREATE TABLE \"auth_rate_limits\" (\n \"key\" text PRIMARY KEY,\n \"count\" bigint NOT NULL,\n \"last_request\" bigint NOT NULL\n);\n",
49
+ "\nCREATE TABLE \"auth_sessions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"expires_at\" timestamp with time zone NOT NULL,\n \"token\" text NOT NULL UNIQUE,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"ip_address\" text,\n \"user_agent\" text,\n \"user_id\" uuid NOT NULL,\n \"impersonated_by\" text\n);\n",
50
+ "\nCREATE TABLE \"auth_users\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"name\" text NOT NULL,\n \"email\" text NOT NULL UNIQUE,\n \"email_verified\" boolean DEFAULT false NOT NULL,\n \"image\" text,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"role\" text DEFAULT 'editor' NOT NULL,\n \"banned\" boolean DEFAULT false NOT NULL,\n \"ban_reason\" text,\n \"ban_expires\" timestamp with time zone,\n \"cms_creation_change_id\" uuid UNIQUE,\n \"cms_sessions_revoked_change_id\" uuid UNIQUE,\n CONSTRAINT \"auth_users_role_check\" CHECK (\"role\" in ('administrator', 'editor', 'viewer'))\n);\n",
51
+ "\nCREATE TABLE \"auth_verifications\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"identifier\" text NOT NULL,\n \"value\" text NOT NULL,\n \"expires_at\" timestamp with time zone NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL\n);\n",
52
+ "\nCREATE TABLE \"change_receipts\" (\n \"change_id\" uuid PRIMARY KEY,\n \"fingerprint\" text NOT NULL,\n \"outcome\" text NOT NULL,\n \"activity_id\" uuid UNIQUE,\n \"completed_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"change_receipts_outcome_check\" CHECK ((\"outcome\" = 'applied' AND \"activity_id\" IS NOT NULL)\n OR (\"outcome\" = 'cancelled' AND \"activity_id\" IS NULL))\n);\n",
53
+ "\nCREATE TABLE \"cms_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"generation\" bigint DEFAULT 0 NOT NULL,\n CONSTRAINT \"cms_state_singleton_check\" CHECK (\"singleton\"),\n CONSTRAINT \"cms_state_generation_check\" CHECK (\"generation\" >= 0)\n);\n",
54
+ "\nCREATE TABLE \"document_heads\" (\n \"document_id\" uuid PRIMARY KEY,\n \"authored_revision_id\" uuid NOT NULL,\n \"published_revision_id\" uuid\n);\n",
55
+ "\nCREATE TABLE \"document_media_references\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"document_id\" uuid NOT NULL,\n \"object_key\" text NOT NULL,\n \"path\" text NOT NULL,\n \"source_path\" text NOT NULL,\n \"node_path\" integer[] NOT NULL,\n CONSTRAINT \"document_media_references_identity_unique\" UNIQUE(\"document_id\",\"source_path\",\"node_path\",\"object_key\"),\n CONSTRAINT \"document_media_references_object_key_check\" CHECK (char_length(\"object_key\") between 1 and 1024\n AND btrim(\"object_key\") = \"object_key\"\n AND \"object_key\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"object_key\") = 0),\n CONSTRAINT \"document_media_references_node_path_check\" CHECK (array_position(\"node_path\", NULL) IS NULL AND 0 <= ALL(\"node_path\"))\n);\n",
56
+ "\nCREATE TABLE \"document_revisions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"document_id\" uuid NOT NULL,\n \"action\" text NOT NULL,\n \"source_path\" text NOT NULL,\n \"markdown\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"activity_details\" jsonb DEFAULT '{}' NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"document_revisions_document_id_unique\" UNIQUE(\"document_id\",\"id\"),\n CONSTRAINT \"document_revisions_action_check\" CHECK (\"action\" in ('document.create', 'document.move', 'document.remove', 'document.restore', 'document.undelete', 'document.update'))\n);\n",
57
+ "\nCREATE TABLE \"documents\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"source_path\" text NOT NULL,\n \"deleted_at\" timestamp with time zone,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL\n);\n",
58
+ "\nCREATE TABLE \"initialization_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"state\" text DEFAULT 'uninitialized' NOT NULL,\n \"change_id\" uuid,\n \"claim\" jsonb,\n CONSTRAINT \"initialization_state_singleton_check\" CHECK (\"singleton\"),\n CONSTRAINT \"initialization_state_state_check\" CHECK (\"state\" in ('uninitialized', 'claiming', 'ready')),\n CONSTRAINT \"initialization_state_claim_check\" CHECK ((\"state\" = 'claiming' AND \"change_id\" IS NOT NULL AND jsonb_typeof(\"claim\") = 'object')\n OR (\"state\" <> 'claiming' AND \"change_id\" IS NULL AND \"claim\" IS NULL))\n);\n",
59
+ "\nCREATE TABLE \"media_assets\" (\n \"id\" uuid PRIMARY KEY,\n \"object_key\" text NOT NULL UNIQUE,\n \"name\" text NOT NULL,\n \"folder\" text DEFAULT '' NOT NULL,\n \"mime_type\" text NOT NULL,\n \"byte_size\" bigint NOT NULL,\n \"status\" text DEFAULT 'uploading' NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"media_assets_byte_size_check\" CHECK (\"byte_size\" > 0 AND \"byte_size\" <= 9007199254740991),\n CONSTRAINT \"media_assets_mime_type_check\" CHECK (\"mime_type\" in ('image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/webp')),\n CONSTRAINT \"media_assets_status_check\" CHECK (\"status\" in ('uploading', 'ready', 'deleting')),\n CONSTRAINT \"media_assets_name_check\" CHECK (char_length(\"name\") between 1 and 255\n AND btrim(\"name\") = \"name\"\n AND \"name\" not in ('.', '..')\n AND \"name\" !~ '[[:cntrl:]/]'\n AND position(chr(92) in \"name\") = 0),\n CONSTRAINT \"media_assets_folder_check\" CHECK (char_length(\"folder\") <= 512\n AND btrim(\"folder\") = \"folder\"\n AND \"folder\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"folder\") = 0),\n CONSTRAINT \"media_assets_object_key_check\" CHECK (\"object_key\" ~ '^media/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$')\n);\n",
60
+ "\nCREATE TABLE \"media_replacements\" (\n \"media_id\" uuid PRIMARY KEY,\n \"object_key\" text NOT NULL,\n \"staging_object_key\" text NOT NULL UNIQUE,\n \"name\" text NOT NULL,\n \"folder\" text NOT NULL,\n \"mime_type\" text NOT NULL,\n \"byte_size\" bigint NOT NULL,\n \"staged\" boolean DEFAULT false NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"media_replacements_byte_size_check\" CHECK (\"byte_size\" > 0 AND \"byte_size\" <= 9007199254740991),\n CONSTRAINT \"media_replacements_mime_type_check\" CHECK (\"mime_type\" in ('image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/webp')),\n CONSTRAINT \"media_replacements_name_check\" CHECK (char_length(\"name\") between 1 and 255\n AND btrim(\"name\") = \"name\"\n AND \"name\" not in ('.', '..')\n AND \"name\" !~ '[[:cntrl:]/]'\n AND position(chr(92) in \"name\") = 0),\n CONSTRAINT \"media_replacements_folder_check\" CHECK (char_length(\"folder\") <= 512\n AND btrim(\"folder\") = \"folder\"\n AND \"folder\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"folder\") = 0),\n CONSTRAINT \"media_replacements_object_key_check\" CHECK (\"object_key\" ~ '^media/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$'),\n CONSTRAINT \"media_replacements_staging_object_key_check\" CHECK (\"staging_object_key\" ~ '^media/replacements/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$'),\n CONSTRAINT \"media_replacements_distinct_object_keys_check\" CHECK (\"staging_object_key\" <> \"object_key\")\n);\n",
61
+ "\nCREATE TABLE \"pending_changes\" (\n \"id\" uuid PRIMARY KEY,\n \"action\" text NOT NULL,\n \"subject\" text NOT NULL,\n \"scope\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"target_kind\" text,\n \"target_id\" text,\n \"intent\" jsonb NOT NULL,\n \"fingerprint\" text NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset')),\n CONSTRAINT \"pending_changes_scope_check\" CHECK (\"scope\" in ('initialization', 'media', 'users')),\n CONSTRAINT \"pending_changes_subject_check\" CHECK (char_length(\"subject\") between 1 and 1024 AND btrim(\"subject\") = \"subject\"),\n CONSTRAINT \"pending_changes_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"pending_changes_intent_check\" CHECK (jsonb_typeof(\"intent\") = 'object'),\n CONSTRAINT \"pending_changes_target_check\" CHECK ((\"target_kind\" IS NULL AND \"target_id\" IS NULL)\n OR (\"target_kind\" = 'media-library' AND \"target_id\" IS NULL)\n OR (\"target_kind\" in ('document', 'media', 'user')\n AND \"target_id\" IS NOT NULL))\n);\n",
62
+ "\nCREATE TABLE \"working_document_publish_attempts\" (\n \"id\" uuid PRIMARY KEY,\n \"activity\" jsonb NOT NULL,\n \"document_id\" uuid NOT NULL,\n \"expected_generation\" uuid NOT NULL,\n \"expected_version\" uuid NOT NULL,\n \"high_watermark\" bigint NOT NULL,\n \"markdown_hash\" text NOT NULL,\n \"state\" bytea NOT NULL,\n \"state_vector\" bytea NOT NULL,\n \"checkpoint_version\" uuid,\n \"phase\" text DEFAULT 'pending' NOT NULL,\n \"failure\" text,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_document_publish_attempts_phase_check\" CHECK (\"phase\" in ('pending', 'checkpointed', 'published', 'failed')),\n CONSTRAINT \"working_document_publish_attempts_high_watermark_check\" CHECK (\"high_watermark\" between 0 and 9007199254740991),\n CONSTRAINT \"working_document_publish_attempts_markdown_hash_check\" CHECK (char_length(\"markdown_hash\") between 1 and 128),\n CONSTRAINT \"working_document_publish_attempts_state_check\" CHECK (octet_length(\"state\") > 0),\n CONSTRAINT \"working_document_publish_attempts_state_vector_check\" CHECK (octet_length(\"state_vector\") > 0),\n CONSTRAINT \"working_document_publish_attempts_payload_check\" CHECK ((\n \"phase\" = 'pending'\n AND \"checkpoint_version\" IS NULL\n AND \"failure\" IS NULL\n ) OR (\n \"phase\" in ('checkpointed', 'published')\n AND \"checkpoint_version\" IS NOT NULL\n AND \"failure\" IS NULL\n ) OR (\n \"phase\" = 'failed'\n AND \"checkpoint_version\" IS NULL\n AND char_length(\"failure\") between 1 and 128\n ))\n);\n",
63
+ "\nCREATE TABLE \"working_document_updates\" (\n \"document_id\" uuid,\n \"generation_id\" uuid NOT NULL,\n \"sequence\" bigint,\n \"update\" bytea NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_document_updates_pkey\" PRIMARY KEY(\"document_id\",\"sequence\"),\n CONSTRAINT \"working_document_updates_sequence_check\" CHECK (\"sequence\" between 1 and 9007199254740991),\n CONSTRAINT \"working_document_updates_update_check\" CHECK (octet_length(\"update\") > 0)\n);\n",
64
+ "\nCREATE TABLE \"working_documents\" (\n \"document_id\" uuid PRIMARY KEY,\n \"format_version\" integer NOT NULL,\n \"generation_id\" uuid NOT NULL,\n \"state\" bytea NOT NULL,\n \"saved_state_vector\" bytea NOT NULL,\n \"saved_version\" uuid NOT NULL,\n \"next_update_sequence\" bigint DEFAULT 1 NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_documents_generation_unique\" UNIQUE(\"document_id\",\"generation_id\"),\n CONSTRAINT \"working_documents_format_version_check\" CHECK (\"format_version\" = 1),\n CONSTRAINT \"working_documents_state_check\" CHECK (octet_length(\"state\") > 0),\n CONSTRAINT \"working_documents_saved_state_vector_check\" CHECK (octet_length(\"saved_state_vector\") > 0),\n CONSTRAINT \"working_documents_next_update_sequence_check\" CHECK (\"next_update_sequence\" between 1 and 9007199254740991)\n);\n",
65
+ "\nCREATE INDEX \"activity_entries_history\" ON \"activity_entries\" (\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
66
+ "\nCREATE INDEX \"activity_entries_actor\" ON \"activity_entries\" (\"actor_id\",\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
67
+ "\nCREATE INDEX \"activity_entries_target\" ON \"activity_entries\" (\"target_kind\",\"target_id\",\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
68
+ "\nCREATE INDEX \"activity_entries_request\" ON \"activity_entries\" (\"request_id\");",
69
+ "\nCREATE INDEX \"auth_accounts_user_id\" ON \"auth_accounts\" (\"user_id\");",
70
+ "\nCREATE UNIQUE INDEX \"auth_accounts_identity\" ON \"auth_accounts\" (\"issuer\",\"account_id\");",
71
+ "\nCREATE INDEX \"auth_sessions_user_id\" ON \"auth_sessions\" (\"user_id\");",
72
+ "\nCREATE INDEX \"auth_verifications_identifier\" ON \"auth_verifications\" (\"identifier\");",
73
+ "\nCREATE INDEX \"change_receipts_activity\" ON \"change_receipts\" (\"activity_id\");",
74
+ "\nCREATE INDEX \"document_media_references_object_key\" ON \"document_media_references\" (\"object_key\");",
75
+ "\nCREATE INDEX \"document_revisions_history\" ON \"document_revisions\" (\"document_id\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
76
+ "\nCREATE UNIQUE INDEX \"documents_active_path\" ON \"documents\" (\"source_path\") WHERE \"deleted_at\" is null;",
77
+ "\nCREATE INDEX \"media_assets_catalog\" ON \"media_assets\" (\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST) WHERE \"status\" = 'ready';",
78
+ "\nCREATE INDEX \"media_assets_folder\" ON \"media_assets\" (\"folder\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST) WHERE \"status\" = 'ready';",
79
+ "\nCREATE INDEX \"media_assets_recovery\" ON \"media_assets\" (\"updated_at\",\"id\") WHERE \"status\" <> 'ready';",
80
+ "\nCREATE INDEX \"media_replacements_recovery\" ON \"media_replacements\" (\"updated_at\",\"media_id\");",
81
+ "\nCREATE UNIQUE INDEX \"pending_changes_subject\" ON \"pending_changes\" (\"subject\");",
82
+ "\nCREATE INDEX \"pending_changes_recovery\" ON \"pending_changes\" (\"scope\",\"updated_at\",\"id\");",
83
+ "\nCREATE UNIQUE INDEX \"working_document_publish_attempts_active\" ON \"working_document_publish_attempts\" (\"document_id\") WHERE \"phase\" in ('pending', 'checkpointed');",
84
+ "\nCREATE INDEX \"working_document_publish_attempts_recovery\" ON \"working_document_publish_attempts\" (\"document_id\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
85
+ "\nALTER TABLE \"auth_accounts\" ADD CONSTRAINT \"auth_accounts_user_id_auth_users_id_fkey\" FOREIGN KEY (\"user_id\") REFERENCES \"auth_users\"(\"id\") ON DELETE CASCADE;",
86
+ "\nALTER TABLE \"auth_sessions\" ADD CONSTRAINT \"auth_sessions_user_id_auth_users_id_fkey\" FOREIGN KEY (\"user_id\") REFERENCES \"auth_users\"(\"id\") ON DELETE CASCADE;",
87
+ "\nALTER TABLE \"change_receipts\" ADD CONSTRAINT \"change_receipts_activity_id_activity_entries_id_fkey\" FOREIGN KEY (\"activity_id\") REFERENCES \"activity_entries\"(\"id\") ON DELETE RESTRICT;",
88
+ "\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE RESTRICT;",
89
+ "\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_authored_revision_fkey\" FOREIGN KEY (\"document_id\",\"authored_revision_id\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
90
+ "\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_published_revision_fkey\" FOREIGN KEY (\"document_id\",\"published_revision_id\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
91
+ "\nALTER TABLE \"document_media_references\" ADD CONSTRAINT \"document_media_references_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE CASCADE;",
92
+ "\nALTER TABLE \"document_revisions\" ADD CONSTRAINT \"document_revisions_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE RESTRICT;",
93
+ "\nALTER TABLE \"media_replacements\" ADD CONSTRAINT \"media_replacements_media_id_media_assets_id_fkey\" FOREIGN KEY (\"media_id\") REFERENCES \"media_assets\"(\"id\") ON DELETE RESTRICT;",
94
+ "\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_document_generation_fkey\" FOREIGN KEY (\"document_id\",\"expected_generation\") REFERENCES \"working_documents\"(\"document_id\",\"generation_id\") ON DELETE CASCADE;",
95
+ "\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_expected_version_fkey\" FOREIGN KEY (\"document_id\",\"expected_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
96
+ "\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_checkpoint_version_fkey\" FOREIGN KEY (\"document_id\",\"checkpoint_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
97
+ "\nALTER TABLE \"working_document_updates\" ADD CONSTRAINT \"working_document_updates_document_generation_fkey\" FOREIGN KEY (\"document_id\",\"generation_id\") REFERENCES \"working_documents\"(\"document_id\",\"generation_id\") ON DELETE CASCADE;",
98
+ "\nALTER TABLE \"working_documents\" ADD CONSTRAINT \"working_documents_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE CASCADE;",
99
+ "\nALTER TABLE \"working_documents\" ADD CONSTRAINT \"working_documents_saved_version_fkey\" FOREIGN KEY (\"document_id\",\"saved_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;"
100
+ ],
101
+ bps: true,
102
+ folderMillis: 1788466567e3,
103
+ hash: "943a4996ef8c4324bd58280a80103e5a1632b088880164904b3857686e26f33e",
104
+ name: "20260903201607_cms_baseline"
105
+ },
106
+ {
107
+ sql: [
108
+ "ALTER TABLE \"auth_rate_limits\" ADD COLUMN \"id\" uuid DEFAULT gen_random_uuid();",
109
+ "\nALTER TABLE \"auth_rate_limits\" DROP CONSTRAINT \"auth_rate_limits_pkey\";",
110
+ "\nALTER TABLE \"auth_rate_limits\" ADD PRIMARY KEY (\"id\");",
111
+ "\nALTER TABLE \"auth_rate_limits\" ADD CONSTRAINT \"auth_rate_limits_key_key\" UNIQUE(\"key\");"
112
+ ],
113
+ bps: true,
114
+ folderMillis: 1788587191e3,
115
+ hash: "78b837c6b72a3de22d68e8db90bd211e61a0b97ff29bf8d16a0bba245eefa7ed",
116
+ name: "20260905054631_burly_northstar"
117
+ },
118
+ {
119
+ sql: ["ALTER TABLE \"auth_accounts\" DROP COLUMN \"issuer\";", "\nCREATE UNIQUE INDEX \"auth_accounts_identity\" ON \"auth_accounts\" (\"provider_id\",\"account_id\");"],
120
+ bps: true,
121
+ folderMillis: 178875937e4,
122
+ hash: "e442485fa6c2d611e3dae508a12d245481bc5ec8f2dd4f5d853910df34484787",
123
+ name: "20260907053610_fancy_lady_deathstrike"
124
+ },
125
+ {
126
+ sql: ["ALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_action_check\", ADD CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));", "\nALTER TABLE \"pending_changes\" DROP CONSTRAINT \"pending_changes_action_check\", ADD CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));"],
127
+ bps: true,
128
+ folderMillis: 1788866265e3,
129
+ hash: "24c56a37796caf8d76c0a97128a382b31e71808aa5b0ca7e5bac96795f9e16c7",
130
+ name: "20260908111745_classy_johnny_storm"
131
+ },
132
+ {
133
+ sql: [
134
+ "CREATE TABLE \"seo_media_references\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"scope\" text NOT NULL,\n \"media_id\" uuid NOT NULL,\n CONSTRAINT \"seo_media_references_scope_media_unique\" UNIQUE(\"scope\",\"media_id\"),\n CONSTRAINT \"seo_media_references_scope_check\" CHECK (\"scope\" in ('working', 'published'))\n);\n",
135
+ "\nCREATE TABLE \"seo_revisions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"settings\" jsonb NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"seo_revisions_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"seo_revisions_settings_check\" CHECK (jsonb_typeof(\"settings\") = 'object')\n);\n",
136
+ "\nCREATE TABLE \"seo_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"working_revision_id\" uuid NOT NULL,\n \"published_revision_id\" uuid NOT NULL,\n CONSTRAINT \"seo_state_singleton_check\" CHECK (\"singleton\")\n);\n",
137
+ "\nCREATE INDEX \"seo_media_references_media\" ON \"seo_media_references\" (\"media_id\");",
138
+ "\nCREATE INDEX \"seo_revisions_history\" ON \"seo_revisions\" (\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
139
+ "\nALTER TABLE \"seo_media_references\" ADD CONSTRAINT \"seo_media_references_media_id_media_assets_id_fkey\" FOREIGN KEY (\"media_id\") REFERENCES \"media_assets\"(\"id\") ON DELETE RESTRICT;",
140
+ "\nALTER TABLE \"seo_state\" ADD CONSTRAINT \"seo_state_working_revision_fkey\" FOREIGN KEY (\"working_revision_id\") REFERENCES \"seo_revisions\"(\"id\") ON DELETE RESTRICT;",
141
+ "\nALTER TABLE \"seo_state\" ADD CONSTRAINT \"seo_state_published_revision_fkey\" FOREIGN KEY (\"published_revision_id\") REFERENCES \"seo_revisions\"(\"id\") ON DELETE RESTRICT;",
142
+ "\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_action_check\", ADD CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'seo.saved', 'seo.published', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));",
143
+ "\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_target_kind_check\", ADD CONSTRAINT \"activity_entries_target_kind_check\" CHECK (\"target_kind\" in ('document', 'media', 'media-library', 'seo', 'user'));",
144
+ "\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_target_check\", ADD CONSTRAINT \"activity_entries_target_check\" CHECK ((\"target_kind\" in ('media-library', 'seo') AND \"target_id\" IS NULL)\n OR (\"target_kind\" not in ('media-library', 'seo') AND \"target_id\" IS NOT NULL));",
145
+ "\nALTER TABLE \"pending_changes\" DROP CONSTRAINT \"pending_changes_action_check\", ADD CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'seo.saved', 'seo.published', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));"
146
+ ],
147
+ bps: true,
148
+ folderMillis: 1789233351e3,
149
+ hash: "8e6a6abf5385ab3ecf8eb083c1923ac9c74d72aa71bd1d444b7402d3e7e77000",
150
+ name: "20260912171551_charming_valkyrie"
151
+ }
152
+ ];
153
+
154
+ //#endregion
155
+ //#region ../sql-pg/src/internal/database/table-helpers.ts
156
+ const transactionTimestamp = sql`transaction_timestamp()`;
157
+ function isOneOf(column, values) {
158
+ return sql`${column} in (${sql.join(values.map((value) => sql`${value}`), sql`, `)})`;
159
+ }
160
+
161
+ //#endregion
162
+ //#region ../sql-pg/src/internal/documents/tables.ts
163
+ const cmsState = pgTable("cms_state", {
164
+ singleton: boolean().default(true).primaryKey(),
165
+ generation: bigint({ mode: "bigint" }).default(sql`0`).notNull()
166
+ }, (table) => [check("cms_state_singleton_check", sql`${table.singleton}`), check("cms_state_generation_check", sql`${table.generation} >= 0`)]);
167
+ const documentsTable = pgTable("documents", {
168
+ id: uuid().defaultRandom().primaryKey(),
169
+ sourcePath: text("source_path").notNull(),
170
+ deletedAt: timestamp("deleted_at", {
171
+ mode: "string",
172
+ withTimezone: true
173
+ }),
174
+ createdAt: timestamp("created_at", {
175
+ mode: "string",
176
+ withTimezone: true
177
+ }).default(transactionTimestamp).notNull(),
178
+ updatedAt: timestamp("updated_at", {
179
+ mode: "string",
180
+ withTimezone: true
181
+ }).default(transactionTimestamp).notNull()
182
+ }, (table) => [uniqueIndex("documents_active_path").on(table.sourcePath).where(sql`${table.deletedAt} is null`)]);
183
+ const documentRevisions = pgTable("document_revisions", {
184
+ id: uuid().defaultRandom().primaryKey(),
185
+ documentId: uuid("document_id").notNull().references(() => documentsTable.id, { onDelete: "restrict" }),
186
+ action: text({ enum: DOCUMENT_REVISION_ACTIONS }).notNull(),
187
+ sourcePath: text("source_path").notNull(),
188
+ markdown: text().notNull(),
189
+ actorId: text("actor_id").notNull(),
190
+ actorEmail: text("actor_email").notNull(),
191
+ actorName: text("actor_name").notNull(),
192
+ actorRoles: jsonb("actor_roles").$type().notNull(),
193
+ requestId: uuid("request_id").notNull(),
194
+ reason: text(),
195
+ activityDetails: jsonb("activity_details").$type().default({}).notNull(),
196
+ createdAt: timestamp("created_at", {
197
+ mode: "string",
198
+ withTimezone: true
199
+ }).default(transactionTimestamp).notNull()
200
+ }, (table) => [
201
+ check("document_revisions_action_check", isOneOf(table.action, DOCUMENT_REVISION_ACTIONS)),
202
+ unique("document_revisions_document_id_unique").on(table.documentId, table.id),
203
+ index("document_revisions_history").on(table.documentId, table.createdAt.desc(), table.id.desc())
204
+ ]);
205
+ const documentHeads = pgTable("document_heads", {
206
+ documentId: uuid("document_id").primaryKey().references(() => documentsTable.id, { onDelete: "restrict" }),
207
+ authoredRevisionId: uuid("authored_revision_id").notNull(),
208
+ publishedRevisionId: uuid("published_revision_id")
209
+ }, (table) => [foreignKey({
210
+ columns: [table.documentId, table.authoredRevisionId],
211
+ foreignColumns: [documentRevisions.documentId, documentRevisions.id],
212
+ name: "document_heads_authored_revision_fkey"
213
+ }).onDelete("restrict"), foreignKey({
214
+ columns: [table.documentId, table.publishedRevisionId],
215
+ foreignColumns: [documentRevisions.documentId, documentRevisions.id],
216
+ name: "document_heads_published_revision_fkey"
217
+ }).onDelete("restrict")]);
218
+ const documentMediaReferences = pgTable("document_media_references", {
219
+ id: uuid().defaultRandom().primaryKey(),
220
+ documentId: uuid("document_id").notNull().references(() => documentsTable.id, { onDelete: "cascade" }),
221
+ objectKey: text("object_key").notNull(),
222
+ path: text().notNull(),
223
+ sourcePath: text("source_path").notNull(),
224
+ nodePath: integer("node_path").array().notNull()
225
+ }, (table) => [
226
+ unique("document_media_references_identity_unique").on(table.documentId, table.sourcePath, table.nodePath, table.objectKey),
227
+ check("document_media_references_object_key_check", sql`char_length(${table.objectKey}) between 1 and 1024
228
+ AND btrim(${table.objectKey}) = ${table.objectKey}
229
+ AND ${table.objectKey} !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'
230
+ AND position(chr(92) in ${table.objectKey}) = 0`),
231
+ check("document_media_references_node_path_check", sql`array_position(${table.nodePath}, NULL) IS NULL AND 0 <= ALL(${table.nodePath})`),
232
+ index("document_media_references_object_key").on(table.objectKey)
233
+ ]);
234
+
235
+ //#endregion
236
+ //#region ../sql-pg/src/internal/initialization/tables.ts
237
+ const INITIALIZATION_STATES = [
238
+ "uninitialized",
239
+ "claiming",
240
+ "ready"
241
+ ];
242
+ const initializationState = pgTable("initialization_state", {
243
+ singleton: boolean().default(true).primaryKey(),
244
+ state: text({ enum: INITIALIZATION_STATES }).default("uninitialized").notNull(),
245
+ changeId: uuid("change_id"),
246
+ claim: jsonb().$type()
247
+ }, (table) => [
248
+ check("initialization_state_singleton_check", sql`${table.singleton}`),
249
+ check("initialization_state_state_check", isOneOf(table.state, INITIALIZATION_STATES)),
250
+ check("initialization_state_claim_check", sql`(${table.state} = 'claiming' AND ${table.changeId} IS NOT NULL AND jsonb_typeof(${table.claim}) = 'object')
251
+ OR (${table.state} <> 'claiming' AND ${table.changeId} IS NULL AND ${table.claim} IS NULL)`)
252
+ ]);
253
+
254
+ //#endregion
255
+ //#region ../sql-pg/src/internal/database/migrations.ts
256
+ const MIGRATION_LOCK_KEY = "cms:database-migrations:v1";
257
+ const migrateCmsDatabase = Effect.fn("CmsDatabase.migrate")(function* (schema) {
258
+ const postgres = yield* PgClient.PgClient;
259
+ const database = yield* PgDrizzle.makeWithDefaults();
260
+ yield* postgres.withTransaction(Effect.gen(function* () {
261
+ yield* postgres.unsafe("select pg_advisory_xact_lock(hashtextextended($1, 0))", [MIGRATION_LOCK_KEY]);
262
+ yield* migrate(embeddedMigrations, database._.session, {
263
+ migrationsFolder: "embedded",
264
+ migrationsSchema: schema,
265
+ migrationsTable: "__drizzle_migrations"
266
+ });
267
+ yield* database.insert(cmsState).values({}).onConflictDoNothing({ target: cmsState.singleton });
268
+ yield* database.insert(initializationState).values({}).onConflictDoNothing({ target: initializationState.singleton });
269
+ }));
270
+ });
271
+ function cmsDatabaseMigrationLayer(schema) {
272
+ return Layer.effectDiscard(migrateCmsDatabase(schema));
273
+ }
274
+
275
+ //#endregion
276
+ //#region ../sql-pg/src/internal/postgres/scoped-client.ts
277
+ const PgJson = Statement.custom("PgJson");
278
+ /**
279
+ * Builds a PostgreSQL client whose every physical pool connection starts in
280
+ * the configured schema. The upstream driver does not yet expose PostgreSQL
281
+ * startup parameters, so the initialization belongs at our pool seam.
282
+ */
283
+ const makeSchemaClient = Effect.fn("Postgres.makeSchemaClient")(function* (options, schema) {
284
+ const pool = yield* PgPool.make(options);
285
+ const initialized = /* @__PURE__ */ new WeakSet();
286
+ const searchPath = `set search_path to "${schema}"`;
287
+ const initialize = (connection) => initialized.has(connection) ? Effect.succeed(connection) : connection.query(searchPath).pipe(Effect.tap(() => Effect.sync(() => initialized.add(connection))), Effect.as(connection));
288
+ const acquirer = Effect.map(Effect.flatMap(pool.get, initialize), makeConnection);
289
+ const transactionAcquirer = Effect.map(Effect.flatMap(pool.reserve, initialize), makeConnection);
290
+ const listenAcquirer = Effect.flatMap(pool.reserve, initialize);
291
+ const borrower = (use) => pool.use((connection) => Effect.flatMap(initialize(connection), (ready) => use(makeConnection(ready))));
292
+ const compiler = PgClient.makeCompiler(options.transformQueryNames, options.transformJson);
293
+ const transformRows = options.transformResultNames ? Statement.defaultTransforms(options.transformResultNames, options.transformJson).array : void 0;
294
+ const listen = (channel) => Effect.flatMap(listenAcquirer, (connection) => connection.listen(channel));
295
+ const json = (value) => Statement.fragment([PgJson(value, void 0, void 0)]);
296
+ return Object.assign(yield* Client.make({
297
+ acquirer,
298
+ borrower,
299
+ compiler,
300
+ prepareTransactionControls: true,
301
+ spanAttributes: [
302
+ ...options.spanAttributes ? Object.entries(options.spanAttributes) : [],
303
+ ["db.system.name", "postgresql"],
304
+ ["cms.database.schema", schema]
305
+ ],
306
+ transactionAcquirer,
307
+ transformRows
308
+ }), {
309
+ [PgClient.TypeId]: PgClient.TypeId,
310
+ config: options,
311
+ json,
312
+ listen,
313
+ notify: (channel, payload) => Effect.asVoid(Effect.scoped(Effect.flatMap(acquirer, (connection) => connection.executeRaw("select pg_notify($1, $2)", [channel, payload]))))
314
+ });
315
+ });
316
+ var ConnectionImpl = class {
317
+ connection;
318
+ constructor(connection) {
319
+ this.connection = connection;
320
+ }
321
+ run(query, params, prepare = true) {
322
+ return Effect.map(this.connection.query(query, params, prepare), (result) => result.rows);
323
+ }
324
+ execute(sql, params, transformRows) {
325
+ const operation = this.run(sql, params);
326
+ return transformRows ? Effect.map(operation, transformRows) : operation;
327
+ }
328
+ executeRaw(sql, params) {
329
+ return this.connection.query(sql, params);
330
+ }
331
+ executeWithoutTransform(sql, params) {
332
+ return this.run(sql, params);
333
+ }
334
+ executeValues(sql, params) {
335
+ return this.connection.queryValues(sql, params);
336
+ }
337
+ executeValuesUnprepared(sql, params) {
338
+ return this.connection.queryValues(sql, params, false);
339
+ }
340
+ executeUnprepared(sql, params, transformRows) {
341
+ const operation = this.run(sql, params, false);
342
+ return transformRows ? Effect.map(operation, transformRows) : operation;
343
+ }
344
+ executeStream(sql, params, transformRows) {
345
+ const stream = this.connection.stream(sql, params);
346
+ if (!transformRows) return stream;
347
+ return Stream.mapArray(stream, (rows) => {
348
+ const transformed = transformRows(rows);
349
+ const first = transformed[0];
350
+ return first === void 0 ? rows : [first, ...transformed.slice(1)];
351
+ });
352
+ }
353
+ };
354
+ function makeConnection(connection) {
355
+ return new ConnectionImpl(connection);
356
+ }
357
+ function schemaClientLayer(options, schema) {
358
+ return PgClient.layerFrom(makeSchemaClient(options, schema));
359
+ }
360
+
361
+ //#endregion
362
+ //#region ../auth/src/internal/user.ts
363
+ const cmsUserCreationChangeField = "cmsCreationChangeId";
364
+ const cmsUserSessionsRevokedChangeField = "cmsSessionsRevokedChangeId";
365
+ const BetterAuthUser = Schema.Struct({
366
+ banned: Schema.optionalKey(Schema.NullOr(Schema.Boolean)),
367
+ createdAt: Schema.Date,
368
+ email: Schema.String,
369
+ emailVerified: Schema.Boolean,
370
+ id: Schema.String,
371
+ name: Schema.String,
372
+ role: Schema.optionalKey(Schema.NullOr(Schema.String)),
373
+ updatedAt: Schema.Date
374
+ });
375
+ const BetterAuthUserRecoveryEvidence = Schema.Struct({
376
+ [cmsUserCreationChangeField]: Schema.optionalKey(Schema.UndefinedOr(Schema.NullOr(ActivityId))),
377
+ [cmsUserSessionsRevokedChangeField]: Schema.optionalKey(Schema.UndefinedOr(Schema.NullOr(ActivityId)))
378
+ });
379
+ function decodeBetterAuthUser(value) {
380
+ return Schema.decodeEffect(BetterAuthUser)(value).pipe(Effect.flatMap((user) => Schema.decodeUnknownEffect(User)({
381
+ banned: user.banned === true,
382
+ createdAt: user.createdAt.toISOString(),
383
+ email: user.email,
384
+ emailVerified: user.emailVerified,
385
+ id: user.id,
386
+ name: user.name,
387
+ role: user.role,
388
+ updatedAt: user.updatedAt.toISOString()
389
+ })));
390
+ }
391
+ function decodeBetterAuthActor(user) {
392
+ return Schema.decodeEffect(StudioActor)(betterAuthActorInput(user));
393
+ }
394
+ function decodeBetterAuthActorOption(user) {
395
+ return Schema.decodeOption(StudioActor)(betterAuthActorInput(user));
396
+ }
397
+ function decodeBetterAuthUserCreationChangeId(user) {
398
+ return decodeChangeId(user, cmsUserCreationChangeField);
399
+ }
400
+ function decodeBetterAuthUserSessionsRevokedChangeId(user) {
401
+ return decodeChangeId(user, cmsUserSessionsRevokedChangeField);
402
+ }
403
+ function decodeChangeId(user, field) {
404
+ return Schema.decodeEffect(BetterAuthUserRecoveryEvidence)(user).pipe(Effect.map((evidence) => evidence[field] ?? null));
405
+ }
406
+ function betterAuthProviderRoles(value) {
407
+ return value ? [...new Set(value.split(",").map((role) => role.trim()).filter(Boolean))] : [];
408
+ }
409
+ function betterAuthActorInput(user) {
410
+ return {
411
+ email: user.email,
412
+ id: user.id,
413
+ name: user.name,
414
+ roles: betterAuthProviderRoles(user.role)
415
+ };
416
+ }
417
+
418
+ //#endregion
419
+ //#region ../auth/src/internal/better-auth.ts
420
+ const cmsBetterAuthAccess = createAccessControl(defaultStatements);
421
+ const cmsBetterAuthRoles = {
422
+ administrator: cmsBetterAuthAccess.newRole({
423
+ session: ["list", "revoke"],
424
+ user: [
425
+ "create",
426
+ "list",
427
+ "get",
428
+ "set-role",
429
+ "delete",
430
+ "update"
431
+ ]
432
+ }),
433
+ editor: cmsBetterAuthAccess.newRole({
434
+ session: [],
435
+ user: []
436
+ }),
437
+ viewer: cmsBetterAuthAccess.newRole({
438
+ session: [],
439
+ user: []
440
+ })
441
+ };
442
+ const timestampFields = {
443
+ createdAt: "created_at",
444
+ updatedAt: "updated_at"
445
+ };
446
+ function createCmsBetterAuthOptions(options, activity) {
447
+ return {
448
+ advanced: { database: {
449
+ generateId: "uuid",
450
+ joins: true
451
+ } },
452
+ appName: "CMS Studio",
453
+ basePath: options.basePath ?? "/api/cms/auth",
454
+ baseURL: options.baseURL,
455
+ database: options.database,
456
+ emailAndPassword: {
457
+ disableSignUp: true,
458
+ enabled: true,
459
+ ...activity?.emailAndPassword
460
+ },
461
+ hooks: activity?.hooks,
462
+ user: {
463
+ additionalFields: {
464
+ [cmsUserCreationChangeField]: hiddenChangeField("cms_creation_change_id"),
465
+ [cmsUserSessionsRevokedChangeField]: hiddenChangeField("cms_sessions_revoked_change_id")
466
+ },
467
+ modelName: "auth_users",
468
+ fields: {
469
+ ...timestampFields,
470
+ emailVerified: "email_verified"
471
+ }
472
+ },
473
+ session: {
474
+ cookieCache: {
475
+ enabled: false,
476
+ strategy: "jwt"
477
+ },
478
+ modelName: "auth_sessions",
479
+ fields: {
480
+ ...timestampFields,
481
+ expiresAt: "expires_at",
482
+ ipAddress: "ip_address",
483
+ userAgent: "user_agent",
484
+ userId: "user_id"
485
+ }
486
+ },
487
+ account: {
488
+ modelName: "auth_accounts",
489
+ fields: {
490
+ accessToken: "access_token",
491
+ accessTokenExpiresAt: "access_token_expires_at",
492
+ accountId: "account_id",
493
+ ...timestampFields,
494
+ idToken: "id_token",
495
+ providerId: "provider_id",
496
+ refreshToken: "refresh_token",
497
+ refreshTokenExpiresAt: "refresh_token_expires_at",
498
+ userId: "user_id"
499
+ }
500
+ },
501
+ verification: {
502
+ modelName: "auth_verifications",
503
+ fields: {
504
+ ...timestampFields,
505
+ expiresAt: "expires_at"
506
+ }
507
+ },
508
+ rateLimit: {
509
+ enabled: true,
510
+ storage: "database",
511
+ modelName: "auth_rate_limits",
512
+ fields: { lastRequest: "last_request" }
513
+ },
514
+ plugins: [admin({
515
+ ac: cmsBetterAuthAccess,
516
+ adminRoles: ["administrator"],
517
+ defaultRole: "editor",
518
+ roles: cmsBetterAuthRoles,
519
+ schema: {
520
+ session: { fields: { impersonatedBy: "impersonated_by" } },
521
+ user: { fields: {
522
+ banExpires: "ban_expires",
523
+ banReason: "ban_reason",
524
+ banned: "banned",
525
+ role: "role"
526
+ } }
527
+ }
528
+ })],
529
+ secret: options.secret
530
+ };
531
+ }
532
+ function createCmsBetterAuth(options, activity) {
533
+ return betterAuth(createCmsBetterAuthOptions(options, activity));
534
+ }
535
+ function hiddenChangeField(fieldName) {
536
+ return {
537
+ fieldName,
538
+ input: false,
539
+ required: false,
540
+ returned: false,
541
+ type: "string"
542
+ };
543
+ }
544
+
545
+ //#endregion
40
546
  //#region ../server/src/internal/activity/activity-storage.ts
41
547
  var ActivityStore = class extends Context.Service()("@internal/server/ActivityStore") {};
42
548
 
@@ -683,63 +1189,6 @@ function appliedResolution(change, intent, userId) {
683
1189
  };
684
1190
  }
685
1191
 
686
- //#endregion
687
- //#region ../auth/src/internal/user.ts
688
- const cmsUserCreationChangeField = "cmsCreationChangeId";
689
- const cmsUserSessionsRevokedChangeField = "cmsSessionsRevokedChangeId";
690
- const BetterAuthUser = Schema.Struct({
691
- banned: Schema.optionalKey(Schema.NullOr(Schema.Boolean)),
692
- createdAt: Schema.Date,
693
- email: Schema.String,
694
- emailVerified: Schema.Boolean,
695
- id: Schema.String,
696
- name: Schema.String,
697
- role: Schema.optionalKey(Schema.NullOr(Schema.String)),
698
- updatedAt: Schema.Date
699
- });
700
- const BetterAuthUserRecoveryEvidence = Schema.Struct({
701
- [cmsUserCreationChangeField]: Schema.optionalKey(Schema.UndefinedOr(Schema.NullOr(ActivityId))),
702
- [cmsUserSessionsRevokedChangeField]: Schema.optionalKey(Schema.UndefinedOr(Schema.NullOr(ActivityId)))
703
- });
704
- function decodeBetterAuthUser(value) {
705
- return Schema.decodeEffect(BetterAuthUser)(value).pipe(Effect.flatMap((user) => Schema.decodeUnknownEffect(User)({
706
- banned: user.banned === true,
707
- createdAt: user.createdAt.toISOString(),
708
- email: user.email,
709
- emailVerified: user.emailVerified,
710
- id: user.id,
711
- name: user.name,
712
- role: user.role,
713
- updatedAt: user.updatedAt.toISOString()
714
- })));
715
- }
716
- function decodeBetterAuthActor(user) {
717
- return Schema.decodeEffect(StudioActor)(betterAuthActorInput(user));
718
- }
719
- function decodeBetterAuthActorOption(user) {
720
- return Schema.decodeOption(StudioActor)(betterAuthActorInput(user));
721
- }
722
- function decodeBetterAuthUserCreationChangeId(user) {
723
- return decodeChangeId(user, cmsUserCreationChangeField);
724
- }
725
- function decodeBetterAuthUserSessionsRevokedChangeId(user) {
726
- return decodeChangeId(user, cmsUserSessionsRevokedChangeField);
727
- }
728
- function decodeChangeId(user, field) {
729
- return Schema.decodeEffect(BetterAuthUserRecoveryEvidence)(user).pipe(Effect.map((evidence) => evidence[field] ?? null));
730
- }
731
- function betterAuthProviderRoles(value) {
732
- return value ? [...new Set(value.split(",").map((role) => role.trim()).filter(Boolean))] : [];
733
- }
734
- function betterAuthActorInput(user) {
735
- return {
736
- email: user.email,
737
- id: user.id,
738
- name: user.name,
739
- roles: betterAuthProviderRoles(user.role)
740
- };
741
- }
742
-
743
1192
  //#endregion
744
1193
  //#region ../auth/src/internal/activity-hooks.ts
745
1194
  function betterAuthActivityWriter(storage, crypto) {
@@ -776,156 +1225,29 @@ function betterAuthActivityOptions(writeActivity, crypto, runPromise) {
776
1225
  if (context.path === "/sign-out") return write("authentication.signed-out", actor);
777
1226
  if (context.path === "/change-password") return write("authentication.password.changed", actor);
778
1227
  return Promise.resolve();
779
- }),
780
- before
781
- }
782
- };
783
- }
784
- function activityDraft(action, actor, requestId) {
785
- return ActivityEntryDraft.make({
786
- action,
787
- context: {
788
- actor,
789
- requestId: RequestId.make(requestId)
790
- },
791
- details: {},
792
- target: {
793
- kind: "user",
794
- userId: actor.id
795
- }
796
- });
797
- }
798
- function decodeActor(user) {
799
- const option = decodeBetterAuthActorOption(user);
800
- return Option.getOrUndefined(option);
801
- }
802
-
803
- //#endregion
804
- //#region ../auth/src/internal/better-auth.ts
805
- const cmsBetterAuthAccess = createAccessControl(defaultStatements);
806
- const cmsBetterAuthRoles = {
807
- administrator: cmsBetterAuthAccess.newRole({
808
- session: ["list", "revoke"],
809
- user: [
810
- "create",
811
- "list",
812
- "get",
813
- "set-role",
814
- "delete",
815
- "update"
816
- ]
817
- }),
818
- editor: cmsBetterAuthAccess.newRole({
819
- session: [],
820
- user: []
821
- }),
822
- viewer: cmsBetterAuthAccess.newRole({
823
- session: [],
824
- user: []
825
- })
826
- };
827
- const timestampFields = {
828
- createdAt: "created_at",
829
- updatedAt: "updated_at"
830
- };
831
- function createCmsBetterAuthOptions(options, activity) {
832
- return {
833
- advanced: { database: {
834
- generateId: "uuid",
835
- joins: true
836
- } },
837
- appName: "CMS Studio",
838
- basePath: options.basePath ?? "/api/cms/auth",
839
- baseURL: options.baseURL,
840
- database: options.database,
841
- emailAndPassword: {
842
- disableSignUp: true,
843
- enabled: true,
844
- ...activity?.emailAndPassword
845
- },
846
- hooks: activity?.hooks,
847
- user: {
848
- additionalFields: {
849
- [cmsUserCreationChangeField]: hiddenChangeField("cms_creation_change_id"),
850
- [cmsUserSessionsRevokedChangeField]: hiddenChangeField("cms_sessions_revoked_change_id")
851
- },
852
- modelName: "auth_users",
853
- fields: {
854
- ...timestampFields,
855
- emailVerified: "email_verified"
856
- }
857
- },
858
- session: {
859
- cookieCache: {
860
- enabled: false,
861
- strategy: "jwt"
862
- },
863
- modelName: "auth_sessions",
864
- fields: {
865
- ...timestampFields,
866
- expiresAt: "expires_at",
867
- ipAddress: "ip_address",
868
- userAgent: "user_agent",
869
- userId: "user_id"
870
- }
871
- },
872
- account: {
873
- modelName: "auth_accounts",
874
- fields: {
875
- accessToken: "access_token",
876
- accessTokenExpiresAt: "access_token_expires_at",
877
- accountId: "account_id",
878
- ...timestampFields,
879
- idToken: "id_token",
880
- providerId: "provider_id",
881
- refreshToken: "refresh_token",
882
- refreshTokenExpiresAt: "refresh_token_expires_at",
883
- userId: "user_id"
884
- }
885
- },
886
- verification: {
887
- modelName: "auth_verifications",
888
- fields: {
889
- ...timestampFields,
890
- expiresAt: "expires_at"
891
- }
892
- },
893
- rateLimit: {
894
- enabled: true,
895
- storage: "database",
896
- modelName: "auth_rate_limits",
897
- fields: { lastRequest: "last_request" }
898
- },
899
- plugins: [admin({
900
- ac: cmsBetterAuthAccess,
901
- adminRoles: ["administrator"],
902
- defaultRole: "editor",
903
- roles: cmsBetterAuthRoles,
904
- schema: {
905
- session: { fields: { impersonatedBy: "impersonated_by" } },
906
- user: { fields: {
907
- banExpires: "ban_expires",
908
- banReason: "ban_reason",
909
- banned: "banned",
910
- role: "role"
911
- } }
912
- }
913
- })],
914
- secret: options.secret
915
- };
916
- }
917
- function createCmsBetterAuth(options, activity) {
918
- return betterAuth(createCmsBetterAuthOptions(options, activity));
919
- }
920
- function hiddenChangeField(fieldName) {
921
- return {
922
- fieldName,
923
- input: false,
924
- required: false,
925
- returned: false,
926
- type: "string"
1228
+ }),
1229
+ before
1230
+ }
927
1231
  };
928
1232
  }
1233
+ function activityDraft(action, actor, requestId) {
1234
+ return ActivityEntryDraft.make({
1235
+ action,
1236
+ context: {
1237
+ actor,
1238
+ requestId: RequestId.make(requestId)
1239
+ },
1240
+ details: {},
1241
+ target: {
1242
+ kind: "user",
1243
+ userId: actor.id
1244
+ }
1245
+ });
1246
+ }
1247
+ function decodeActor(user) {
1248
+ const option = decodeBetterAuthActorOption(user);
1249
+ return Option.getOrUndefined(option);
1250
+ }
929
1251
 
930
1252
  //#endregion
931
1253
  //#region ../auth/src/internal/handler.ts
@@ -5398,13 +5720,6 @@ function createCmsInstallationLayer(options) {
5398
5720
  });
5399
5721
  }
5400
5722
 
5401
- //#endregion
5402
- //#region ../sql-pg/src/internal/database/table-helpers.ts
5403
- const transactionTimestamp = sql`transaction_timestamp()`;
5404
- function isOneOf(column, values) {
5405
- return sql`${column} in (${sql.join(values.map((value) => sql`${value}`), sql`, `)})`;
5406
- }
5407
-
5408
5723
  //#endregion
5409
5724
  //#region ../sql-pg/src/internal/activity/tables.ts
5410
5725
  const ACTIVITY_TARGET_KINDS = [
@@ -5896,227 +6211,6 @@ function changeJournalUnavailable(operation, cause) {
5896
6211
  });
5897
6212
  }
5898
6213
 
5899
- //#endregion
5900
- //#region ../sql-pg/src/internal/database/embedded-migrations.generated.ts
5901
- const embeddedMigrations = [
5902
- {
5903
- sql: [
5904
- "CREATE TABLE \"activity_entries\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"action\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"target_kind\" text NOT NULL,\n \"target_id\" text,\n \"details\" jsonb DEFAULT '{}' NOT NULL,\n \"occurred_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset')),\n CONSTRAINT \"activity_entries_target_kind_check\" CHECK (\"target_kind\" in ('document', 'media', 'media-library', 'user')),\n CONSTRAINT \"activity_entries_target_check\" CHECK ((\"target_kind\" = 'media-library' AND \"target_id\" IS NULL)\n OR (\"target_kind\" <> 'media-library' AND \"target_id\" IS NOT NULL)),\n CONSTRAINT \"activity_entries_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"activity_entries_details_check\" CHECK (jsonb_typeof(\"details\") = 'object')\n);\n",
5905
- "\nCREATE TABLE \"auth_accounts\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"issuer\" text NOT NULL,\n \"account_id\" text NOT NULL,\n \"provider_id\" text NOT NULL,\n \"user_id\" uuid NOT NULL,\n \"access_token\" text,\n \"refresh_token\" text,\n \"id_token\" text,\n \"access_token_expires_at\" timestamp with time zone,\n \"refresh_token_expires_at\" timestamp with time zone,\n \"scope\" text,\n \"password\" text,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL\n);\n",
5906
- "\nCREATE TABLE \"auth_rate_limits\" (\n \"key\" text PRIMARY KEY,\n \"count\" bigint NOT NULL,\n \"last_request\" bigint NOT NULL\n);\n",
5907
- "\nCREATE TABLE \"auth_sessions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"expires_at\" timestamp with time zone NOT NULL,\n \"token\" text NOT NULL UNIQUE,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"ip_address\" text,\n \"user_agent\" text,\n \"user_id\" uuid NOT NULL,\n \"impersonated_by\" text\n);\n",
5908
- "\nCREATE TABLE \"auth_users\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"name\" text NOT NULL,\n \"email\" text NOT NULL UNIQUE,\n \"email_verified\" boolean DEFAULT false NOT NULL,\n \"image\" text,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"role\" text DEFAULT 'editor' NOT NULL,\n \"banned\" boolean DEFAULT false NOT NULL,\n \"ban_reason\" text,\n \"ban_expires\" timestamp with time zone,\n \"cms_creation_change_id\" uuid UNIQUE,\n \"cms_sessions_revoked_change_id\" uuid UNIQUE,\n CONSTRAINT \"auth_users_role_check\" CHECK (\"role\" in ('administrator', 'editor', 'viewer'))\n);\n",
5909
- "\nCREATE TABLE \"auth_verifications\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"identifier\" text NOT NULL,\n \"value\" text NOT NULL,\n \"expires_at\" timestamp with time zone NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT now() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT now() NOT NULL\n);\n",
5910
- "\nCREATE TABLE \"change_receipts\" (\n \"change_id\" uuid PRIMARY KEY,\n \"fingerprint\" text NOT NULL,\n \"outcome\" text NOT NULL,\n \"activity_id\" uuid UNIQUE,\n \"completed_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"change_receipts_outcome_check\" CHECK ((\"outcome\" = 'applied' AND \"activity_id\" IS NOT NULL)\n OR (\"outcome\" = 'cancelled' AND \"activity_id\" IS NULL))\n);\n",
5911
- "\nCREATE TABLE \"cms_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"generation\" bigint DEFAULT 0 NOT NULL,\n CONSTRAINT \"cms_state_singleton_check\" CHECK (\"singleton\"),\n CONSTRAINT \"cms_state_generation_check\" CHECK (\"generation\" >= 0)\n);\n",
5912
- "\nCREATE TABLE \"document_heads\" (\n \"document_id\" uuid PRIMARY KEY,\n \"authored_revision_id\" uuid NOT NULL,\n \"published_revision_id\" uuid\n);\n",
5913
- "\nCREATE TABLE \"document_media_references\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"document_id\" uuid NOT NULL,\n \"object_key\" text NOT NULL,\n \"path\" text NOT NULL,\n \"source_path\" text NOT NULL,\n \"node_path\" integer[] NOT NULL,\n CONSTRAINT \"document_media_references_identity_unique\" UNIQUE(\"document_id\",\"source_path\",\"node_path\",\"object_key\"),\n CONSTRAINT \"document_media_references_object_key_check\" CHECK (char_length(\"object_key\") between 1 and 1024\n AND btrim(\"object_key\") = \"object_key\"\n AND \"object_key\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"object_key\") = 0),\n CONSTRAINT \"document_media_references_node_path_check\" CHECK (array_position(\"node_path\", NULL) IS NULL AND 0 <= ALL(\"node_path\"))\n);\n",
5914
- "\nCREATE TABLE \"document_revisions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"document_id\" uuid NOT NULL,\n \"action\" text NOT NULL,\n \"source_path\" text NOT NULL,\n \"markdown\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"activity_details\" jsonb DEFAULT '{}' NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"document_revisions_document_id_unique\" UNIQUE(\"document_id\",\"id\"),\n CONSTRAINT \"document_revisions_action_check\" CHECK (\"action\" in ('document.create', 'document.move', 'document.remove', 'document.restore', 'document.undelete', 'document.update'))\n);\n",
5915
- "\nCREATE TABLE \"documents\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"source_path\" text NOT NULL,\n \"deleted_at\" timestamp with time zone,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL\n);\n",
5916
- "\nCREATE TABLE \"initialization_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"state\" text DEFAULT 'uninitialized' NOT NULL,\n \"change_id\" uuid,\n \"claim\" jsonb,\n CONSTRAINT \"initialization_state_singleton_check\" CHECK (\"singleton\"),\n CONSTRAINT \"initialization_state_state_check\" CHECK (\"state\" in ('uninitialized', 'claiming', 'ready')),\n CONSTRAINT \"initialization_state_claim_check\" CHECK ((\"state\" = 'claiming' AND \"change_id\" IS NOT NULL AND jsonb_typeof(\"claim\") = 'object')\n OR (\"state\" <> 'claiming' AND \"change_id\" IS NULL AND \"claim\" IS NULL))\n);\n",
5917
- "\nCREATE TABLE \"media_assets\" (\n \"id\" uuid PRIMARY KEY,\n \"object_key\" text NOT NULL UNIQUE,\n \"name\" text NOT NULL,\n \"folder\" text DEFAULT '' NOT NULL,\n \"mime_type\" text NOT NULL,\n \"byte_size\" bigint NOT NULL,\n \"status\" text DEFAULT 'uploading' NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"media_assets_byte_size_check\" CHECK (\"byte_size\" > 0 AND \"byte_size\" <= 9007199254740991),\n CONSTRAINT \"media_assets_mime_type_check\" CHECK (\"mime_type\" in ('image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/webp')),\n CONSTRAINT \"media_assets_status_check\" CHECK (\"status\" in ('uploading', 'ready', 'deleting')),\n CONSTRAINT \"media_assets_name_check\" CHECK (char_length(\"name\") between 1 and 255\n AND btrim(\"name\") = \"name\"\n AND \"name\" not in ('.', '..')\n AND \"name\" !~ '[[:cntrl:]/]'\n AND position(chr(92) in \"name\") = 0),\n CONSTRAINT \"media_assets_folder_check\" CHECK (char_length(\"folder\") <= 512\n AND btrim(\"folder\") = \"folder\"\n AND \"folder\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"folder\") = 0),\n CONSTRAINT \"media_assets_object_key_check\" CHECK (\"object_key\" ~ '^media/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$')\n);\n",
5918
- "\nCREATE TABLE \"media_replacements\" (\n \"media_id\" uuid PRIMARY KEY,\n \"object_key\" text NOT NULL,\n \"staging_object_key\" text NOT NULL UNIQUE,\n \"name\" text NOT NULL,\n \"folder\" text NOT NULL,\n \"mime_type\" text NOT NULL,\n \"byte_size\" bigint NOT NULL,\n \"staged\" boolean DEFAULT false NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"media_replacements_byte_size_check\" CHECK (\"byte_size\" > 0 AND \"byte_size\" <= 9007199254740991),\n CONSTRAINT \"media_replacements_mime_type_check\" CHECK (\"mime_type\" in ('image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/webp')),\n CONSTRAINT \"media_replacements_name_check\" CHECK (char_length(\"name\") between 1 and 255\n AND btrim(\"name\") = \"name\"\n AND \"name\" not in ('.', '..')\n AND \"name\" !~ '[[:cntrl:]/]'\n AND position(chr(92) in \"name\") = 0),\n CONSTRAINT \"media_replacements_folder_check\" CHECK (char_length(\"folder\") <= 512\n AND btrim(\"folder\") = \"folder\"\n AND \"folder\" !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'\n AND position(chr(92) in \"folder\") = 0),\n CONSTRAINT \"media_replacements_object_key_check\" CHECK (\"object_key\" ~ '^media/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$'),\n CONSTRAINT \"media_replacements_staging_object_key_check\" CHECK (\"staging_object_key\" ~ '^media/replacements/[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\\.(avif|gif|jpg|png|webp)$'),\n CONSTRAINT \"media_replacements_distinct_object_keys_check\" CHECK (\"staging_object_key\" <> \"object_key\")\n);\n",
5919
- "\nCREATE TABLE \"pending_changes\" (\n \"id\" uuid PRIMARY KEY,\n \"action\" text NOT NULL,\n \"subject\" text NOT NULL,\n \"scope\" text NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"target_kind\" text,\n \"target_id\" text,\n \"intent\" jsonb NOT NULL,\n \"fingerprint\" text NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset')),\n CONSTRAINT \"pending_changes_scope_check\" CHECK (\"scope\" in ('initialization', 'media', 'users')),\n CONSTRAINT \"pending_changes_subject_check\" CHECK (char_length(\"subject\") between 1 and 1024 AND btrim(\"subject\") = \"subject\"),\n CONSTRAINT \"pending_changes_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"pending_changes_intent_check\" CHECK (jsonb_typeof(\"intent\") = 'object'),\n CONSTRAINT \"pending_changes_target_check\" CHECK ((\"target_kind\" IS NULL AND \"target_id\" IS NULL)\n OR (\"target_kind\" = 'media-library' AND \"target_id\" IS NULL)\n OR (\"target_kind\" in ('document', 'media', 'user')\n AND \"target_id\" IS NOT NULL))\n);\n",
5920
- "\nCREATE TABLE \"working_document_publish_attempts\" (\n \"id\" uuid PRIMARY KEY,\n \"activity\" jsonb NOT NULL,\n \"document_id\" uuid NOT NULL,\n \"expected_generation\" uuid NOT NULL,\n \"expected_version\" uuid NOT NULL,\n \"high_watermark\" bigint NOT NULL,\n \"markdown_hash\" text NOT NULL,\n \"state\" bytea NOT NULL,\n \"state_vector\" bytea NOT NULL,\n \"checkpoint_version\" uuid,\n \"phase\" text DEFAULT 'pending' NOT NULL,\n \"failure\" text,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_document_publish_attempts_phase_check\" CHECK (\"phase\" in ('pending', 'checkpointed', 'published', 'failed')),\n CONSTRAINT \"working_document_publish_attempts_high_watermark_check\" CHECK (\"high_watermark\" between 0 and 9007199254740991),\n CONSTRAINT \"working_document_publish_attempts_markdown_hash_check\" CHECK (char_length(\"markdown_hash\") between 1 and 128),\n CONSTRAINT \"working_document_publish_attempts_state_check\" CHECK (octet_length(\"state\") > 0),\n CONSTRAINT \"working_document_publish_attempts_state_vector_check\" CHECK (octet_length(\"state_vector\") > 0),\n CONSTRAINT \"working_document_publish_attempts_payload_check\" CHECK ((\n \"phase\" = 'pending'\n AND \"checkpoint_version\" IS NULL\n AND \"failure\" IS NULL\n ) OR (\n \"phase\" in ('checkpointed', 'published')\n AND \"checkpoint_version\" IS NOT NULL\n AND \"failure\" IS NULL\n ) OR (\n \"phase\" = 'failed'\n AND \"checkpoint_version\" IS NULL\n AND char_length(\"failure\") between 1 and 128\n ))\n);\n",
5921
- "\nCREATE TABLE \"working_document_updates\" (\n \"document_id\" uuid,\n \"generation_id\" uuid NOT NULL,\n \"sequence\" bigint,\n \"update\" bytea NOT NULL,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_document_updates_pkey\" PRIMARY KEY(\"document_id\",\"sequence\"),\n CONSTRAINT \"working_document_updates_sequence_check\" CHECK (\"sequence\" between 1 and 9007199254740991),\n CONSTRAINT \"working_document_updates_update_check\" CHECK (octet_length(\"update\") > 0)\n);\n",
5922
- "\nCREATE TABLE \"working_documents\" (\n \"document_id\" uuid PRIMARY KEY,\n \"format_version\" integer NOT NULL,\n \"generation_id\" uuid NOT NULL,\n \"state\" bytea NOT NULL,\n \"saved_state_vector\" bytea NOT NULL,\n \"saved_version\" uuid NOT NULL,\n \"next_update_sequence\" bigint DEFAULT 1 NOT NULL,\n \"updated_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"working_documents_generation_unique\" UNIQUE(\"document_id\",\"generation_id\"),\n CONSTRAINT \"working_documents_format_version_check\" CHECK (\"format_version\" = 1),\n CONSTRAINT \"working_documents_state_check\" CHECK (octet_length(\"state\") > 0),\n CONSTRAINT \"working_documents_saved_state_vector_check\" CHECK (octet_length(\"saved_state_vector\") > 0),\n CONSTRAINT \"working_documents_next_update_sequence_check\" CHECK (\"next_update_sequence\" between 1 and 9007199254740991)\n);\n",
5923
- "\nCREATE INDEX \"activity_entries_history\" ON \"activity_entries\" (\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
5924
- "\nCREATE INDEX \"activity_entries_actor\" ON \"activity_entries\" (\"actor_id\",\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
5925
- "\nCREATE INDEX \"activity_entries_target\" ON \"activity_entries\" (\"target_kind\",\"target_id\",\"occurred_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
5926
- "\nCREATE INDEX \"activity_entries_request\" ON \"activity_entries\" (\"request_id\");",
5927
- "\nCREATE INDEX \"auth_accounts_user_id\" ON \"auth_accounts\" (\"user_id\");",
5928
- "\nCREATE UNIQUE INDEX \"auth_accounts_identity\" ON \"auth_accounts\" (\"issuer\",\"account_id\");",
5929
- "\nCREATE INDEX \"auth_sessions_user_id\" ON \"auth_sessions\" (\"user_id\");",
5930
- "\nCREATE INDEX \"auth_verifications_identifier\" ON \"auth_verifications\" (\"identifier\");",
5931
- "\nCREATE INDEX \"change_receipts_activity\" ON \"change_receipts\" (\"activity_id\");",
5932
- "\nCREATE INDEX \"document_media_references_object_key\" ON \"document_media_references\" (\"object_key\");",
5933
- "\nCREATE INDEX \"document_revisions_history\" ON \"document_revisions\" (\"document_id\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
5934
- "\nCREATE UNIQUE INDEX \"documents_active_path\" ON \"documents\" (\"source_path\") WHERE \"deleted_at\" is null;",
5935
- "\nCREATE INDEX \"media_assets_catalog\" ON \"media_assets\" (\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST) WHERE \"status\" = 'ready';",
5936
- "\nCREATE INDEX \"media_assets_folder\" ON \"media_assets\" (\"folder\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST) WHERE \"status\" = 'ready';",
5937
- "\nCREATE INDEX \"media_assets_recovery\" ON \"media_assets\" (\"updated_at\",\"id\") WHERE \"status\" <> 'ready';",
5938
- "\nCREATE INDEX \"media_replacements_recovery\" ON \"media_replacements\" (\"updated_at\",\"media_id\");",
5939
- "\nCREATE UNIQUE INDEX \"pending_changes_subject\" ON \"pending_changes\" (\"subject\");",
5940
- "\nCREATE INDEX \"pending_changes_recovery\" ON \"pending_changes\" (\"scope\",\"updated_at\",\"id\");",
5941
- "\nCREATE UNIQUE INDEX \"working_document_publish_attempts_active\" ON \"working_document_publish_attempts\" (\"document_id\") WHERE \"phase\" in ('pending', 'checkpointed');",
5942
- "\nCREATE INDEX \"working_document_publish_attempts_recovery\" ON \"working_document_publish_attempts\" (\"document_id\",\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
5943
- "\nALTER TABLE \"auth_accounts\" ADD CONSTRAINT \"auth_accounts_user_id_auth_users_id_fkey\" FOREIGN KEY (\"user_id\") REFERENCES \"auth_users\"(\"id\") ON DELETE CASCADE;",
5944
- "\nALTER TABLE \"auth_sessions\" ADD CONSTRAINT \"auth_sessions_user_id_auth_users_id_fkey\" FOREIGN KEY (\"user_id\") REFERENCES \"auth_users\"(\"id\") ON DELETE CASCADE;",
5945
- "\nALTER TABLE \"change_receipts\" ADD CONSTRAINT \"change_receipts_activity_id_activity_entries_id_fkey\" FOREIGN KEY (\"activity_id\") REFERENCES \"activity_entries\"(\"id\") ON DELETE RESTRICT;",
5946
- "\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE RESTRICT;",
5947
- "\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_authored_revision_fkey\" FOREIGN KEY (\"document_id\",\"authored_revision_id\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
5948
- "\nALTER TABLE \"document_heads\" ADD CONSTRAINT \"document_heads_published_revision_fkey\" FOREIGN KEY (\"document_id\",\"published_revision_id\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
5949
- "\nALTER TABLE \"document_media_references\" ADD CONSTRAINT \"document_media_references_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE CASCADE;",
5950
- "\nALTER TABLE \"document_revisions\" ADD CONSTRAINT \"document_revisions_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE RESTRICT;",
5951
- "\nALTER TABLE \"media_replacements\" ADD CONSTRAINT \"media_replacements_media_id_media_assets_id_fkey\" FOREIGN KEY (\"media_id\") REFERENCES \"media_assets\"(\"id\") ON DELETE RESTRICT;",
5952
- "\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_document_generation_fkey\" FOREIGN KEY (\"document_id\",\"expected_generation\") REFERENCES \"working_documents\"(\"document_id\",\"generation_id\") ON DELETE CASCADE;",
5953
- "\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_expected_version_fkey\" FOREIGN KEY (\"document_id\",\"expected_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
5954
- "\nALTER TABLE \"working_document_publish_attempts\" ADD CONSTRAINT \"working_document_publish_attempts_checkpoint_version_fkey\" FOREIGN KEY (\"document_id\",\"checkpoint_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;",
5955
- "\nALTER TABLE \"working_document_updates\" ADD CONSTRAINT \"working_document_updates_document_generation_fkey\" FOREIGN KEY (\"document_id\",\"generation_id\") REFERENCES \"working_documents\"(\"document_id\",\"generation_id\") ON DELETE CASCADE;",
5956
- "\nALTER TABLE \"working_documents\" ADD CONSTRAINT \"working_documents_document_id_documents_id_fkey\" FOREIGN KEY (\"document_id\") REFERENCES \"documents\"(\"id\") ON DELETE CASCADE;",
5957
- "\nALTER TABLE \"working_documents\" ADD CONSTRAINT \"working_documents_saved_version_fkey\" FOREIGN KEY (\"document_id\",\"saved_version\") REFERENCES \"document_revisions\"(\"document_id\",\"id\") ON DELETE RESTRICT;"
5958
- ],
5959
- bps: true,
5960
- folderMillis: 1788466567e3,
5961
- hash: "943a4996ef8c4324bd58280a80103e5a1632b088880164904b3857686e26f33e",
5962
- name: "20260903201607_cms_baseline"
5963
- },
5964
- {
5965
- sql: [
5966
- "ALTER TABLE \"auth_rate_limits\" ADD COLUMN \"id\" uuid DEFAULT gen_random_uuid();",
5967
- "\nALTER TABLE \"auth_rate_limits\" DROP CONSTRAINT \"auth_rate_limits_pkey\";",
5968
- "\nALTER TABLE \"auth_rate_limits\" ADD PRIMARY KEY (\"id\");",
5969
- "\nALTER TABLE \"auth_rate_limits\" ADD CONSTRAINT \"auth_rate_limits_key_key\" UNIQUE(\"key\");"
5970
- ],
5971
- bps: true,
5972
- folderMillis: 1788587191e3,
5973
- hash: "78b837c6b72a3de22d68e8db90bd211e61a0b97ff29bf8d16a0bba245eefa7ed",
5974
- name: "20260905054631_burly_northstar"
5975
- },
5976
- {
5977
- sql: ["ALTER TABLE \"auth_accounts\" DROP COLUMN \"issuer\";", "\nCREATE UNIQUE INDEX \"auth_accounts_identity\" ON \"auth_accounts\" (\"provider_id\",\"account_id\");"],
5978
- bps: true,
5979
- folderMillis: 178875937e4,
5980
- hash: "e442485fa6c2d611e3dae508a12d245481bc5ec8f2dd4f5d853910df34484787",
5981
- name: "20260907053610_fancy_lady_deathstrike"
5982
- },
5983
- {
5984
- sql: ["ALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_action_check\", ADD CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));", "\nALTER TABLE \"pending_changes\" DROP CONSTRAINT \"pending_changes_action_check\", ADD CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));"],
5985
- bps: true,
5986
- folderMillis: 1788866265e3,
5987
- hash: "24c56a37796caf8d76c0a97128a382b31e71808aa5b0ca7e5bac96795f9e16c7",
5988
- name: "20260908111745_classy_johnny_storm"
5989
- },
5990
- {
5991
- sql: [
5992
- "CREATE TABLE \"seo_media_references\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"scope\" text NOT NULL,\n \"media_id\" uuid NOT NULL,\n CONSTRAINT \"seo_media_references_scope_media_unique\" UNIQUE(\"scope\",\"media_id\"),\n CONSTRAINT \"seo_media_references_scope_check\" CHECK (\"scope\" in ('working', 'published'))\n);\n",
5993
- "\nCREATE TABLE \"seo_revisions\" (\n \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n \"settings\" jsonb NOT NULL,\n \"actor_id\" text NOT NULL,\n \"actor_email\" text NOT NULL,\n \"actor_name\" text NOT NULL,\n \"actor_roles\" jsonb NOT NULL,\n \"request_id\" uuid NOT NULL,\n \"reason\" text,\n \"created_at\" timestamp with time zone DEFAULT transaction_timestamp() NOT NULL,\n CONSTRAINT \"seo_revisions_actor_roles_check\" CHECK (jsonb_typeof(\"actor_roles\") = 'array'),\n CONSTRAINT \"seo_revisions_settings_check\" CHECK (jsonb_typeof(\"settings\") = 'object')\n);\n",
5994
- "\nCREATE TABLE \"seo_state\" (\n \"singleton\" boolean PRIMARY KEY DEFAULT true,\n \"working_revision_id\" uuid NOT NULL,\n \"published_revision_id\" uuid NOT NULL,\n CONSTRAINT \"seo_state_singleton_check\" CHECK (\"singleton\")\n);\n",
5995
- "\nCREATE INDEX \"seo_media_references_media\" ON \"seo_media_references\" (\"media_id\");",
5996
- "\nCREATE INDEX \"seo_revisions_history\" ON \"seo_revisions\" (\"created_at\" DESC NULLS LAST,\"id\" DESC NULLS LAST);",
5997
- "\nALTER TABLE \"seo_media_references\" ADD CONSTRAINT \"seo_media_references_media_id_media_assets_id_fkey\" FOREIGN KEY (\"media_id\") REFERENCES \"media_assets\"(\"id\") ON DELETE RESTRICT;",
5998
- "\nALTER TABLE \"seo_state\" ADD CONSTRAINT \"seo_state_working_revision_fkey\" FOREIGN KEY (\"working_revision_id\") REFERENCES \"seo_revisions\"(\"id\") ON DELETE RESTRICT;",
5999
- "\nALTER TABLE \"seo_state\" ADD CONSTRAINT \"seo_state_published_revision_fkey\" FOREIGN KEY (\"published_revision_id\") REFERENCES \"seo_revisions\"(\"id\") ON DELETE RESTRICT;",
6000
- "\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_action_check\", ADD CONSTRAINT \"activity_entries_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'seo.saved', 'seo.published', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));",
6001
- "\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_target_kind_check\", ADD CONSTRAINT \"activity_entries_target_kind_check\" CHECK (\"target_kind\" in ('document', 'media', 'media-library', 'seo', 'user'));",
6002
- "\nALTER TABLE \"activity_entries\" DROP CONSTRAINT \"activity_entries_target_check\", ADD CONSTRAINT \"activity_entries_target_check\" CHECK ((\"target_kind\" in ('media-library', 'seo') AND \"target_id\" IS NULL)\n OR (\"target_kind\" not in ('media-library', 'seo') AND \"target_id\" IS NOT NULL));",
6003
- "\nALTER TABLE \"pending_changes\" DROP CONSTRAINT \"pending_changes_action_check\", ADD CONSTRAINT \"pending_changes_action_check\" CHECK (\"action\" in ('document.created', 'document.updated', 'document.moved', 'document.trashed', 'document.revision.restored', 'document.untrashed', 'document.published', 'document.unpublished', 'media.uploaded', 'media.replaced', 'media.removed', 'media.cleaned', 'seo.saved', 'seo.published', 'user.created', 'user.removed', 'user.role.changed', 'user.sessions.revoked', 'authentication.signed-in', 'authentication.signed-out', 'authentication.password.changed', 'authentication.password.reset'));"
6004
- ],
6005
- bps: true,
6006
- folderMillis: 1789233351e3,
6007
- hash: "8e6a6abf5385ab3ecf8eb083c1923ac9c74d72aa71bd1d444b7402d3e7e77000",
6008
- name: "20260912171551_charming_valkyrie"
6009
- }
6010
- ];
6011
-
6012
- //#endregion
6013
- //#region ../sql-pg/src/internal/documents/tables.ts
6014
- const cmsState = pgTable("cms_state", {
6015
- singleton: boolean().default(true).primaryKey(),
6016
- generation: bigint({ mode: "bigint" }).default(sql`0`).notNull()
6017
- }, (table) => [check("cms_state_singleton_check", sql`${table.singleton}`), check("cms_state_generation_check", sql`${table.generation} >= 0`)]);
6018
- const documentsTable = pgTable("documents", {
6019
- id: uuid().defaultRandom().primaryKey(),
6020
- sourcePath: text("source_path").notNull(),
6021
- deletedAt: timestamp("deleted_at", {
6022
- mode: "string",
6023
- withTimezone: true
6024
- }),
6025
- createdAt: timestamp("created_at", {
6026
- mode: "string",
6027
- withTimezone: true
6028
- }).default(transactionTimestamp).notNull(),
6029
- updatedAt: timestamp("updated_at", {
6030
- mode: "string",
6031
- withTimezone: true
6032
- }).default(transactionTimestamp).notNull()
6033
- }, (table) => [uniqueIndex("documents_active_path").on(table.sourcePath).where(sql`${table.deletedAt} is null`)]);
6034
- const documentRevisions = pgTable("document_revisions", {
6035
- id: uuid().defaultRandom().primaryKey(),
6036
- documentId: uuid("document_id").notNull().references(() => documentsTable.id, { onDelete: "restrict" }),
6037
- action: text({ enum: DOCUMENT_REVISION_ACTIONS }).notNull(),
6038
- sourcePath: text("source_path").notNull(),
6039
- markdown: text().notNull(),
6040
- actorId: text("actor_id").notNull(),
6041
- actorEmail: text("actor_email").notNull(),
6042
- actorName: text("actor_name").notNull(),
6043
- actorRoles: jsonb("actor_roles").$type().notNull(),
6044
- requestId: uuid("request_id").notNull(),
6045
- reason: text(),
6046
- activityDetails: jsonb("activity_details").$type().default({}).notNull(),
6047
- createdAt: timestamp("created_at", {
6048
- mode: "string",
6049
- withTimezone: true
6050
- }).default(transactionTimestamp).notNull()
6051
- }, (table) => [
6052
- check("document_revisions_action_check", isOneOf(table.action, DOCUMENT_REVISION_ACTIONS)),
6053
- unique("document_revisions_document_id_unique").on(table.documentId, table.id),
6054
- index("document_revisions_history").on(table.documentId, table.createdAt.desc(), table.id.desc())
6055
- ]);
6056
- const documentHeads = pgTable("document_heads", {
6057
- documentId: uuid("document_id").primaryKey().references(() => documentsTable.id, { onDelete: "restrict" }),
6058
- authoredRevisionId: uuid("authored_revision_id").notNull(),
6059
- publishedRevisionId: uuid("published_revision_id")
6060
- }, (table) => [foreignKey({
6061
- columns: [table.documentId, table.authoredRevisionId],
6062
- foreignColumns: [documentRevisions.documentId, documentRevisions.id],
6063
- name: "document_heads_authored_revision_fkey"
6064
- }).onDelete("restrict"), foreignKey({
6065
- columns: [table.documentId, table.publishedRevisionId],
6066
- foreignColumns: [documentRevisions.documentId, documentRevisions.id],
6067
- name: "document_heads_published_revision_fkey"
6068
- }).onDelete("restrict")]);
6069
- const documentMediaReferences = pgTable("document_media_references", {
6070
- id: uuid().defaultRandom().primaryKey(),
6071
- documentId: uuid("document_id").notNull().references(() => documentsTable.id, { onDelete: "cascade" }),
6072
- objectKey: text("object_key").notNull(),
6073
- path: text().notNull(),
6074
- sourcePath: text("source_path").notNull(),
6075
- nodePath: integer("node_path").array().notNull()
6076
- }, (table) => [
6077
- unique("document_media_references_identity_unique").on(table.documentId, table.sourcePath, table.nodePath, table.objectKey),
6078
- check("document_media_references_object_key_check", sql`char_length(${table.objectKey}) between 1 and 1024
6079
- AND btrim(${table.objectKey}) = ${table.objectKey}
6080
- AND ${table.objectKey} !~ '(^/|/$|//|(^|/)\\.{1,2}(/|$)|[[:cntrl:]])'
6081
- AND position(chr(92) in ${table.objectKey}) = 0`),
6082
- check("document_media_references_node_path_check", sql`array_position(${table.nodePath}, NULL) IS NULL AND 0 <= ALL(${table.nodePath})`),
6083
- index("document_media_references_object_key").on(table.objectKey)
6084
- ]);
6085
-
6086
- //#endregion
6087
- //#region ../sql-pg/src/internal/initialization/tables.ts
6088
- const INITIALIZATION_STATES = [
6089
- "uninitialized",
6090
- "claiming",
6091
- "ready"
6092
- ];
6093
- const initializationState = pgTable("initialization_state", {
6094
- singleton: boolean().default(true).primaryKey(),
6095
- state: text({ enum: INITIALIZATION_STATES }).default("uninitialized").notNull(),
6096
- changeId: uuid("change_id"),
6097
- claim: jsonb().$type()
6098
- }, (table) => [
6099
- check("initialization_state_singleton_check", sql`${table.singleton}`),
6100
- check("initialization_state_state_check", isOneOf(table.state, INITIALIZATION_STATES)),
6101
- check("initialization_state_claim_check", sql`(${table.state} = 'claiming' AND ${table.changeId} IS NOT NULL AND jsonb_typeof(${table.claim}) = 'object')
6102
- OR (${table.state} <> 'claiming' AND ${table.changeId} IS NULL AND ${table.claim} IS NULL)`)
6103
- ]);
6104
-
6105
- //#endregion
6106
- //#region ../sql-pg/src/internal/database/migrations.ts
6107
- const MIGRATION_LOCK_KEY = "cms:database-migrations:v1";
6108
- const migrateCmsDatabase = Effect.fn("CmsDatabase.migrate")(function* () {
6109
- const postgres = yield* PgClient.PgClient;
6110
- const database = yield* PgDrizzle.makeWithDefaults();
6111
- yield* postgres.withTransaction(Effect.gen(function* () {
6112
- yield* postgres.unsafe("select pg_advisory_xact_lock(hashtextextended($1, 0))", [MIGRATION_LOCK_KEY]);
6113
- yield* migrate(embeddedMigrations, database._.session, "__drizzle_migrations");
6114
- yield* database.insert(cmsState).values({}).onConflictDoNothing({ target: cmsState.singleton });
6115
- yield* database.insert(initializationState).values({}).onConflictDoNothing({ target: initializationState.singleton });
6116
- }));
6117
- });
6118
- const cmsDatabaseMigrationLayer = Layer.effectDiscard(migrateCmsDatabase());
6119
-
6120
6214
  //#endregion
6121
6215
  //#region ../sql-pg/src/internal/documents/commands.ts
6122
6216
  const isEffectDrizzleQueryError = Schema.is(EffectDrizzleQueryError);
@@ -8078,21 +8172,32 @@ function notifyWorkingDocumentChange(database, kind, documentId, generationId) {
8078
8172
  * Mutations that span seams remain transactions inside this adapter.
8079
8173
  */
8080
8174
  function postgresLayer(options) {
8081
- const database = PgClient.layer({
8082
- ...options,
8175
+ const { schema, ...poolOptions } = options;
8176
+ const clientOptions = {
8177
+ ...poolOptions,
8083
8178
  applicationName: options.applicationName ?? "@internal/sql-pg"
8084
- });
8085
- const migrations = cmsDatabaseMigrationLayer.pipe(Layer.provide(database));
8086
- const locks = postgresAdvisoryLockLayer(options);
8087
- return Layer.mergeAll(postgresActivityStoreLayer, changeJournalLayer, documentStoreLayer, mediaStoreLayer, seoStoreLayer, initializationStoreLayer.pipe(Layer.provide(locks)), postgresUserCommandFenceLayer.pipe(Layer.provide(locks)), postgresWorkingDocumentChangesLayer(options), workingDocumentStoreLayer).pipe(Layer.provide(migrations), Layer.provide(database));
8179
+ };
8180
+ const database = schemaClientLayer(clientOptions, schema);
8181
+ const migrations = cmsDatabaseMigrationLayer(schema).pipe(Layer.provide(database));
8182
+ const locks = postgresAdvisoryLockLayer(poolOptions);
8183
+ return Layer.mergeAll(postgresActivityStoreLayer, changeJournalLayer, documentStoreLayer, mediaStoreLayer, seoStoreLayer, initializationStoreLayer.pipe(Layer.provide(locks)), postgresUserCommandFenceLayer.pipe(Layer.provide(locks)), postgresWorkingDocumentChangesLayer(poolOptions), workingDocumentStoreLayer).pipe(Layer.provide(migrations), Layer.provide(database));
8088
8184
  }
8089
8185
 
8090
8186
  //#endregion
8091
8187
  //#region src/runtime/installation.ts
8188
+ var DatabaseSchemaProvisionFailed = class extends Schema.TaggedError()("NuxtCmsInstallation.DatabaseSchemaProvisionFailed", {
8189
+ cause: Schema.Defect(),
8190
+ schema: Schema.String
8191
+ }) {};
8092
8192
  const installCms = Effect.fn("NuxtCmsInstallation.install")(function* (options) {
8193
+ yield* provisionDatabaseSchema(options.database);
8093
8194
  const crypto = NodeCrypto.layer;
8094
- const postgres = postgresLayer({ url: Redacted.make(options.databaseUrl) });
8095
- const identity = Layer.unwrap(Effect.acquireRelease(Effect.sync(() => new Pool({ connectionString: options.databaseUrl })), (pool) => Effect.promise(() => pool.end()).pipe(Effect.asVoid)).pipe(Effect.map((pool) => betterAuthLayer({
8195
+ const databaseUrl = scopedDatabaseUrl(options.database);
8196
+ const postgres = postgresLayer({
8197
+ schema: options.database.schema,
8198
+ url: Redacted.make(options.database.url)
8199
+ });
8200
+ const identity = Layer.unwrap(Effect.acquireRelease(Effect.sync(() => new Pool({ connectionString: databaseUrl })), (pool) => Effect.promise(() => pool.end()).pipe(Effect.asVoid)).pipe(Effect.map((pool) => betterAuthLayer({
8096
8201
  baseURL: options.baseUrl,
8097
8202
  database: pool,
8098
8203
  secret: `cms-authentication:${options.secret}`
@@ -8119,6 +8224,16 @@ const installCms = Effect.fn("NuxtCmsInstallation.install")(function* (options)
8119
8224
  studioSecret: Redacted.make(`cms-collaboration:${options.secret}`)
8120
8225
  });
8121
8226
  });
8227
+ const provisionDatabaseSchema = Effect.fn("NuxtCmsInstallation.provisionDatabaseSchema")(function* (database) {
8228
+ const pool = new Pool({ connectionString: database.url });
8229
+ yield* Effect.tryPromise({
8230
+ try: () => pool.query(`create schema if not exists "${database.schema}"`),
8231
+ catch: (cause) => new DatabaseSchemaProvisionFailed({
8232
+ cause,
8233
+ schema: database.schema
8234
+ })
8235
+ }).pipe(Effect.ensuring(Effect.promise(() => pool.end())));
8236
+ });
8122
8237
  function toS3MediaObjectStoreOptions(options) {
8123
8238
  const { credentials: authoredCredentials, publicBaseUrl: _publicBaseUrl, ...storeOptions } = options;
8124
8239
  if (!authoredCredentials) return storeOptions;
@@ -8135,7 +8250,13 @@ function toS3MediaObjectStoreOptions(options) {
8135
8250
  credentials
8136
8251
  };
8137
8252
  }
8253
+ function scopedDatabaseUrl(database) {
8254
+ if (!/^[a-z_][a-z0-9_]{0,62}$/u.test(database.schema)) throw new Error("Invalid CMS PostgreSQL schema.");
8255
+ const url = new URL(database.url);
8256
+ url.searchParams.set("options", `-csearch_path=${database.schema}`);
8257
+ return url.href;
8258
+ }
8138
8259
 
8139
8260
  //#endregion
8140
- export { toS3MediaObjectStoreOptions as n, installCms as t };
8141
- //# sourceMappingURL=installation-CNfIriVm.js.map
8261
+ export { embeddedMigrations as a, createCmsBetterAuth as i, scopedDatabaseUrl as n, toS3MediaObjectStoreOptions as r, installCms as t };
8262
+ //# sourceMappingURL=installation-DsGst1BH.js.map