@phtngyn/cms 0.1.0-beta.5 → 0.2.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +114 -41
- package/package.json +13 -1
- package/src/ApplicationTypes.d.ts +84 -0
- package/src/ApplicationTypes.js +1 -0
- package/src/{Configuration-CDMYfTre.js → Configuration-BU-UyGoH.js} +4 -4
- package/src/{Configuration-CDMYfTre.js.map → Configuration-BU-UyGoH.js.map} +1 -1
- package/src/Configuration.d.ts +43 -21
- package/src/Configuration.js.map +1 -1
- package/src/Content.d.ts +67 -0
- package/src/Content.js +291 -0
- package/src/Content.js.map +1 -0
- package/src/{ContentTransfer-C3Av9sWz.js → ContentTransfer-BhF9G56s.js} +8 -4
- package/src/ContentTransfer-BhF9G56s.js.map +1 -0
- package/src/ContentTransfer-CRQet3QJ.d.ts +48 -0
- package/src/{DocumentEngine-J7g-emdf.js → DocumentEngine-ClhFXW9M.js} +4 -4
- package/src/{DocumentEngine-J7g-emdf.js.map → DocumentEngine-ClhFXW9M.js.map} +1 -1
- package/src/DocumentModel.d.ts +14 -2
- package/src/DocumentModel.js +32 -4
- package/src/DocumentModel.js.map +1 -1
- package/src/{Forms-CfcI3tPU.js → Forms-BbkE7QfC.js} +47 -16
- package/src/Forms-BbkE7QfC.js.map +1 -0
- package/src/{Forms-Dj6NuW66.js → Forms-DoB56hfe.js} +24 -7
- package/src/Forms-DoB56hfe.js.map +1 -0
- package/src/{Forms-BsJMev5_.d.ts → Forms-R0HoTR-o.d.ts} +31 -13
- package/src/Forms.d.ts +23 -11
- package/src/Forms.js.map +1 -1
- package/src/I18n-zbqpWxki.d.ts +29 -0
- package/src/I18n.d.ts +2 -20
- package/src/Module.js +18 -7
- package/src/Module.js.map +1 -1
- package/src/{S3MediaObjects-CpPSzJto.js → S3MediaObjects-D5Ns4FM6.js} +61 -40
- package/src/S3MediaObjects-D5Ns4FM6.js.map +1 -0
- package/src/cli/content.js +63 -221
- package/src/cli/content.js.map +1 -1
- package/src/cli.js +120 -5
- package/src/cli.js.map +1 -1
- package/src/{connection-CBAy2qGy.js → connection-D5S9Iph-.js} +2 -2
- package/src/{connection-CBAy2qGy.js.map → connection-D5S9Iph-.js.map} +1 -1
- package/src/dev-lifecycle-CZ7iCzG9.js +515 -0
- package/src/dev-lifecycle-CZ7iCzG9.js.map +1 -0
- package/src/{installation-CNfIriVm.js → installation-BNuoRDOz.js} +601 -468
- package/src/installation-BNuoRDOz.js.map +1 -0
- package/src/internal/application-types.js +43 -0
- package/src/internal/application-types.js.map +1 -0
- package/src/internal/authoring-catalog.js +9 -4
- package/src/internal/authoring-catalog.js.map +1 -1
- package/src/internal/authoring-metadata.js +1 -1
- package/src/internal/configuration.js +149 -46
- package/src/internal/configuration.js.map +1 -1
- package/src/internal/dev-lifecycle.js +3 -0
- package/src/internal/diagnostics.js +47 -0
- package/src/internal/diagnostics.js.map +1 -0
- package/src/internal/document-model.js +2 -2
- package/src/internal/document-model.js.map +1 -1
- package/src/internal/form-capabilities.js +1 -1
- package/src/internal/i18n.js +27 -1
- package/src/internal/i18n.js.map +1 -1
- package/src/{location-BTqdfIzX.js → location-CPX7oj0o.js} +2 -2
- package/src/{location-BTqdfIzX.js.map → location-CPX7oj0o.js.map} +1 -1
- package/src/{models-B4IoTmp7.js → models-C9kF9JlQ.js} +2 -2
- package/src/{models-B4IoTmp7.js.map → models-C9kF9JlQ.js.map} +1 -1
- package/src/{models-Bah5B3bT.js → models-ChRxBChy.js} +9 -2
- package/src/models-ChRxBChy.js.map +1 -0
- package/src/runtime/delivery/context.js +1 -1
- package/src/runtime/delivery/plugin.js +28 -5
- package/src/runtime/delivery/plugin.js.map +1 -1
- package/src/runtime/delivery/preview.d.ts +1 -1
- package/src/runtime/delivery/types.d.ts +2 -85
- package/src/runtime/delivery/useCmsDocumentSeo.d.ts +8 -1
- package/src/runtime/delivery/useCmsDocumentSeo.js +19 -7
- package/src/runtime/delivery/useCmsDocumentSeo.js.map +1 -1
- package/src/runtime/delivery/useDocument.d.ts +2 -2
- package/src/runtime/delivery/useDocument.js.map +1 -1
- package/src/runtime/delivery/useDocumentQuery.d.ts +3 -3
- package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
- package/src/runtime/forms/document.js +1 -1
- package/src/runtime/forms/useCmsForm.js +89 -45
- package/src/runtime/forms/useCmsForm.js.map +1 -1
- package/src/runtime/i18n/useCmsI18n.d.ts +9 -7
- package/src/runtime/i18n/useCmsI18n.js +5 -4
- package/src/runtime/i18n/useCmsI18n.js.map +1 -1
- package/src/runtime/installation.js +2 -2
- package/src/runtime/plugin.js +12 -4
- package/src/runtime/plugin.js.map +1 -1
- package/src/runtime/preview/connection.js +1 -1
- package/src/runtime/preview/controller.js +2 -2
- package/src/runtime/preview/plugin.client.js +3 -3
- package/src/runtime/preview/store.js +1 -1
- package/src/runtime/sitemap.js +1 -1
- package/src/scalars-CA6kyipS.d.ts +7 -0
- package/src/{store-b2CSXgMt.js → store-B49J21NA.js} +3 -3
- package/src/{store-b2CSXgMt.js.map → store-B49J21NA.js.map} +1 -1
- package/src/types-DutFRtaG.d.ts +90 -0
- package/studio/{CreateDocumentDialog-GGey1uBc.js → CreateDocumentDialog-DJ8c0WZb.js} +3 -3
- package/studio/{documentPlanning-DRErYmBU.js → documentPlanning-CDb31mnl.js} +5935 -5869
- package/studio/host.css +1 -1
- package/studio/host.js +7608 -7250
- package/src/ContentTransfer-C3Av9sWz.js.map +0 -1
- package/src/Forms-CfcI3tPU.js.map +0 -1
- package/src/Forms-Dj6NuW66.js.map +0 -1
- package/src/S3MediaObjects-CpPSzJto.js.map +0 -1
- package/src/installation-CNfIriVm.js.map +0 -1
- 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 {
|
|
3
|
-
import { a as
|
|
4
|
-
import {
|
|
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-ChRxBChy.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-D5Ns4FM6.js";
|
|
4
|
+
import { o as ContentTransferConflict } from "./ContentTransfer-BhF9G56s.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 { n as FORM_SUBMISSION_MAX_BYTES, o as FormResult } from "./Forms-BbkE7QfC.js";
|
|
7
|
+
import { a as encodeCmsEditorComponentAttributes, d as createCmsComarkRenderData, i as validateFormValues, t as documentForms } from "./Forms-DoB56hfe.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-
|
|
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-BU-UyGoH.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
|
|
16
|
-
import {
|
|
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) {
|
|
@@ -790,141 +1239,14 @@ function activityDraft(action, actor, requestId) {
|
|
|
790
1239
|
},
|
|
791
1240
|
details: {},
|
|
792
1241
|
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"
|
|
927
|
-
};
|
|
1242
|
+
kind: "user",
|
|
1243
|
+
userId: actor.id
|
|
1244
|
+
}
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
function decodeActor(user) {
|
|
1248
|
+
const option = decodeBetterAuthActorOption(user);
|
|
1249
|
+
return Option.getOrUndefined(option);
|
|
928
1250
|
}
|
|
929
1251
|
|
|
930
1252
|
//#endregion
|
|
@@ -4953,25 +5275,16 @@ function targetError(operation) {
|
|
|
4953
5275
|
//#endregion
|
|
4954
5276
|
//#region ../server/src/Forms.ts
|
|
4955
5277
|
/** Only the currently published definition can authorize a submission. Never trust client rules. */
|
|
4956
|
-
const submitForm = Effect.fn("Forms.submit")(function* (input, components, handlers) {
|
|
5278
|
+
const submitForm = Effect.fn("Forms.submit")(function* (input, components, handlers, request) {
|
|
4957
5279
|
const document = yield* (yield* PublishedDocuments).read({
|
|
4958
5280
|
kind: "id",
|
|
4959
5281
|
documentId: input.documentId
|
|
4960
5282
|
}).pipe(Effect.orElseSucceed(() => void 0));
|
|
4961
|
-
if (!document) return FormResult.make({
|
|
4962
|
-
status: "unavailable",
|
|
4963
|
-
errors: {}
|
|
4964
|
-
});
|
|
5283
|
+
if (!document) return FormResult.make({ status: "unavailable" });
|
|
4965
5284
|
const form = documentForms(document, components).find((candidate) => JSON.stringify(candidate.nodePath) === JSON.stringify(input.nodePath));
|
|
4966
|
-
if (!form || form.revision !== input.revision) return FormResult.make({
|
|
4967
|
-
status: "stale",
|
|
4968
|
-
errors: {}
|
|
4969
|
-
});
|
|
5285
|
+
if (!form || form.revision !== input.revision) return FormResult.make({ status: "stale" });
|
|
4970
5286
|
const handler = Object.hasOwn(handlers, form.name) ? handlers[form.name] : void 0;
|
|
4971
|
-
if (!handler) return FormResult.make({
|
|
4972
|
-
status: "unavailable",
|
|
4973
|
-
errors: {}
|
|
4974
|
-
});
|
|
5287
|
+
if (!handler) return FormResult.make({ status: "unavailable" });
|
|
4975
5288
|
const fields = form.steps.flatMap((step) => step.fields);
|
|
4976
5289
|
const errors = validateFormValues(fields, input.values);
|
|
4977
5290
|
if (Object.keys(input.values).some((id) => !fields.some((field) => field.id === id))) errors._form = "The submission contains unknown answers.";
|
|
@@ -4980,17 +5293,32 @@ const submitForm = Effect.fn("Forms.submit")(function* (input, components, handl
|
|
|
4980
5293
|
errors
|
|
4981
5294
|
});
|
|
4982
5295
|
const values = Object.fromEntries(fields.map((field) => [field.id, normalizedAnswer(Object.hasOwn(input.values, field.id) ? input.values[field.id] : void 0)]));
|
|
5296
|
+
const startedAt = yield* Clock.currentTimeMillis;
|
|
4983
5297
|
return yield* Effect.tryPromise(() => Promise.resolve(handler({
|
|
4984
5298
|
form,
|
|
5299
|
+
request,
|
|
4985
5300
|
values
|
|
4986
|
-
}))).pipe(Effect.
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
})));
|
|
5301
|
+
}))).pipe(Effect.map((outcome) => formResult(outcome, fields)), Effect.tapError((cause) => Clock.currentTimeMillis.pipe(Effect.flatMap((finishedAt) => Effect.logError("CMS form submission handler failed.", cause).pipe(Effect.annotateLogs({
|
|
5302
|
+
documentId: String(form.documentId),
|
|
5303
|
+
durationMillis: Math.max(0, finishedAt - startedAt),
|
|
5304
|
+
form: form.name,
|
|
5305
|
+
requestId: request.id
|
|
5306
|
+
}))))), Effect.orElseSucceed(() => FormResult.make({ status: "failed" })));
|
|
4993
5307
|
});
|
|
5308
|
+
function formResult(outcome, fields) {
|
|
5309
|
+
if (outcome.status === "accepted") return FormResult.make({
|
|
5310
|
+
status: "accepted",
|
|
5311
|
+
...outcome.reference ? { reference: outcome.reference } : void 0
|
|
5312
|
+
});
|
|
5313
|
+
if (outcome.status === "unavailable") return FormResult.make({ status: "unavailable" });
|
|
5314
|
+
const fieldIds = new Set(fields.map((field) => field.id));
|
|
5315
|
+
const errors = Object.fromEntries(Object.entries(outcome.errors).filter(([field]) => field === "_form" || fieldIds.has(field)));
|
|
5316
|
+
if (Object.keys(outcome.errors).some((field) => field !== "_form" && !fieldIds.has(field)) && !errors._form) errors._form = "The submission could not be accepted.";
|
|
5317
|
+
return FormResult.make({
|
|
5318
|
+
status: "invalid",
|
|
5319
|
+
errors
|
|
5320
|
+
});
|
|
5321
|
+
}
|
|
4994
5322
|
function normalizedAnswer(value) {
|
|
4995
5323
|
return value === void 0 || Predicate.isString(value) && !value.trim() ? null : value;
|
|
4996
5324
|
}
|
|
@@ -5006,12 +5334,18 @@ function formsApiLayer(components, handlers) {
|
|
|
5006
5334
|
limit: 60,
|
|
5007
5335
|
window: "1 minute",
|
|
5008
5336
|
onExceeded: "fail"
|
|
5009
|
-
}).pipe(Effect.andThen(
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5337
|
+
}).pipe(Effect.andThen(Effect.gen(function* () {
|
|
5338
|
+
const request = {
|
|
5339
|
+
id: requestId(),
|
|
5340
|
+
submittedAt: DateTime.toDate(DateTime.makeUnsafe(yield* Clock.currentTimeMillis))
|
|
5341
|
+
};
|
|
5342
|
+
return yield* submitForm(payload, components, handlers, request);
|
|
5343
|
+
}).pipe(Effect.provideService(PublishedDocuments, documents))), Effect.orElseSucceed(() => FormResult.make({ status: "unavailable" }))));
|
|
5013
5344
|
})).pipe(Layer.provide(RateLimiter.layer.pipe(Layer.provide(RateLimiter.layerStoreMemory))));
|
|
5014
5345
|
}
|
|
5346
|
+
function requestId() {
|
|
5347
|
+
return globalThis.crypto.randomUUID();
|
|
5348
|
+
}
|
|
5015
5349
|
|
|
5016
5350
|
//#endregion
|
|
5017
5351
|
//#region ../platform-node/src/internal/http/errors.ts
|
|
@@ -5398,13 +5732,6 @@ function createCmsInstallationLayer(options) {
|
|
|
5398
5732
|
});
|
|
5399
5733
|
}
|
|
5400
5734
|
|
|
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
5735
|
//#endregion
|
|
5409
5736
|
//#region ../sql-pg/src/internal/activity/tables.ts
|
|
5410
5737
|
const ACTIVITY_TARGET_KINDS = [
|
|
@@ -5896,227 +6223,6 @@ function changeJournalUnavailable(operation, cause) {
|
|
|
5896
6223
|
});
|
|
5897
6224
|
}
|
|
5898
6225
|
|
|
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
6226
|
//#endregion
|
|
6121
6227
|
//#region ../sql-pg/src/internal/documents/commands.ts
|
|
6122
6228
|
const isEffectDrizzleQueryError = Schema.is(EffectDrizzleQueryError);
|
|
@@ -8078,21 +8184,32 @@ function notifyWorkingDocumentChange(database, kind, documentId, generationId) {
|
|
|
8078
8184
|
* Mutations that span seams remain transactions inside this adapter.
|
|
8079
8185
|
*/
|
|
8080
8186
|
function postgresLayer(options) {
|
|
8081
|
-
const
|
|
8082
|
-
|
|
8187
|
+
const { schema, ...poolOptions } = options;
|
|
8188
|
+
const clientOptions = {
|
|
8189
|
+
...poolOptions,
|
|
8083
8190
|
applicationName: options.applicationName ?? "@internal/sql-pg"
|
|
8084
|
-
}
|
|
8085
|
-
const
|
|
8086
|
-
const
|
|
8087
|
-
|
|
8191
|
+
};
|
|
8192
|
+
const database = schemaClientLayer(clientOptions, schema);
|
|
8193
|
+
const migrations = cmsDatabaseMigrationLayer(schema).pipe(Layer.provide(database));
|
|
8194
|
+
const locks = postgresAdvisoryLockLayer(poolOptions);
|
|
8195
|
+
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
8196
|
}
|
|
8089
8197
|
|
|
8090
8198
|
//#endregion
|
|
8091
8199
|
//#region src/runtime/installation.ts
|
|
8200
|
+
var DatabaseSchemaProvisionFailed = class extends Schema.TaggedError()("NuxtCmsInstallation.DatabaseSchemaProvisionFailed", {
|
|
8201
|
+
cause: Schema.Defect(),
|
|
8202
|
+
schema: Schema.String
|
|
8203
|
+
}) {};
|
|
8092
8204
|
const installCms = Effect.fn("NuxtCmsInstallation.install")(function* (options) {
|
|
8205
|
+
yield* provisionDatabaseSchema(options.database);
|
|
8093
8206
|
const crypto = NodeCrypto.layer;
|
|
8094
|
-
const
|
|
8095
|
-
const
|
|
8207
|
+
const databaseUrl = scopedDatabaseUrl(options.database);
|
|
8208
|
+
const postgres = postgresLayer({
|
|
8209
|
+
schema: options.database.schema,
|
|
8210
|
+
url: Redacted.make(options.database.url)
|
|
8211
|
+
});
|
|
8212
|
+
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
8213
|
baseURL: options.baseUrl,
|
|
8097
8214
|
database: pool,
|
|
8098
8215
|
secret: `cms-authentication:${options.secret}`
|
|
@@ -8119,6 +8236,16 @@ const installCms = Effect.fn("NuxtCmsInstallation.install")(function* (options)
|
|
|
8119
8236
|
studioSecret: Redacted.make(`cms-collaboration:${options.secret}`)
|
|
8120
8237
|
});
|
|
8121
8238
|
});
|
|
8239
|
+
const provisionDatabaseSchema = Effect.fn("NuxtCmsInstallation.provisionDatabaseSchema")(function* (database) {
|
|
8240
|
+
const pool = new Pool({ connectionString: database.url });
|
|
8241
|
+
yield* Effect.tryPromise({
|
|
8242
|
+
try: () => pool.query(`create schema if not exists "${database.schema}"`),
|
|
8243
|
+
catch: (cause) => new DatabaseSchemaProvisionFailed({
|
|
8244
|
+
cause,
|
|
8245
|
+
schema: database.schema
|
|
8246
|
+
})
|
|
8247
|
+
}).pipe(Effect.ensuring(Effect.promise(() => pool.end())));
|
|
8248
|
+
});
|
|
8122
8249
|
function toS3MediaObjectStoreOptions(options) {
|
|
8123
8250
|
const { credentials: authoredCredentials, publicBaseUrl: _publicBaseUrl, ...storeOptions } = options;
|
|
8124
8251
|
if (!authoredCredentials) return storeOptions;
|
|
@@ -8135,7 +8262,13 @@ function toS3MediaObjectStoreOptions(options) {
|
|
|
8135
8262
|
credentials
|
|
8136
8263
|
};
|
|
8137
8264
|
}
|
|
8265
|
+
function scopedDatabaseUrl(database) {
|
|
8266
|
+
if (!/^[a-z_][a-z0-9_]{0,62}$/u.test(database.schema)) throw new Error("Invalid CMS PostgreSQL schema.");
|
|
8267
|
+
const url = new URL(database.url);
|
|
8268
|
+
url.searchParams.set("options", `-csearch_path=${database.schema}`);
|
|
8269
|
+
return url.href;
|
|
8270
|
+
}
|
|
8138
8271
|
|
|
8139
8272
|
//#endregion
|
|
8140
|
-
export {
|
|
8141
|
-
//# sourceMappingURL=installation-
|
|
8273
|
+
export { embeddedMigrations as a, createCmsBetterAuth as i, scopedDatabaseUrl as n, toS3MediaObjectStoreOptions as r, installCms as t };
|
|
8274
|
+
//# sourceMappingURL=installation-BNuoRDOz.js.map
|