@shapio/cms 0.5.9 → 0.5.10
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/dist/admin/assets/{AssetTile-Da76KsyX.js → AssetTile-DecaDqjj.js} +2 -2
- package/dist/admin/assets/{AssetTile-Da76KsyX.js.map → AssetTile-DecaDqjj.js.map} +1 -1
- package/dist/admin/assets/{AssistError-Wr62cDj3.js → AssistError-rslPtgWB.js} +2 -2
- package/dist/admin/assets/{AssistError-Wr62cDj3.js.map → AssistError-rslPtgWB.js.map} +1 -1
- package/dist/admin/assets/{BlockMenuItems-BMiEVCIT.js → BlockMenuItems-JHFue7Qt.js} +2 -2
- package/dist/admin/assets/{BlockMenuItems-BMiEVCIT.js.map → BlockMenuItems-JHFue7Qt.js.map} +1 -1
- package/dist/admin/assets/{Body-BEW1sAAB.js → Body-7NgJl9Pi.js} +2 -2
- package/dist/admin/assets/Body-7NgJl9Pi.js.map +1 -0
- package/dist/admin/assets/Builder-DmlYcgiP.js +2 -0
- package/dist/admin/assets/Builder-DmlYcgiP.js.map +1 -0
- package/dist/admin/assets/{CodeEditor-Ck7ggv6w.js → CodeEditor-Dv1FtkvI.js} +2 -2
- package/dist/admin/assets/{CodeEditor-Ck7ggv6w.js.map → CodeEditor-Dv1FtkvI.js.map} +1 -1
- package/dist/admin/assets/{CopyButton-WMWuSVsk.js → CopyButton-Brnpfqe0.js} +2 -2
- package/dist/admin/assets/{CopyButton-WMWuSVsk.js.map → CopyButton-Brnpfqe0.js.map} +1 -1
- package/dist/admin/assets/{CursorPager-CsnzX1P8.js → CursorPager-C7cAK5Qe.js} +2 -2
- package/dist/admin/assets/{CursorPager-CsnzX1P8.js.map → CursorPager-C7cAK5Qe.js.map} +1 -1
- package/dist/admin/assets/{FocalPoint-CstZuVmt.js → FocalPoint-Bhtb1gUa.js} +2 -2
- package/dist/admin/assets/{FocalPoint-CstZuVmt.js.map → FocalPoint-Bhtb1gUa.js.map} +1 -1
- package/dist/admin/assets/{Form-CEOW2OFF.js → Form-Cf1ephPH.js} +2 -2
- package/dist/admin/assets/{Form-CEOW2OFF.js.map → Form-Cf1ephPH.js.map} +1 -1
- package/dist/admin/assets/FormCheckboxGroup-BzVZFR3W.js +2 -0
- package/dist/admin/assets/FormCheckboxGroup-BzVZFR3W.js.map +1 -0
- package/dist/admin/assets/{FormRadioGroup-BQurJa8M.js → FormRadioGroup-BzmLzRnI.js} +2 -2
- package/dist/admin/assets/{FormRadioGroup-BQurJa8M.js.map → FormRadioGroup-BzmLzRnI.js.map} +1 -1
- package/dist/admin/assets/{FormSelectField-B4sjP-pj.js → FormSelectField-Cl7EjXc3.js} +2 -2
- package/dist/admin/assets/{FormSelectField-B4sjP-pj.js.map → FormSelectField-Cl7EjXc3.js.map} +1 -1
- package/dist/admin/assets/{FormSheet-V99zdfQe.js → FormSheet-CLZpd_7B.js} +2 -2
- package/dist/admin/assets/FormSheet-CLZpd_7B.js.map +1 -0
- package/dist/admin/assets/{FormSwitchField-RZgoP--n.js → FormSwitchField-BbqQ3tx_.js} +2 -2
- package/dist/admin/assets/{FormSwitchField-RZgoP--n.js.map → FormSwitchField-BbqQ3tx_.js.map} +1 -1
- package/dist/admin/assets/{FormTextareaField-CzXgoQzf.js → FormTextareaField-9RN5Pt3B.js} +2 -2
- package/dist/admin/assets/{FormTextareaField-CzXgoQzf.js.map → FormTextareaField-9RN5Pt3B.js.map} +1 -1
- package/dist/admin/assets/{HintedLabel-Cd9nuSqV.js → HintedLabel-D9IVF0EE.js} +2 -2
- package/dist/admin/assets/{HintedLabel-Cd9nuSqV.js.map → HintedLabel-D9IVF0EE.js.map} +1 -1
- package/dist/admin/assets/{InfoHint-ymRmHKMr.js → InfoHint-tlSeZB9U.js} +2 -2
- package/dist/admin/assets/{InfoHint-ymRmHKMr.js.map → InfoHint-tlSeZB9U.js.map} +1 -1
- package/dist/admin/assets/{InlineConfirm-A4IqkrGp.js → InlineConfirm-Kj9AOIFO.js} +2 -2
- package/dist/admin/assets/{InlineConfirm-A4IqkrGp.js.map → InlineConfirm-Kj9AOIFO.js.map} +1 -1
- package/dist/admin/assets/{InsertMenuItem-Bf7S7qbm.js → InsertMenuItem-CHAp2tH7.js} +2 -2
- package/dist/admin/assets/{InsertMenuItem-Bf7S7qbm.js.map → InsertMenuItem-CHAp2tH7.js.map} +1 -1
- package/dist/admin/assets/{Match-DJq8wn3e.js → Match-BfNRwPfR.js} +2 -2
- package/dist/admin/assets/{Match-DJq8wn3e.js.map → Match-BfNRwPfR.js.map} +1 -1
- package/dist/admin/assets/{NoAccess-CZufdbPI.js → NoAccess-DnEpYj9l.js} +2 -2
- package/dist/admin/assets/{NoAccess-CZufdbPI.js.map → NoAccess-DnEpYj9l.js.map} +1 -1
- package/dist/admin/assets/Panel-Bcl09TtM.js.map +1 -1
- package/dist/admin/assets/{QueryView-DO9TFWYE.js → QueryView-B86NcRt5.js} +2 -2
- package/dist/admin/assets/{QueryView-DO9TFWYE.js.map → QueryView-B86NcRt5.js.map} +1 -1
- package/dist/admin/assets/{RadioTile-DmKBFkpy.js → RadioTile-Bwd2Pmlk.js} +2 -2
- package/dist/admin/assets/RadioTile-Bwd2Pmlk.js.map +1 -0
- package/dist/admin/assets/{RichTextField-BpxyusP4.js → RichTextField-Dou79MHF.js} +2 -2
- package/dist/admin/assets/RichTextField-Dou79MHF.js.map +1 -0
- package/dist/admin/assets/{RowTitle-DVOfgxOd.js → RowTitle-DH9OZs3g.js} +2 -2
- package/dist/admin/assets/{RowTitle-DVOfgxOd.js.map → RowTitle-DH9OZs3g.js.map} +1 -1
- package/dist/admin/assets/{SecretReveal-DRCqVEFF.js → SecretReveal-D95oACLj.js} +2 -2
- package/dist/admin/assets/{SecretReveal-DRCqVEFF.js.map → SecretReveal-D95oACLj.js.map} +1 -1
- package/dist/admin/assets/{SharedGlyph-nsXJPCew.js → SharedGlyph-Chwb1EIS.js} +2 -2
- package/dist/admin/assets/{SharedGlyph-nsXJPCew.js.map → SharedGlyph-Chwb1EIS.js.map} +1 -1
- package/dist/admin/assets/{StepList-CDZPRd3-.js → StepList-D9iHsUZJ.js} +2 -2
- package/dist/admin/assets/StepList-D9iHsUZJ.js.map +1 -0
- package/dist/admin/assets/Structure-CewJL1b3.js +2 -0
- package/dist/admin/assets/{Structure-CL51Bvbm.js.map → Structure-CewJL1b3.js.map} +1 -1
- package/dist/admin/assets/SubNavLink-7Cs1LqMv.js.map +1 -1
- package/dist/admin/assets/{SuggestAltButton-4SaZQOJu.js → SuggestAltButton-BK1uo4yC.js} +2 -2
- package/dist/admin/assets/{SuggestAltButton-4SaZQOJu.js.map → SuggestAltButton-BK1uo4yC.js.map} +1 -1
- package/dist/admin/assets/{Thumbnail-DauHAkh8.js → Thumbnail-C2A_Ub77.js} +2 -2
- package/dist/admin/assets/{Thumbnail-DauHAkh8.js.map → Thumbnail-C2A_Ub77.js.map} +1 -1
- package/dist/admin/assets/{Trans-B3UWiZaU.js → Trans-CPoNNUK1.js} +2 -2
- package/dist/admin/assets/{Trans-B3UWiZaU.js.map → Trans-CPoNNUK1.js.map} +1 -1
- package/dist/admin/assets/{UnsavedChangesGuard-DPgih7BX.js → UnsavedChangesGuard-BsEyn9oH.js} +2 -2
- package/dist/admin/assets/{UnsavedChangesGuard-DPgih7BX.js.map → UnsavedChangesGuard-BsEyn9oH.js.map} +1 -1
- package/dist/admin/assets/{UserAvatar-If-zlQNY.js → UserAvatar-CgGKOFfP.js} +2 -2
- package/dist/admin/assets/{UserAvatar-If-zlQNY.js.map → UserAvatar-CgGKOFfP.js.map} +1 -1
- package/dist/admin/assets/{badge-DEe9tqLS.js → badge-DGqA_yr_.js} +2 -2
- package/dist/admin/assets/{badge-DEe9tqLS.js.map → badge-DGqA_yr_.js.map} +1 -1
- package/dist/admin/assets/baseExtensions-TVKN1UwW.js.map +1 -1
- package/dist/admin/assets/{changeSets-D5i2SgFV.js → changeSets-B6HxCJ4A.js} +2 -2
- package/dist/admin/assets/{changeSets-D5i2SgFV.js.map → changeSets-B6HxCJ4A.js.map} +1 -1
- package/dist/admin/assets/cn-DVhJ55Mo.js.map +1 -1
- package/dist/admin/assets/{constants-FKg_ke3y.js → constants-DY3YJAKH.js} +2 -2
- package/dist/admin/assets/{constants-FKg_ke3y.js.map → constants-DY3YJAKH.js.map} +1 -1
- package/dist/admin/assets/content-BNZF26Ve.js +3 -0
- package/dist/admin/assets/content-BNZF26Ve.js.map +1 -0
- package/dist/admin/assets/{contentTypes-B5taZv3y.js → contentTypes-Bz2xpqGf.js} +2 -2
- package/dist/admin/assets/{contentTypes-B5taZv3y.js.map → contentTypes-Bz2xpqGf.js.map} +1 -1
- package/dist/admin/assets/createLucideIcon-BOsNKleB.js.map +1 -1
- package/dist/admin/assets/{develop-CFlv7IdP.js → develop-D6CtwuYj.js} +2 -2
- package/dist/admin/assets/develop-D6CtwuYj.js.map +1 -0
- package/dist/admin/assets/{dropdown-menu-B7dJyA8h.js → dropdown-menu-Bz7CLcRK.js} +2 -2
- package/dist/admin/assets/{dropdown-menu-B7dJyA8h.js.map → dropdown-menu-Bz7CLcRK.js.map} +1 -1
- package/dist/admin/assets/es2015-Cv57ynE1.js +42 -0
- package/dist/admin/assets/es2015-Cv57ynE1.js.map +1 -0
- package/dist/admin/assets/{field-BDCHXkZE.js → field-D-xWW2E7.js} +2 -2
- package/dist/admin/assets/{field-BDCHXkZE.js.map → field-D-xWW2E7.js.map} +1 -1
- package/dist/admin/assets/{fileRoute-c9UMUr9b.js → fileRoute-DMal-zYL.js} +2 -2
- package/dist/admin/assets/{fileRoute-c9UMUr9b.js.map → fileRoute-DMal-zYL.js.map} +1 -1
- package/dist/admin/assets/{followPlural-CHpz-yo4.js → followPlural-CsgeALTW.js} +2 -2
- package/dist/admin/assets/{followPlural-CHpz-yo4.js.map → followPlural-CsgeALTW.js.map} +1 -1
- package/dist/admin/assets/{inbox-Daw10v5C.js → inbox-C0PVc6UI.js} +2 -2
- package/dist/admin/assets/{inbox-Daw10v5C.js.map → inbox-C0PVc6UI.js.map} +1 -1
- package/dist/admin/assets/{index-BRx5mel0.js → index-BqtCXB0u.js} +4 -4
- package/dist/admin/assets/{index-BRx5mel0.js.map → index-BqtCXB0u.js.map} +1 -1
- package/dist/admin/assets/{labels-B83cEX9w.js → labels-BtktCNGw.js} +2 -2
- package/dist/admin/assets/{labels-B83cEX9w.js.map → labels-BtktCNGw.js.map} +1 -1
- package/dist/admin/assets/{media-CgxriwNL.js → media-CeZGDGh7.js} +2 -2
- package/dist/admin/assets/{media-CgxriwNL.js.map → media-CeZGDGh7.js.map} +1 -1
- package/dist/admin/assets/{network-Cc1TAyal.js → network-BflLSKFO.js} +2 -2
- package/dist/admin/assets/{network-Cc1TAyal.js.map → network-BflLSKFO.js.map} +1 -1
- package/dist/admin/assets/publishing-BkxBplUZ.js +2 -0
- package/dist/admin/assets/publishing-BkxBplUZ.js.map +1 -0
- package/dist/admin/assets/{radio-group-Btmx7dlD.js → radio-group-CRuWQnuV.js} +2 -2
- package/dist/admin/assets/{radio-group-Btmx7dlD.js.map → radio-group-CRuWQnuV.js.map} +1 -1
- package/dist/admin/assets/schema-6eUoC8fJ.js +2 -0
- package/dist/admin/assets/schema-6eUoC8fJ.js.map +1 -0
- package/dist/admin/assets/{searchSchemas-fO_49fDI.js → searchSchemas-DAnwh3I3.js} +2 -2
- package/dist/admin/assets/{searchSchemas-fO_49fDI.js.map → searchSchemas-DAnwh3I3.js.map} +1 -1
- package/dist/admin/assets/{sections-SX-oiQoE.js → sections-CWL-XD6m.js} +2 -2
- package/dist/admin/assets/sections-CWL-XD6m.js.map +1 -0
- package/dist/admin/assets/{select-JB2Vv7ep.js → select-DVrPV1b3.js} +2 -2
- package/dist/admin/assets/{select-JB2Vv7ep.js.map → select-DVrPV1b3.js.map} +1 -1
- package/dist/admin/assets/{settings-CrRFxhSo.js → settings-CqnrPmzR.js} +2 -2
- package/dist/admin/assets/{settings-CrRFxhSo.js.map → settings-CqnrPmzR.js.map} +1 -1
- package/dist/admin/assets/{shapes-EMjfYsXV.js → shapes-ZAkMBB-Z.js} +4 -4
- package/dist/admin/assets/shapes-ZAkMBB-Z.js.map +1 -0
- package/dist/admin/assets/{skeleton-Dk-qdg0z.js → skeleton-CiX26LnL.js} +2 -2
- package/dist/admin/assets/{skeleton-Dk-qdg0z.js.map → skeleton-CiX26LnL.js.map} +1 -1
- package/dist/admin/assets/src-CMor9izq.js.map +1 -1
- package/dist/admin/assets/{switch-DyCRGDs7.js → switch-CiVf05NF.js} +2 -2
- package/dist/admin/assets/{switch-DyCRGDs7.js.map → switch-CiVf05NF.js.map} +1 -1
- package/dist/admin/assets/theme-Cv-MfOv8.js.map +1 -1
- package/dist/admin/assets/{tooltip-CCOeMqiL.js → tooltip-Bqf3oyqC.js} +2 -2
- package/dist/admin/assets/{tooltip-CCOeMqiL.js.map → tooltip-Bqf3oyqC.js.map} +1 -1
- package/dist/admin/assets/{useContentSchema-uXOfT985.js → useContentSchema-B_q1rMrG.js} +2 -2
- package/dist/admin/assets/{useContentSchema-uXOfT985.js.map → useContentSchema-B_q1rMrG.js.map} +1 -1
- package/dist/admin/assets/useCursorPager-BHYqHb3M.js.map +1 -1
- package/dist/admin/assets/{useDiscardGuard-DvBI3VIz.js → useDiscardGuard-C4QTfiU4.js} +2 -2
- package/dist/admin/assets/{useDiscardGuard-DvBI3VIz.js.map → useDiscardGuard-C4QTfiU4.js.map} +1 -1
- package/dist/admin/assets/{useMediaPickerDialog-CehOsykG.js → useMediaPickerDialog-BLrVV1Kn.js} +2 -2
- package/dist/admin/assets/{useMediaPickerDialog-CehOsykG.js.map → useMediaPickerDialog-BLrVV1Kn.js.map} +1 -1
- package/dist/admin/assets/{useMediaUploader-DvtxYXxD.js → useMediaUploader-CFy6lasO.js} +2 -2
- package/dist/admin/assets/useMediaUploader-CFy6lasO.js.map +1 -0
- package/dist/admin/assets/{useModelIndex-D8Q0oM4M.js → useModelIndex-NU-WlHQY.js} +2 -2
- package/dist/admin/assets/{useModelIndex-D8Q0oM4M.js.map → useModelIndex-NU-WlHQY.js.map} +1 -1
- package/dist/admin/assets/{usePlaces-CySN2Vwz.js → usePlaces-BA4x6503.js} +2 -2
- package/dist/admin/assets/{usePlaces-CySN2Vwz.js.map → usePlaces-BA4x6503.js.map} +1 -1
- package/dist/admin/assets/{useResolvedDefinitions-C279ueCH.js → useResolvedDefinitions-30lnwFQ1.js} +2 -2
- package/dist/admin/assets/{useResolvedDefinitions-C279ueCH.js.map → useResolvedDefinitions-30lnwFQ1.js.map} +1 -1
- package/dist/admin/assets/{useResolvedScheme-DEq7P4R5.js → useResolvedScheme-BVM4qLct.js} +2 -2
- package/dist/admin/assets/{useResolvedScheme-DEq7P4R5.js.map → useResolvedScheme-BVM4qLct.js.map} +1 -1
- package/dist/admin/assets/{zod-vPzaNsuW.js → zod-ZaQjjiAq.js} +2 -2
- package/dist/admin/assets/{zod-vPzaNsuW.js.map → zod-ZaQjjiAq.js.map} +1 -1
- package/dist/admin/index.html +29 -29
- package/dist/cli.js +1 -1
- package/dist/{cliMain-DzBXO7Oa.js → cliMain-CTntiVc2.js} +11 -11
- package/dist/cliMain-CTntiVc2.js.map +1 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/{contentDisposition-DOL2Xt0l.js → contentDisposition-DzhPhncr.js} +2 -2
- package/dist/{contentDisposition-DOL2Xt0l.js.map → contentDisposition-DzhPhncr.js.map} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{public-jttKsns_.d.ts → public-CMFaGDyf.d.ts} +4 -4
- package/dist/{public-B57h4F7Y.js → public-sJCQaNaP.js} +2 -2
- package/dist/{public-B57h4F7Y.js.map → public-sJCQaNaP.js.map} +1 -1
- package/dist/{s3Adapter-U01iEAcK.js → s3Adapter-CZcCl0sy.js} +2 -2
- package/dist/{s3Adapter-U01iEAcK.js.map → s3Adapter-CZcCl0sy.js.map} +1 -1
- package/dist/{worker-6ru1tYBs.js → worker-DHm2JwMZ.js} +353 -232
- package/dist/worker-DHm2JwMZ.js.map +1 -0
- package/package.json +5 -5
- package/dist/admin/assets/Body-BEW1sAAB.js.map +0 -1
- package/dist/admin/assets/Builder-Tk_5Orrl.js +0 -2
- package/dist/admin/assets/Builder-Tk_5Orrl.js.map +0 -1
- package/dist/admin/assets/FormCheckboxGroup-VjWVMiF3.js +0 -2
- package/dist/admin/assets/FormCheckboxGroup-VjWVMiF3.js.map +0 -1
- package/dist/admin/assets/FormSheet-V99zdfQe.js.map +0 -1
- package/dist/admin/assets/RadioTile-DmKBFkpy.js.map +0 -1
- package/dist/admin/assets/RichTextField-BpxyusP4.js.map +0 -1
- package/dist/admin/assets/StepList-CDZPRd3-.js.map +0 -1
- package/dist/admin/assets/Structure-CL51Bvbm.js +0 -2
- package/dist/admin/assets/content-DKT2ziPH.js +0 -3
- package/dist/admin/assets/content-DKT2ziPH.js.map +0 -1
- package/dist/admin/assets/develop-CFlv7IdP.js.map +0 -1
- package/dist/admin/assets/es2015-1nJWBurR.js +0 -42
- package/dist/admin/assets/es2015-1nJWBurR.js.map +0 -1
- package/dist/admin/assets/publishing-RQUj-CyN.js +0 -2
- package/dist/admin/assets/publishing-RQUj-CyN.js.map +0 -1
- package/dist/admin/assets/schema-BMQEabwO.js +0 -2
- package/dist/admin/assets/schema-BMQEabwO.js.map +0 -1
- package/dist/admin/assets/sections-SX-oiQoE.js.map +0 -1
- package/dist/admin/assets/shapes-EMjfYsXV.js.map +0 -1
- package/dist/admin/assets/useMediaUploader-DvtxYXxD.js.map +0 -1
- package/dist/cliMain-DzBXO7Oa.js.map +0 -1
- package/dist/worker-6ru1tYBs.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as buildAssetKey, c as isValidStorageKey, d as withVisibility, i as ObjectNotFoundError, l as sanitizeFilename, n as contentDisposition, o as buildVariantKey, r as InvalidStorageKeyError, s as encodeKeyPath, u as visibilityOfKey } from "./contentDisposition-
|
|
2
|
-
import { i as isHookError, n as HookError } from "./public-
|
|
1
|
+
import { a as buildAssetKey, c as isValidStorageKey, d as withVisibility, i as ObjectNotFoundError, l as sanitizeFilename, n as contentDisposition, o as buildVariantKey, r as InvalidStorageKeyError, s as encodeKeyPath, u as visibilityOfKey } from "./contentDisposition-DzhPhncr.js";
|
|
2
|
+
import { i as isHookError, n as HookError } from "./public-sJCQaNaP.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { createCipheriv, createDecipheriv, createHash, createHmac, hkdfSync, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
5
5
|
import { closeSync, createReadStream, createWriteStream, existsSync, openSync, readFileSync, statSync } from "node:fs";
|
|
@@ -2065,7 +2065,7 @@ const REFUSES_UPDATES = /* @__PURE__ */ new Set(["content_revisions", "schema_re
|
|
|
2065
2065
|
const targetOf = (conflict) => conflict.columns?.map((column) => column.column.name);
|
|
2066
2066
|
/**
|
|
2067
2067
|
* `ON CONFLICT … DO UPDATE` as `ON DUPLICATE KEY UPDATE`, and `ON CONFLICT … DO NOTHING` without RETURNING
|
|
2068
|
-
* as `ON DUPLICATE KEY UPDATE <key> = <key>` (a no-op), when MySQL's any-key
|
|
2068
|
+
* as `ON DUPLICATE KEY UPDATE <key> = <key>` (a no-op), when MySQL's any-key behavior equals the target's
|
|
2069
2069
|
* (`duplicateKeyMatchesTarget`). Any other conflict clause (another unique key could fire, a `WHERE` on the
|
|
2070
2070
|
* update, RETURNING) is left for the compiler's plan: each row inserted under a savepoint, and a duplicate
|
|
2071
2071
|
* on the target either skipped or turned into an UPDATE of the row it found.
|
|
@@ -2277,7 +2277,7 @@ const insertPlan = (node, compile) => {
|
|
|
2277
2277
|
/**
|
|
2278
2278
|
* Subquery shapes MySQL rejects, rewritten (ADR 0001, "MySQL"): `IN (… LIMIT n)` (error 1235) and a subquery
|
|
2279
2279
|
* reading the table an UPDATE, DELETE or INSERT writes (error 1093) read a derived table instead, which MySQL
|
|
2280
|
-
*
|
|
2280
|
+
* materializes first; PostgreSQL's `UPDATE … FROM` becomes a multi-table UPDATE.
|
|
2281
2281
|
*/
|
|
2282
2282
|
/** The alias of a derived table wrapped around a subquery. */
|
|
2283
2283
|
const DERIVED_ALIAS = "shapio_derived";
|
|
@@ -2287,7 +2287,7 @@ const tableNameOf$1 = (node) => node && TableNode.is(node) ? node.table.identifi
|
|
|
2287
2287
|
* reads `table`, the target of the enclosing UPDATE, DELETE or INSERT (error 1093).
|
|
2288
2288
|
*/
|
|
2289
2289
|
const needsDerivedTable = (node, table) => node.limit !== void 0 || table !== void 0 && ((node.from?.froms ?? []).some((item) => tableNameOf$1(AliasNode.is(item) ? item.node : item) === table) || (node.joins ?? []).some((join) => tableNameOf$1(AliasNode.is(join.table) ? join.table.node : join.table) === table));
|
|
2290
|
-
/** `(select * from (<subquery>) as shapio_derived)`: MySQL
|
|
2290
|
+
/** `(select * from (<subquery>) as shapio_derived)`: MySQL materializes it first. */
|
|
2291
2291
|
const derived = (node) => Object.freeze({
|
|
2292
2292
|
...SelectQueryNode.createFrom([AliasNode.create(node, IdentifierNode.create(DERIVED_ALIAS))]),
|
|
2293
2293
|
selections: [SelectionNode.create(SelectAllNode.create())]
|
|
@@ -2317,7 +2317,7 @@ var DerivedTableWrapper = class extends OperationNodeTransformer {
|
|
|
2317
2317
|
const wrapSubqueries = (where, table) => where ? new DerivedTableWrapper(table).transformNode(where) : where;
|
|
2318
2318
|
/**
|
|
2319
2319
|
* An INSERT whose VALUES read the target table in a scalar subquery (`coalesce(max(position) + 1, 0)`):
|
|
2320
|
-
* MySQL rejects that (error 1093) unless the subquery reads a derived table, which it
|
|
2320
|
+
* MySQL rejects that (error 1093) unless the subquery reads a derived table, which it materializes first.
|
|
2321
2321
|
*/
|
|
2322
2322
|
const withDerivedValueSubqueries = (node) => {
|
|
2323
2323
|
const table = node.into?.table.identifier.name;
|
|
@@ -2494,7 +2494,7 @@ var ShapioMysqlQueryCompiler = class ShapioMysqlQueryCompiler extends MysqlQuery
|
|
|
2494
2494
|
//#endregion
|
|
2495
2495
|
//#region src/db/notifyHub.ts
|
|
2496
2496
|
/**
|
|
2497
|
-
* In-process notification delivery (ADR 0002 notes notifications are an
|
|
2497
|
+
* In-process notification delivery (ADR 0002 notes notifications are an optimization; consumers also check
|
|
2498
2498
|
* a durable version): an event bus per database. Every handle on the same database in this process shares
|
|
2499
2499
|
* one bus, so two app instances in one test process still hear each other.
|
|
2500
2500
|
* - SQLite: the only delivery (SQLite deployments are single-process).
|
|
@@ -2880,7 +2880,7 @@ var MysqlDriver = class {
|
|
|
2880
2880
|
this.#pool = pool;
|
|
2881
2881
|
}
|
|
2882
2882
|
#pooled() {
|
|
2883
|
-
if (!this.#pool) throw new Error("The MySQL driver is not
|
|
2883
|
+
if (!this.#pool) throw new Error("The MySQL driver is not initialized");
|
|
2884
2884
|
return this.#pool;
|
|
2885
2885
|
}
|
|
2886
2886
|
/**
|
|
@@ -3044,7 +3044,7 @@ const ISO_TIMESTAMP = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}/;
|
|
|
3044
3044
|
*/
|
|
3045
3045
|
const timestampText = (value) => typeof value === "string" && ISO_TIMESTAMP.test(value) ? toDatetimeText(value) : value;
|
|
3046
3046
|
const isTimestampColumn = (table, column) => table !== void 0 && (tableInfo(table)?.timestamps ?? []).includes(column);
|
|
3047
|
-
/** A value node (or primitive list) bound to a timestamp column, with ISO text
|
|
3047
|
+
/** A value node (or primitive list) bound to a timestamp column, with ISO text normalized. */
|
|
3048
3048
|
const timestampValue = (node) => {
|
|
3049
3049
|
if (ValueNode.is(node)) {
|
|
3050
3050
|
const value = timestampText(node.value);
|
|
@@ -3053,7 +3053,7 @@ const timestampValue = (node) => {
|
|
|
3053
3053
|
if (PrimitiveValueListNode.is(node)) return PrimitiveValueListNode.create(node.values.map(timestampText));
|
|
3054
3054
|
return node;
|
|
3055
3055
|
};
|
|
3056
|
-
/** Insert rows with ISO text for timestamp columns
|
|
3056
|
+
/** Insert rows with ISO text for timestamp columns normalized. */
|
|
3057
3057
|
const withTimestampValues = (node) => {
|
|
3058
3058
|
const table = node.into?.table.identifier.name;
|
|
3059
3059
|
const positions = (node.columns?.map((column) => column.column.name) ?? []).flatMap((column, index) => isTimestampColumn(table, column) ? [index] : []);
|
|
@@ -3172,7 +3172,7 @@ const decodeRow = (row, markers) => {
|
|
|
3172
3172
|
* Adapts Kysely queries written for PostgreSQL to MySQL (dialect boundary, ADR 0001, "MySQL"). Rewrites that
|
|
3173
3173
|
* stay one statement happen here; statements MySQL cannot run as one (`RETURNING`, most `ON CONFLICT`) are
|
|
3174
3174
|
* planned by the compiler (`plans.ts`). This plugin:
|
|
3175
|
-
* - fills the columns PostgreSQL defaults that MySQL cannot, and
|
|
3175
|
+
* - fills the columns PostgreSQL defaults that MySQL cannot, and normalizes ISO text bound to timestamp
|
|
3176
3176
|
* columns (`insertValues.ts`);
|
|
3177
3177
|
* - spells casts MySQL's way (`text` → `char`, `bigint`/`integer` → `signed`) and maps row locks MySQL lacks;
|
|
3178
3178
|
* - keeps PostgreSQL's NULL placement in ORDER BY (`nullOrdering.ts`);
|
|
@@ -3393,7 +3393,7 @@ const currentTimestamp = () => {
|
|
|
3393
3393
|
};
|
|
3394
3394
|
/**
|
|
3395
3395
|
* A bound value read as a timestamp (ISO-8601 text or a Date; null stays null).
|
|
3396
|
-
* PostgreSQL: `cast($1 as timestamptz)`. SQLite: the value
|
|
3396
|
+
* PostgreSQL: `cast($1 as timestamptz)`. SQLite: the value normalized by `toStoredTimestamp` and bound.
|
|
3397
3397
|
* MySQL: `cast($1 as datetime(6))` with UTC `DATETIME` text (ISO text keeps its microseconds).
|
|
3398
3398
|
* Contract: compares and sorts against timestamp columns as an instant, at the precision the text carries
|
|
3399
3399
|
* (microseconds from `timestampCursorText` on PostgreSQL, milliseconds on SQLite).
|
|
@@ -3918,7 +3918,7 @@ const indexExpressionSql = (index) => index.columns.map((column) => index.nullab
|
|
|
3918
3918
|
const nullsNotDistinctIndexFor = (table, columns) => NULLS_NOT_DISTINCT_INDEXES.find((index) => index.table === table && index.columns.length === columns.length && index.columns.every((column) => columns.includes(column)));
|
|
3919
3919
|
//#endregion
|
|
3920
3920
|
//#region src/db/sqlite/plugin.ts
|
|
3921
|
-
/** Row-lock modifiers PostgreSQL needs and SQLite rejects; its write transactions are already
|
|
3921
|
+
/** Row-lock modifiers PostgreSQL needs and SQLite rejects; its write transactions are already serialized. */
|
|
3922
3922
|
const ROW_LOCKS = /* @__PURE__ */ new Set([
|
|
3923
3923
|
"ForUpdate",
|
|
3924
3924
|
"ForNoKeyUpdate",
|
|
@@ -4102,7 +4102,7 @@ const OPTIMIZE = {
|
|
|
4102
4102
|
};
|
|
4103
4103
|
/**
|
|
4104
4104
|
* A Kysely driver over Node's built-in `node:sqlite` (no native dependency). One writer connection runs
|
|
4105
|
-
* every write,
|
|
4105
|
+
* every write, serialized by an in-process lock (`writeLock.ts`, `BEGIN IMMEDIATE`); reader connections
|
|
4106
4106
|
* serve read-only transactions and autocommit reads concurrently (WAL). An in-memory database has the
|
|
4107
4107
|
* writer only, and every statement takes the lock.
|
|
4108
4108
|
*/
|
|
@@ -4331,7 +4331,7 @@ var SqliteSession = class {
|
|
|
4331
4331
|
//#region src/db/sqlite/index.ts
|
|
4332
4332
|
/**
|
|
4333
4333
|
* SQLite runs DDL inside transactions, so each migration commits or rolls back whole. The driver handles
|
|
4334
|
-
* concurrency itself (one writer, several readers), so Kysely must not
|
|
4334
|
+
* concurrency itself (one writer, several readers), so Kysely must not serialize connections on top.
|
|
4335
4335
|
*/
|
|
4336
4336
|
var ShapioSqliteAdapter = class extends SqliteAdapter {
|
|
4337
4337
|
get supportsTransactionalDdl() {
|
|
@@ -5260,11 +5260,11 @@ const richTextMediaIds = (document) => {
|
|
|
5260
5260
|
return [...ids];
|
|
5261
5261
|
};
|
|
5262
5262
|
//#endregion
|
|
5263
|
-
//#region ../../packages/schema/dist/resolve-
|
|
5263
|
+
//#region ../../packages/schema/dist/resolve-Csjpkpue.js
|
|
5264
5264
|
/**
|
|
5265
5265
|
* The built-in SEO component (plan seo-fields). It is ordinary schema data, created through the change planner
|
|
5266
5266
|
* and always shared with every site; what makes it "the" SEO component is its stable ID, never its API ID, so
|
|
5267
|
-
* a renamed or extended copy is still
|
|
5267
|
+
* a renamed or extended copy is still recognized and an unrelated `seo` component (an import) never is.
|
|
5268
5268
|
*/
|
|
5269
5269
|
const SEO_COMPONENT_ID = "f3905a00-d2a3-4c62-899a-c894bfd6cb9b";
|
|
5270
5270
|
/** Stable field IDs of the built-in's fields. Resolver and admin look fields up by these. */
|
|
@@ -6297,7 +6297,7 @@ const entries = [
|
|
|
6297
6297
|
optionsSchema: Type.Object({ collapsed: Type.Optional(Type.Boolean()) }, closed$1$1)
|
|
6298
6298
|
}
|
|
6299
6299
|
];
|
|
6300
|
-
const
|
|
6300
|
+
const EDITOR_CATALOG = new Map(entries.map((entry) => [entry.id, entry]));
|
|
6301
6301
|
/** The editor a field gets when its definition names none. */
|
|
6302
6302
|
const DEFAULT_EDITORS = {
|
|
6303
6303
|
string: "textInput",
|
|
@@ -7167,7 +7167,7 @@ const checkFlags = (field, path, isComponent) => {
|
|
|
7167
7167
|
const checkEditor = (field, path) => {
|
|
7168
7168
|
const { id, options } = field.editor;
|
|
7169
7169
|
if (isCustomEditorId(id)) return [];
|
|
7170
|
-
const entry =
|
|
7170
|
+
const entry = EDITOR_CATALOG.get(id);
|
|
7171
7171
|
if (!entry) return [issue$1(`${path}/editor/id`, "UNKNOWN_EDITOR", `"${id}" is not a built-in editor (custom editors use a vendor.name ID)`)];
|
|
7172
7172
|
if (!entry.dataTypes.includes(field.type) || !(entry.supports?.(field) ?? true)) return [issue$1(`${path}/editor/id`, "INCOMPATIBLE_EDITOR", `the ${id} editor cannot edit this ${field.type} field`)];
|
|
7173
7173
|
return collectSchemaErrors(entry.optionsSchema, options, `${path}/editor/options`).map((error) => issue$1(error.path, "INVALID_EDITOR_OPTIONS", error.message));
|
|
@@ -8544,11 +8544,11 @@ const BUILT_IN_THEME_KEYS = [
|
|
|
8544
8544
|
"butter"
|
|
8545
8545
|
];
|
|
8546
8546
|
/**
|
|
8547
|
-
* A token value an extension may use: a hex
|
|
8547
|
+
* A token value an extension may use: a hex color or a color function whose arguments are numbers, units
|
|
8548
8548
|
* and separators only (no `;`, quotes, braces or nested functions such as `url()` or `var()`), so a value
|
|
8549
8549
|
* can never escape its declaration.
|
|
8550
8550
|
*/
|
|
8551
|
-
const
|
|
8551
|
+
const THEME_COLOR_PATTERN = /^(?:#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|(?:rgba?|hsla?|oklch|oklab)\([0-9a-z.,%\s/+-]{1,80}\))$/;
|
|
8552
8552
|
const SURFACES = [
|
|
8553
8553
|
"background",
|
|
8554
8554
|
"card",
|
|
@@ -8631,7 +8631,7 @@ const luminance = (hex) => {
|
|
|
8631
8631
|
].map((index) => channel(parseInt(hex.slice(index, index + 2), 16)));
|
|
8632
8632
|
return .2126 * (r ?? 0) + .7152 * (g ?? 0) + .0722 * (b ?? 0);
|
|
8633
8633
|
};
|
|
8634
|
-
/** The WCAG contrast ratio of two `#rrggbb`
|
|
8634
|
+
/** The WCAG contrast ratio of two `#rrggbb` colors. */
|
|
8635
8635
|
const contrastRatio = (a, b) => {
|
|
8636
8636
|
const [high = 0, low = 0] = [luminance(a), luminance(b)].sort((x, y) => y - x);
|
|
8637
8637
|
return (high + .05) / (low + .05);
|
|
@@ -8844,7 +8844,7 @@ const purgeDeletedEntriesOfModels = async (modelIds, trx) => {
|
|
|
8844
8844
|
/**
|
|
8845
8845
|
* The publication sequence and log behind `?snapshot=N` (ADR 0001). The sequence is one row incremented
|
|
8846
8846
|
* inside each publishing transaction: its row lock orders publications by commit, so a reader that sees N
|
|
8847
|
-
* also sees every publication before N. Take it as late as possible in the transaction (it
|
|
8847
|
+
* also sees every publication before N. Take it as late as possible in the transaction (it serializes every
|
|
8848
8848
|
* publication instance-wide until commit), and never ahead of the transaction that uses it.
|
|
8849
8849
|
*
|
|
8850
8850
|
* Every number also gets a `publication_snapshots` ledger row (why, who, the schema version live with it),
|
|
@@ -9032,7 +9032,7 @@ const purgeDefinitions = async (ids, trx = db) => {
|
|
|
9032
9032
|
await trx.deleteFrom("models").where("id", "in", ids).execute();
|
|
9033
9033
|
};
|
|
9034
9034
|
/**
|
|
9035
|
-
* Keeps the
|
|
9035
|
+
* Keeps the denormalized kind, API key and scope in step with the active revision; also undeletes. The scope
|
|
9036
9036
|
* only differs from the stored one for a scope change (`ActivationItem.moveScope`).
|
|
9037
9037
|
*/
|
|
9038
9038
|
const markModelActive = (model, trx = db) => trx.updateTable("models").set({
|
|
@@ -9305,7 +9305,7 @@ const sleep = (ms, signal) => new Promise((resolve) => {
|
|
|
9305
9305
|
//#region src/db/sqlite/keyedMutex.ts
|
|
9306
9306
|
/**
|
|
9307
9307
|
* An in-process mutex per key: SQLite's stand-in for PostgreSQL session advisory locks (migrations, index
|
|
9308
|
-
* builds). It
|
|
9308
|
+
* builds). It serializes holders inside one process only; SQLite deployments are single-process.
|
|
9309
9309
|
*/
|
|
9310
9310
|
const TAILS = /* @__PURE__ */ new Map();
|
|
9311
9311
|
/** Runs `fn` while holding the lock for `key`; waiters run in arrival order. */
|
|
@@ -9417,10 +9417,10 @@ const acquireXactLockShared = async (trx, namespace, key) => {
|
|
|
9417
9417
|
//#endregion
|
|
9418
9418
|
//#region src/schema/planner/locks.ts
|
|
9419
9419
|
/**
|
|
9420
|
-
*
|
|
9420
|
+
* Serializes every schema activation (and the start of every planned change) instance-wide. Activations are
|
|
9421
9421
|
* rare, and holding this lock while re-validating the whole schema closes races between changes to
|
|
9422
9422
|
* *different* definitions (e.g. two renames to colliding GraphQL names). It lives in the model namespace;
|
|
9423
|
-
* a collision with a model's hash only costs extra
|
|
9423
|
+
* a collision with a model's hash only costs extra serialization.
|
|
9424
9424
|
*/
|
|
9425
9425
|
const SCHEMA_ACTIVATION_LOCK_KEY = lockKeyFromId("shapio:schema-activation");
|
|
9426
9426
|
/**
|
|
@@ -10879,7 +10879,7 @@ const MEDIA_PROCESS_JOB = "media.process";
|
|
|
10879
10879
|
const MEDIA_PURGE_JOB = "media.purge";
|
|
10880
10880
|
const MEDIA_RELOCATE_JOB = "media.relocate";
|
|
10881
10881
|
const MEDIA_GRANT_EXPIRE_JOB = "media.grant.expire";
|
|
10882
|
-
/** Outbox event types (webhook
|
|
10882
|
+
/** Outbox event types (webhook catalog `media.*`, package H). */
|
|
10883
10883
|
const MEDIA_EVENTS = {
|
|
10884
10884
|
created: "media.created",
|
|
10885
10885
|
updated: "media.updated",
|
|
@@ -12884,7 +12884,7 @@ const getOwnerRoleId = async (trx) => {
|
|
|
12884
12884
|
const isOwnerActor = (actor, ownerRoleId) => actor.kind === "system" || actor.kind === "admin" && actor.networkRoleIds.includes(ownerRoleId);
|
|
12885
12885
|
/**
|
|
12886
12886
|
* Inserts an admin user with role assignments (`roleIds`: those roles on every site). Shared by setup,
|
|
12887
|
-
* invitations and `shapio admin create`; the caller owns the transaction, validation,
|
|
12887
|
+
* invitations and `shapio admin create`; the caller owns the transaction, validation, authorization and
|
|
12888
12888
|
* audit.
|
|
12889
12889
|
*/
|
|
12890
12890
|
const insertAdminUser = async (input, trx) => {
|
|
@@ -12909,7 +12909,7 @@ const getAdminUser = async (id) => {
|
|
|
12909
12909
|
if (!row) throw notFound$7();
|
|
12910
12910
|
return toAdminUserView(row);
|
|
12911
12911
|
};
|
|
12912
|
-
/** Fails when no active owner other than `exceptUserId` would remain. Locks owners to
|
|
12912
|
+
/** Fails when no active owner other than `exceptUserId` would remain. Locks owners to serialize checks. */
|
|
12913
12913
|
const assertAnotherOwnerRemains = async (exceptUserId, trx) => {
|
|
12914
12914
|
if (!(await lockActiveHoldersOfRoleKey(SYSTEM_ROLE_KEYS.owner, trx)).some((owner) => owner.id !== exceptUserId)) throw new AppError(409, "LAST_OWNER", "Shapio needs at least one active owner");
|
|
12915
12915
|
};
|
|
@@ -14817,7 +14817,7 @@ const groupByRole = (grants) => {
|
|
|
14817
14817
|
* Every role's grants, held in memory and reloaded when `system_versions.permissions_version` moves.
|
|
14818
14818
|
* The version is checked on every lookup: read here, or read once by the request (`versions`, see
|
|
14819
14819
|
* `KnownVersions`). That durable check is what makes a permission change visible to every instance from the
|
|
14820
|
-
* next request (NOTIFY would only be an
|
|
14820
|
+
* next request (NOTIFY would only be an optimization). Lookups on the pool share one reload; a
|
|
14821
14821
|
* lookup inside a transaction reads (and, when stale, reloads) through that transaction alone, never
|
|
14822
14822
|
* through a reload running on another request's transaction.
|
|
14823
14823
|
*/
|
|
@@ -15414,7 +15414,7 @@ const findNamingProblems = (config) => {
|
|
|
15414
15414
|
return [...problems, ...findThemeProblems(config.themes)];
|
|
15415
15415
|
};
|
|
15416
15416
|
const BUILT_IN_THEMES = new Set(BUILT_IN_THEME_KEYS);
|
|
15417
|
-
/** Theme keys (pattern, built-in, unique), at least one variant, and
|
|
15417
|
+
/** Theme keys (pattern, built-in, unique), at least one variant, and color values (no CSS injection). */
|
|
15418
15418
|
const findThemeProblems = (themes) => {
|
|
15419
15419
|
const problems = [];
|
|
15420
15420
|
const keys = /* @__PURE__ */ new Set();
|
|
@@ -15442,9 +15442,9 @@ const findThemeProblems = (themes) => {
|
|
|
15442
15442
|
});
|
|
15443
15443
|
for (const variant of THEME_VARIANTS) {
|
|
15444
15444
|
const tokens = theme[variant];
|
|
15445
|
-
for (const [token, value] of Object.entries(isRecord$6(tokens) ? tokens : {})) if (typeof value === "string" && !
|
|
15445
|
+
for (const [token, value] of Object.entries(isRecord$6(tokens) ? tokens : {})) if (typeof value === "string" && !THEME_COLOR_PATTERN.test(value)) problems.push({
|
|
15446
15446
|
path: `${path}/${variant}/${token}`,
|
|
15447
|
-
message: `"${value}" is not a
|
|
15447
|
+
message: `"${value}" is not a color: use #rrggbb, rgb(), hsl(), oklch() or oklab()`
|
|
15448
15448
|
});
|
|
15449
15449
|
}
|
|
15450
15450
|
});
|
|
@@ -17625,7 +17625,7 @@ const themeCss = (theme) => {
|
|
|
17625
17625
|
return block(selector, tokens);
|
|
17626
17626
|
}).join("\n");
|
|
17627
17627
|
};
|
|
17628
|
-
const
|
|
17628
|
+
const buildThemeCatalog = (themes) => ({
|
|
17629
17629
|
items: themes.map((theme) => ({
|
|
17630
17630
|
key: theme.key,
|
|
17631
17631
|
name: theme.name,
|
|
@@ -17835,7 +17835,7 @@ const resolveMediaOrigins = async (storage) => {
|
|
|
17835
17835
|
const base = originOf(storage.publicBaseUrl);
|
|
17836
17836
|
if (base) origins.add(base);
|
|
17837
17837
|
if (storage.s3) {
|
|
17838
|
-
const { createS3Adapter } = await import("./s3Adapter-
|
|
17838
|
+
const { createS3Adapter } = await import("./s3Adapter-CZcCl0sy.js");
|
|
17839
17839
|
const adapter = createS3Adapter({
|
|
17840
17840
|
config: storage.s3,
|
|
17841
17841
|
publicBaseUrl: void 0
|
|
@@ -17939,7 +17939,7 @@ const LAST_SEEN_WRITE_INTERVAL_MS = 6e4;
|
|
|
17939
17939
|
const CSRF_HEADER = "x-csrf-token";
|
|
17940
17940
|
const INVITATION_TTL_MS = 6048e5;
|
|
17941
17941
|
const PASSWORD_RESET_TTL_MS = 36e5;
|
|
17942
|
-
/** API tokens carry a
|
|
17942
|
+
/** API tokens carry a recognizable prefix (secret scanners, and telling them apart from app-user JWTs). */
|
|
17943
17943
|
const API_TOKEN_PREFIX = "shp_";
|
|
17944
17944
|
/** Rate limits for unauthenticated credential endpoints. Per IP via @fastify/rate-limit route config. */
|
|
17945
17945
|
const CREDENTIAL_RATE_LIMIT_PER_IP = {
|
|
@@ -18044,7 +18044,7 @@ const isSetupRequired = async (database = db) => await countAll(database) === 0;
|
|
|
18044
18044
|
/**
|
|
18045
18045
|
* At boot, while no admin exists: supersedes any earlier setup token and issues a new one. Returns the
|
|
18046
18046
|
* token for the caller to show exactly once (it is stored only as a hash), or undefined when setup is done.
|
|
18047
|
-
*
|
|
18047
|
+
* Serialized with setup itself by the setup advisory lock.
|
|
18048
18048
|
*/
|
|
18049
18049
|
const issueSetupToken = async (database) => database.transaction().execute(async (trx) => {
|
|
18050
18050
|
await acquireXactLock(trx, LOCK_NAMESPACE.setup, 1);
|
|
@@ -18206,7 +18206,7 @@ const findSummaryByIdInSite = (id, siteId, trx = db) => summaries(trx).where("ap
|
|
|
18206
18206
|
const findByEmailWithHash = (siteId, email, trx = db) => trx.selectFrom("app_users").selectAll().where("site_id", "=", siteId).where((eb) => eb(eb.fn("lower", ["email"]), "=", email.toLowerCase())).where("deleted_at", "is", null).executeTakeFirst();
|
|
18207
18207
|
/** Includes the password hash: for credential checks only. Live (not deleted) accounts only. */
|
|
18208
18208
|
const findByIdWithHash = (id, trx = db) => trx.selectFrom("app_users").selectAll().where("id", "=", id).where("deleted_at", "is", null).executeTakeFirst();
|
|
18209
|
-
/** Locks the live account row (status changes, deletion and credential changes
|
|
18209
|
+
/** Locks the live account row (status changes, deletion and credential changes serialize on it). */
|
|
18210
18210
|
const lockById$2 = (id, trx) => trx.selectFrom("app_users").selectAll().where("id", "=", id).where("deleted_at", "is", null).forUpdate().executeTakeFirst();
|
|
18211
18211
|
/** Locks the live account row of one site (another site's account reads as not found). */
|
|
18212
18212
|
const lockByIdInSite = (id, siteId, trx) => trx.selectFrom("app_users").selectAll().where("id", "=", id).where("site_id", "=", siteId).where("deleted_at", "is", null).forUpdate().executeTakeFirst();
|
|
@@ -19831,11 +19831,11 @@ const jsonInstruction = (request) => request.json ? `\n\nAnswer with one JSON ob
|
|
|
19831
19831
|
* Chat Completions (`POST {AI_BASE_URL}/chat/completions`). `openai` uses `response_format` with the
|
|
19832
19832
|
* schema; `openai-compatible` (Ollama, LM Studio, vLLM) gets the schema in the prompt.
|
|
19833
19833
|
*/
|
|
19834
|
-
const createChatCompletionsProvider = (transport,
|
|
19835
|
-
id:
|
|
19834
|
+
const createChatCompletionsProvider = (transport, flavor) => ({
|
|
19835
|
+
id: flavor,
|
|
19836
19836
|
model: transport.config.model,
|
|
19837
19837
|
complete: async (request) => {
|
|
19838
|
-
const native =
|
|
19838
|
+
const native = flavor === "openai";
|
|
19839
19839
|
const system = native ? request.system : `${request.system}${jsonInstruction(request)}`;
|
|
19840
19840
|
const responseFormat = request.json && native ? {
|
|
19841
19841
|
type: "json_schema",
|
|
@@ -20785,9 +20785,9 @@ const createMysqlNotificationListener = (options) => {
|
|
|
20785
20785
|
//#endregion
|
|
20786
20786
|
//#region src/db/notifications.ts
|
|
20787
20787
|
/**
|
|
20788
|
-
* LISTEN/NOTIFY primitives (ADR 0002). Notifications are an
|
|
20788
|
+
* LISTEN/NOTIFY primitives (ADR 0002). Notifications are an optimization only: a listener can miss
|
|
20789
20789
|
* messages while disconnected, so every consumer must also check a durable version. Callers get an
|
|
20790
|
-
* `onConnect` callback after every (re)connect to
|
|
20790
|
+
* `onConnect` callback after every (re)connect to resynchronize for anything missed in between.
|
|
20791
20791
|
*
|
|
20792
20792
|
* SQLite: `shapio_notify()` queues on the connection and an in-process bus delivers on commit
|
|
20793
20793
|
* (`notifyHub.ts`); only listeners in the same process hear it.
|
|
@@ -21742,9 +21742,9 @@ const THEMED = [
|
|
|
21742
21742
|
];
|
|
21743
21743
|
const themed = (theme) => THEMED.map((selector) => `body.graphiql-${theme} ${selector}`).join(",\n");
|
|
21744
21744
|
/**
|
|
21745
|
-
* Page layout, and GraphiQL's palette adjusted to WCAG AA: every text
|
|
21745
|
+
* Page layout, and GraphiQL's palette adjusted to WCAG AA: every text color (syntax highlighting, links,
|
|
21746
21746
|
* secondary text) reaches 4.5:1 on the backgrounds it is drawn on, in both themes (GraphiQL's own light
|
|
21747
|
-
* palette is 2.3–4.3:1 there), and links in the docs are underlined so they don't rely on
|
|
21747
|
+
* palette is 2.3–4.3:1 there), and links in the docs are underlined so they don't rely on color alone.
|
|
21748
21748
|
*/
|
|
21749
21749
|
const STYLE$1 = `html, body, #graphiql { height: 100%; margin: 0; }
|
|
21750
21750
|
${themed("light")} {
|
|
@@ -24681,7 +24681,7 @@ const createMediaStorage = async (config, deps) => {
|
|
|
24681
24681
|
publicBaseUrl: config.publicBaseUrl
|
|
24682
24682
|
}));
|
|
24683
24683
|
if (config.s3) {
|
|
24684
|
-
const { createS3Adapter } = await import("./s3Adapter-
|
|
24684
|
+
const { createS3Adapter } = await import("./s3Adapter-CZcCl0sy.js");
|
|
24685
24685
|
adapters.set("s3", createS3Adapter({
|
|
24686
24686
|
config: config.s3,
|
|
24687
24687
|
publicBaseUrl: config.publicBaseUrl
|
|
@@ -24858,7 +24858,7 @@ const CORS_METHODS = [
|
|
|
24858
24858
|
/**
|
|
24859
24859
|
* Baseline HTTP hardening: security headers, CORS (off unless origins are configured; the admin and API
|
|
24860
24860
|
* share one origin, so CORS is only for the user's own sites and apps), a global rate limit keyed by the
|
|
24861
|
-
* client IP (which
|
|
24861
|
+
* client IP (which honors TRUST_PROXY), and @fastify/sensible's httpErrors.
|
|
24862
24862
|
* The rate-limit store is in memory, so with several instances each counts on its own (documented: put a
|
|
24863
24863
|
* shared limiter in front for strict limits; ADR 0008).
|
|
24864
24864
|
*/
|
|
@@ -24925,11 +24925,11 @@ const textInputPlugin = fp(async (app) => {
|
|
|
24925
24925
|
});
|
|
24926
24926
|
}, { name: "shapio-text-input" });
|
|
24927
24927
|
//#endregion
|
|
24928
|
-
//#region src/plugins/
|
|
24929
|
-
/** The
|
|
24930
|
-
const
|
|
24931
|
-
app.decorate("
|
|
24932
|
-
}, { name: "shapio-theme-
|
|
24928
|
+
//#region src/plugins/themeCatalog.ts
|
|
24929
|
+
/** The catalog is built from the project config by the app (extensions/themeStylesheet.ts). */
|
|
24930
|
+
const themeCatalogPlugin = fp(async (app, { catalog }) => {
|
|
24931
|
+
app.decorate("themeCatalog", catalog);
|
|
24932
|
+
}, { name: "shapio-theme-catalog" });
|
|
24933
24933
|
//#endregion
|
|
24934
24934
|
//#region src/repositories/usage.ts
|
|
24935
24935
|
const upsertFieldReads = async (rows, trx = db) => {
|
|
@@ -25441,7 +25441,7 @@ const PUBLISHING_JOBS = {
|
|
|
25441
25441
|
deploymentTrigger: "deployment.trigger",
|
|
25442
25442
|
deploymentPoll: "deployment.poll"
|
|
25443
25443
|
};
|
|
25444
|
-
/** Change set events (also in the webhook
|
|
25444
|
+
/** Change set events (also in the webhook catalog). `shipped` carries the snapshot it went live in. */
|
|
25445
25445
|
const CHANGE_SET_EVENTS = {
|
|
25446
25446
|
scheduled: "change_set.scheduled",
|
|
25447
25447
|
shipping: "change_set.shipping",
|
|
@@ -28479,13 +28479,13 @@ const RevisionSummarySchema = Type.Object({
|
|
|
28479
28479
|
});
|
|
28480
28480
|
/** A revision in a definition's history: whether its change went live, and whether it is the active one. */
|
|
28481
28481
|
const RevisionListItemSchema = Type.Intersect([RevisionSummarySchema, Type.Object({
|
|
28482
|
-
/** The change that wrote it: `failed` and `
|
|
28482
|
+
/** The change that wrote it: `failed` and `canceled` revisions never went live. */
|
|
28483
28483
|
status: Type.Union([
|
|
28484
28484
|
Type.Literal("pending"),
|
|
28485
28485
|
Type.Literal("running"),
|
|
28486
28486
|
Type.Literal("activated"),
|
|
28487
28487
|
Type.Literal("failed"),
|
|
28488
|
-
Type.Literal("
|
|
28488
|
+
Type.Literal("canceled")
|
|
28489
28489
|
]),
|
|
28490
28490
|
active: Type.Boolean()
|
|
28491
28491
|
})]);
|
|
@@ -29374,7 +29374,7 @@ const activateDefinitions = async (db, request) => {
|
|
|
29374
29374
|
* with the schema version it activated. The ledger row of the change set's own site is `change_set`; other
|
|
29375
29375
|
* sites' rows are `conversion` and name the change set; without a change set every row is `schema`. Each
|
|
29376
29376
|
* site's number is taken on first use (a change set's publications, an entry-level conversion) or at the
|
|
29377
|
-
* end, under the schema lock, and that site's deferred work then runs with it. Activations are
|
|
29377
|
+
* end, under the schema lock, and that site's deferred work then runs with it. Activations are serialized
|
|
29378
29378
|
* by the schema lock and every other publisher holds one site's sequence row at most, so taking several
|
|
29379
29379
|
* sites' rows in first-use order cannot deadlock. A metadata-only activation (a label rename) takes no
|
|
29380
29380
|
* number anywhere: live content and every API response stay exactly as they were (brief §10).
|
|
@@ -30668,7 +30668,7 @@ const markFailed$2 = (id, error, now, trx = db) => trx.updateTable("scheduled_pu
|
|
|
30668
30668
|
}).where("id", "=", id).where("status", "in", ["scheduled", "failed"]).execute();
|
|
30669
30669
|
/** Cancels a schedule that has not run yet; returns the row when it changed. */
|
|
30670
30670
|
const cancel = (id, now, trx = db) => trx.updateTable("scheduled_publications").set({
|
|
30671
|
-
status: "
|
|
30671
|
+
status: "canceled",
|
|
30672
30672
|
updated_at: now
|
|
30673
30673
|
}).where("id", "=", id).where("status", "in", ["scheduled", "failed"]).returningAll().executeTakeFirst();
|
|
30674
30674
|
/** Whether the entry has a publication still scheduled (change kind waits for it). */
|
|
@@ -31143,9 +31143,9 @@ const getEditorFile = async (request, reply) => {
|
|
|
31143
31143
|
return reply.type("text/javascript; charset=utf-8").header("cache-control", "private, max-age=31536000, immutable").send(await readFile(entry.path));
|
|
31144
31144
|
};
|
|
31145
31145
|
//#endregion
|
|
31146
|
-
//#region src/controllers/
|
|
31146
|
+
//#region src/controllers/themeCatalog.ts
|
|
31147
31147
|
/** The project's extension themes, for the admin's theme menu. */
|
|
31148
|
-
const listThemes = async (request) => ({ items: request.server.
|
|
31148
|
+
const listThemes = async (request) => ({ items: request.server.themeCatalog.items });
|
|
31149
31149
|
let stylesheetEtag;
|
|
31150
31150
|
const etagOf = (stylesheet) => {
|
|
31151
31151
|
if (stylesheetEtag?.stylesheet !== stylesheet) stylesheetEtag = {
|
|
@@ -31156,11 +31156,11 @@ const etagOf = (stylesheet) => {
|
|
|
31156
31156
|
};
|
|
31157
31157
|
/**
|
|
31158
31158
|
* Their CSS, linked render-blocking from the admin's index.html (empty without extension themes). Public:
|
|
31159
|
-
* it holds
|
|
31159
|
+
* it holds colors only, and the signed-out screens render in the chosen theme too. Revalidated on each
|
|
31160
31160
|
* load (it changes only with a restart), so a changed theme shows without a stale cache.
|
|
31161
31161
|
*/
|
|
31162
31162
|
const getThemeStylesheet = async (request, reply) => {
|
|
31163
|
-
const { stylesheet } = request.server.
|
|
31163
|
+
const { stylesheet } = request.server.themeCatalog;
|
|
31164
31164
|
const etag = etagOf(stylesheet);
|
|
31165
31165
|
reply.header("etag", etag).header("cache-control", "no-cache").type("text/css; charset=utf-8");
|
|
31166
31166
|
if (request.headers["if-none-match"] === etag) return reply.code(304).send();
|
|
@@ -31190,7 +31190,7 @@ const listThemesSchema = { response: { 200: Type.Object({ items: Type.Array(Type
|
|
|
31190
31190
|
//#endregion
|
|
31191
31191
|
//#region src/routes/admin/extensions/index.ts
|
|
31192
31192
|
/**
|
|
31193
|
-
* /api/admin/extensions: what the project installed for the admin (custom field editors, ADR 0009;
|
|
31193
|
+
* /api/admin/extensions: what the project installed for the admin (custom field editors, ADR 0009; color
|
|
31194
31194
|
* themes, docs/plans/themes.md).
|
|
31195
31195
|
*/
|
|
31196
31196
|
const adminExtensionsRoutes = async (app) => {
|
|
@@ -33925,7 +33925,7 @@ const createReplaceGrant = async (context, assetId, input) => {
|
|
|
33925
33925
|
const goneGrant = () => new AppError(404, "UPLOAD_GRANT_INVALID", "This upload grant is unknown, used or expired");
|
|
33926
33926
|
/**
|
|
33927
33927
|
* Local driver only: receives the bytes of a grant (the S3 driver's browser uploads go to the bucket).
|
|
33928
|
-
*
|
|
33928
|
+
* Authorized by the grant's signature, not by a session. `readUpload` parses the request with the grant's
|
|
33929
33929
|
* size limit; the bytes stream to disk and are re-checked on confirm.
|
|
33930
33930
|
*/
|
|
33931
33931
|
const receiveLocalUpload = async (context, grantId, readUpload) => {
|
|
@@ -34445,7 +34445,7 @@ const confirmUploadSchema = {
|
|
|
34445
34445
|
};
|
|
34446
34446
|
//#endregion
|
|
34447
34447
|
//#region src/routes/admin/media/index.ts
|
|
34448
|
-
const NOT_AUDITED = "media library
|
|
34448
|
+
const NOT_AUDITED = "media library organization (folders, metadata, moves) is recorded by media.* outbox events, not audited";
|
|
34449
34449
|
const GRANT_ONLY = "issues an upload grant only; the change is audited on confirm (media.upload / media.replace)";
|
|
34450
34450
|
/** /api/admin/media: the media library (folders, assets, uploads, usage). */
|
|
34451
34451
|
const adminMediaRoutes = async (app) => {
|
|
@@ -35557,7 +35557,7 @@ const summarizeItem = (component, item, lookups) => {
|
|
|
35557
35557
|
}
|
|
35558
35558
|
return "";
|
|
35559
35559
|
};
|
|
35560
|
-
const
|
|
35560
|
+
const labeled = (label, summary) => summary ? `${label} (${summary})` : label;
|
|
35561
35561
|
const componentSummary = (field, value, lookups) => {
|
|
35562
35562
|
const component = lookups.component(field.settings.component);
|
|
35563
35563
|
const items = listOf(value);
|
|
@@ -35572,7 +35572,7 @@ const zoneSummary = (value, lookups) => {
|
|
|
35572
35572
|
const blocks = value.map((item) => {
|
|
35573
35573
|
const id = item[COMPONENT_KEY];
|
|
35574
35574
|
const component = typeof id === "string" ? lookups.component(id) : void 0;
|
|
35575
|
-
return component ?
|
|
35575
|
+
return component ? labeled(component.label, summarizeItem(component, item, lookups)) : String(id);
|
|
35576
35576
|
});
|
|
35577
35577
|
return `${plural(value.length, "block", "blocks")}: ${blocks.join(", ")}`;
|
|
35578
35578
|
};
|
|
@@ -40250,12 +40250,12 @@ const markDeliveryDead = (id, error, now, trx = db) => trx.updateTable("webhook_
|
|
|
40250
40250
|
updated_at: now
|
|
40251
40251
|
}).where("id", "=", id).where("status", "in", ["pending", "retrying"]).execute();
|
|
40252
40252
|
//#endregion
|
|
40253
|
-
//#region src/webhooks/
|
|
40253
|
+
//#region src/webhooks/catalog.ts
|
|
40254
40254
|
const group = (name, types) => types.map((type) => ({
|
|
40255
40255
|
type,
|
|
40256
40256
|
group: name
|
|
40257
40257
|
}));
|
|
40258
|
-
const
|
|
40258
|
+
const WEBHOOK_EVENT_CATALOG = [
|
|
40259
40259
|
...group("entry", [
|
|
40260
40260
|
"entry.created",
|
|
40261
40261
|
"entry.updated",
|
|
@@ -40279,8 +40279,8 @@ const WEBHOOK_EVENT_CATALOGUE = [
|
|
|
40279
40279
|
];
|
|
40280
40280
|
/** Sent by "Send test"; never produced by the outbox. */
|
|
40281
40281
|
const WEBHOOK_TEST_EVENT = "webhook.test";
|
|
40282
|
-
const TYPES = new Set(
|
|
40283
|
-
const GROUPS = new Set(
|
|
40282
|
+
const TYPES = new Set(WEBHOOK_EVENT_CATALOG.map((event) => event.type));
|
|
40283
|
+
const GROUPS = new Set(WEBHOOK_EVENT_CATALOG.map((event) => event.group));
|
|
40284
40284
|
const isValidEventPattern = (pattern) => TYPES.has(pattern) || pattern.endsWith(".*") && GROUPS.has(pattern.slice(0, -2));
|
|
40285
40285
|
const matchesEvent = (patterns, type) => patterns.some((pattern) => pattern === type || pattern.endsWith(".*") && type.startsWith(pattern.slice(0, -1)));
|
|
40286
40286
|
//#endregion
|
|
@@ -40356,7 +40356,7 @@ const assertEvents = (events) => {
|
|
|
40356
40356
|
const invalid = events.filter((event) => !isValidEventPattern(event));
|
|
40357
40357
|
if (invalid.length > 0) throw new AppError(400, "INVALID_EVENTS", `Unknown events: ${invalid.join(", ")}`, { invalid });
|
|
40358
40358
|
};
|
|
40359
|
-
const listEventTypes$1 = () =>
|
|
40359
|
+
const listEventTypes$1 = () => WEBHOOK_EVENT_CATALOG;
|
|
40360
40360
|
const listWebhooks$2 = async (runtime, site) => (await list$1(site.id, runtime.db)).map((row) => toView(runtime, row));
|
|
40361
40361
|
const getWebhook$1 = async (runtime, site, id) => {
|
|
40362
40362
|
const row = await findSummaryVisible(site.id, id, runtime.db);
|
|
@@ -41029,7 +41029,7 @@ const cancelSchedule$1 = async (context, id) => {
|
|
|
41029
41029
|
if (!existing) throw scheduleNotFound(id);
|
|
41030
41030
|
if (modelKey) await modelWithPolicy(context, modelKey, "publish");
|
|
41031
41031
|
await context.db.transaction().execute(async (trx) => {
|
|
41032
|
-
if (!await cancel(id, /* @__PURE__ */ new Date(), trx)) throw new AppError(409, "SCHEDULE_NOT_PENDING", "Only schedules that have not run can be
|
|
41032
|
+
if (!await cancel(id, /* @__PURE__ */ new Date(), trx)) throw new AppError(409, "SCHEDULE_NOT_PENDING", "Only schedules that have not run can be canceled", {
|
|
41033
41033
|
id,
|
|
41034
41034
|
status: existing.status
|
|
41035
41035
|
});
|
|
@@ -41090,7 +41090,7 @@ const ScheduleStatusSchema = Type.Enum([
|
|
|
41090
41090
|
"scheduled",
|
|
41091
41091
|
"done",
|
|
41092
41092
|
"failed",
|
|
41093
|
-
"
|
|
41093
|
+
"canceled"
|
|
41094
41094
|
]);
|
|
41095
41095
|
const ScheduleSchema = Type.Object({
|
|
41096
41096
|
id: UuidSchema,
|
|
@@ -41145,7 +41145,7 @@ const cancelScheduleSchema = {
|
|
|
41145
41145
|
//#endregion
|
|
41146
41146
|
//#region src/routes/admin/publishing/schedules/index.ts
|
|
41147
41147
|
/**
|
|
41148
|
-
* /api/admin/publishing/schedules: publish-at / unpublish-at per entry and locale. Creating and
|
|
41148
|
+
* /api/admin/publishing/schedules: publish-at / unpublish-at per entry and locale. Creating and canceling
|
|
41149
41149
|
* need publish permission on the model (checked by the service through the evaluator); listing everything
|
|
41150
41150
|
* needs `publishing.manage`, listing one entry's schedules needs read permission on its model.
|
|
41151
41151
|
*/
|
|
@@ -42921,7 +42921,7 @@ const openStoredBundle = (storage, stored) => storage.get(stored.driver).getStre
|
|
|
42921
42921
|
const removeStoredBundle = (storage, stored) => storage.get(stored.driver).delete(stored.key);
|
|
42922
42922
|
//#endregion
|
|
42923
42923
|
//#region src/constants/version.ts
|
|
42924
|
-
const SHAPIO_VERSION = "0.5.
|
|
42924
|
+
const SHAPIO_VERSION = "0.5.10";
|
|
42925
42925
|
//#endregion
|
|
42926
42926
|
//#region src/repositories/transferExport.ts
|
|
42927
42927
|
/**
|
|
@@ -43612,7 +43612,7 @@ const readPayload = (payload) => {
|
|
|
43612
43612
|
pendingChangeIds: value.pendingChangeIds ?? []
|
|
43613
43613
|
};
|
|
43614
43614
|
};
|
|
43615
|
-
/** The import acts as Shapio itself: the request that started it was
|
|
43615
|
+
/** The import acts as Shapio itself: the request that started it was authorized as an instance admin. */
|
|
43616
43616
|
const SYSTEM_ACTOR = {
|
|
43617
43617
|
kind: "system",
|
|
43618
43618
|
component: "transfer"
|
|
@@ -43653,7 +43653,7 @@ const forEachBatch = async (run, type, handle) => {
|
|
|
43653
43653
|
};
|
|
43654
43654
|
const waitForSchema = async (run) => {
|
|
43655
43655
|
const changes = await findSchemaChangeStatuses(run.payload.pendingChangeIds);
|
|
43656
|
-
const failed = changes.find((change) => change.status === "failed" || change.status === "
|
|
43656
|
+
const failed = changes.find((change) => change.status === "failed" || change.status === "canceled");
|
|
43657
43657
|
if (failed) throw new PermanentJobError(`Schema change ${failed.id} failed: ${JSON.stringify(failed.error)}`);
|
|
43658
43658
|
if (changes.some((change) => change.status !== "activated")) throw new Error("Waiting for the imported schema changes to activate");
|
|
43659
43659
|
};
|
|
@@ -44163,7 +44163,7 @@ const putMediaFileSchema = {
|
|
|
44163
44163
|
/**
|
|
44164
44164
|
* /api/admin/transfer: content export and import (`shapio export` / `shapio import`). Bundles and media
|
|
44165
44165
|
* files travel as raw streams (never buffered whole), so this scope passes those bodies through unparsed.
|
|
44166
|
-
* The service
|
|
44166
|
+
* The service authorizes every call as an instance administrator.
|
|
44167
44167
|
*/
|
|
44168
44168
|
const adminTransferRoutes = async (app) => {
|
|
44169
44169
|
declareSiteScope(app, "site");
|
|
@@ -46442,14 +46442,14 @@ const docsRoutes = async (app) => {
|
|
|
46442
46442
|
//#endregion
|
|
46443
46443
|
//#region src/db/migrations/20261001120000_create_platform_tables.ts
|
|
46444
46444
|
var _20261001120000_create_platform_tables_exports = /* @__PURE__ */ __exportAll({
|
|
46445
|
-
down: () => down$
|
|
46446
|
-
up: () => up$
|
|
46445
|
+
down: () => down$37,
|
|
46446
|
+
up: () => up$37
|
|
46447
46447
|
});
|
|
46448
46448
|
/**
|
|
46449
46449
|
* Foundation tables shared by every package: durable versions, the job queue, the transactional outbox
|
|
46450
46450
|
* and the audit log. Statuses are text with CHECK constraints so new states need only a constraint change.
|
|
46451
46451
|
*/
|
|
46452
|
-
const up$
|
|
46452
|
+
const up$37 = async (db) => {
|
|
46453
46453
|
await db.schema.createTable("system_versions").addColumn("id", "boolean", (col) => col.primaryKey().defaultTo(true).check(sql`id`)).addColumn("schema_version", "integer", (col) => col.notNull().defaultTo(0)).addColumn("permissions_version", "integer", (col) => col.notNull().defaultTo(0)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
46454
46454
|
await sql`insert into system_versions default values`.execute(db);
|
|
46455
46455
|
await db.schema.createTable("jobs").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("type", "text", (col) => col.notNull()).addColumn("payload", "jsonb", (col) => col.notNull().defaultTo(sql`'{}'::jsonb`)).addColumn("status", "text", (col) => col.notNull().defaultTo("pending").check(sql`status in ('pending', 'running', 'succeeded', 'dead')`)).addColumn("priority", "integer", (col) => col.notNull().defaultTo(0)).addColumn("run_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("attempts", "integer", (col) => col.notNull().defaultTo(0)).addColumn("max_attempts", "integer", (col) => col.notNull().defaultTo(10).check(sql`max_attempts > 0`)).addColumn("idempotency_key", "text").addColumn("locked_by", "text").addColumn("locked_until", "timestamptz").addColumn("checkpoint", "jsonb").addColumn("result", "jsonb").addColumn("last_error", "text").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("finished_at", "timestamptz").execute();
|
|
@@ -46471,7 +46471,7 @@ const up$34 = async (db) => {
|
|
|
46471
46471
|
"occurred_at desc"
|
|
46472
46472
|
]).execute();
|
|
46473
46473
|
};
|
|
46474
|
-
const down$
|
|
46474
|
+
const down$37 = async (db) => {
|
|
46475
46475
|
await db.schema.dropTable("audit_events").execute();
|
|
46476
46476
|
await db.schema.dropTable("outbox_events").execute();
|
|
46477
46477
|
await db.schema.dropTable("jobs").execute();
|
|
@@ -46480,8 +46480,8 @@ const down$34 = async (db) => {
|
|
|
46480
46480
|
//#endregion
|
|
46481
46481
|
//#region src/db/migrations/20261001130000_create_admin_identity.ts
|
|
46482
46482
|
var _20261001130000_create_admin_identity_exports = /* @__PURE__ */ __exportAll({
|
|
46483
|
-
down: () => down$
|
|
46484
|
-
up: () => up$
|
|
46483
|
+
down: () => down$36,
|
|
46484
|
+
up: () => up$36
|
|
46485
46485
|
});
|
|
46486
46486
|
/**
|
|
46487
46487
|
* Admin identity (package B, ADR 0005): admin users, roles and their permission grants, server-side
|
|
@@ -46490,7 +46490,7 @@ var _20261001130000_create_admin_identity_exports = /* @__PURE__ */ __exportAll(
|
|
|
46490
46490
|
*/
|
|
46491
46491
|
const withTimestamps$3 = (table) => table.addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`));
|
|
46492
46492
|
const uuidPrimaryKey$3 = (table) => table.addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`));
|
|
46493
|
-
const up$
|
|
46493
|
+
const up$36 = async (db) => {
|
|
46494
46494
|
await withTimestamps$3(uuidPrimaryKey$3(db.schema.createTable("admin_users")).addColumn("email", "text", (col) => col.notNull().unique()).addColumn("name", "text", (col) => col.notNull().defaultTo("")).addColumn("password_hash", "text", (col) => col.notNull()).addColumn("status", "text", (col) => col.notNull().defaultTo("active").check(sql`status in ('active', 'disabled')`)).addColumn("last_login_at", "timestamptz").addColumn("password_changed_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`))).execute();
|
|
46495
46495
|
await withTimestamps$3(uuidPrimaryKey$3(db.schema.createTable("admin_roles")).addColumn("key", "text", (col) => col.notNull().unique().check(sql`key ~ '^[a-z][a-z0-9-]{0,62}$'`)).addColumn("name", "text", (col) => col.notNull()).addColumn("description", "text", (col) => col.notNull().defaultTo("")).addColumn("kind", "text", (col) => col.notNull().defaultTo("admin").check(sql`kind in ('admin', 'delivery')`)).addColumn("is_system", "boolean", (col) => col.notNull().defaultTo(false)).addColumn("version", "integer", (col) => col.notNull().defaultTo(1))).execute();
|
|
46496
46496
|
await withTimestamps$3(uuidPrimaryKey$3(db.schema.createTable("admin_role_permissions")).addColumn("role_id", "uuid", (col) => col.notNull().references("admin_roles.id").onDelete("cascade")).addColumn("action", "text", (col) => col.notNull()).addColumn("model_id", "text").addColumn("condition", "text", (col) => col.check(sql`condition in ('ownedByPrincipal')`)).addColumn("field_ids", sql`text[]`).addUniqueConstraint("admin_role_permissions_grant_uq", [
|
|
@@ -46510,7 +46510,7 @@ const up$33 = async (db) => {
|
|
|
46510
46510
|
await withTimestamps$3(uuidPrimaryKey$3(db.schema.createTable("api_tokens")).addColumn("name", "text", (col) => col.notNull()).addColumn("token_hash", "text", (col) => col.notNull().unique()).addColumn("token_prefix", "text", (col) => col.notNull()).addColumn("role_id", "uuid", (col) => col.notNull().references("admin_roles.id").onDelete("restrict")).addColumn("created_by", "uuid", (col) => col.references("admin_users.id").onDelete("set null")).addColumn("expires_at", "timestamptz").addColumn("last_used_at", "timestamptz").addColumn("revoked_at", "timestamptz")).execute();
|
|
46511
46511
|
await db.schema.createIndex("api_tokens_role_idx").on("api_tokens").column("role_id").execute();
|
|
46512
46512
|
};
|
|
46513
|
-
const down$
|
|
46513
|
+
const down$36 = async (db) => {
|
|
46514
46514
|
await db.schema.dropTable("api_tokens").execute();
|
|
46515
46515
|
await db.schema.dropTable("setup_tokens").execute();
|
|
46516
46516
|
await db.schema.dropTable("password_resets").execute();
|
|
@@ -46524,31 +46524,31 @@ const down$33 = async (db) => {
|
|
|
46524
46524
|
//#endregion
|
|
46525
46525
|
//#region src/db/migrations/20261001130500_create_system_settings.ts
|
|
46526
46526
|
var _20261001130500_create_system_settings_exports = /* @__PURE__ */ __exportAll({
|
|
46527
|
-
down: () => down$
|
|
46528
|
-
up: () => up$
|
|
46527
|
+
down: () => down$35,
|
|
46528
|
+
up: () => up$35
|
|
46529
46529
|
});
|
|
46530
46530
|
/**
|
|
46531
46531
|
* Instance-wide key/value settings that must survive restarts and be shared by every instance, e.g. the
|
|
46532
46532
|
* generated signing secret. General purpose: later packages add keys, not tables.
|
|
46533
46533
|
*/
|
|
46534
|
-
const up$
|
|
46534
|
+
const up$35 = async (db) => {
|
|
46535
46535
|
await db.schema.createTable("system_settings").addColumn("key", "text", (col) => col.primaryKey()).addColumn("value", "text", (col) => col.notNull()).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
46536
46536
|
};
|
|
46537
|
-
const down$
|
|
46537
|
+
const down$35 = async (db) => {
|
|
46538
46538
|
await db.schema.dropTable("system_settings").execute();
|
|
46539
46539
|
};
|
|
46540
46540
|
//#endregion
|
|
46541
46541
|
//#region src/db/migrations/20261001140000_create_schema_tables.ts
|
|
46542
46542
|
var _20261001140000_create_schema_tables_exports = /* @__PURE__ */ __exportAll({
|
|
46543
|
-
down: () => down$
|
|
46544
|
-
up: () => up$
|
|
46543
|
+
down: () => down$34,
|
|
46544
|
+
up: () => up$34
|
|
46545
46545
|
});
|
|
46546
46546
|
/**
|
|
46547
46547
|
* Schema registry (package D, ADR 0002): models and components (one table, `kind` discriminator), immutable
|
|
46548
46548
|
* schema revisions, the per-model active pointer, schema change jobs, locales and schema settings.
|
|
46549
46549
|
* Model definitions are data: creating or changing a model never runs DDL (CONTRIBUTING.md rule 1).
|
|
46550
46550
|
*/
|
|
46551
|
-
const up$
|
|
46551
|
+
const up$34 = async (db) => {
|
|
46552
46552
|
await db.schema.createTable("models").addColumn("id", "uuid", (col) => col.primaryKey()).addColumn("kind", "text", (col) => col.notNull().check(sql`kind in ('collection', 'singleton', 'component')`)).addColumn("api_key", "text", (col) => col.notNull()).addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("deleted_at", "timestamptz").execute();
|
|
46553
46553
|
await sql`create unique index models_api_key_uq on models (lower(api_key)) where deleted_at is null`.execute(db);
|
|
46554
46554
|
await db.schema.createTable("schema_revisions").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("model_id", "uuid", (col) => col.notNull().references("models.id").onDelete("restrict")).addColumn("version", "integer", (col) => col.notNull().check(sql`version > 0`)).addColumn("definition", "jsonb", (col) => col.notNull()).addColumn("hash", "text", (col) => col.notNull()).addColumn("parent_revision_id", "uuid", (col) => col.references("schema_revisions.id")).addColumn("created_by_type", "text", (col) => col.notNull()).addColumn("created_by_id", "text").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addUniqueConstraint("schema_revisions_model_version_uq", ["model_id", "version"]).execute();
|
|
@@ -46576,7 +46576,7 @@ const up$31 = async (db) => {
|
|
|
46576
46576
|
await db.schema.createTable("schema_settings").addColumn("id", "boolean", (col) => col.primaryKey().defaultTo(true).check(sql`id`)).addColumn("read_only", "boolean", (col) => col.notNull().defaultTo(false)).addColumn("read_only_reason", "text").addColumn("updated_by_type", "text").addColumn("updated_by_id", "text").addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
46577
46577
|
await sql`insert into schema_settings default values`.execute(db);
|
|
46578
46578
|
};
|
|
46579
|
-
const down$
|
|
46579
|
+
const down$34 = async (db) => {
|
|
46580
46580
|
await db.schema.dropTable("schema_settings").execute();
|
|
46581
46581
|
await db.schema.dropTable("locales").execute();
|
|
46582
46582
|
await db.schema.dropTable("schema_change_jobs").execute();
|
|
@@ -46588,8 +46588,8 @@ const down$31 = async (db) => {
|
|
|
46588
46588
|
//#endregion
|
|
46589
46589
|
//#region src/db/migrations/20261001150000_create_content_tables.ts
|
|
46590
46590
|
var _20261001150000_create_content_tables_exports = /* @__PURE__ */ __exportAll({
|
|
46591
|
-
down: () => down$
|
|
46592
|
-
up: () => up$
|
|
46591
|
+
down: () => down$33,
|
|
46592
|
+
up: () => up$33
|
|
46593
46593
|
});
|
|
46594
46594
|
/**
|
|
46595
46595
|
* Content storage (package E, ADR 0001): entries, immutable content revisions, mutable heads (one per
|
|
@@ -46597,7 +46597,7 @@ var _20261001150000_create_content_tables_exports = /* @__PURE__ */ __exportAll(
|
|
|
46597
46597
|
* and the publication log behind `?snapshot=N`. User content models never get tables of their own
|
|
46598
46598
|
* (CONTRIBUTING.md rule 1): their values are JSONB keyed by stable field IDs.
|
|
46599
46599
|
*/
|
|
46600
|
-
const up$
|
|
46600
|
+
const up$33 = async (db) => {
|
|
46601
46601
|
await db.schema.createTable("entries").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("model_id", "uuid", (col) => col.notNull().references("models.id").onDelete("restrict")).addColumn("owner_app_user_id", "uuid").addColumn("created_by_admin_id", "uuid", (col) => col.references("admin_users.id").onDelete("set null")).addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("deleted_at", "timestamptz").execute();
|
|
46602
46602
|
await sql`create index entries_model_idx on entries (model_id, created_at) where deleted_at is null`.execute(db);
|
|
46603
46603
|
await sql`create index entries_owner_idx on entries (owner_app_user_id) where owner_app_user_id is not null`.execute(db);
|
|
@@ -46661,7 +46661,7 @@ const up$30 = async (db) => {
|
|
|
46661
46661
|
await sql`create unique index publication_log_open_uq on publication_log (entry_id, locale) where to_seq is null`.execute(db);
|
|
46662
46662
|
await db.schema.createIndex("publication_log_model_seq_idx").on("publication_log").columns(["model_id", "from_seq"]).execute();
|
|
46663
46663
|
};
|
|
46664
|
-
const down$
|
|
46664
|
+
const down$33 = async (db) => {
|
|
46665
46665
|
await db.schema.dropTable("publication_log").execute();
|
|
46666
46666
|
await db.schema.dropTable("publication_state").execute();
|
|
46667
46667
|
await db.schema.dropTable("unique_values").execute();
|
|
@@ -46674,8 +46674,8 @@ const down$30 = async (db) => {
|
|
|
46674
46674
|
//#endregion
|
|
46675
46675
|
//#region src/db/migrations/20261001160000_create_media_tables.ts
|
|
46676
46676
|
var _20261001160000_create_media_tables_exports = /* @__PURE__ */ __exportAll({
|
|
46677
|
-
down: () => down$
|
|
46678
|
-
up: () => up$
|
|
46677
|
+
down: () => down$32,
|
|
46678
|
+
up: () => up$32
|
|
46679
46679
|
});
|
|
46680
46680
|
/**
|
|
46681
46681
|
* Media library (package G): folders, assets, image variants, references from content and upload grants.
|
|
@@ -46686,7 +46686,7 @@ const withTimestamps$2 = (table) => table.addColumn("created_at", "timestamptz",
|
|
|
46686
46686
|
const uuidPrimaryKey$2 = (table) => table.addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`));
|
|
46687
46687
|
const STORAGE_DRIVER_CHECK = sql`storage_driver in ('local', 's3')`;
|
|
46688
46688
|
const VISIBILITY_CHECK = sql`visibility in ('public', 'private')`;
|
|
46689
|
-
const up$
|
|
46689
|
+
const up$32 = async (db) => {
|
|
46690
46690
|
await withTimestamps$2(uuidPrimaryKey$2(db.schema.createTable("media_folders")).addColumn("parent_id", "uuid", (col) => col.references("media_folders.id").onDelete("restrict")).addColumn("name", "text", (col) => col.notNull().check(sql`length(name) between 1 and 255`)).addColumn("created_by", "uuid", (col) => col.references("admin_users.id").onDelete("set null")).addColumn("version", "integer", (col) => col.notNull().defaultTo(1))).execute();
|
|
46691
46691
|
await sql`create unique index media_folders_sibling_name_uq on media_folders
|
|
46692
46692
|
(coalesce(parent_id, '00000000-0000-0000-0000-000000000000'::uuid), lower(name))`.execute(db);
|
|
@@ -46715,7 +46715,7 @@ const up$29 = async (db) => {
|
|
|
46715
46715
|
]).execute();
|
|
46716
46716
|
await db.schema.createTable("media_upload_grants").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("asset_id", "uuid", (col) => col.notNull()).addColumn("kind", "text", (col) => col.notNull().check(sql`kind in ('create', 'replace')`)).addColumn("storage_driver", "text", (col) => col.notNull().check(STORAGE_DRIVER_CHECK)).addColumn("storage_key", "text", (col) => col.notNull().unique()).addColumn("original_filename", "text", (col) => col.notNull()).addColumn("declared_mime_type", "text", (col) => col.notNull()).addColumn("max_size_bytes", "bigint", (col) => col.notNull()).addColumn("folder_id", "uuid").addColumn("visibility", "text", (col) => col.notNull().check(VISIBILITY_CHECK)).addColumn("created_by", "uuid", (col) => col.references("admin_users.id").onDelete("set null")).addColumn("created_by_principal", "text", (col) => col.notNull()).addColumn("status", "text", (col) => col.notNull().defaultTo("pending").check(sql`status in ('pending', 'consumed', 'rejected', 'expired')`)).addColumn("expires_at", "timestamptz", (col) => col.notNull()).addColumn("consumed_at", "timestamptz").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
46717
46717
|
};
|
|
46718
|
-
const down$
|
|
46718
|
+
const down$32 = async (db) => {
|
|
46719
46719
|
await db.schema.dropTable("media_upload_grants").execute();
|
|
46720
46720
|
await db.schema.dropTable("media_references").execute();
|
|
46721
46721
|
await db.schema.dropTable("media_variants").execute();
|
|
@@ -46725,8 +46725,8 @@ const down$29 = async (db) => {
|
|
|
46725
46725
|
//#endregion
|
|
46726
46726
|
//#region src/db/migrations/20261001170000_create_publishing_tables.ts
|
|
46727
46727
|
var _20261001170000_create_publishing_tables_exports = /* @__PURE__ */ __exportAll({
|
|
46728
|
-
down: () => down$
|
|
46729
|
-
up: () => up$
|
|
46728
|
+
down: () => down$31,
|
|
46729
|
+
up: () => up$31
|
|
46730
46730
|
});
|
|
46731
46731
|
/**
|
|
46732
46732
|
* Publishing (package H): scheduled publications, releases, webhooks and their delivery log, deployment
|
|
@@ -46765,13 +46765,13 @@ const createPreviewTables = async (db) => {
|
|
|
46765
46765
|
await uuidPrimaryKey$1(db.schema.createTable("preview_tokens")).addColumn("token_hash", "text", (col) => col.notNull().unique()).addColumn("token_prefix", "text", (col) => col.notNull()).addColumn("model_id", "uuid", (col) => col.notNull()).addColumn("entry_id", "uuid", (col) => col.references("entries.id").onDelete("cascade")).addColumn("locale", "text").addColumn("connection_id", "uuid", (col) => col.references("deployment_connections.id").onDelete("set null")).addColumn("delivery_role_id", "uuid", (col) => col.references("admin_roles.id").onDelete("set null")).addColumn("created_by", "uuid", (col) => col.notNull().references("admin_users.id").onDelete("cascade")).addColumn("expires_at", "timestamptz", (col) => col.notNull()).addColumn("revoked_at", "timestamptz").addColumn("last_used_at", "timestamptz").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
46766
46766
|
await db.schema.createIndex("preview_tokens_entry_idx").on("preview_tokens").columns(["entry_id", "created_at desc"]).execute();
|
|
46767
46767
|
};
|
|
46768
|
-
const up$
|
|
46768
|
+
const up$31 = async (db) => {
|
|
46769
46769
|
await createSchedulingTables(db);
|
|
46770
46770
|
await createWebhookTables(db);
|
|
46771
46771
|
await createDeploymentTables(db);
|
|
46772
46772
|
await createPreviewTables(db);
|
|
46773
46773
|
};
|
|
46774
|
-
const down$
|
|
46774
|
+
const down$31 = async (db) => {
|
|
46775
46775
|
await db.schema.dropTable("preview_tokens").execute();
|
|
46776
46776
|
await db.schema.dropTable("deployment_runs").execute();
|
|
46777
46777
|
await db.schema.dropTable("deployment_connections").execute();
|
|
@@ -46784,8 +46784,8 @@ const down$28 = async (db) => {
|
|
|
46784
46784
|
//#endregion
|
|
46785
46785
|
//#region src/db/migrations/20261001180000_create_app_users.ts
|
|
46786
46786
|
var _20261001180000_create_app_users_exports = /* @__PURE__ */ __exportAll({
|
|
46787
|
-
down: () => down$
|
|
46788
|
-
up: () => up$
|
|
46787
|
+
down: () => down$30,
|
|
46788
|
+
up: () => up$30
|
|
46789
46789
|
});
|
|
46790
46790
|
/**
|
|
46791
46791
|
* App users (package I, ADR 0005): the end users of sites and apps built on Shapio, with their own roles
|
|
@@ -46836,7 +46836,7 @@ const createCredentials = async (db) => {
|
|
|
46836
46836
|
}
|
|
46837
46837
|
await db.schema.createTable("app_login_codes").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("app_user_id", "uuid", (col) => col.notNull().references("app_users.id").onDelete("cascade")).addColumn("code_hash", "text", (col) => col.notNull().unique()).addColumn("expires_at", "timestamptz", (col) => col.notNull()).addColumn("used_at", "timestamptz").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
46838
46838
|
};
|
|
46839
|
-
const up$
|
|
46839
|
+
const up$30 = async (db) => {
|
|
46840
46840
|
await createUsers(db);
|
|
46841
46841
|
await createRoles(db);
|
|
46842
46842
|
await createCredentials(db);
|
|
@@ -46846,7 +46846,7 @@ const up$27 = async (db) => {
|
|
|
46846
46846
|
foreign key (owner_app_user_id) references app_users (id) on delete set null
|
|
46847
46847
|
`.execute(db);
|
|
46848
46848
|
};
|
|
46849
|
-
const down$
|
|
46849
|
+
const down$30 = async (db) => {
|
|
46850
46850
|
await sql`alter table entries drop constraint if exists entries_owner_app_user_fk`.execute(db);
|
|
46851
46851
|
await db.schema.dropTable("app_login_codes").execute();
|
|
46852
46852
|
await db.schema.dropTable("app_password_resets").execute();
|
|
@@ -46861,8 +46861,8 @@ const down$27 = async (db) => {
|
|
|
46861
46861
|
//#endregion
|
|
46862
46862
|
//#region src/db/migrations/20261002120000_create_extension_hook_runs.ts
|
|
46863
46863
|
var _20261002120000_create_extension_hook_runs_exports = /* @__PURE__ */ __exportAll({
|
|
46864
|
-
down: () => down$
|
|
46865
|
-
up: () => up$
|
|
46864
|
+
down: () => down$29,
|
|
46865
|
+
up: () => up$29
|
|
46866
46866
|
});
|
|
46867
46867
|
/**
|
|
46868
46868
|
* Extension points (package K, ADR 0009): the ledger of post-commit lifecycle hooks (`afterCreate`,
|
|
@@ -46870,17 +46870,17 @@ var _20261002120000_create_extension_hook_runs_exports = /* @__PURE__ */ __expor
|
|
|
46870
46870
|
* as the hook's own database work, so a hook re-run after a worker crash finds its row and is skipped:
|
|
46871
46871
|
* exactly once for everything the hook does through its transaction.
|
|
46872
46872
|
*/
|
|
46873
|
-
const up$
|
|
46873
|
+
const up$29 = async (db) => {
|
|
46874
46874
|
await db.schema.createTable("extension_hook_runs").addColumn("event_id", "uuid", (col) => col.notNull()).addColumn("hook", "text", (col) => col.notNull()).addColumn("job_id", "uuid").addColumn("completed_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addPrimaryKeyConstraint("extension_hook_runs_pkey", ["event_id", "hook"]).execute();
|
|
46875
46875
|
};
|
|
46876
|
-
const down$
|
|
46876
|
+
const down$29 = async (db) => {
|
|
46877
46877
|
await db.schema.dropTable("extension_hook_runs").execute();
|
|
46878
46878
|
};
|
|
46879
46879
|
//#endregion
|
|
46880
46880
|
//#region src/db/migrations/20261002130000_app_auth_token_version_and_login_code_pkce.ts
|
|
46881
46881
|
var _20261002130000_app_auth_token_version_and_login_code_pkce_exports = /* @__PURE__ */ __exportAll({
|
|
46882
|
-
down: () => down$
|
|
46883
|
-
up: () => up$
|
|
46882
|
+
down: () => down$28,
|
|
46883
|
+
up: () => up$28
|
|
46884
46884
|
});
|
|
46885
46885
|
/**
|
|
46886
46886
|
* App users (ADR 0005):
|
|
@@ -46891,20 +46891,20 @@ var _20261002130000_app_auth_token_version_and_login_code_pkce_exports = /* @__P
|
|
|
46891
46891
|
* sign-in; the one-time login code is only exchanged with the matching verifier. Codes live a minute, so
|
|
46892
46892
|
* any pending ones (issued without a challenge) are dropped rather than given a placeholder.
|
|
46893
46893
|
*/
|
|
46894
|
-
const up$
|
|
46894
|
+
const up$28 = async (db) => {
|
|
46895
46895
|
await db.schema.alterTable("app_users").addColumn("token_version", "integer", (col) => col.notNull().defaultTo(0)).execute();
|
|
46896
46896
|
await sql`delete from app_login_codes`.execute(db);
|
|
46897
46897
|
await db.schema.alterTable("app_login_codes").addColumn("code_challenge", "text", (col) => col.notNull()).execute();
|
|
46898
46898
|
};
|
|
46899
|
-
const down$
|
|
46899
|
+
const down$28 = async (db) => {
|
|
46900
46900
|
await db.schema.alterTable("app_login_codes").dropColumn("code_challenge").execute();
|
|
46901
46901
|
await db.schema.alterTable("app_users").dropColumn("token_version").execute();
|
|
46902
46902
|
};
|
|
46903
46903
|
//#endregion
|
|
46904
46904
|
//#region src/db/migrations/20261002180000_add_publication_log_diff_indexes.ts
|
|
46905
46905
|
var _20261002180000_add_publication_log_diff_indexes_exports = /* @__PURE__ */ __exportAll({
|
|
46906
|
-
down: () => down$
|
|
46907
|
-
up: () => up$
|
|
46906
|
+
down: () => down$27,
|
|
46907
|
+
up: () => up$27
|
|
46908
46908
|
});
|
|
46909
46909
|
/**
|
|
46910
46910
|
* The snapshot diff (repositories/snapshotDiff.ts) finds the (entry, locale) pairs whose live period opened
|
|
@@ -46913,7 +46913,7 @@ var _20261002180000_add_publication_log_diff_indexes_exports = /* @__PURE__ */ _
|
|
|
46913
46913
|
* - `(entry_id, locale, from_seq)`: "the row live at seq N" is the latest row starting at or before N.
|
|
46914
46914
|
* Periods that opened in the range use the existing `(model_id, from_seq)` index.
|
|
46915
46915
|
*/
|
|
46916
|
-
const up$
|
|
46916
|
+
const up$27 = async (db) => {
|
|
46917
46917
|
await sql`create index publication_log_to_seq_idx on publication_log (to_seq) where to_seq is not null`.execute(db);
|
|
46918
46918
|
await db.schema.createIndex("publication_log_entry_locale_from_idx").on("publication_log").columns([
|
|
46919
46919
|
"entry_id",
|
|
@@ -46921,15 +46921,15 @@ const up$24 = async (db) => {
|
|
|
46921
46921
|
"from_seq"
|
|
46922
46922
|
]).execute();
|
|
46923
46923
|
};
|
|
46924
|
-
const down$
|
|
46924
|
+
const down$27 = async (db) => {
|
|
46925
46925
|
await db.schema.dropIndex("publication_log_entry_locale_from_idx").execute();
|
|
46926
46926
|
await db.schema.dropIndex("publication_log_to_seq_idx").execute();
|
|
46927
46927
|
};
|
|
46928
46928
|
//#endregion
|
|
46929
46929
|
//#region src/db/migrations/20261002180100_create_usage_tables.ts
|
|
46930
46930
|
var _20261002180100_create_usage_tables_exports = /* @__PURE__ */ __exportAll({
|
|
46931
|
-
down: () => down$
|
|
46932
|
-
up: () => up$
|
|
46931
|
+
down: () => down$26,
|
|
46932
|
+
up: () => up$26
|
|
46933
46933
|
});
|
|
46934
46934
|
/**
|
|
46935
46935
|
* Field usage from delivery traffic (plan developer-face §5): daily counters written by the in-memory
|
|
@@ -46937,7 +46937,7 @@ var _20261002180100_create_usage_tables_exports = /* @__PURE__ */ __exportAll({
|
|
|
46937
46937
|
* payloads. `principal_key` is `token:<id>`, `app_users` or `anonymous`. Pruned by the retention job
|
|
46938
46938
|
* after USAGE_RETENTION_DAYS.
|
|
46939
46939
|
*/
|
|
46940
|
-
const up$
|
|
46940
|
+
const up$26 = async (db) => {
|
|
46941
46941
|
await db.schema.createTable("field_reads").addColumn("day", "date", (col) => col.notNull()).addColumn("model_id", "uuid", (col) => col.notNull()).addColumn("field_path", "text", (col) => col.notNull()).addColumn("principal_key", "text", (col) => col.notNull()).addColumn("selection", "text", (col) => col.notNull().check(sql`selection in ('explicit', 'implicit')`)).addColumn("reads", "bigint", (col) => col.notNull().defaultTo(0)).addColumn("last_read_at", "timestamptz", (col) => col.notNull()).addPrimaryKeyConstraint("field_reads_pkey", [
|
|
46942
46942
|
"day",
|
|
46943
46943
|
"model_id",
|
|
@@ -46948,15 +46948,15 @@ const up$23 = async (db) => {
|
|
|
46948
46948
|
await db.schema.createIndex("field_reads_model_day_idx").on("field_reads").columns(["model_id", "day"]).execute();
|
|
46949
46949
|
await db.schema.createTable("token_reads").addColumn("day", "date", (col) => col.notNull()).addColumn("principal_key", "text", (col) => col.notNull()).addColumn("requests", "bigint", (col) => col.notNull().defaultTo(0)).addColumn("last_snapshot", "bigint").addColumn("last_read_at", "timestamptz", (col) => col.notNull()).addPrimaryKeyConstraint("token_reads_pkey", ["day", "principal_key"]).execute();
|
|
46950
46950
|
};
|
|
46951
|
-
const down$
|
|
46951
|
+
const down$26 = async (db) => {
|
|
46952
46952
|
await db.schema.dropTable("token_reads").execute();
|
|
46953
46953
|
await db.schema.dropTable("field_reads").execute();
|
|
46954
46954
|
};
|
|
46955
46955
|
//#endregion
|
|
46956
46956
|
//#region src/db/migrations/20261002180200_create_change_sets.ts
|
|
46957
46957
|
var _20261002180200_create_change_sets_exports = /* @__PURE__ */ __exportAll({
|
|
46958
|
-
down: () => down$
|
|
46959
|
-
up: () => up$
|
|
46958
|
+
down: () => down$25,
|
|
46959
|
+
up: () => up$25
|
|
46960
46960
|
});
|
|
46961
46961
|
/**
|
|
46962
46962
|
* Change sets (developer-face plan §5, ADR 0010): schema drafts and entry publications that ship as ONE
|
|
@@ -47135,7 +47135,7 @@ const migrateReleases = async (db) => {
|
|
|
47135
47135
|
await sql`drop table release_items`.execute(db);
|
|
47136
47136
|
await sql`drop table releases`.execute(db);
|
|
47137
47137
|
};
|
|
47138
|
-
const up$
|
|
47138
|
+
const up$25 = async (db) => {
|
|
47139
47139
|
await createTables(db);
|
|
47140
47140
|
await linkExecutionRecords(db);
|
|
47141
47141
|
await allowConversionRevisions(db);
|
|
@@ -47207,7 +47207,7 @@ const restoreReleases = async (db) => {
|
|
|
47207
47207
|
await sql`update webhooks set events = array_remove(array_remove(events, 'change_set.shipping'),
|
|
47208
47208
|
'change_set.discarded')`.execute(db);
|
|
47209
47209
|
};
|
|
47210
|
-
const down$
|
|
47210
|
+
const down$25 = async (db) => {
|
|
47211
47211
|
await restoreReleases(db);
|
|
47212
47212
|
await sql`alter table content_revisions drop constraint content_revisions_reason_check`.execute(db);
|
|
47213
47213
|
await sql`alter table content_revisions add constraint content_revisions_reason_check
|
|
@@ -47228,8 +47228,8 @@ const down$22 = async (db) => {
|
|
|
47228
47228
|
//#endregion
|
|
47229
47229
|
//#region src/db/migrations/20261002190000_create_editor_presence_and_content_health.ts
|
|
47230
47230
|
var _20261002190000_create_editor_presence_and_content_health_exports = /* @__PURE__ */ __exportAll({
|
|
47231
|
-
down: () => down$
|
|
47232
|
-
up: () => up$
|
|
47231
|
+
down: () => down$24,
|
|
47232
|
+
up: () => up$24
|
|
47233
47233
|
});
|
|
47234
47234
|
/**
|
|
47235
47235
|
* Editor experience (plan editor-experience §9):
|
|
@@ -47240,7 +47240,7 @@ var _20261002190000_create_editor_presence_and_content_health_exports = /* @__PU
|
|
|
47240
47240
|
* - `content_health_findings`: open and recently resolved findings of the health rules per entry and
|
|
47241
47241
|
* locale (`*` for the entry as a whole). An evaluation upserts what it found and resolves the rest.
|
|
47242
47242
|
*/
|
|
47243
|
-
const up$
|
|
47243
|
+
const up$24 = async (db) => {
|
|
47244
47244
|
await sql`
|
|
47245
47245
|
create unlogged table editor_presence (
|
|
47246
47246
|
entry_id uuid not null,
|
|
@@ -47277,15 +47277,15 @@ const up$21 = async (db) => {
|
|
|
47277
47277
|
await sql`create index content_health_findings_resolved_idx on content_health_findings (resolved_at)
|
|
47278
47278
|
where resolved_at is not null`.execute(db);
|
|
47279
47279
|
};
|
|
47280
|
-
const down$
|
|
47280
|
+
const down$24 = async (db) => {
|
|
47281
47281
|
await sql`drop table content_health_findings`.execute(db);
|
|
47282
47282
|
await sql`drop table editor_presence`.execute(db);
|
|
47283
47283
|
};
|
|
47284
47284
|
//#endregion
|
|
47285
47285
|
//#region src/db/migrations/20261003120000_add_changes_ship_permission.ts
|
|
47286
47286
|
var _20261003120000_add_changes_ship_permission_exports = /* @__PURE__ */ __exportAll({
|
|
47287
|
-
down: () => down$
|
|
47288
|
-
up: () => up$
|
|
47287
|
+
down: () => down$23,
|
|
47288
|
+
up: () => up$23
|
|
47289
47289
|
});
|
|
47290
47290
|
/**
|
|
47291
47291
|
* `changes.ship` (agentic plan §I): shipping a change set (and scheduling a ship) becomes its own global
|
|
@@ -47293,7 +47293,7 @@ var _20261003120000_add_changes_ship_permission_exports = /* @__PURE__ */ __expo
|
|
|
47293
47293
|
* live. Every role that holds `changes.manage` today keeps what it could do: it gets `changes.ship` too.
|
|
47294
47294
|
* The permissions version moves only when grants changed, so running instances reload exactly then.
|
|
47295
47295
|
*/
|
|
47296
|
-
const up$
|
|
47296
|
+
const up$23 = async (db) => {
|
|
47297
47297
|
await sql`
|
|
47298
47298
|
with granted as (
|
|
47299
47299
|
insert into admin_role_permissions (role_id, action, model_id, condition, field_ids)
|
|
@@ -47307,7 +47307,7 @@ const up$20 = async (db) => {
|
|
|
47307
47307
|
where exists (select 1 from granted)
|
|
47308
47308
|
`.execute(db);
|
|
47309
47309
|
};
|
|
47310
|
-
const down$
|
|
47310
|
+
const down$23 = async (db) => {
|
|
47311
47311
|
await sql`
|
|
47312
47312
|
with revoked as (
|
|
47313
47313
|
delete from admin_role_permissions where action = 'changes.ship' returning 1
|
|
@@ -47319,8 +47319,8 @@ const down$20 = async (db) => {
|
|
|
47319
47319
|
//#endregion
|
|
47320
47320
|
//#region src/db/migrations/20261003130000_create_sites.ts
|
|
47321
47321
|
var _20261003130000_create_sites_exports = /* @__PURE__ */ __exportAll({
|
|
47322
|
-
down: () => down$
|
|
47323
|
-
up: () => up$
|
|
47322
|
+
down: () => down$22,
|
|
47323
|
+
up: () => up$22
|
|
47324
47324
|
});
|
|
47325
47325
|
/**
|
|
47326
47326
|
* Sites (plan agentic-ecosystem §H, ADR 0011): one instance hosts many sites with one schema and one login.
|
|
@@ -47508,7 +47508,7 @@ const siteRoleAssignments = async (db) => {
|
|
|
47508
47508
|
`.execute(db);
|
|
47509
47509
|
await sql`alter table admin_invitations drop column role_ids`.execute(db);
|
|
47510
47510
|
};
|
|
47511
|
-
const up$
|
|
47511
|
+
const up$22 = async (db) => {
|
|
47512
47512
|
await createSites(db);
|
|
47513
47513
|
await addSiteColumns(db);
|
|
47514
47514
|
await tieCopiesToEntries(db);
|
|
@@ -47521,7 +47521,7 @@ const assertSingleSite = async (db) => {
|
|
|
47521
47521
|
const { rows } = await sql`select count(*)::text as count from sites`.execute(db);
|
|
47522
47522
|
if (Number(rows[0]?.count ?? 0) > 1) throw new Error("Cannot roll back sites while more than one site exists: merging them would merge their snapshot ledgers and uniqueness and widen role assignments. Delete the other sites first.");
|
|
47523
47523
|
};
|
|
47524
|
-
const down$
|
|
47524
|
+
const down$22 = async (db) => {
|
|
47525
47525
|
await assertSingleSite(db);
|
|
47526
47526
|
await sql`alter table admin_invitations add column role_ids uuid[] not null default '{}'::uuid[]`.execute(db);
|
|
47527
47527
|
await sql`
|
|
@@ -47592,8 +47592,8 @@ const down$19 = async (db) => {
|
|
|
47592
47592
|
//#endregion
|
|
47593
47593
|
//#region src/db/migrations/20261003140200_enqueue_field_index_layout.ts
|
|
47594
47594
|
var _20261003140200_enqueue_field_index_layout_exports = /* @__PURE__ */ __exportAll({
|
|
47595
|
-
down: () => down$
|
|
47596
|
-
up: () => up$
|
|
47595
|
+
down: () => down$21,
|
|
47596
|
+
up: () => up$21
|
|
47597
47597
|
});
|
|
47598
47598
|
/**
|
|
47599
47599
|
* Field index layout v2 (sites plan §H): per-field expression indexes on `entry_heads` lead with `site_id`,
|
|
@@ -47605,7 +47605,7 @@ var _20261003140200_enqueue_field_index_layout_exports = /* @__PURE__ */ __expor
|
|
|
47605
47605
|
*/
|
|
47606
47606
|
const JOB_TYPE$1 = "schema.fieldIndexLayout";
|
|
47607
47607
|
const IDEMPOTENCY_KEY$1 = "schema.fieldIndexLayout:v2";
|
|
47608
|
-
const up$
|
|
47608
|
+
const up$21 = async (db) => {
|
|
47609
47609
|
await sql`
|
|
47610
47610
|
insert into jobs (type, payload, max_attempts, idempotency_key)
|
|
47611
47611
|
select ${JOB_TYPE$1}, '{}'::jsonb, 5, ${IDEMPOTENCY_KEY$1}
|
|
@@ -47618,14 +47618,14 @@ const up$18 = async (db) => {
|
|
|
47618
47618
|
`.execute(db);
|
|
47619
47619
|
};
|
|
47620
47620
|
/** The layout job is idempotent; rolling back only forgets it if it has not run yet. */
|
|
47621
|
-
const down$
|
|
47621
|
+
const down$21 = async (db) => {
|
|
47622
47622
|
await sql`delete from jobs where idempotency_key = ${IDEMPOTENCY_KEY$1} and status = 'pending'`.execute(db);
|
|
47623
47623
|
};
|
|
47624
47624
|
//#endregion
|
|
47625
47625
|
//#region src/db/migrations/20261003140500_change_set_items_site_and_preview_entry.ts
|
|
47626
47626
|
var _20261003140500_change_set_items_site_and_preview_entry_exports = /* @__PURE__ */ __exportAll({
|
|
47627
|
-
down: () => down$
|
|
47628
|
-
up: () => up$
|
|
47627
|
+
down: () => down$20,
|
|
47628
|
+
up: () => up$20
|
|
47629
47629
|
});
|
|
47630
47630
|
/**
|
|
47631
47631
|
* Sites, publishing (plan agentic-ecosystem §H, package G5).
|
|
@@ -47636,7 +47636,7 @@ var _20261003140500_change_set_items_site_and_preview_entry_exports = /* @__PURE
|
|
|
47636
47636
|
* - `preview_tokens.entry_id` becomes required: a preview token previews one entry of one site. Model-wide
|
|
47637
47637
|
* tokens (short-lived by design) are deleted; whoever needs one opens the entry's preview again.
|
|
47638
47638
|
*/
|
|
47639
|
-
const up$
|
|
47639
|
+
const up$20 = async (db) => {
|
|
47640
47640
|
await sql`alter table change_sets add constraint change_sets_id_site_uq unique (id, site_id)`.execute(db);
|
|
47641
47641
|
await sql`alter table change_set_items add column site_id uuid`.execute(db);
|
|
47642
47642
|
await sql`
|
|
@@ -47652,7 +47652,7 @@ const up$17 = async (db) => {
|
|
|
47652
47652
|
await sql`delete from preview_tokens where entry_id is null`.execute(db);
|
|
47653
47653
|
await sql`alter table preview_tokens alter column entry_id set not null`.execute(db);
|
|
47654
47654
|
};
|
|
47655
|
-
const down$
|
|
47655
|
+
const down$20 = async (db) => {
|
|
47656
47656
|
await sql`alter table preview_tokens alter column entry_id drop not null`.execute(db);
|
|
47657
47657
|
await sql`alter table change_set_items drop constraint change_set_items_entry_site_fk`.execute(db);
|
|
47658
47658
|
await sql`alter table change_set_items drop constraint change_set_items_set_site_fk`.execute(db);
|
|
@@ -47662,8 +47662,8 @@ const down$17 = async (db) => {
|
|
|
47662
47662
|
//#endregion
|
|
47663
47663
|
//#region src/db/migrations/20261003150000_widen_deployment_providers.ts
|
|
47664
47664
|
var _20261003150000_widen_deployment_providers_exports = /* @__PURE__ */ __exportAll({
|
|
47665
|
-
down: () => down$
|
|
47666
|
-
up: () => up$
|
|
47665
|
+
down: () => down$19,
|
|
47666
|
+
up: () => up$19
|
|
47667
47667
|
});
|
|
47668
47668
|
/**
|
|
47669
47669
|
* Deploy adapters (plan agentic-ecosystem §B2): deployment connections may use the Vercel and Netlify
|
|
@@ -47678,11 +47678,11 @@ const replaceCheck = async (db, check) => {
|
|
|
47678
47678
|
check (${check}) not valid`.execute(db);
|
|
47679
47679
|
await sql`alter table deployment_connections validate constraint deployment_connections_provider_check`.execute(db);
|
|
47680
47680
|
};
|
|
47681
|
-
const up$
|
|
47681
|
+
const up$19 = async (db) => {
|
|
47682
47682
|
await replaceCheck(db, WIDENED);
|
|
47683
47683
|
};
|
|
47684
47684
|
/** Refuses while Vercel or Netlify connections exist: a down migration never deletes user data. */
|
|
47685
|
-
const down$
|
|
47685
|
+
const down$19 = async (db) => {
|
|
47686
47686
|
const { rows } = await sql`
|
|
47687
47687
|
select count(*)::text as count from deployment_connections where provider in ('vercel', 'netlify')
|
|
47688
47688
|
`.execute(db);
|
|
@@ -47693,8 +47693,8 @@ const down$16 = async (db) => {
|
|
|
47693
47693
|
//#endregion
|
|
47694
47694
|
//#region src/db/migrations/20261003160000_create_assist_runs.ts
|
|
47695
47695
|
var _20261003160000_create_assist_runs_exports = /* @__PURE__ */ __exportAll({
|
|
47696
|
-
down: () => down$
|
|
47697
|
-
up: () => up$
|
|
47696
|
+
down: () => down$18,
|
|
47697
|
+
up: () => up$18
|
|
47698
47698
|
});
|
|
47699
47699
|
/**
|
|
47700
47700
|
* Editor assists (plan agentic-ecosystem §A0, §I): one `assist_runs` row per assist request (who, which
|
|
@@ -47710,14 +47710,14 @@ const replaceSourceCheck = async (db, check) => {
|
|
|
47710
47710
|
await sql`alter table change_sets add constraint change_sets_source_check check (${check}) not valid`.execute(db);
|
|
47711
47711
|
await sql`alter table change_sets validate constraint change_sets_source_check`.execute(db);
|
|
47712
47712
|
};
|
|
47713
|
-
const up$
|
|
47713
|
+
const up$18 = async (db) => {
|
|
47714
47714
|
await db.schema.createTable("assist_runs").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("site_id", "uuid", (col) => col.notNull().references("sites.id").onDelete("cascade")).addColumn("actor_type", "text", (col) => col.notNull()).addColumn("actor_id", "text", (col) => col.notNull()).addColumn("action", "text", (col) => col.notNull().check(ACTIONS)).addColumn("rule", "text").addColumn("provider", "text", (col) => col.notNull()).addColumn("model", "text", (col) => col.notNull()).addColumn("input_tokens", "integer", (col) => col.notNull().defaultTo(0)).addColumn("output_tokens", "integer", (col) => col.notNull().defaultTo(0)).addColumn("duration_ms", "integer", (col) => col.notNull().defaultTo(0)).addColumn("status", "text", (col) => col.notNull().check(sql`status in ('queued', 'running', 'succeeded', 'failed')`)).addColumn("error_code", "text").addColumn("job_id", "uuid", (col) => col.references("jobs.id").onDelete("set null")).addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("finished_at", "timestamptz").execute();
|
|
47715
47715
|
await db.schema.createIndex("assist_runs_site_created_idx").on("assist_runs").columns(["site_id", "created_at"]).execute();
|
|
47716
47716
|
await db.schema.createIndex("assist_runs_created_idx").on("assist_runs").column("created_at").execute();
|
|
47717
47717
|
await replaceSourceCheck(db, SOURCES_WIDENED);
|
|
47718
47718
|
};
|
|
47719
47719
|
/** Refuses while change sets opened by assist exist: a down migration never deletes user data. */
|
|
47720
|
-
const down$
|
|
47720
|
+
const down$18 = async (db) => {
|
|
47721
47721
|
const { rows } = await sql`
|
|
47722
47722
|
select count(*)::text as count from change_sets where source = 'assist'
|
|
47723
47723
|
`.execute(db);
|
|
@@ -47729,8 +47729,8 @@ const down$15 = async (db) => {
|
|
|
47729
47729
|
//#endregion
|
|
47730
47730
|
//#region src/db/migrations/20261003170000_audit_events_seq.ts
|
|
47731
47731
|
var _20261003170000_audit_events_seq_exports$2 = /* @__PURE__ */ __exportAll({
|
|
47732
|
-
down: () => down$
|
|
47733
|
-
up: () => up$
|
|
47732
|
+
down: () => down$17,
|
|
47733
|
+
up: () => up$17
|
|
47734
47734
|
});
|
|
47735
47735
|
/**
|
|
47736
47736
|
* `audit_events.seq`: a monotonic tiebreaker after `occurred_at`, so events written in the same instant (one
|
|
@@ -47739,17 +47739,17 @@ var _20261003170000_audit_events_seq_exports$2 = /* @__PURE__ */ __exportAll({
|
|
|
47739
47739
|
* are numbered in the order the rewrite reads them. No index: the audit queries filter and sort by
|
|
47740
47740
|
* `occurred_at` first, and `seq` only breaks ties.
|
|
47741
47741
|
*/
|
|
47742
|
-
const up$
|
|
47742
|
+
const up$17 = async (db) => {
|
|
47743
47743
|
await db.schema.alterTable("audit_events").addColumn("seq", "bigint", (col) => col.notNull().generatedAlwaysAsIdentity()).execute();
|
|
47744
47744
|
};
|
|
47745
|
-
const down$
|
|
47745
|
+
const down$17 = async (db) => {
|
|
47746
47746
|
await db.schema.alterTable("audit_events").dropColumn("seq").execute();
|
|
47747
47747
|
};
|
|
47748
47748
|
//#endregion
|
|
47749
47749
|
//#region src/db/migrations/20261004120000_models_site_scope.ts
|
|
47750
47750
|
var _20261004120000_models_site_scope_exports$2 = /* @__PURE__ */ __exportAll({
|
|
47751
|
-
down: () => down$
|
|
47752
|
-
up: () => up$
|
|
47751
|
+
down: () => down$16,
|
|
47752
|
+
up: () => up$16
|
|
47753
47753
|
});
|
|
47754
47754
|
/**
|
|
47755
47755
|
* Per-site schema (plan site-schema): a definition belongs to one site (`models.site_id`) or is shared by every
|
|
@@ -47762,7 +47762,7 @@ var _20261004120000_models_site_scope_exports$2 = /* @__PURE__ */ __exportAll({
|
|
|
47762
47762
|
* over `lower(api_key)` cannot hold. Share or delete them first; then `down` is lossless.
|
|
47763
47763
|
*/
|
|
47764
47764
|
const NIL_UUID$1 = "00000000-0000-0000-0000-000000000000";
|
|
47765
|
-
const up$
|
|
47765
|
+
const up$16 = async (db) => {
|
|
47766
47766
|
await sql`alter table models add column site_id uuid references sites (id)`.execute(db);
|
|
47767
47767
|
await sql`create index models_site_idx on models (site_id)`.execute(db);
|
|
47768
47768
|
await sql`drop index models_api_key_uq`.execute(db);
|
|
@@ -47772,7 +47772,7 @@ const up$13 = async (db) => {
|
|
|
47772
47772
|
`.execute(db);
|
|
47773
47773
|
await sql`alter table schema_drafts add column shared boolean not null default false`.execute(db);
|
|
47774
47774
|
};
|
|
47775
|
-
const down$
|
|
47775
|
+
const down$16 = async (db) => {
|
|
47776
47776
|
const { rows } = await sql`select count(*)::text as count from models where site_id is not null`.execute(db);
|
|
47777
47777
|
if (Number(rows[0]?.count ?? 0) > 0) throw new Error("Cannot roll back per-site schema while definitions belong to a site: two sites may share an API ID. Share or delete the site definitions first.");
|
|
47778
47778
|
await sql`alter table schema_drafts drop column shared`.execute(db);
|
|
@@ -47784,8 +47784,8 @@ const down$13 = async (db) => {
|
|
|
47784
47784
|
//#endregion
|
|
47785
47785
|
//#region src/db/migrations/20261004130000_site_seo_settings.ts
|
|
47786
47786
|
var _20261004130000_site_seo_settings_exports$2 = /* @__PURE__ */ __exportAll({
|
|
47787
|
-
down: () => down$
|
|
47788
|
-
up: () => up$
|
|
47787
|
+
down: () => down$15,
|
|
47788
|
+
up: () => up$15
|
|
47789
47789
|
});
|
|
47790
47790
|
/**
|
|
47791
47791
|
* SEO defaults per site (plan seo-fields): `sites.seo_defaults` holds the site's default texts per locale, its
|
|
@@ -47796,7 +47796,7 @@ var _20261004130000_site_seo_settings_exports$2 = /* @__PURE__ */ __exportAll({
|
|
|
47796
47796
|
* about what a site publishes) gets it; the built-in owner and admin roles get it from `ensureSystemRoles`.
|
|
47797
47797
|
* The permissions version moves only when grants changed, so running instances reload exactly then.
|
|
47798
47798
|
*/
|
|
47799
|
-
const up$
|
|
47799
|
+
const up$15 = async (db) => {
|
|
47800
47800
|
await sql`alter table sites add column seo_defaults jsonb`.execute(db);
|
|
47801
47801
|
await sql`
|
|
47802
47802
|
with granted as (
|
|
@@ -47811,7 +47811,7 @@ const up$12 = async (db) => {
|
|
|
47811
47811
|
where exists (select 1 from granted)
|
|
47812
47812
|
`.execute(db);
|
|
47813
47813
|
};
|
|
47814
|
-
const down$
|
|
47814
|
+
const down$15 = async (db) => {
|
|
47815
47815
|
await sql`
|
|
47816
47816
|
with revoked as (
|
|
47817
47817
|
delete from admin_role_permissions where action = 'site.settings' returning 1
|
|
@@ -47824,8 +47824,8 @@ const down$12 = async (db) => {
|
|
|
47824
47824
|
//#endregion
|
|
47825
47825
|
//#region src/db/migrations/20261005120000_entry_heads_entry_created_at.ts
|
|
47826
47826
|
var _20261005120000_entry_heads_entry_created_at_exports$2 = /* @__PURE__ */ __exportAll({
|
|
47827
|
-
down: () => down$
|
|
47828
|
-
up: () => up$
|
|
47827
|
+
down: () => down$14,
|
|
47828
|
+
up: () => up$14
|
|
47829
47829
|
});
|
|
47830
47830
|
/**
|
|
47831
47831
|
* Delivery perf 2 (ADR 0001 amendment): the entry's `created_at` on each head (`entry_created_at`), so a list
|
|
@@ -47842,7 +47842,7 @@ const INDEX$2 = "entry_heads_entry_order_idx";
|
|
|
47842
47842
|
const JOB_TYPE = "schema.entryOrderIndex";
|
|
47843
47843
|
const IDEMPOTENCY_KEY = "schema.entryOrderIndex:v1";
|
|
47844
47844
|
const BATCH$1 = 5e3;
|
|
47845
|
-
const up$
|
|
47845
|
+
const up$14 = async (db) => {
|
|
47846
47846
|
await sql`alter table entry_heads add column entry_created_at timestamptz`.execute(db);
|
|
47847
47847
|
for (;;) {
|
|
47848
47848
|
const result = await sql`
|
|
@@ -47867,7 +47867,7 @@ const up$11 = async (db) => {
|
|
|
47867
47867
|
create index ${sql.id(INDEX$2)} on entry_heads (site_id, model_id, state, entry_created_at desc, entry_id)
|
|
47868
47868
|
`.execute(db);
|
|
47869
47869
|
};
|
|
47870
|
-
const down$
|
|
47870
|
+
const down$14 = async (db) => {
|
|
47871
47871
|
await sql`delete from jobs where idempotency_key = ${IDEMPOTENCY_KEY} and status = 'pending'`.execute(db);
|
|
47872
47872
|
await sql`drop index if exists ${sql.id(INDEX$2)}`.execute(db);
|
|
47873
47873
|
await sql`alter table entry_heads drop column entry_created_at`.execute(db);
|
|
@@ -47876,20 +47876,58 @@ const down$11 = async (db) => {
|
|
|
47876
47876
|
//#region src/db/migrations/20261006120000_system_versions_release.ts
|
|
47877
47877
|
var _20261006120000_system_versions_release_exports = /* @__PURE__ */ __exportAll({
|
|
47878
47878
|
dialectNeutral: () => true,
|
|
47879
|
-
down: () => down$
|
|
47880
|
-
up: () => up$
|
|
47879
|
+
down: () => down$13,
|
|
47880
|
+
up: () => up$13
|
|
47881
47881
|
});
|
|
47882
|
-
const up$
|
|
47882
|
+
const up$13 = async (db) => {
|
|
47883
47883
|
await db.schema.alterTable("system_versions").addColumn("release", "text").execute();
|
|
47884
47884
|
};
|
|
47885
|
-
const down$
|
|
47885
|
+
const down$13 = async (db) => {
|
|
47886
47886
|
await db.schema.alterTable("system_versions").dropColumn("release").execute();
|
|
47887
47887
|
};
|
|
47888
47888
|
//#endregion
|
|
47889
|
+
//#region src/db/migrations/20261014120000_canceled_status.ts
|
|
47890
|
+
var _20261014120000_canceled_status_exports$2 = /* @__PURE__ */ __exportAll({
|
|
47891
|
+
down: () => down$12,
|
|
47892
|
+
up: () => up$12
|
|
47893
|
+
});
|
|
47894
|
+
/**
|
|
47895
|
+
* The `cancelled` status of schema change jobs and scheduled publications becomes `canceled`. Rows are
|
|
47896
|
+
* rewritten and the check constraints swapped. MySQL has its own twin; SQLite rebuilds the two tables
|
|
47897
|
+
* (`./sqlite/20261014120000_canceled_status.ts`).
|
|
47898
|
+
*/
|
|
47899
|
+
const TABLES$4 = [{
|
|
47900
|
+
table: "schema_change_jobs",
|
|
47901
|
+
values: [
|
|
47902
|
+
"pending",
|
|
47903
|
+
"running",
|
|
47904
|
+
"activated",
|
|
47905
|
+
"failed"
|
|
47906
|
+
]
|
|
47907
|
+
}, {
|
|
47908
|
+
table: "scheduled_publications",
|
|
47909
|
+
values: [
|
|
47910
|
+
"scheduled",
|
|
47911
|
+
"done",
|
|
47912
|
+
"failed"
|
|
47913
|
+
]
|
|
47914
|
+
}];
|
|
47915
|
+
const swap$1 = async (db, from, to) => {
|
|
47916
|
+
for (const { table, values } of TABLES$4) {
|
|
47917
|
+
const constraint = `${table}_status_check`;
|
|
47918
|
+
await sql`alter table ${sql.table(table)} drop constraint ${sql.id(constraint)}`.execute(db);
|
|
47919
|
+
await sql`update ${sql.table(table)} set status = ${to} where status = ${from}`.execute(db);
|
|
47920
|
+
const allowed = sql.join([...values, to].map((value) => sql.lit(value)));
|
|
47921
|
+
await sql`alter table ${sql.table(table)} add constraint ${sql.id(constraint)} check (status in (${allowed}))`.execute(db);
|
|
47922
|
+
}
|
|
47923
|
+
};
|
|
47924
|
+
const up$12 = (db) => swap$1(db, "cancelled", "canceled");
|
|
47925
|
+
const down$12 = (db) => swap$1(db, "canceled", "cancelled");
|
|
47926
|
+
//#endregion
|
|
47889
47927
|
//#region src/db/migrations/mysql/0001_baseline.ts
|
|
47890
47928
|
var _0001_baseline_exports$1 = /* @__PURE__ */ __exportAll({
|
|
47891
|
-
down: () => down$
|
|
47892
|
-
up: () => up$
|
|
47929
|
+
down: () => down$11,
|
|
47930
|
+
up: () => up$11
|
|
47893
47931
|
});
|
|
47894
47932
|
/**
|
|
47895
47933
|
* MySQL baseline: Shapio's whole system schema as of PostgreSQL migration
|
|
@@ -48999,7 +49037,7 @@ const STATEMENTS$1 = [
|
|
|
48999
49037
|
('00000000-0000-4000-b000-000000000001', 'public', '00000000-0000-4000-a000-000000000001'),
|
|
49000
49038
|
('00000000-0000-4000-b000-000000000001', 'authenticated', '00000000-0000-4000-a000-000000000002')`
|
|
49001
49039
|
];
|
|
49002
|
-
const TABLES$
|
|
49040
|
+
const TABLES$3 = [
|
|
49003
49041
|
"system_versions",
|
|
49004
49042
|
"jobs",
|
|
49005
49043
|
"outbox_events",
|
|
@@ -49072,13 +49110,13 @@ const withoutForeignKeyChecks = async (db, statements) => db.connection().execut
|
|
|
49072
49110
|
await sql`set foreign_key_checks = 1`.execute(connection);
|
|
49073
49111
|
}
|
|
49074
49112
|
});
|
|
49075
|
-
const up$
|
|
49076
|
-
const down$
|
|
49113
|
+
const up$11 = async (db) => withoutForeignKeyChecks(db, STATEMENTS$1);
|
|
49114
|
+
const down$11 = async (db) => withoutForeignKeyChecks(db, [...TABLES$3].reverse().map((table) => `drop table if exists \`${table}\``));
|
|
49077
49115
|
//#endregion
|
|
49078
49116
|
//#region src/db/migrations/mysql/20261003170000_audit_events_seq.ts
|
|
49079
49117
|
var _20261003170000_audit_events_seq_exports$1 = /* @__PURE__ */ __exportAll({
|
|
49080
|
-
down: () => down$
|
|
49081
|
-
up: () => up$
|
|
49118
|
+
down: () => down$10,
|
|
49119
|
+
up: () => up$10
|
|
49082
49120
|
});
|
|
49083
49121
|
/**
|
|
49084
49122
|
* MySQL twin of `../20261003170000_audit_events_seq.ts`: `seq` is `AUTO_INCREMENT`, which InnoDB only allows
|
|
@@ -49086,26 +49124,26 @@ var _20261003170000_audit_events_seq_exports$1 = /* @__PURE__ */ __exportAll({
|
|
|
49086
49124
|
* tiebreaker). Existing rows are numbered in primary-key order. `db/mysql/tables.ts` lists `seq` as the
|
|
49087
49125
|
* table's identity, so an insert's emulated RETURNING finds its row by `LAST_INSERT_ID()`.
|
|
49088
49126
|
*/
|
|
49089
|
-
const up$
|
|
49127
|
+
const up$10 = async (db) => {
|
|
49090
49128
|
await sql`alter table \`audit_events\`
|
|
49091
49129
|
add column \`seq\` bigint not null auto_increment,
|
|
49092
49130
|
add unique key \`audit_events_seq_key\` (\`seq\`)`.execute(db);
|
|
49093
49131
|
};
|
|
49094
|
-
const down$
|
|
49132
|
+
const down$10 = async (db) => {
|
|
49095
49133
|
await sql`alter table \`audit_events\` drop column \`seq\``.execute(db);
|
|
49096
49134
|
};
|
|
49097
49135
|
//#endregion
|
|
49098
49136
|
//#region src/db/migrations/mysql/20261004120000_models_site_scope.ts
|
|
49099
49137
|
var _20261004120000_models_site_scope_exports$1 = /* @__PURE__ */ __exportAll({
|
|
49100
|
-
down: () => down$
|
|
49101
|
-
up: () => up$
|
|
49138
|
+
down: () => down$9,
|
|
49139
|
+
up: () => up$9
|
|
49102
49140
|
});
|
|
49103
49141
|
/**
|
|
49104
49142
|
* MySQL twin of `../20261004120000_models_site_scope.ts`. The per-scope API ID key uses functional key parts,
|
|
49105
49143
|
* like the baseline: `coalesce(site_id, '')` for the scope (MySQL has no `NULLS NOT DISTINCT`) and the
|
|
49106
49144
|
* case-folded API ID of live rows only (a deleted row's part is NULL, and NULLs never collide).
|
|
49107
49145
|
*/
|
|
49108
|
-
const up$
|
|
49146
|
+
const up$9 = async (db) => {
|
|
49109
49147
|
await sql`alter table \`models\` add column \`site_id\` char(36) character set ascii collate ascii_general_ci`.execute(db);
|
|
49110
49148
|
await sql`create index \`models_site_idx\` on \`models\` (\`site_id\`)`.execute(db);
|
|
49111
49149
|
await sql`alter table \`models\` add constraint \`models_site_id_fkey\` foreign key (\`site_id\`) references \`sites\` (\`id\`)`.execute(db);
|
|
@@ -49114,7 +49152,7 @@ const up$7 = async (db) => {
|
|
|
49114
49152
|
((coalesce(\`site_id\`, '')), (case when (\`deleted_at\` IS NULL) then lower(\`api_key\`) end))`.execute(db);
|
|
49115
49153
|
await sql`alter table \`schema_drafts\` add column \`shared\` tinyint(1) not null default 0`.execute(db);
|
|
49116
49154
|
};
|
|
49117
|
-
const down$
|
|
49155
|
+
const down$9 = async (db) => {
|
|
49118
49156
|
const { rows } = await sql`select count(*) as count from \`models\` where \`site_id\` is not null`.execute(db);
|
|
49119
49157
|
if (Number(rows[0]?.count ?? 0) > 0) throw new Error("Cannot roll back per-site schema while definitions belong to a site: two sites may share an API ID. Share or delete the site definitions first.");
|
|
49120
49158
|
await sql`alter table \`schema_drafts\` drop column \`shared\``.execute(db);
|
|
@@ -49128,8 +49166,8 @@ const down$7 = async (db) => {
|
|
|
49128
49166
|
//#endregion
|
|
49129
49167
|
//#region src/db/migrations/mysql/20261004130000_site_seo_settings.ts
|
|
49130
49168
|
var _20261004130000_site_seo_settings_exports$1 = /* @__PURE__ */ __exportAll({
|
|
49131
|
-
down: () => down$
|
|
49132
|
-
up: () => up$
|
|
49169
|
+
down: () => down$8,
|
|
49170
|
+
up: () => up$8
|
|
49133
49171
|
});
|
|
49134
49172
|
/**
|
|
49135
49173
|
* MySQL twin of `../20261004130000_site_seo_settings.ts`. `insert ignore` stands in for `on conflict do
|
|
@@ -49137,7 +49175,7 @@ var _20261004130000_site_seo_settings_exports$1 = /* @__PURE__ */ __exportAll({
|
|
|
49137
49175
|
*/
|
|
49138
49176
|
const bumpPermissionsVersion$1 = (db) => sql`update \`system_versions\` set \`permissions_version\` = \`permissions_version\` + 1,
|
|
49139
49177
|
\`updated_at\` = current_timestamp(6)`.execute(db);
|
|
49140
|
-
const up$
|
|
49178
|
+
const up$8 = async (db) => {
|
|
49141
49179
|
await sql`alter table \`sites\` add column \`seo_defaults\` json`.execute(db);
|
|
49142
49180
|
const granted = await sql`
|
|
49143
49181
|
insert ignore into \`admin_role_permissions\` (\`id\`, \`role_id\`, \`action\`, \`model_id\`, \`condition\`, \`field_ids\`)
|
|
@@ -49147,7 +49185,7 @@ const up$6 = async (db) => {
|
|
|
49147
49185
|
`.execute(db);
|
|
49148
49186
|
if (Number(granted.numAffectedRows ?? 0) > 0) await bumpPermissionsVersion$1(db);
|
|
49149
49187
|
};
|
|
49150
|
-
const down$
|
|
49188
|
+
const down$8 = async (db) => {
|
|
49151
49189
|
const revoked = await sql`delete from \`admin_role_permissions\` where \`action\` = 'site.settings'`.execute(db);
|
|
49152
49190
|
if (Number(revoked.numAffectedRows ?? 0) > 0) await bumpPermissionsVersion$1(db);
|
|
49153
49191
|
await sql`alter table \`sites\` drop column \`seo_defaults\``.execute(db);
|
|
@@ -49155,8 +49193,8 @@ const down$6 = async (db) => {
|
|
|
49155
49193
|
//#endregion
|
|
49156
49194
|
//#region src/db/migrations/mysql/20261005120000_entry_heads_entry_created_at.ts
|
|
49157
49195
|
var _20261005120000_entry_heads_entry_created_at_exports$1 = /* @__PURE__ */ __exportAll({
|
|
49158
|
-
down: () => down$
|
|
49159
|
-
up: () => up$
|
|
49196
|
+
down: () => down$7,
|
|
49197
|
+
up: () => up$7
|
|
49160
49198
|
});
|
|
49161
49199
|
/**
|
|
49162
49200
|
* MySQL twin of `../20261005120000_entry_heads_entry_created_at.ts`. The column is added `ALGORITHM=INSTANT`
|
|
@@ -49165,7 +49203,7 @@ var _20261005120000_entry_heads_entry_created_at_exports$1 = /* @__PURE__ */ __e
|
|
|
49165
49203
|
*/
|
|
49166
49204
|
const INDEX$1 = "entry_heads_entry_order_idx";
|
|
49167
49205
|
const BATCH = 5e3;
|
|
49168
|
-
const up$
|
|
49206
|
+
const up$7 = async (db) => {
|
|
49169
49207
|
await sql`alter table \`entry_heads\` add column \`entry_created_at\` datetime(6), algorithm=instant`.execute(db);
|
|
49170
49208
|
for (;;) {
|
|
49171
49209
|
const result = await sql`update \`entry_heads\` set \`entry_created_at\` = (
|
|
@@ -49176,11 +49214,48 @@ const up$5 = async (db) => {
|
|
|
49176
49214
|
await sql`create index ${sql.id(INDEX$1)} on \`entry_heads\`
|
|
49177
49215
|
(\`site_id\`, \`model_id\`, \`state\`, \`entry_created_at\` desc, \`entry_id\`) algorithm=inplace lock=none`.execute(db);
|
|
49178
49216
|
};
|
|
49179
|
-
const down$
|
|
49217
|
+
const down$7 = async (db) => {
|
|
49180
49218
|
await sql`drop index ${sql.id(INDEX$1)} on \`entry_heads\``.execute(db);
|
|
49181
49219
|
await sql`alter table \`entry_heads\` drop column \`entry_created_at\``.execute(db);
|
|
49182
49220
|
};
|
|
49183
49221
|
//#endregion
|
|
49222
|
+
//#region src/db/migrations/mysql/20261014120000_canceled_status.ts
|
|
49223
|
+
var _20261014120000_canceled_status_exports$1 = /* @__PURE__ */ __exportAll({
|
|
49224
|
+
down: () => down$6,
|
|
49225
|
+
up: () => up$6
|
|
49226
|
+
});
|
|
49227
|
+
/**
|
|
49228
|
+
* MySQL twin of `../20261014120000_canceled_status.ts`: MySQL 8.4 drops a check constraint with
|
|
49229
|
+
* `drop check`, not `drop constraint`.
|
|
49230
|
+
*/
|
|
49231
|
+
const TABLES$2 = [{
|
|
49232
|
+
table: "schema_change_jobs",
|
|
49233
|
+
values: [
|
|
49234
|
+
"pending",
|
|
49235
|
+
"running",
|
|
49236
|
+
"activated",
|
|
49237
|
+
"failed"
|
|
49238
|
+
]
|
|
49239
|
+
}, {
|
|
49240
|
+
table: "scheduled_publications",
|
|
49241
|
+
values: [
|
|
49242
|
+
"scheduled",
|
|
49243
|
+
"done",
|
|
49244
|
+
"failed"
|
|
49245
|
+
]
|
|
49246
|
+
}];
|
|
49247
|
+
const swap = async (db, from, to) => {
|
|
49248
|
+
for (const { table, values } of TABLES$2) {
|
|
49249
|
+
const constraint = `${table}_status_check`;
|
|
49250
|
+
await sql`alter table ${sql.table(table)} drop check ${sql.id(constraint)}`.execute(db);
|
|
49251
|
+
await sql`update ${sql.table(table)} set status = ${to} where status = ${from}`.execute(db);
|
|
49252
|
+
const allowed = sql.join([...values, to].map((value) => sql.lit(value)));
|
|
49253
|
+
await sql`alter table ${sql.table(table)} add constraint ${sql.id(constraint)} check (status in (${allowed}))`.execute(db);
|
|
49254
|
+
}
|
|
49255
|
+
};
|
|
49256
|
+
const up$6 = (db) => swap(db, "cancelled", "canceled");
|
|
49257
|
+
const down$6 = (db) => swap(db, "canceled", "cancelled");
|
|
49258
|
+
//#endregion
|
|
49184
49259
|
//#region src/db/migrations/mysql/index.ts
|
|
49185
49260
|
const MYSQL_MIGRATIONS = {
|
|
49186
49261
|
"0001_baseline": _0001_baseline_exports$1,
|
|
@@ -49188,13 +49263,14 @@ const MYSQL_MIGRATIONS = {
|
|
|
49188
49263
|
"20261004120000_models_site_scope": _20261004120000_models_site_scope_exports$1,
|
|
49189
49264
|
"20261004130000_site_seo_settings": _20261004130000_site_seo_settings_exports$1,
|
|
49190
49265
|
"20261005120000_entry_heads_entry_created_at": _20261005120000_entry_heads_entry_created_at_exports$1,
|
|
49191
|
-
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports
|
|
49266
|
+
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports,
|
|
49267
|
+
"20261014120000_canceled_status": _20261014120000_canceled_status_exports$1
|
|
49192
49268
|
};
|
|
49193
49269
|
//#endregion
|
|
49194
49270
|
//#region src/db/migrations/sqlite/0001_baseline.ts
|
|
49195
49271
|
var _0001_baseline_exports = /* @__PURE__ */ __exportAll({
|
|
49196
|
-
down: () => down$
|
|
49197
|
-
up: () => up$
|
|
49272
|
+
down: () => down$5,
|
|
49273
|
+
up: () => up$5
|
|
49198
49274
|
});
|
|
49199
49275
|
/**
|
|
49200
49276
|
* SQLite baseline: Shapio's whole system schema as of PostgreSQL migration
|
|
@@ -50277,7 +50353,7 @@ const STATEMENTS = [
|
|
|
50277
50353
|
('00000000-0000-4000-b000-000000000001', 'public', '00000000-0000-4000-a000-000000000001'),
|
|
50278
50354
|
('00000000-0000-4000-b000-000000000001', 'authenticated', '00000000-0000-4000-a000-000000000002')`
|
|
50279
50355
|
];
|
|
50280
|
-
const TABLES = [
|
|
50356
|
+
const TABLES$1 = [
|
|
50281
50357
|
"system_versions",
|
|
50282
50358
|
"jobs",
|
|
50283
50359
|
"outbox_events",
|
|
@@ -50339,18 +50415,18 @@ const TABLES = [
|
|
|
50339
50415
|
"assist_runs",
|
|
50340
50416
|
"sequences"
|
|
50341
50417
|
];
|
|
50342
|
-
const up$
|
|
50418
|
+
const up$5 = async (db) => {
|
|
50343
50419
|
for (const statement of STATEMENTS) await sql.raw(statement).execute(db);
|
|
50344
50420
|
};
|
|
50345
|
-
const down$
|
|
50421
|
+
const down$5 = async (db) => {
|
|
50346
50422
|
await sql`pragma defer_foreign_keys = on`.execute(db);
|
|
50347
|
-
for (const table of [...TABLES].reverse()) await sql.raw(`drop table if exists "${table}"`).execute(db);
|
|
50423
|
+
for (const table of [...TABLES$1].reverse()) await sql.raw(`drop table if exists "${table}"`).execute(db);
|
|
50348
50424
|
};
|
|
50349
50425
|
//#endregion
|
|
50350
50426
|
//#region src/db/migrations/sqlite/20261003170000_audit_events_seq.ts
|
|
50351
50427
|
var _20261003170000_audit_events_seq_exports = /* @__PURE__ */ __exportAll({
|
|
50352
|
-
down: () => down$
|
|
50353
|
-
up: () => up$
|
|
50428
|
+
down: () => down$4,
|
|
50429
|
+
up: () => up$4
|
|
50354
50430
|
});
|
|
50355
50431
|
/**
|
|
50356
50432
|
* SQLite twin of `../20261003170000_audit_events_seq.ts`. SQLite cannot add a column whose default calls a
|
|
@@ -50377,7 +50453,7 @@ const INDEXES = [
|
|
|
50377
50453
|
`create index "audit_events_occurred_at_idx" on "audit_events" (occurred_at DESC)`,
|
|
50378
50454
|
`create index "audit_events_target_idx" on "audit_events" (target_type, target_id, occurred_at DESC)`
|
|
50379
50455
|
];
|
|
50380
|
-
const up$
|
|
50456
|
+
const up$4 = async (db) => {
|
|
50381
50457
|
await sql`insert into "sequences" (name, value) values ('audit_events_seq', 0)`.execute(db);
|
|
50382
50458
|
await sql`alter table "audit_events" rename to "audit_events_before_seq"`.execute(db);
|
|
50383
50459
|
await sql`create table "audit_events" (
|
|
@@ -50405,15 +50481,15 @@ const up$3 = async (db) => {
|
|
|
50405
50481
|
await sql`drop table "audit_events_before_seq"`.execute(db);
|
|
50406
50482
|
for (const statement of INDEXES) await sql.raw(statement).execute(db);
|
|
50407
50483
|
};
|
|
50408
|
-
const down$
|
|
50484
|
+
const down$4 = async (db) => {
|
|
50409
50485
|
await sql`alter table "audit_events" drop column "seq"`.execute(db);
|
|
50410
50486
|
await sql`delete from "sequences" where name = 'audit_events_seq'`.execute(db);
|
|
50411
50487
|
};
|
|
50412
50488
|
//#endregion
|
|
50413
50489
|
//#region src/db/migrations/sqlite/20261004120000_models_site_scope.ts
|
|
50414
50490
|
var _20261004120000_models_site_scope_exports = /* @__PURE__ */ __exportAll({
|
|
50415
|
-
down: () => down$
|
|
50416
|
-
up: () => up$
|
|
50491
|
+
down: () => down$3,
|
|
50492
|
+
up: () => up$3
|
|
50417
50493
|
});
|
|
50418
50494
|
/**
|
|
50419
50495
|
* SQLite twin of `../20261004120000_models_site_scope.ts`. `down` rebuilds `models` without `site_id`
|
|
@@ -50423,7 +50499,7 @@ var _20261004120000_models_site_scope_exports = /* @__PURE__ */ __exportAll({
|
|
|
50423
50499
|
* deletes nothing they reference.
|
|
50424
50500
|
*/
|
|
50425
50501
|
const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
50426
|
-
const up$
|
|
50502
|
+
const up$3 = async (db) => {
|
|
50427
50503
|
await sql`alter table "models" add column "site_id" text_uuid references sites (id)`.execute(db);
|
|
50428
50504
|
await sql`create index "models_site_idx" on "models" (site_id)`.execute(db);
|
|
50429
50505
|
await sql`drop index "models_api_key_uq"`.execute(db);
|
|
@@ -50433,7 +50509,7 @@ const up$2 = async (db) => {
|
|
|
50433
50509
|
`.execute(db);
|
|
50434
50510
|
await sql`alter table "schema_drafts" add column "shared" integer_boolean not null default 0`.execute(db);
|
|
50435
50511
|
};
|
|
50436
|
-
const down$
|
|
50512
|
+
const down$3 = async (db) => {
|
|
50437
50513
|
const { rows } = await sql`select count(*) as count from "models" where site_id is not null`.execute(db);
|
|
50438
50514
|
if (Number(rows[0]?.count ?? 0) > 0) throw new Error("Cannot roll back per-site schema while definitions belong to a site: two sites may share an API ID. Share or delete the site definitions first.");
|
|
50439
50515
|
await sql`alter table "schema_drafts" drop column "shared"`.execute(db);
|
|
@@ -50458,15 +50534,15 @@ const down$2 = async (db) => {
|
|
|
50458
50534
|
//#endregion
|
|
50459
50535
|
//#region src/db/migrations/sqlite/20261004130000_site_seo_settings.ts
|
|
50460
50536
|
var _20261004130000_site_seo_settings_exports = /* @__PURE__ */ __exportAll({
|
|
50461
|
-
down: () => down$
|
|
50462
|
-
up: () => up$
|
|
50537
|
+
down: () => down$2,
|
|
50538
|
+
up: () => up$2
|
|
50463
50539
|
});
|
|
50464
50540
|
/**
|
|
50465
50541
|
* SQLite twin of `../20261004130000_site_seo_settings.ts`. `insert or ignore` stands in for `on conflict do
|
|
50466
50542
|
* nothing` (the grant's unique index); the permissions version moves only when a grant was added or removed.
|
|
50467
50543
|
*/
|
|
50468
50544
|
const bumpPermissionsVersion = (db) => sql`update "system_versions" set permissions_version = permissions_version + 1, updated_at = shapio_now()`.execute(db);
|
|
50469
|
-
const up$
|
|
50545
|
+
const up$2 = async (db) => {
|
|
50470
50546
|
await sql`alter table "sites" add column "seo_defaults" text_jsonb`.execute(db);
|
|
50471
50547
|
const granted = await sql`
|
|
50472
50548
|
insert or ignore into "admin_role_permissions" (role_id, action, model_id, condition, field_ids)
|
|
@@ -50476,7 +50552,7 @@ const up$1 = async (db) => {
|
|
|
50476
50552
|
`.execute(db);
|
|
50477
50553
|
if (Number(granted.numAffectedRows ?? 0) > 0) await bumpPermissionsVersion(db);
|
|
50478
50554
|
};
|
|
50479
|
-
const down$
|
|
50555
|
+
const down$2 = async (db) => {
|
|
50480
50556
|
const revoked = await sql`delete from "admin_role_permissions" where action = 'site.settings'`.execute(db);
|
|
50481
50557
|
if (Number(revoked.numAffectedRows ?? 0) > 0) await bumpPermissionsVersion(db);
|
|
50482
50558
|
await sql`alter table "sites" drop column "seo_defaults"`.execute(db);
|
|
@@ -50484,8 +50560,8 @@ const down$1 = async (db) => {
|
|
|
50484
50560
|
//#endregion
|
|
50485
50561
|
//#region src/db/migrations/sqlite/20261005120000_entry_heads_entry_created_at.ts
|
|
50486
50562
|
var _20261005120000_entry_heads_entry_created_at_exports = /* @__PURE__ */ __exportAll({
|
|
50487
|
-
down: () => down,
|
|
50488
|
-
up: () => up
|
|
50563
|
+
down: () => down$1,
|
|
50564
|
+
up: () => up$1
|
|
50489
50565
|
});
|
|
50490
50566
|
/**
|
|
50491
50567
|
* SQLite twin of `../20261005120000_entry_heads_entry_created_at.ts`. One process holds the write lock, so
|
|
@@ -50493,18 +50569,61 @@ var _20261005120000_entry_heads_entry_created_at_exports = /* @__PURE__ */ __exp
|
|
|
50493
50569
|
* documented single-process limitation of ADR 0001, "D2: as built").
|
|
50494
50570
|
*/
|
|
50495
50571
|
const INDEX = "entry_heads_entry_order_idx";
|
|
50496
|
-
const up = async (db) => {
|
|
50572
|
+
const up$1 = async (db) => {
|
|
50497
50573
|
await sql`alter table "entry_heads" add column "entry_created_at" text_timestamptz`.execute(db);
|
|
50498
50574
|
await sql`update "entry_heads" set entry_created_at = (
|
|
50499
50575
|
select e.created_at from "entries" e where e.id = "entry_heads".entry_id
|
|
50500
50576
|
) where entry_created_at is null`.execute(db);
|
|
50501
50577
|
await sql`create index ${sql.id(INDEX)} on "entry_heads" (site_id, model_id, state, entry_created_at desc, entry_id)`.execute(db);
|
|
50502
50578
|
};
|
|
50503
|
-
const down = async (db) => {
|
|
50579
|
+
const down$1 = async (db) => {
|
|
50504
50580
|
await sql`drop index if exists ${sql.id(INDEX)}`.execute(db);
|
|
50505
50581
|
await sql`alter table "entry_heads" drop column "entry_created_at"`.execute(db);
|
|
50506
50582
|
};
|
|
50507
50583
|
//#endregion
|
|
50584
|
+
//#region src/db/migrations/sqlite/20261014120000_canceled_status.ts
|
|
50585
|
+
var _20261014120000_canceled_status_exports = /* @__PURE__ */ __exportAll({
|
|
50586
|
+
down: () => down,
|
|
50587
|
+
up: () => up
|
|
50588
|
+
});
|
|
50589
|
+
/**
|
|
50590
|
+
* SQLite twin of `../20261014120000_canceled_status.ts`. SQLite cannot change a check constraint, so each
|
|
50591
|
+
* table is rebuilt from its own stored `create table` statement with the one value swapped: renamed aside
|
|
50592
|
+
* (with `legacy_alter_table` on, so references to the name keep pointing at it), recreated, refilled with the
|
|
50593
|
+
* status rewritten, and its indexes recreated from `sqlite_master`. Nothing references either table.
|
|
50594
|
+
*/
|
|
50595
|
+
const TABLES = ["schema_change_jobs", "scheduled_publications"];
|
|
50596
|
+
const rebuild = async (db, table, from, to) => {
|
|
50597
|
+
const { rows: created } = await sql`
|
|
50598
|
+
select sql from sqlite_master where type = 'table' and name = ${table}
|
|
50599
|
+
`.execute(db);
|
|
50600
|
+
const { rows: indexes } = await sql`
|
|
50601
|
+
select sql from sqlite_master where type = 'index' and tbl_name = ${table} and sql is not null
|
|
50602
|
+
`.execute(db);
|
|
50603
|
+
const definition = created[0]?.sql;
|
|
50604
|
+
if (!definition || !definition.includes(`'${from}'`)) throw new Error(`${table}: expected a status check allowing '${from}'`);
|
|
50605
|
+
const repaired = definition.replace(/references\s+("?)(\w+?)_before_\w+\1/gi, (_, quote, base) => `references ${quote}${base}${quote}`);
|
|
50606
|
+
const aside = `${table}_before_${to}`;
|
|
50607
|
+
await sql`pragma legacy_alter_table = on`.execute(db);
|
|
50608
|
+
await sql`alter table ${sql.table(table)} rename to ${sql.table(aside)}`.execute(db);
|
|
50609
|
+
await sql.raw(repaired.replace(`'${from}'`, `'${to}'`)).execute(db);
|
|
50610
|
+
const { rows: columns } = await sql`
|
|
50611
|
+
select name from pragma_table_info(${aside}) order by cid
|
|
50612
|
+
`.execute(db);
|
|
50613
|
+
const names = columns.map(({ name }) => sql.id(name));
|
|
50614
|
+
const values = columns.map(({ name }) => name === "status" ? sql`case when status = ${from} then ${to} else status end` : sql.id(name));
|
|
50615
|
+
await sql`insert into ${sql.table(table)} (${sql.join(names)}) select ${sql.join(values)} from ${sql.table(aside)}`.execute(db);
|
|
50616
|
+
await sql`drop table ${sql.table(aside)}`.execute(db);
|
|
50617
|
+
await sql`pragma legacy_alter_table = off`.execute(db);
|
|
50618
|
+
for (const { sql: index } of indexes) await sql.raw(index).execute(db);
|
|
50619
|
+
};
|
|
50620
|
+
const up = async (db) => {
|
|
50621
|
+
for (const table of TABLES) await rebuild(db, table, "cancelled", "canceled");
|
|
50622
|
+
};
|
|
50623
|
+
const down = async (db) => {
|
|
50624
|
+
for (const table of TABLES) await rebuild(db, table, "canceled", "cancelled");
|
|
50625
|
+
};
|
|
50626
|
+
//#endregion
|
|
50508
50627
|
//#region src/db/migrations/sqlite/index.ts
|
|
50509
50628
|
const SQLITE_MIGRATIONS = {
|
|
50510
50629
|
"0001_baseline": _0001_baseline_exports,
|
|
@@ -50512,7 +50631,8 @@ const SQLITE_MIGRATIONS = {
|
|
|
50512
50631
|
"20261004120000_models_site_scope": _20261004120000_models_site_scope_exports,
|
|
50513
50632
|
"20261004130000_site_seo_settings": _20261004130000_site_seo_settings_exports,
|
|
50514
50633
|
"20261005120000_entry_heads_entry_created_at": _20261005120000_entry_heads_entry_created_at_exports,
|
|
50515
|
-
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports
|
|
50634
|
+
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports,
|
|
50635
|
+
"20261014120000_canceled_status": _20261014120000_canceled_status_exports
|
|
50516
50636
|
};
|
|
50517
50637
|
//#endregion
|
|
50518
50638
|
//#region src/db/migrations/index.ts
|
|
@@ -50546,7 +50666,8 @@ const MIGRATIONS = {
|
|
|
50546
50666
|
"20261004120000_models_site_scope": _20261004120000_models_site_scope_exports$2,
|
|
50547
50667
|
"20261004130000_site_seo_settings": _20261004130000_site_seo_settings_exports$2,
|
|
50548
50668
|
"20261005120000_entry_heads_entry_created_at": _20261005120000_entry_heads_entry_created_at_exports$2,
|
|
50549
|
-
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports
|
|
50669
|
+
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports,
|
|
50670
|
+
"20261014120000_canceled_status": _20261014120000_canceled_status_exports$2
|
|
50550
50671
|
};
|
|
50551
50672
|
const PROVIDERS = {
|
|
50552
50673
|
postgres: { getMigrations: () => Promise.resolve({ ...MIGRATIONS }) },
|
|
@@ -51016,7 +51137,7 @@ const mediaFilesRoutes = async (app) => {
|
|
|
51016
51137
|
//#region src/services/previewContent.ts
|
|
51017
51138
|
/**
|
|
51018
51139
|
* `/api/preview/content/:modelKey[/:id]` (brief §7): DRAFT content for a site's preview, in the delivery
|
|
51019
|
-
* shape,
|
|
51140
|
+
* shape, authorized by a preview token. Reads are evaluated with the token creator's CURRENT permissions
|
|
51020
51141
|
* (so revoking their role ends the preview), limited to read, to the token's model, entry and locale, and to
|
|
51021
51142
|
* fields a delivery reader would see (`public` fields within the creator's read mask), so a shared preview
|
|
51022
51143
|
* link never shows more than the published site would.
|
|
@@ -51207,7 +51328,7 @@ const getPreview = async (request, reply) => send(reply, await getPreview$1(requ
|
|
|
51207
51328
|
//#region src/routes/preview/index.ts
|
|
51208
51329
|
/**
|
|
51209
51330
|
* /api/preview/content/:modelKey[/:id]: draft content for site previews, addressed by route key like
|
|
51210
|
-
* delivery (plural API ID of a collection),
|
|
51331
|
+
* delivery (plural API ID of a collection), authorized by a preview token in
|
|
51211
51332
|
* `Authorization: Bearer shpv_…` (never a query parameter, so tokens stay out of access logs).
|
|
51212
51333
|
*/
|
|
51213
51334
|
const previewRoutes = async (app) => {
|
|
@@ -51452,7 +51573,7 @@ const buildApp = async (config, deps) => {
|
|
|
51452
51573
|
await app.register(contentHooksPlugin, { hooks: deps.contentHooks ?? extensions.hooks });
|
|
51453
51574
|
await app.register(adminContentRoutes, { prefix: urls.withBasePath("/api/admin/content") });
|
|
51454
51575
|
await app.register(editorManifestPlugin, { manifest: deps.editorManifest ?? buildEditorManifest(extensions.loaded.projectDir, extensions.loaded.config.editors ?? [], app.log.child({ component: "extensions" })) });
|
|
51455
|
-
await app.register(
|
|
51576
|
+
await app.register(themeCatalogPlugin, { catalog: buildThemeCatalog(extensions.loaded.config.themes ?? []) });
|
|
51456
51577
|
await app.register(adminExtensionsRoutes, { prefix: urls.withBasePath("/api/admin/extensions") });
|
|
51457
51578
|
await app.register(deliveryRoutes, { prefix: urls.withBasePath("/api/content") });
|
|
51458
51579
|
await app.register(siteRoutes, { prefix: urls.withBasePath("/api/site") });
|
|
@@ -52397,7 +52518,7 @@ const EXPIRING_CREDENTIAL_TABLES = [
|
|
|
52397
52518
|
"admin_invitations"
|
|
52398
52519
|
];
|
|
52399
52520
|
/**
|
|
52400
|
-
* Credentials that expired before the cutoff: they no longer
|
|
52521
|
+
* Credentials that expired before the cutoff: they no longer authorize anything, and the retention period
|
|
52401
52522
|
* keeps recently expired ones for looking into an incident.
|
|
52402
52523
|
*/
|
|
52403
52524
|
const pruneExpiredCredentials$1 = (table) => async (before, limit, trx = db) => deleted(await trx.deleteFrom(table).where("id", "in", (eb) => eb.selectFrom(table).select("id").where("expires_at", "<", before).limit(limit)).executeTakeFirstOrThrow());
|
|
@@ -52884,7 +53005,7 @@ var AssetBusyError = class extends Error {
|
|
|
52884
53005
|
/**
|
|
52885
53006
|
* The `media.relocate` job: after a visibility change, copies the original and its variants under the
|
|
52886
53007
|
* new visibility prefix (verified by checksum), points the rows at them, and purges the old objects.
|
|
52887
|
-
* Shapio's own routes
|
|
53008
|
+
* Shapio's own routes honor the new visibility before this runs; the move matters for a CDN or bucket
|
|
52888
53009
|
* policy that exposes only `public/`.
|
|
52889
53010
|
*/
|
|
52890
53011
|
const relocateAsset = async (deps, payload) => {
|
|
@@ -53022,7 +53143,7 @@ const summarizeResponse = (response) => {
|
|
|
53022
53143
|
* network errors are retried by the queue with exponential backoff up to the webhook's max attempts; then
|
|
53023
53144
|
* the delivery is dead (dead-lettered). A destination refused by the network policy, or a signing secret that
|
|
53024
53145
|
* can no longer be decrypted (SESSION_SECRET changed; rotate it to repair), is dead at once.
|
|
53025
|
-
* Every attempt is
|
|
53146
|
+
* Every attempt is summarized in the delivery log, with the signature redacted and the body truncated.
|
|
53026
53147
|
*/
|
|
53027
53148
|
const createWebhookDeliveryHandler = (runtime) => async (job) => {
|
|
53028
53149
|
const { deliveryId } = job.payload;
|
|
@@ -53781,4 +53902,4 @@ const startDedicatedWorker = async (config) => {
|
|
|
53781
53902
|
//#endregion
|
|
53782
53903
|
export { parseLockFile as $, listForAssets as A, SCHEMA_KIND_DIRECTORIES as B, SITE_KEY_PATTERN as C, EXTENSION_JOB_PREFIX as D, BEFORE_EVENTS as E, describeError as F, foldApiKey as G, THEME_VARIANTS as H, LOCK_FILE_PATH as I, isDataType as J, generatedNames as K, RESERVED_DEFINITION_API_KEYS as L, listLiveByDriver as M, lockById$5 as N, EXTENSION_ROUTE_ROOT as O, update$8 as P, parseDefinition as Q, RESERVED_FIELD_API_KEYS as R, loopbackUrl as S, AFTER_EVENTS as T, checkThemeContrast as U, SITES_DIRECTORY as V, createDefinitionIndex as W, lockEntriesForSite as X, lockCoversSite as Y, mergePulledLock as Z, createAdminDirect as _, loadConfig as a, suggestPlural as at, createLogger as b, getPendingMigrations as c, upgradeLockFile as ct, EmailSchema as d, RICHTEXT_FORMAT as dt, routeKeyOf as et, PasswordSchema as f, SAFE_LINK_PATTERN as ft, listAllSites as g, sqliteDriverOf as gt, createSite$1 as h, createDb as ht, assertDatabaseReachable as i, serializeLockFile as it, STORAGE_DRIVERS$1 as j, buildEditorManifest as k, migrateToLatest as l, validateSchema as lt, createMediaStorage as m, validateRichText as mt, startServer as n, scopeDirectory as nt, loadEnvFileIfPresent as o, toTypeName as ot, PersonNameSchema as p, createStableId as pt, hashDefinition as q, copyObjectVerified as r, serializeDefinition as rt, buildApp as s, typeChangeDropsValues as st, startDedicatedWorker as t, schemaFilePath as tt, SHAPIO_VERSION as u, withSiteCovered as ut, SYSTEM_CLI_ACTOR as v, loadProjectConfig as w, createUrlBuilder as x, generateToken as y, RESERVED_TYPE_NAMES as z };
|
|
53783
53904
|
|
|
53784
|
-
//# sourceMappingURL=worker-
|
|
53905
|
+
//# sourceMappingURL=worker-DHm2JwMZ.js.map
|