@murumets-ee/content 0.107.0 → 0.108.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/admin.d.mts +23 -1
  2. package/dist/admin.d.mts.map +1 -1
  3. package/dist/admin.mjs +1 -1
  4. package/dist/chrome-provider.d.mts +1 -1
  5. package/dist/client.d.mts +2 -2
  6. package/dist/client.mjs +1 -1
  7. package/dist/context-D7eEItCY.mjs +2 -0
  8. package/dist/{context-DtHgyrgb.mjs.map → context-D7eEItCY.mjs.map} +1 -1
  9. package/dist/entities/index.d.mts +2 -2
  10. package/dist/{index-Bni-PiIz.d.mts → index-cT8Qk4gu.d.mts} +2 -2
  11. package/dist/{index-Bni-PiIz.d.mts.map → index-cT8Qk4gu.d.mts.map} +1 -1
  12. package/dist/index.d.mts +4 -4
  13. package/dist/lock-service.d.mts +1 -1
  14. package/dist/plugin-CjgqBSFy.mjs +2 -0
  15. package/dist/{plugin-CvPWz399.mjs.map → plugin-CjgqBSFy.mjs.map} +1 -1
  16. package/dist/plugin.d.mts +2 -2
  17. package/dist/plugin.mjs +1 -1
  18. package/dist/registry-CaPbY5lm.mjs +2 -0
  19. package/dist/registry-CaPbY5lm.mjs.map +1 -0
  20. package/dist/routes-siXmjKDA.mjs +2 -0
  21. package/dist/routes-siXmjKDA.mjs.map +1 -0
  22. package/dist/{routing-strategy-DVWB7qPp.d.mts → routing-strategy-CAG3tZP0.d.mts} +2 -2
  23. package/dist/{routing-strategy-DVWB7qPp.d.mts.map → routing-strategy-CAG3tZP0.d.mts.map} +1 -1
  24. package/dist/{site-chrome-BiV3zhw0.d.mts → site-chrome-DNCcePSR.d.mts} +2 -2
  25. package/dist/{site-chrome-BiV3zhw0.d.mts.map → site-chrome-DNCcePSR.d.mts.map} +1 -1
  26. package/dist/translation-provenance-B41lEDM-.mjs +2 -0
  27. package/dist/translation-provenance-B41lEDM-.mjs.map +1 -0
  28. package/dist/{translation-provenance--dHtcmfg.d.mts → translation-provenance-BZ0MlbFR.d.mts} +2 -2
  29. package/dist/{translation-provenance--dHtcmfg.d.mts.map → translation-provenance-BZ0MlbFR.d.mts.map} +1 -1
  30. package/dist/translation.d.mts +144 -2
  31. package/dist/translation.d.mts.map +1 -0
  32. package/dist/translation.mjs +2 -1
  33. package/dist/translation.mjs.map +1 -0
  34. package/dist/{types-wMTglM4j.d.mts → types-BOk9tg_9.d.mts} +2 -2
  35. package/dist/{types-wMTglM4j.d.mts.map → types-BOk9tg_9.d.mts.map} +1 -1
  36. package/dist/{versionable-D2JjselN.d.mts → versionable-CRvV87nZ.d.mts} +2 -2
  37. package/dist/{versionable-D2JjselN.d.mts.map → versionable-CRvV87nZ.d.mts.map} +1 -1
  38. package/dist/{versions-B0_9TtZ0.mjs → versions-w2ui-Vzb.mjs} +2 -2
  39. package/dist/{versions-B0_9TtZ0.mjs.map → versions-w2ui-Vzb.mjs.map} +1 -1
  40. package/package.json +10 -10
  41. package/dist/context-DtHgyrgb.mjs +0 -2
  42. package/dist/plugin-CvPWz399.mjs +0 -2
  43. package/dist/routes-D-NWP0hK.mjs +0 -2
  44. package/dist/routes-D-NWP0hK.mjs.map +0 -1
  45. package/dist/translation-provenance-eqhsGAyi.mjs +0 -2
  46. package/dist/translation-provenance-eqhsGAyi.mjs.map +0 -1
package/dist/admin.d.mts CHANGED
@@ -4,16 +4,38 @@ import { AdminRoute } from "@murumets-ee/core";
4
4
  /** Route permission + the roles that hold it by default. */
5
5
  declare const PATH_RESOLVE_PERMISSION = "path:resolve";
6
6
  /** The answer shape the caller (admin-ui's editor canvas) consumes. */
7
- type ResolvePathResponse = /** The path is served by this document. */{
7
+ type ResolvePathResponse =
8
+ /**
9
+ * The path is served by this document.
10
+ *
11
+ * `form` is present exactly when the document's TYPE has no canvas (no
12
+ * `field.blockTree()` — an article with a rich-text body): the editor has
13
+ * nothing to draw it with, so preview shows the site's own page instead and
14
+ * the bar needs a name for it and a way to its form (editor-refurb D017).
15
+ * Absent for a type with a canvas, whose answer is unchanged.
16
+ */
17
+ {
8
18
  readonly kind: 'document';
9
19
  readonly entityType: string;
10
20
  readonly id: string;
21
+ readonly form?: ResolvedFormDocument;
11
22
  } /** The path redirects OFF-SITE (a `url`-kind manual redirect). */ | {
12
23
  readonly kind: 'redirect';
13
24
  readonly to: string;
14
25
  } /** Nothing the caller may see owns this path. */ | {
15
26
  readonly kind: 'none';
16
27
  };
28
+ /** What the editor may say about a document it cannot draw. */
29
+ interface ResolvedFormDocument {
30
+ /** The row's title in the asked locale; `null` when it has none or the read failed. */
31
+ readonly title: string | null;
32
+ /**
33
+ * Whether the SITE shows it: `false` for a draft of a publishable type (the
34
+ * front serves published content only, so there is nothing to frame), `true`
35
+ * otherwise. `null` when the row could not be read.
36
+ */
37
+ readonly published: boolean | null;
38
+ }
17
39
  /**
18
40
  * Build the path-resolution admin routes. One entry: `GET /paths/resolve`.
19
41
  */
@@ -1 +1 @@
1
- {"version":3,"file":"admin.d.mts","names":[],"sources":["../src/paths/routes.ts","../src/redirects/routes.ts"],"mappings":";;;;cA2Da,uBAAA;;KAWD,mBAAA;WAEG,IAAA;EAAA,SAA2B,UAAA;EAAA,SAA6B,EAAA;AAAA;WAExD,IAAA;EAAA,SAA2B,EAAA;AAAA;WAE3B,IAAA;AAAA;;;;iBAiHC,UAAA,CAAA,GAAc,UAAU;;;;;;;;;;;iBCgXxB,cAAA,CAAA,GAAkB,UAAU"}
1
+ {"version":3,"file":"admin.d.mts","names":[],"sources":["../src/paths/routes.ts","../src/redirects/routes.ts"],"mappings":";;;;cA+Da,uBAAA;;KAWD,mBAAA;;;;;;;;;;;WAWG,IAAA;EAAA,SACA,UAAA;EAAA,SACA,EAAA;EAAA,SACA,IAAA,GAAO,oBAAoB;AAAA;WAG3B,IAAA;EAAA,SAA2B,EAAA;AAAA;WAE3B,IAAA;AAAA;;UAGE,oBAAA;;WAEN,KAAA;;;;;;WAMA,SAAS;AAAA;;;;iBAwKJ,UAAA,CAAA,GAAc,UAAU;;;AC6RxC;;;;AAA4C;;;;AAA5C,iBAAgB,cAAA,CAAA,GAAkB,UAAU"}
package/dist/admin.mjs CHANGED
@@ -1 +1 @@
1
- import{n as e,r as t,t as n}from"./routes-D-NWP0hK.mjs";export{e as PATH_RESOLVE_PERMISSION,t as pathRoutes,n as redirectRoutes};
1
+ import{n as e,r as t,t as n}from"./routes-siXmjKDA.mjs";export{e as PATH_RESOLVE_PERMISSION,t as pathRoutes,n as redirectRoutes};
@@ -1,4 +1,4 @@
1
- import { r as ChromePlacement } from "./site-chrome-BiV3zhw0.mjs";
1
+ import { r as ChromePlacement } from "./site-chrome-DNCcePSR.mjs";
2
2
  import { ToolkitApp } from "@murumets-ee/core";
3
3
 
4
4
  //#region src/chrome-provider.d.ts
package/dist/client.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { d as TranslationReport, f as TranslationStatus, n as DraftEntry, p as VersionEntry, s as LocalePublishStatus } from "./types-wMTglM4j.mjs";
2
- import { h as FieldDiff } from "./index-Bni-PiIz.mjs";
1
+ import { d as TranslationReport, f as TranslationStatus, n as DraftEntry, p as VersionEntry, s as LocalePublishStatus } from "./types-BOk9tg_9.mjs";
2
+ import { h as FieldDiff } from "./index-cT8Qk4gu.mjs";
3
3
  import { Entity, FieldConfig } from "@murumets-ee/entity";
4
4
  import { Logger } from "@murumets-ee/core";
5
5
  import { AdminClient, FindManyOptions, InferCreateInput, InferEntityDTO, InferUpdateInput } from "@murumets-ee/entity/admin";
package/dist/client.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{t as e}from"./versionable-Br_G5VGR.mjs";import{n as t,r as n,t as r}from"./errors-NRNILhhm.mjs";import{t as i}from"./content-config-store-8omQF5p5.mjs";import{a,d as o,f as s,h as c,i as l,l as u,m as d,n as f,o as p,p as m,r as h,s as g,t as _,u as v}from"./versions-B0_9TtZ0.mjs";import{c as y,f as b,r as x}from"./translation-provenance-eqhsGAyi.mjs";import{n as S}from"./plugin-CvPWz399.mjs";import{t as C}from"./locale-utils-B0mFoV47.mjs";import{i as w,n as T,r as E}from"./context-DtHgyrgb.mjs";import{blockTreeFieldsOf as D,buildPartitionCondition as O}from"@murumets-ee/entity";import{getApp as k,getContext as A,requireSiteFor as ee}from"@murumets-ee/core";import{schemaRegistry as te}from"@murumets-ee/db";import{and as ne,inArray as j}from"drizzle-orm";import"server-only";import{createAdminClient as M}from"@murumets-ee/core/clients";function N(e){return{id:e.id,entityId:e.entityId,locale:e.locale,data:e.data,createdBy:e.createdBy,createdByName:e.createdByName??null,createdAt:e.createdAt,updatedAt:e.updatedAt}}async function P(e,t,n){try{return await e.admin.findById(t,n===`_`?{}:{locale:n})??void 0}catch(n){e.logger?.warn({entity:e.entity.name,entityId:t,error:n},`draft: the live row could not be read to grandfather its block tree`);return}}async function F(e,t,n,r,i){let a=typeof i==`object`&&i?i:void 0;if(!D(e.entity).some(({name:e})=>Object.hasOwn(r,e)&&!Array.isArray(a?.[e])))return a;let o=await P(e,t,n);return o===void 0?a:{...o,...a}}async function I(e,n,r,i=`_`,a){C(i);let s=await E(e);if(!s)throw new t(e.entity.name,`drafts`);let c=o(e.entity,r);e.admin.assertBlockTreesValid(c);let l=D(e.entity).some(({name:e})=>Object.hasOwn(c,e))?await s.findOne({entityId:n,locale:i}):null;await e.admin.assertBlockTreesFitDocument(c,()=>F(e,n,i,c,l?.data),{loadAreaRow:()=>P(e,n,i)}),await e.admin.assertMediaKindsValid(c,l?.data);let u=new Date,d=a?.id??``,f=a?.name??null,p=await s.upsert({entityId:n,locale:i,data:c,createdBy:d,createdByName:f,createdAt:u,updatedAt:u},{target:[`entityId`,`locale`],set:{data:c,updatedAt:u}});return await y({entityName:e.entity.name,entityId:n,locale:i,userId:a?.id,draftData:p.data??{}}),N(p)}const L=[`slug`,`slugMode`,`parent`];async function R(e,n,r,i=`_`,a){C(i);let s=await E(e);if(!s)throw new t(e.entity.name,`drafts`);let c=o(e.entity,r);if(Object.keys(c).length===0){let e=await s.findOne({entityId:n,locale:i});return e?N(e):null}e.admin.assertBlockTreesValid(c),e.admin.assertUpdateValid(c);let l=D(e.entity).some(({name:e})=>Object.hasOwn(c,e)),u=e.entity.frontend?.path!==void 0&&L.some(e=>Object.hasOwn(c,e)),d=l||u?await s.findOne({entityId:n,locale:i}):null;if(await e.admin.assertBlockTreesFitDocument(c,()=>F(e,n,i,c,d?.data),{loadAreaRow:()=>P(e,n,i)}),await e.admin.assertMediaKindsValid(c,d?.data),u){let t={...d?.data??{},...c};if(i===`_`)await e.admin.assertPathAvailable(n,t);else{let r=e.entity.allFields,a={},o={};for(let[e,n]of Object.entries(t))r[e]?.translatable===!0?a[e]=n:o[e]=n;let s=e=>L.some(t=>Object.hasOwn(e,t)&&Object.hasOwn(c,t));s(a)&&await e.admin.assertPathAvailable(n,a,i),s(o)&&await e.admin.assertPathAvailable(n,o)}}let f=new Date,p=await s.upsert({entityId:n,locale:i,data:c,createdBy:a?.id??``,createdByName:a?.name??null,createdAt:f,updatedAt:f},{target:[`entityId`,`locale`],set:{updatedAt:f},mergeJsonb:[`data`]});return await y({entityName:e.entity.name,entityId:n,locale:i,userId:a?.id,draftData:p.data??{}}),N(p)}async function z(e,t,n=`_`){C(n);let r=await E(e);if(!r)return null;let i=await r.findOne({entityId:t,locale:n});return i?N(i):null}async function B(e,t,n=`_`){C(n);let r=await E(e);if(!r)return!1;let i=await r.deleteMany({entityId:t,locale:n});return i.length>0&&await y({entityName:e.entity.name,entityId:t,locale:n,reverted:!0}),i.length>0}async function V(e,n,i=`_`,a){if(C(i),!await E(e))throw new t(e.entity.name,`drafts`);let c=e.versionableOptions?await e.admin.findById(n,m(i)):null;return e.db.transaction(async l=>{let u={...e,db:l},d=await E(u);if(!d)throw new t(e.entity.name,`drafts`);let[p]=await d.deleteMany({entityId:n,locale:i});if(!p)throw new r(n,i);let{publishedAt:m,...h}=p.data??{},g=await s(u,n,o(e.entity,{...h,status:`published`}),i,l),_=H(e.entity,h);return _!==void 0&&await e.admin.updateInternal(n,{_overrides:_},{tx:l}),e.versionableOptions&&await f(u,n,g,c,i,a),g})}function H(e,t){if(!(e.behaviors??[]).some(e=>e.name===`withOverrides`))return;let n=e.allFields._overrides;if(n===void 0||n.internal!==!0)return;let r=t._overrides;if(!(typeof r!=`object`||!r||Array.isArray(r)))return r}async function U(e,t,n=`_`){C(n);let r=await E(e);return r?r.exists({entityId:t,locale:n}):!1}async function W(e,t=`_`){C(t);let n=await E(e);return n?n.count({locale:t}):0}async function G(e,t,n=`_`){C(n);let r=new Set;if(t.length===0)return r;let i=await E(e);if(!i)return r;let a=await i.findMany({where:{entityId:{in:t},locale:n}});for(let e of a)r.add(e.entityId);return r}async function K(e,t,n=`_`){C(n);let r=await z(e,t,n);if(!r)return null;let a=i().defaultLocale,o=n===`_`?{defaultLocale:a}:{locale:n,defaultLocale:a},s=await e.admin.findById(t,o);if(!s)return null;let l=e.entity.allFields,u=s,f=r.data,p={};for(let e of Object.keys(f))p[e]=u[e];let m=c(p,f,l);for(let e of m)e.type===`blockTree`&&(e.blockDiffs=d(Array.isArray(e.from)?e.from:[],Array.isArray(e.to)?e.to:[]));return{diffs:m,current:s,draft:r}}async function q(e,t){let n=(await Y(e,[t])).get(t);return n?Object.values(n):[]}async function J(e,n,r,a){C(r);let o=i();if(r===o.defaultLocale){let t={status:a};a===`published`&&(t.publishedAt=new Date),await e.admin.update(n,t);return}let s=await w(e);if(!s)throw new t(e.entity.name,`localeStatus`);let c={status:a};await e.admin.updateForLocale(n,c,r,{defaultLocale:o.defaultLocale,localeStatusWriter:(e,t,n)=>S(s,e,t,n)})}async function Y(e,t){let n=new Map;if(t.length===0)return n;let r=await w(e);if(!r)return n;let i=await r.findMany({where:{entityId:{in:t}}});for(let e of i){let t=e.entityId,r=e.locale,i=n.get(t);i||(i={},n.set(t,i)),i[r]={locale:r,status:e.status,publishedAt:e.publishedAt??null}}return n}function X(){let e=i(),t=A();return{locales:(t?.availableLocales??e.locales.map(e=>e.code)).map(e=>({code:e})),defaultLocale:t?.defaultLocale??e.defaultLocale}}function re(e,t,n,r){let i={};for(let a of n){if(a.code===r)continue;let n=t?.get(a.code)??{},o=[];for(let t of e)(n[t]===void 0||n[t]===null)&&o.push(t);i[a.code]={complete:o.length===0,total:e.length,translated:e.length-o.length,missing:o}}return i}async function ie(e,t){return(await Z(e,[t])).get(t)??{}}async function Z(e,t){let n=new Map;if(t.length===0)return n;let{locales:r,defaultLocale:i}=X(),a=Object.entries(e.entity.allFields).filter(([e,t])=>t.translatable).map(([e])=>e);if(a.length===0)return n;let o=te.get(`${e.entity.name}_translations`);if(!o)return n;let s=await ee(e.entity),c=j(o.entityId,t),l=await e.db.select().from(o).where(s===void 0?c:ne(c,O(o,{site:s},e.entity.name))),u=new Map;for(let e of l){let t=e,n=t.entityId,r=t.locale,i={};for(let e of a)i[e]=t[e];let o=u.get(n);o||(o=new Map,u.set(n,o)),o.set(r,i)}let d=await x(e.entity.name,t,e.db);for(let e of t){let t=re(a,u.get(e),r,i),o=d.get(e);for(let[e,n]of Object.entries(t)){let t=b(o,e);t&&(n.freshness=t)}n.set(e,t)}return n}const Q={total:0,complete:0,partial:0,missing:0,outdated:0,machineUnreviewed:0};async function ae(e,t){let{locales:r,defaultLocale:i}=X(),a=t?.locale??r.find(e=>e.code!==i)?.code;if(!a)return{...Q};if(!r.some(e=>e.code===a))throw new n(a,r.map(e=>e.code));let o=await e.admin.findMany();if(o.length===0)return{...Q};let s=await Z(e,o.map(e=>e.id)),c=0,l=0,u=0,d=0,f=0;for(let e of o){let t=s.get(e.id)?.[a];!t||t.translated===0?u++:t.complete?c++:l++,t?.freshness?.outdated===!0&&d++,t?.freshness?.machineUnreviewed===!0&&f++}return{total:o.length,complete:c,partial:l,missing:u,outdated:d,machineUnreviewed:f}}var $=class{ctx;constructor(t){let n=e(t.entity.behaviors);this.ctx=T(t,n)}async create(e){let t=await this.ctx.admin.create(e);return this.ctx.versionableOptions&&await g(this.ctx,t.id,t,null,!1),t}findById(e,t){return this.ctx.admin.findById(e,t)}findMany(e){return this.ctx.admin.findMany(e)}async update(e,t){let n=null;this.ctx.versionableOptions&&(n=await this.ctx.admin.findById(e));let r=await this.ctx.admin.update(e,t);if(this.ctx.versionableOptions&&n){let t=v(n,r),i=await g(this.ctx,e,r,t,!1);if(i!==void 0)return await u(this.ctx,e,i),await a(this.ctx,e),{...r,_version:i};await a(this.ctx,e)}return r}delete(e){return this.ctx.admin.delete(e)}saveTranslation(e,t,n){return this.ctx.admin.saveTranslation(e,t,n)}deleteTranslation(e,t){return this.ctx.admin.deleteTranslation(e,t)}getVersions(e,t){return l(this.ctx,e,t)}getVersion(e,t,n){return h(this.ctx,e,t,n)}compareVersions(e,t,n,r){return _(this.ctx,e,t,n,r)}restoreVersion(e,t,n){return p(this.ctx,e,t,n)}pruneVersions(e,t){return a(this.ctx,e,t)}createVersionSnapshot(e,t,n,r,i){return f(this.ctx,e,t,n,r,i)}getTranslationStatus(e){return ie(this.ctx,e)}getTranslationStatusBatch(e){return Z(this.ctx,e)}getTranslationReport(e){return ae(this.ctx,e)}getLocaleStatus(e){return q(this.ctx,e)}setLocaleStatus(e,t,n){return J(this.ctx,e,t,n)}getLocaleStatusBatch(e){return Y(this.ctx,e)}saveDraft(e,t,n,r){return I(this.ctx,e,t,n,r)}mergeDraft(e,t,n,r){return R(this.ctx,e,t,n,r)}getDraft(e,t){return z(this.ctx,e,t)}deleteDraft(e,t){return B(this.ctx,e,t)}publishDraft(e,t,n){return V(this.ctx,e,t,n)}hasDraft(e,t){return U(this.ctx,e,t)}countDrafts(e){return W(this.ctx,e)}hasDraftBatch(e,t){return G(this.ctx,e,t)}compareDraftWithCurrent(e,t){return K(this.ctx,e,t)}};function oe(e){return new $({admin:M(e),entity:e,logger:k().logger.child({content:e.name})})}export{$ as ContentClient,oe as createContentClient};
1
+ import{t as e}from"./versionable-Br_G5VGR.mjs";import{n as t,r as n,t as r}from"./errors-NRNILhhm.mjs";import{t as i}from"./content-config-store-8omQF5p5.mjs";import{a,d as o,f as s,h as c,i as l,l as u,m as d,n as f,o as p,p as m,r as h,s as g,t as _,u as v}from"./versions-w2ui-Vzb.mjs";import{n as y}from"./plugin-CjgqBSFy.mjs";import{t as b}from"./locale-utils-B0mFoV47.mjs";import{i as x,n as S,r as C}from"./context-D7eEItCY.mjs";import{c as w,f as T,r as E}from"./translation-provenance-B41lEDM-.mjs";import{blockTreeFieldsOf as D,buildPartitionCondition as O}from"@murumets-ee/entity";import{getApp as k,getContext as A,requireSiteFor as ee}from"@murumets-ee/core";import{schemaRegistry as te}from"@murumets-ee/db";import{and as ne,inArray as j}from"drizzle-orm";import"server-only";import{createAdminClient as M}from"@murumets-ee/core/clients";function N(e){return{id:e.id,entityId:e.entityId,locale:e.locale,data:e.data,createdBy:e.createdBy,createdByName:e.createdByName??null,createdAt:e.createdAt,updatedAt:e.updatedAt}}async function P(e,t,n){try{return await e.admin.findById(t,n===`_`?{}:{locale:n})??void 0}catch(n){e.logger?.warn({entity:e.entity.name,entityId:t,error:n},`draft: the live row could not be read to grandfather its block tree`);return}}async function F(e,t,n,r,i){let a=typeof i==`object`&&i?i:void 0;if(!D(e.entity).some(({name:e})=>Object.hasOwn(r,e)&&!Array.isArray(a?.[e])))return a;let o=await P(e,t,n);return o===void 0?a:{...o,...a}}async function I(e,n,r,i=`_`,a){b(i);let s=await C(e);if(!s)throw new t(e.entity.name,`drafts`);let c=o(e.entity,r);e.admin.assertBlockTreesValid(c);let l=D(e.entity).some(({name:e})=>Object.hasOwn(c,e))?await s.findOne({entityId:n,locale:i}):null;await e.admin.assertBlockTreesFitDocument(c,()=>F(e,n,i,c,l?.data),{loadAreaRow:()=>P(e,n,i)}),await e.admin.assertMediaKindsValid(c,l?.data);let u=new Date,d=a?.id??``,f=a?.name??null,p=await s.upsert({entityId:n,locale:i,data:c,createdBy:d,createdByName:f,createdAt:u,updatedAt:u},{target:[`entityId`,`locale`],set:{data:c,updatedAt:u}});return await w({entityName:e.entity.name,entityId:n,locale:i,userId:a?.id,draftData:p.data??{}}),N(p)}const L=[`slug`,`slugMode`,`parent`];async function R(e,n,r,i=`_`,a){b(i);let s=await C(e);if(!s)throw new t(e.entity.name,`drafts`);let c=o(e.entity,r);if(Object.keys(c).length===0){let e=await s.findOne({entityId:n,locale:i});return e?N(e):null}e.admin.assertBlockTreesValid(c),e.admin.assertUpdateValid(c);let l=D(e.entity).some(({name:e})=>Object.hasOwn(c,e)),u=e.entity.frontend?.path!==void 0&&L.some(e=>Object.hasOwn(c,e)),d=l||u?await s.findOne({entityId:n,locale:i}):null;if(await e.admin.assertBlockTreesFitDocument(c,()=>F(e,n,i,c,d?.data),{loadAreaRow:()=>P(e,n,i)}),await e.admin.assertMediaKindsValid(c,d?.data),u){let t={...d?.data??{},...c};if(i===`_`)await e.admin.assertPathAvailable(n,t);else{let r=e.entity.allFields,a={},o={};for(let[e,n]of Object.entries(t))r[e]?.translatable===!0?a[e]=n:o[e]=n;let s=e=>L.some(t=>Object.hasOwn(e,t)&&Object.hasOwn(c,t));s(a)&&await e.admin.assertPathAvailable(n,a,i),s(o)&&await e.admin.assertPathAvailable(n,o)}}let f=new Date,p=await s.upsert({entityId:n,locale:i,data:c,createdBy:a?.id??``,createdByName:a?.name??null,createdAt:f,updatedAt:f},{target:[`entityId`,`locale`],set:{updatedAt:f},mergeJsonb:[`data`]});return await w({entityName:e.entity.name,entityId:n,locale:i,userId:a?.id,draftData:p.data??{}}),N(p)}async function z(e,t,n=`_`){b(n);let r=await C(e);if(!r)return null;let i=await r.findOne({entityId:t,locale:n});return i?N(i):null}async function B(e,t,n=`_`){b(n);let r=await C(e);if(!r)return!1;let i=await r.deleteMany({entityId:t,locale:n});return i.length>0&&await w({entityName:e.entity.name,entityId:t,locale:n,reverted:!0}),i.length>0}async function V(e,n,i=`_`,a){if(b(i),!await C(e))throw new t(e.entity.name,`drafts`);let c=e.versionableOptions?await e.admin.findById(n,m(i)):null;return e.db.transaction(async l=>{let u={...e,db:l},d=await C(u);if(!d)throw new t(e.entity.name,`drafts`);let[p]=await d.deleteMany({entityId:n,locale:i});if(!p)throw new r(n,i);let{publishedAt:m,...h}=p.data??{},g=await s(u,n,o(e.entity,{...h,status:`published`}),i,l),_=H(e.entity,h);return _!==void 0&&await e.admin.updateInternal(n,{_overrides:_},{tx:l}),e.versionableOptions&&await f(u,n,g,c,i,a),g})}function H(e,t){if(!(e.behaviors??[]).some(e=>e.name===`withOverrides`))return;let n=e.allFields._overrides;if(n===void 0||n.internal!==!0)return;let r=t._overrides;if(!(typeof r!=`object`||!r||Array.isArray(r)))return r}async function U(e,t,n=`_`){b(n);let r=await C(e);return r?r.exists({entityId:t,locale:n}):!1}async function W(e,t=`_`){b(t);let n=await C(e);return n?n.count({locale:t}):0}async function G(e,t,n=`_`){b(n);let r=new Set;if(t.length===0)return r;let i=await C(e);if(!i)return r;let a=await i.findMany({where:{entityId:{in:t},locale:n}});for(let e of a)r.add(e.entityId);return r}async function K(e,t,n=`_`){b(n);let r=await z(e,t,n);if(!r)return null;let a=i().defaultLocale,o=n===`_`?{defaultLocale:a}:{locale:n,defaultLocale:a},s=await e.admin.findById(t,o);if(!s)return null;let l=e.entity.allFields,u=s,f=r.data,p={};for(let e of Object.keys(f))p[e]=u[e];let m=c(p,f,l);for(let e of m)e.type===`blockTree`&&(e.blockDiffs=d(Array.isArray(e.from)?e.from:[],Array.isArray(e.to)?e.to:[]));return{diffs:m,current:s,draft:r}}async function q(e,t){let n=(await Y(e,[t])).get(t);return n?Object.values(n):[]}async function J(e,n,r,a){b(r);let o=i();if(r===o.defaultLocale){let t={status:a};a===`published`&&(t.publishedAt=new Date),await e.admin.update(n,t);return}let s=await x(e);if(!s)throw new t(e.entity.name,`localeStatus`);let c={status:a};await e.admin.updateForLocale(n,c,r,{defaultLocale:o.defaultLocale,localeStatusWriter:(e,t,n)=>y(s,e,t,n)})}async function Y(e,t){let n=new Map;if(t.length===0)return n;let r=await x(e);if(!r)return n;let i=await r.findMany({where:{entityId:{in:t}}});for(let e of i){let t=e.entityId,r=e.locale,i=n.get(t);i||(i={},n.set(t,i)),i[r]={locale:r,status:e.status,publishedAt:e.publishedAt??null}}return n}function X(){let e=i(),t=A();return{locales:(t?.availableLocales??e.locales.map(e=>e.code)).map(e=>({code:e})),defaultLocale:t?.defaultLocale??e.defaultLocale}}function re(e,t,n,r){let i={};for(let a of n){if(a.code===r)continue;let n=t?.get(a.code)??{},o=[];for(let t of e)(n[t]===void 0||n[t]===null)&&o.push(t);i[a.code]={complete:o.length===0,total:e.length,translated:e.length-o.length,missing:o}}return i}async function ie(e,t){return(await Z(e,[t])).get(t)??{}}async function Z(e,t){let n=new Map;if(t.length===0)return n;let{locales:r,defaultLocale:i}=X(),a=Object.entries(e.entity.allFields).filter(([e,t])=>t.translatable).map(([e])=>e);if(a.length===0)return n;let o=te.get(`${e.entity.name}_translations`);if(!o)return n;let s=await ee(e.entity),c=j(o.entityId,t),l=await e.db.select().from(o).where(s===void 0?c:ne(c,O(o,{site:s},e.entity.name))),u=new Map;for(let e of l){let t=e,n=t.entityId,r=t.locale,i={};for(let e of a)i[e]=t[e];let o=u.get(n);o||(o=new Map,u.set(n,o)),o.set(r,i)}let d=await E(e.entity.name,t,e.db);for(let e of t){let t=re(a,u.get(e),r,i),o=d.get(e);for(let[e,n]of Object.entries(t)){let t=T(o,e);t&&(n.freshness=t)}n.set(e,t)}return n}const Q={total:0,complete:0,partial:0,missing:0,outdated:0,machineUnreviewed:0};async function ae(e,t){let{locales:r,defaultLocale:i}=X(),a=t?.locale??r.find(e=>e.code!==i)?.code;if(!a)return{...Q};if(!r.some(e=>e.code===a))throw new n(a,r.map(e=>e.code));let o=await e.admin.findMany();if(o.length===0)return{...Q};let s=await Z(e,o.map(e=>e.id)),c=0,l=0,u=0,d=0,f=0;for(let e of o){let t=s.get(e.id)?.[a];!t||t.translated===0?u++:t.complete?c++:l++,t?.freshness?.outdated===!0&&d++,t?.freshness?.machineUnreviewed===!0&&f++}return{total:o.length,complete:c,partial:l,missing:u,outdated:d,machineUnreviewed:f}}var $=class{ctx;constructor(t){let n=e(t.entity.behaviors);this.ctx=S(t,n)}async create(e){let t=await this.ctx.admin.create(e);return this.ctx.versionableOptions&&await g(this.ctx,t.id,t,null,!1),t}findById(e,t){return this.ctx.admin.findById(e,t)}findMany(e){return this.ctx.admin.findMany(e)}async update(e,t){let n=null;this.ctx.versionableOptions&&(n=await this.ctx.admin.findById(e));let r=await this.ctx.admin.update(e,t);if(this.ctx.versionableOptions&&n){let t=v(n,r),i=await g(this.ctx,e,r,t,!1);if(i!==void 0)return await u(this.ctx,e,i),await a(this.ctx,e),{...r,_version:i};await a(this.ctx,e)}return r}delete(e){return this.ctx.admin.delete(e)}saveTranslation(e,t,n){return this.ctx.admin.saveTranslation(e,t,n)}deleteTranslation(e,t){return this.ctx.admin.deleteTranslation(e,t)}getVersions(e,t){return l(this.ctx,e,t)}getVersion(e,t,n){return h(this.ctx,e,t,n)}compareVersions(e,t,n,r){return _(this.ctx,e,t,n,r)}restoreVersion(e,t,n){return p(this.ctx,e,t,n)}pruneVersions(e,t){return a(this.ctx,e,t)}createVersionSnapshot(e,t,n,r,i){return f(this.ctx,e,t,n,r,i)}getTranslationStatus(e){return ie(this.ctx,e)}getTranslationStatusBatch(e){return Z(this.ctx,e)}getTranslationReport(e){return ae(this.ctx,e)}getLocaleStatus(e){return q(this.ctx,e)}setLocaleStatus(e,t,n){return J(this.ctx,e,t,n)}getLocaleStatusBatch(e){return Y(this.ctx,e)}saveDraft(e,t,n,r){return I(this.ctx,e,t,n,r)}mergeDraft(e,t,n,r){return R(this.ctx,e,t,n,r)}getDraft(e,t){return z(this.ctx,e,t)}deleteDraft(e,t){return B(this.ctx,e,t)}publishDraft(e,t,n){return V(this.ctx,e,t,n)}hasDraft(e,t){return U(this.ctx,e,t)}countDrafts(e){return W(this.ctx,e)}hasDraftBatch(e,t){return G(this.ctx,e,t)}compareDraftWithCurrent(e,t){return K(this.ctx,e,t)}};function oe(e){return new $({admin:M(e),entity:e,logger:k().logger.child({content:e.name})})}export{$ as ContentClient,oe as createContentClient};
2
2
  //# sourceMappingURL=client.mjs.map
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./rolldown-runtime-DK3Fl9T5.mjs";import{t}from"./registry-CaPbY5lm.mjs";import{requireSiteFor as n}from"@murumets-ee/core";import"server-only";var r=e({createContentContext:()=>i,getDraftsClient:()=>a,getLocaleStatusClient:()=>s,getVersionsClient:()=>o});function i(e,t){return{entity:e.entity,admin:e.admin,db:e.admin.getDb(),versionableOptions:t,logger:e.logger}}async function a(e){let{drafts:r}=t(e.entity.name);return r?r.makeClient(e.db,await n(e.entity)):null}async function o(e){let{versions:r}=t(e.entity.name);return r?r.makeClient(e.db,await n(e.entity)):null}async function s(e){let{localeStatus:r}=t(e.entity.name);return r?r.makeClient(e.db,await n(e.entity)):null}export{o as a,s as i,i as n,a as r,r as t};
2
+ //# sourceMappingURL=context-D7eEItCY.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-DtHgyrgb.mjs","names":[],"sources":["../src/internal/context.ts"],"sourcesContent":["/**\n * Shared per-instance state for ContentClient feature modules.\n *\n * The package's domain modules (`versions.ts`, `drafts.ts`,\n * `translation-status.ts`, `locale-status.ts`, `layout.ts`) are written\n * as free functions that take a `ContentContext` as their first\n * argument. ContentClient itself is a thin shell that builds the\n * context once and forwards every public method to the corresponding\n * free function.\n *\n * Why free functions instead of one class with everything inline:\n * - 1000+ LoC in one class is impossible to navigate and audit.\n * - Each module has clear inputs (the context + method args) and no\n * hidden dependencies on private state.\n * - Splits cleanly along the same boundaries as the per-entity\n * capability tables (drafts, versions, locale_status, ...) — every\n * module owns exactly one capability surface.\n */\n\nimport 'server-only'\n\nimport { type Logger, requireSiteFor } from '@murumets-ee/core'\nimport type { Entity, FieldConfig } from '@murumets-ee/entity'\nimport type { AdminClient } from '@murumets-ee/entity/admin'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport type { getVersionableOptions } from '../behaviors/versionable.js'\nimport { getContentTables } from '../schema/registry.js'\n\n/**\n * Per-instance content context. Built once in `createContentContext()`\n * and threaded through every domain module's free functions.\n */\nexport interface ContentContext<\n AllFields extends Record<string, FieldConfig> = Record<string, FieldConfig>,\n> {\n entity: Entity<AllFields>\n admin: AdminClient<AllFields>\n db: PostgresJsDatabase\n versionableOptions: ReturnType<typeof getVersionableOptions>\n logger?: Logger | undefined\n}\n\n/**\n * Build a content context from an AdminClient + entity. The DB handle\n * is read off the AdminClient (it owns the read-write connection).\n */\nexport function createContentContext<AllFields extends Record<string, FieldConfig>>(\n config: {\n admin: AdminClient<AllFields>\n entity: Entity<AllFields>\n logger?: Logger\n },\n // Lazy import to avoid a static cycle: behaviors/versionable.ts is loaded\n // by client.ts which would otherwise close the loop. Phase-2 validated\n // the static import graph; this is a private helper bundled into the\n // same chunk so the dynamic-vs-static rule doesn't apply.\n versionableOptions: ReturnType<typeof getVersionableOptions>,\n): ContentContext<AllFields> {\n return {\n entity: config.entity,\n admin: config.admin,\n db: config.admin.getDb(),\n versionableOptions,\n logger: config.logger,\n }\n}\n\n// -------------------------------------------------------------------\n// Per-capability TableClient lookups. For a site-bound entity the client\n// is CONFINED to the request's site (multisite D003) — `requireSiteFor`\n// throws when there is none, so a companion read can never widen to every\n// site. Async for that reason: the single-site answer may need a lookup.\n// Each returns null if the entity\n// hasn't registered the corresponding table (i.e. doesn't have the\n// behavior). ContentClient public methods translate that null into\n// either a thrown EntityCapabilityError (writes) or a falsy return\n// (reads).\n// -------------------------------------------------------------------\n\nexport async function getDraftsClient(ctx: ContentContext) {\n const { drafts } = getContentTables(ctx.entity.name)\n return drafts ? drafts.makeClient(ctx.db, await requireSiteFor(ctx.entity)) : null\n}\n\nexport async function getVersionsClient(ctx: ContentContext) {\n const { versions } = getContentTables(ctx.entity.name)\n return versions ? versions.makeClient(ctx.db, await requireSiteFor(ctx.entity)) : null\n}\n\nexport async function getLocaleStatusClient(ctx: ContentContext) {\n const { localeStatus } = getContentTables(ctx.entity.name)\n return localeStatus ? localeStatus.makeClient(ctx.db, await requireSiteFor(ctx.entity)) : null\n}\n"],"mappings":"qSA8CA,SAAgB,EACd,EASA,EAC2B,CAC3B,MAAO,CACL,OAAQ,EAAO,OACf,MAAO,EAAO,MACd,GAAI,EAAO,MAAM,MAAM,EACvB,qBACA,OAAQ,EAAO,MACjB,CACF,CAcA,eAAsB,EAAgB,EAAqB,CACzD,GAAM,CAAE,UAAW,EAAiB,EAAI,OAAO,IAAI,EACnD,OAAO,EAAS,EAAO,WAAW,EAAI,GAAI,MAAM,EAAe,EAAI,MAAM,CAAC,EAAI,IAChF,CAEA,eAAsB,EAAkB,EAAqB,CAC3D,GAAM,CAAE,YAAa,EAAiB,EAAI,OAAO,IAAI,EACrD,OAAO,EAAW,EAAS,WAAW,EAAI,GAAI,MAAM,EAAe,EAAI,MAAM,CAAC,EAAI,IACpF,CAEA,eAAsB,EAAsB,EAAqB,CAC/D,GAAM,CAAE,gBAAiB,EAAiB,EAAI,OAAO,IAAI,EACzD,OAAO,EAAe,EAAa,WAAW,EAAI,GAAI,MAAM,EAAe,EAAI,MAAM,CAAC,EAAI,IAC5F"}
1
+ {"version":3,"file":"context-D7eEItCY.mjs","names":[],"sources":["../src/internal/context.ts"],"sourcesContent":["/**\n * Shared per-instance state for ContentClient feature modules.\n *\n * The package's domain modules (`versions.ts`, `drafts.ts`,\n * `translation-status.ts`, `locale-status.ts`, `layout.ts`) are written\n * as free functions that take a `ContentContext` as their first\n * argument. ContentClient itself is a thin shell that builds the\n * context once and forwards every public method to the corresponding\n * free function.\n *\n * Why free functions instead of one class with everything inline:\n * - 1000+ LoC in one class is impossible to navigate and audit.\n * - Each module has clear inputs (the context + method args) and no\n * hidden dependencies on private state.\n * - Splits cleanly along the same boundaries as the per-entity\n * capability tables (drafts, versions, locale_status, ...) — every\n * module owns exactly one capability surface.\n */\n\nimport 'server-only'\n\nimport { type Logger, requireSiteFor } from '@murumets-ee/core'\nimport type { Entity, FieldConfig } from '@murumets-ee/entity'\nimport type { AdminClient } from '@murumets-ee/entity/admin'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport type { getVersionableOptions } from '../behaviors/versionable.js'\nimport { getContentTables } from '../schema/registry.js'\n\n/**\n * Per-instance content context. Built once in `createContentContext()`\n * and threaded through every domain module's free functions.\n */\nexport interface ContentContext<\n AllFields extends Record<string, FieldConfig> = Record<string, FieldConfig>,\n> {\n entity: Entity<AllFields>\n admin: AdminClient<AllFields>\n db: PostgresJsDatabase\n versionableOptions: ReturnType<typeof getVersionableOptions>\n logger?: Logger | undefined\n}\n\n/**\n * Build a content context from an AdminClient + entity. The DB handle\n * is read off the AdminClient (it owns the read-write connection).\n */\nexport function createContentContext<AllFields extends Record<string, FieldConfig>>(\n config: {\n admin: AdminClient<AllFields>\n entity: Entity<AllFields>\n logger?: Logger\n },\n // Lazy import to avoid a static cycle: behaviors/versionable.ts is loaded\n // by client.ts which would otherwise close the loop. Phase-2 validated\n // the static import graph; this is a private helper bundled into the\n // same chunk so the dynamic-vs-static rule doesn't apply.\n versionableOptions: ReturnType<typeof getVersionableOptions>,\n): ContentContext<AllFields> {\n return {\n entity: config.entity,\n admin: config.admin,\n db: config.admin.getDb(),\n versionableOptions,\n logger: config.logger,\n }\n}\n\n// -------------------------------------------------------------------\n// Per-capability TableClient lookups. For a site-bound entity the client\n// is CONFINED to the request's site (multisite D003) — `requireSiteFor`\n// throws when there is none, so a companion read can never widen to every\n// site. Async for that reason: the single-site answer may need a lookup.\n// Each returns null if the entity\n// hasn't registered the corresponding table (i.e. doesn't have the\n// behavior). ContentClient public methods translate that null into\n// either a thrown EntityCapabilityError (writes) or a falsy return\n// (reads).\n// -------------------------------------------------------------------\n\nexport async function getDraftsClient(ctx: ContentContext) {\n const { drafts } = getContentTables(ctx.entity.name)\n return drafts ? drafts.makeClient(ctx.db, await requireSiteFor(ctx.entity)) : null\n}\n\nexport async function getVersionsClient(ctx: ContentContext) {\n const { versions } = getContentTables(ctx.entity.name)\n return versions ? versions.makeClient(ctx.db, await requireSiteFor(ctx.entity)) : null\n}\n\nexport async function getLocaleStatusClient(ctx: ContentContext) {\n const { localeStatus } = getContentTables(ctx.entity.name)\n return localeStatus ? localeStatus.makeClient(ctx.db, await requireSiteFor(ctx.entity)) : null\n}\n"],"mappings":"kRA8CA,SAAgB,EACd,EASA,EAC2B,CAC3B,MAAO,CACL,OAAQ,EAAO,OACf,MAAO,EAAO,MACd,GAAI,EAAO,MAAM,MAAM,EACvB,qBACA,OAAQ,EAAO,MACjB,CACF,CAcA,eAAsB,EAAgB,EAAqB,CACzD,GAAM,CAAE,UAAW,EAAiB,EAAI,OAAO,IAAI,EACnD,OAAO,EAAS,EAAO,WAAW,EAAI,GAAI,MAAM,EAAe,EAAI,MAAM,CAAC,EAAI,IAChF,CAEA,eAAsB,EAAkB,EAAqB,CAC3D,GAAM,CAAE,YAAa,EAAiB,EAAI,OAAO,IAAI,EACrD,OAAO,EAAW,EAAS,WAAW,EAAI,GAAI,MAAM,EAAe,EAAI,MAAM,CAAC,EAAI,IACpF,CAEA,eAAsB,EAAsB,EAAqB,CAC/D,GAAM,CAAE,gBAAiB,EAAiB,EAAI,OAAO,IAAI,EACzD,OAAO,EAAe,EAAa,WAAW,EAAI,GAAI,MAAM,EAAe,EAAI,MAAM,CAAC,EAAI,IAC5F"}
@@ -1,5 +1,5 @@
1
- import { t as VersionableFields } from "../versionable-D2JjselN.mjs";
2
- import { a as siteChromeEntity, i as SiteChromeEntityOptions, n as CHROME_PLACEMENT_LABELS, r as ChromePlacement, t as CHROME_PLACEMENTS } from "../site-chrome-BiV3zhw0.mjs";
1
+ import { t as VersionableFields } from "../versionable-CRvV87nZ.mjs";
2
+ import { a as siteChromeEntity, i as SiteChromeEntityOptions, n as CHROME_PLACEMENT_LABELS, r as ChromePlacement, t as CHROME_PLACEMENTS } from "../site-chrome-DNCcePSR.mjs";
3
3
  import { Behavior, Entity, EntityAdminConfig, ForbiddenError } from "@murumets-ee/entity";
4
4
 
5
5
  //#region src/entities/detail-template.d.ts
@@ -1,4 +1,4 @@
1
- import { o as LocaleEntry, r as I18nConfig } from "./types-wMTglM4j.mjs";
1
+ import { o as LocaleEntry, r as I18nConfig } from "./types-BOk9tg_9.mjs";
2
2
  import { Behavior, DateField, Entity, JsonField, SelectField, TextField } from "@murumets-ee/entity";
3
3
  import { ToolkitApp } from "@murumets-ee/core";
4
4
  import { MessageEntry } from "@murumets-ee/i18n";
@@ -272,4 +272,4 @@ declare function resolveSiteI18n(app: ToolkitApp, options?: {
272
272
  declare function resolveMessageOverrides(app: ToolkitApp, locale: string): Promise<MessageEntry[]>;
273
273
  //#endregion
274
274
  export { withOverrides as A, WorkflowableFields as C, OverridesMap as D, OverrideDirective as E, WithOverridesFields as O, WorkflowTransitionError as S, workflowable as T, EntityCapability as _, resolveI18nConfig as a, WORKFLOW_TRANSITIONS as b, DraftNotFoundError as c, VersionNotFoundError as d, BlockDiffEntry as f, PropDiff as g, FieldDiff as h, resolveEffectiveLocales as i, hasWithOverrides as k, EntityCapabilityError as l, DiffSegment as m, SiteI18n as n, resolveSiteI18n as o, BlockDiffStatus as p, enabledLocaleCodes as r, resolveSiteLocales as s, resolveMessageOverrides as t, InvalidLocaleError as u, entitySupports as v, isAllowedTransition as w, WorkflowState as x, WORKFLOW_STATES as y };
275
- //# sourceMappingURL=index-Bni-PiIz.d.mts.map
275
+ //# sourceMappingURL=index-cT8Qk4gu.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-Bni-PiIz.d.mts","names":[],"sources":["../src/behaviors/with-overrides.ts","../src/behaviors/workflowable.ts","../src/capabilities.ts","../src/diff/types.ts","../src/errors.ts","../src/locale-registry.ts","../src/message-registry.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index-cT8Qk4gu.d.mts","names":[],"sources":["../src/behaviors/with-overrides.ts","../src/behaviors/workflowable.ts","../src/capabilities.ts","../src/diff/types.ts","../src/errors.ts","../src/locale-registry.ts","../src/message-registry.ts"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as LocaleDirection, c as LockInfo, d as TranslationReport, f as TranslationStatus, i as LocaleConfig, l as RoutingStrategy, m as VersionableOptions, n as DraftEntry, o as LocaleEntry, p as VersionEntry, r as I18nConfig, t as ContentConfig, u as TranslationFieldStatus } from "./types-wMTglM4j.mjs";
2
- import { n as getVersionableOptions, r as versionable } from "./versionable-D2JjselN.mjs";
3
- import { A as withOverrides, C as WorkflowableFields, D as OverridesMap, E as OverrideDirective, O as WithOverridesFields, S as WorkflowTransitionError, T as workflowable, _ as EntityCapability, a as resolveI18nConfig, b as WORKFLOW_TRANSITIONS, c as DraftNotFoundError, d as VersionNotFoundError, f as BlockDiffEntry, g as PropDiff, h as FieldDiff, i as resolveEffectiveLocales, k as hasWithOverrides, l as EntityCapabilityError, m as DiffSegment, n as SiteI18n, o as resolveSiteI18n, p as BlockDiffStatus, r as enabledLocaleCodes, s as resolveSiteLocales, t as resolveMessageOverrides, u as InvalidLocaleError, v as entitySupports, w as isAllowedTransition, x as WorkflowState, y as WORKFLOW_STATES } from "./index-Bni-PiIz.mjs";
4
- import { a as ROUTING_STRATEGIES, i as Locale, n as prefixDefaultLocaleForStrategy, o as i18nSettings, r as Message, t as localePrefixForStrategy } from "./routing-strategy-DVWB7qPp.mjs";
1
+ import { a as LocaleDirection, c as LockInfo, d as TranslationReport, f as TranslationStatus, i as LocaleConfig, l as RoutingStrategy, m as VersionableOptions, n as DraftEntry, o as LocaleEntry, p as VersionEntry, r as I18nConfig, t as ContentConfig, u as TranslationFieldStatus } from "./types-BOk9tg_9.mjs";
2
+ import { n as getVersionableOptions, r as versionable } from "./versionable-CRvV87nZ.mjs";
3
+ import { A as withOverrides, C as WorkflowableFields, D as OverridesMap, E as OverrideDirective, O as WithOverridesFields, S as WorkflowTransitionError, T as workflowable, _ as EntityCapability, a as resolveI18nConfig, b as WORKFLOW_TRANSITIONS, c as DraftNotFoundError, d as VersionNotFoundError, f as BlockDiffEntry, g as PropDiff, h as FieldDiff, i as resolveEffectiveLocales, k as hasWithOverrides, l as EntityCapabilityError, m as DiffSegment, n as SiteI18n, o as resolveSiteI18n, p as BlockDiffStatus, r as enabledLocaleCodes, s as resolveSiteLocales, t as resolveMessageOverrides, u as InvalidLocaleError, v as entitySupports, w as isAllowedTransition, x as WorkflowState, y as WORKFLOW_STATES } from "./index-cT8Qk4gu.mjs";
4
+ import { a as ROUTING_STRATEGIES, i as Locale, n as prefixDefaultLocaleForStrategy, o as i18nSettings, r as Message, t as localePrefixForStrategy } from "./routing-strategy-CAG3tZP0.mjs";
5
5
  export { type BlockDiffEntry, type BlockDiffStatus, type ContentConfig, type DiffSegment, type DraftEntry, DraftNotFoundError, type EntityCapability, EntityCapabilityError, type FieldDiff, type I18nConfig, InvalidLocaleError, Locale, type LocaleConfig, type LocaleDirection, type LocaleEntry, type LockInfo, Message, type OverrideDirective, type OverridesMap, type PropDiff, ROUTING_STRATEGIES, type RoutingStrategy, type SiteI18n, type TranslationFieldStatus, type TranslationReport, type TranslationStatus, type VersionEntry, VersionNotFoundError, type VersionableOptions, WORKFLOW_STATES, WORKFLOW_TRANSITIONS, type WithOverridesFields, type WorkflowState, WorkflowTransitionError, type WorkflowableFields, enabledLocaleCodes, entitySupports, getVersionableOptions, hasWithOverrides, i18nSettings, isAllowedTransition, localePrefixForStrategy, prefixDefaultLocaleForStrategy, resolveEffectiveLocales, resolveI18nConfig, resolveMessageOverrides, resolveSiteI18n, resolveSiteLocales, versionable, withOverrides, workflowable };
@@ -1,4 +1,4 @@
1
- import { c as LockInfo } from "./types-wMTglM4j.mjs";
1
+ import { c as LockInfo } from "./types-BOk9tg_9.mjs";
2
2
  import { ToolkitApp } from "@murumets-ee/core";
3
3
  //#region src/lock-service.d.ts
4
4
  interface LockServiceConfig {
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./versionable-Br_G5VGR.mjs";import{r as t}from"./errors-NRNILhhm.mjs";import{r as n,t as r}from"./locale-entity-CoSq3C77.mjs";import{n as i,t as a}from"./content-config-store-8omQF5p5.mjs";import{r as o}from"./routing-strategy-D6B4ngT9.mjs";import{n as s,t as c}from"./registry-CaPbY5lm.mjs";import"./locale-utils-B0mFoV47.mjs";import{n as l}from"./document-site-B8tmEqLw.mjs";import{m as u,n as d,p as f}from"./translation-provenance-B41lEDM-.mjs";import{n as p}from"./chrome-entity-names-zYJzP-_U.mjs";import{r as m}from"./detail-template-names-CD1Y9n1U.mjs";import{c as h,i as g,n as _,o as v,r as y,t as b}from"./schema-BYrYzsmO.mjs";import{l as x,t as S,u as C}from"./schema-LlK6EkOJ.mjs";import{r as w,t as T}from"./routes-siXmjKDA.mjs";import{n as E}from"./locks-5779ugSW.mjs";import{MAX_PATH_DEPTH as ee,buildPartitionCondition as D,hasPathParent as O,isSiteBound as k,resolveEffectiveSlugMode as A,resolvePattern as j}from"@murumets-ee/entity";import{definePlugin as M,getApp as N,getContext as P,getCurrentSite as F,requireRequestSite as I,resolveImplicitSite as L,runAsCli as R,runInEverySite as z,runInSite as B}from"@murumets-ee/core";import{column as V,defineTable as te,schemaRegistry as H}from"@murumets-ee/db";import{and as U,asc as W,eq as G,getTableColumns as ne,inArray as re,sql as ie}from"drizzle-orm";import{createHash as ae}from"node:crypto";import{z as K}from"zod";const oe=Symbol.for(`@murumets-ee/content:locale-status-writer`);async function q(e,t,n,r){let i=r===`published`?new Date:null;await e.upsert({entityId:t,locale:n,status:r,publishedAt:i},{target:[`entityId`,`locale`],set:{status:r,publishedAt:i}})}function se(e){globalThis[oe]=(n,r)=>{let{localeStatus:i}=c(n.name);if(i)return async(n,a,o,s)=>{let c=P()?.availableLocales??e;if(!c.includes(a))throw new t(a,[...c]);await q(i.makeClient(r,s),n,a,o)}}}function ce(){return{async writeDraft({documentType:e,documentId:t,locale:n,dataPatch:r,user:i,tx:a}){let{drafts:o}=c(e);if(!o)return!1;let s=o.makeClient(a,await l(e)),u=new Date,f=await s.upsert({entityId:t,locale:n,data:r,createdBy:i.id,createdByName:i.name??null,createdAt:u,updatedAt:u},{target:[`entityId`,`locale`],set:{updatedAt:u},mergeJsonb:[`data`]});return d({entityName:e,entityId:t,locale:n,userId:i.id,draftData:f.data??r}),!0},async readDraft({documentType:e,documentId:t,locale:n,db:r}){let{drafts:i}=c(e);if(!i)return null;let a=await i.makeClient(r,await l(e)).findOne({entityId:t,locale:n});return a?{data:a.data??{},createdBy:a.createdBy??null,createdByName:a.createdByName??null,updatedAt:a.updatedAt??null}:null},async readLocaleStatus({documentType:e,documentId:t,locale:n,db:r}){let{localeStatus:i}=c(e);if(!i)return null;let a=await i.makeClient(r,await l(e)).findOne({entityId:t,locale:n});return a?a.status===`published`?`published`:`draft`:null},async hasAnyDraft({documentType:e,documentId:t,db:n}){let{drafts:r}=c(e);return r?r.makeClient(n,await l(e)).exists({entityId:t}):!1},async hasAnyLocaleActivity({documentType:e,documentId:t,db:n}){let{localeStatus:r}=c(e),i=await l(e);if(r&&await r.makeClient(n,i).exists({entityId:t}))return!0;let a=H.get(`${e}_translations`);if(a){let r=a.entityId;if(r!==void 0){let o=i===void 0?G(r,t):U(G(r,t),D(a,{site:i},e));if((await n.select({one:ie`1`}).from(a).where(o).limit(1)).length>0)return!0}}return!1}}}function le(e){let{defaultLocale:t}=a();return e===`_`||e===t?{defaultLocale:t}:{locale:e,defaultLocale:t}}function ue(e){let{defaultLocale:t}=a();return e===`_`||e===t?`_`:e}async function de(e,t,n,r){let{drafts:i}=c(e);if(!i)return;let a=await i.makeClient(r,await l(e)).findOne({entityId:t,locale:n});return a?a.data??void 0:void 0}function fe(){return{async snapshotCurrentState({documentType:t,documentId:n,locale:r,user:i}){let a=N(),o=a.entities.get(t);if(!o)return!1;let s=e(o.behaviors);if(!s)return!1;let c=a.getClient(o),l=c.getDb(),u=ue(r),d=await c.findById(n,le(u));if(!d)return!1;let f=await de(t,n,u,l),p=f?{...d,...f}:{...d},[{createContentContext:m},{createVersionSnapshot:h}]=await Promise.all([import(`./context-D7eEItCY.mjs`).then(e=>e.t),import(`./versions-w2ui-Vzb.mjs`).then(e=>e.c)]);return await h(m({admin:c,entity:o},s),n,p,d,u,{id:i.id,...i.name==null?{}:{name:i.name}}),!0}}}async function pe(e,t,n){let r=ne(b),i=r[y],a=r.entityType,o=r.entityId;if(!i||!a||!o)throw Error(`toolkit_paths is missing '${y}'/entity columns`);let s=await e.selectDistinct({site:i}).from(b).where(U(G(a,t),G(o,n))).limit(2);if(s.length>1)return null;let c=s[0]?.site;return typeof c==`string`?c:void 0}const me=Symbol.for(`@murumets-ee/content:path-writers-factory`),J=Symbol.for(`@murumets-ee/content:cascade-trigger-factory`);function he(e){globalThis[J]=e}function ge(){let e=globalThis[J];return typeof e==`function`?e:void 0}function _e(e,t){return async r=>{let i=await ve(e,t,r);if(i===null)return;let a=_.makeClient(e.db.readWrite,i),o=F();if(o!==void 0&&o!==i&&!(r.action===`delete`||r.action===`release`)){e.logger.warn({entity:r.entityName,id:r.id,site:i,requestSite:o},"toolkit_paths: a cascade reached a document on another site — its path is left for `lumi paths:rebuild` on that site rather than recomputed from this request");return}return o===void 0&&r.viaCascade===!0&&k(t)?B(i,()=>n(a,r)):n(a,r)};async function n(n,r){if(r.action===`delete`){await n.deleteMany({entityType:r.entityName,entityId:r.id});return}if(r.action===`release`){await n.deleteMany({entityType:r.entityName,entityId:r.id,isCanonical:!0});return}let i=a(),o=i.defaultLocale,s=i.reservedPathPrefixes??[],c=r.locale?[r.locale]:i.locales.map(e=>e.code),l=r.viaCascade===!0?e.getSystemClient(t):e.getClient(t),u=async n=>{if(!O(t))return;let i=ge();if(i)try{await i(e,t,r.id,n)}catch(t){e.logger.warn({err:t,entity:r.entityName,id:r.id,locale:n},`toolkit_paths: descendant-cascade trigger threw — the entity write already committed, so tolerating and continuing (paths are rebuildable, D005)`)}};for(let i of c){let a=i===r.locale?r.row??null:await l.findById(r.id,{locale:i,defaultLocale:o});if(!a){await v({pathsClient:n,entityType:r.entityName,entityId:r.id,locale:i,path:null,skipReason:`row-unreadable`,reservedPathPrefixes:s,logger:e.logger});continue}let c=await x({entity:t,row:a,locale:i,defaultLocale:o,pathsClient:n}),d=await v({pathsClient:n,entityType:r.entityName,entityId:r.id,locale:i,path:c.path,...c.skipReason!==void 0&&{skipReason:c.skipReason},reservedPathPrefixes:s,logger:e.logger});(d.outcome===`renamed`||r.action===`restore`&&d.outcome===`created`)&&await u(i)}}}async function ve(e,t,n){if(n.viaCascade===!0&&k(t)){let t=await pe(e.db.readWrite,n.entityName,n.id);if(t===null)return e.logger.warn({entity:n.entityName,id:n.id},"toolkit_paths: a document has path rows on SEVERAL sites — refusing to guess which one this cascade maintains; `lumi paths:rebuild` per site repairs it"),null;if(t!==void 0)return t;let r=F();if(r!==void 0)return r;let i=await L(e).catch(()=>void 0);return i===void 0?(e.logger.warn({entity:n.entityName,id:n.id,action:n.action},"toolkit_paths: cascade child has no path rows and the request names no site — nothing to maintain here; `lumi paths:rebuild` recomputes it per site"),null):i}return I(`toolkit_paths`,e)}function ye(e,t){return async n=>{let r=_.makeClient(e.db.readWrite,await I(`toolkit_paths`,e)),i=a(),o=i.defaultLocale,s=i.reservedPathPrefixes??[],c=n.locale??o,l=null;n.id!==void 0&&(l=await e.getClient(t).findById(n.id,{locale:c,defaultLocale:o}));let u=A(n.data.slugMode,l?.slugMode);await C({entity:t,data:n.data,currentRow:l,id:n.id,locale:c,defaultLocale:o,slugMode:u,reservedPathPrefixes:s,pathsClient:r})}}function be(){globalThis[me]=(e,t)=>({pathIndexWriter:_e(e,t),pathConflictGuard:ye(e,t)})}const Y=K.object({entityType:K.string().min(1),parentId:K.string().uuid(),locale:K.string().min(1)}),X=K.object({entity:K.string().min(1).optional(),locale:K.string().min(1).optional(),dryRun:K.boolean()}),Z=K.object({dryRun:K.boolean()});async function xe(e,t,n={}){let{entityType:r,parentId:i,locale:o}=t,s=n.maxItems??2e3,c=n.concurrency??5,l={processed:0,regenerated:0,unchanged:0,skipped:0,failed:0,truncated:!1},u=e=>({phase:e,...l}),d=()=>({entityType:r,parentId:i,locale:o,cap:s,...l}),f=e.entities.get(r);if(!f)return e.logger.warn({entityType:r,parentId:i,locale:o},`paths-cascade: unknown entity type — nothing to regenerate`),n.onProgress?.(u(`done`)),d();if(!O(f))return e.logger.warn({entityType:r,parentId:i,locale:o},`paths-cascade: entity is not a pathParent() hierarchy — nothing to regenerate`),n.onProgress?.(u(`done`)),d();let p=a(),m=p.defaultLocale,g=p.reservedPathPrefixes??[],y=_.makeClient(e.db.readWrite,await I(`toolkit_paths`,e)),b=e.getClient(f),S=b.getTable().parent,C=async t=>{let n=t.id;try{let i=await x({entity:f,row:t,locale:o,defaultLocale:m,pathsClient:y});switch((await v({pathsClient:y,entityType:r,entityId:n,locale:o,path:i.path,...i.skipReason!==void 0&&{skipReason:i.skipReason},reservedPathPrefixes:g,logger:e.logger})).outcome){case`created`:case`renamed`:l.regenerated+=1;break;case`unchanged`:l.unchanged+=1;break;default:l.skipped+=1;break}}catch(t){l.failed+=1,e.logger.warn({err:t,entityType:r,id:n,locale:o},`paths-cascade: failed to regenerate one descendant path — continuing (per-item isolation)`)}},w=[i];for(;w.length>0;){let e=s-l.processed;if(e<=0){l.truncated=!0;break}let t=await b.findMany({where:re(S,w),locale:o,defaultLocale:m,limit:e+1});if(t.length===0)break;let r=t;if(t.length>e&&(r=t.slice(0,e),l.truncated=!0),await h(r,c,C),l.processed+=r.length,n.onProgress?.(u(`walking`)),l.truncated)break;w=r.map(e=>e.id)}return l.truncated&&e.logger.warn({entityType:r,parentId:i,locale:o,processed:l.processed,cap:s},`paths-cascade: descendant subtree exceeded the cap — deeper/remaining descendants were NOT regenerated. Run \`lumi paths:rebuild --entity ${r}\` for guaranteed full coverage.`),n.onProgress?.(u(`done`)),d()}async function Se(e,t,n={}){let r=n.pageSize??200,i=n.concurrency??5,o=n.sampleCap??25,s=t.dryRun,c=a(),l=c.defaultLocale,u=c.reservedPathPrefixes??[],d=c.locales.map(e=>e.code),f=t.locale?d.filter(e=>e===t.locale):d,p=[...e.entities.values()].filter(e=>!!e.frontend?.path&&(t.entity===void 0||e.name===t.entity)),m=t.entity!==void 0&&p.length===0,g=t.locale!==void 0&&f.length===0;m&&e.logger.warn({entity:t.entity,dryRun:s},`paths-rebuild: --entity matches no routable entity (one declaring frontend.path) — nothing to rebuild (likely a typo in the entity name)`),g&&e.logger.warn({locale:t.locale,configuredLocales:d,dryRun:s},`paths-rebuild: --locale matches no configured locale — nothing to rebuild (likely a typo in the locale code)`);let y=m||g?{entity:m,locale:g}:void 0,b=p.some(e=>O(e)),S=s&&b?`Preview reflects a SINGLE pass; a pathParent() hierarchy drifted at multiple levels may need the real (non-dry-run) rebuild's multi-pass convergence to fully resolve. The real run always converges.`:void 0,C=_.makeClient(e.db.readWrite,await I(`toolkit_paths`,e)),w={scanned:0,changed:0,applied:0,failed:0},T=new Map,E={missing:0,conflicts:0,unchanged:0,skipped:0},D=(e,t)=>{let n=T.get(e);n!==t&&(n!==void 0&&n!==`resolved`&&--E[n],T.set(e,t),t!==`resolved`&&(E[t]+=1))},k=[],A=!1,j=e=>{k.length<o?k.push(e):A=!0},M=0,N=e=>({phase:e,dryRun:s,scope:{entity:t.entity??null,locale:t.locale??null},scanned:w.scanned,changed:w.changed,applied:w.applied,failed:w.failed,missing:E.missing,conflicts:E.conflicts,unchanged:E.unchanged,skipped:E.skipped,passes:M,sample:k,sampleTruncated:A,...S===void 0?{}:{hierarchyNote:S},...y===void 0?{}:{unmatchedScope:y}}),P=async(t,n,r,i)=>{let a=r.id,o=!1;try{let c=await x({entity:t,row:r,locale:i,defaultLocale:l,pathsClient:C}),d=await v({pathsClient:C,entityType:n,entityId:a,locale:i,path:c.path,...c.skipReason!==void 0&&{skipReason:c.skipReason},suppressNoteworthy:[`parent-not-indexed`],reservedPathPrefixes:u,logger:e.logger,dryRun:s}),f=`${n}:${a}:${i}`;switch(d.outcome){case`unchanged`:D(f,`unchanged`);break;case`skipped-null`:case`skipped-reserved`:D(f,`skipped`);break;case`conflict`:D(f,`conflicts`),j({kind:`conflict`,entityType:n,entityId:a,locale:i,oldPath:d.oldPath,newPath:d.newPath,...d.conflictWith?{conflictWith:d.conflictWith.entityId}:{}});break;case`created`:s?D(f,`missing`):(w.applied+=1,o=!0,D(f,`resolved`)),j({kind:`missing`,entityType:n,entityId:a,locale:i,oldPath:null,newPath:d.newPath});break;case`renamed`:w.changed+=1,s||(w.applied+=1,o=!0),D(f,`resolved`),j({kind:`changed`,entityType:n,entityId:a,locale:i,oldPath:d.oldPath,newPath:d.newPath});break}}catch(t){w.failed+=1,e.logger.warn({err:t,entityType:n,id:a,locale:i},`paths-rebuild: failed to process one document — continuing (per-item isolation)`)}return o},F=async t=>{let a=0;for(let o of t){let t=e.getClient(o),s=o.name,c=t.getTable().id;for(let e of f){let u;for(;;){let d=await t.findMany({locale:e,defaultLocale:l,limit:r,orderBy:W(c),...u===void 0?{}:{cursor:{field:`id`,value:u,direction:`asc`}}});if(d.length===0)break;await h(d,i,async t=>{await P(o,s,t,e)&&(a+=1)}),w.scanned+=d.length;let f=d[d.length-1];if(f&&(u=f.id),n.onProgress?.(N(`scanning`)),d.length<r)break}}}return a},L=async t=>{let r=[];for(let[n,i]of T){if(i!==`conflicts`&&i!==`skipped`&&i!==`missing`)continue;let a=n.indexOf(`:`),o=n.lastIndexOf(`:`);if(a<=0||o<=a)continue;let s=n.slice(0,a);if(t.has(s))continue;let c=e.entities.get(s);c!==void 0&&r.push({entity:c,entityType:s,entityId:n.slice(a+1,o),locale:n.slice(o+1)})}if(r.length===0)return 0;let a=0;return await h(r,i,async t=>{let n=await e.getClient(t.entity).findById(t.entityId,{locale:t.locale,defaultLocale:l});n!==null&&(w.scanned+=1,await P(t.entity,t.entityType,n,t.locale)&&(a+=1))}),n.onProgress?.(N(`scanning`)),a},R=p.filter(e=>O(e)),z=new Set(R.map(e=>e.name)),B=s||!b?1:ee;for(let e=0;e<B;e++){M=e+1;let t=await F(e===0?p:R);if(e>0&&(t+=await L(z)),t===0)break}A&&e.logger.warn({scanned:w.scanned,changed:w.changed,missing:E.missing,conflicts:E.conflicts,sampleCap:o},`paths-rebuild: more diff entries than the progress sample can hold — see the aggregate counts; the stored sample is truncated`);let V=N(`done`);n.onProgress?.(V);let{phase:te,...H}=V;return H}async function Ce(e,t,n={}){let r=n.maxRows??1e4,i=n.batchSize??500,a={dryRun:t.dryRun,orphans:[],found:0,deleted:0,truncated:!1,refused:!1},o=new Set([...e.entities.values()].filter(e=>!!e.frontend?.path).map(e=>e.name));if(o.size===0)return e.logger.warn({dryRun:t.dryRun},`paths-prune: no entity declares frontend.path — refusing to treat every row as an orphan`),a.refused=!0,a;let s=_.makeClient(e.db.readWrite,await I(`toolkit_paths`,e)),c=(await s.distinct(`entityType`)).filter(e=>!o.has(e));for(let e of c){let t=await s.count({entityType:e});t>0&&a.orphans.push({entityType:e,rows:t}),a.found+=t}if(t.dryRun)return a;for(let{entityType:e}of a.orphans)for(;a.deleted<r;){let t=await s.findMany({where:{entityType:e},limit:Math.min(i,r-a.deleted)});if(t.length===0)break;let n=await s.deleteMany({id:{in:t.map(e=>e.id)}});a.deleted+=n.length}return a.truncated=a.deleted<a.found&&a.deleted>=r,a.truncated&&e.logger.warn({deleted:a.deleted,found:a.found,maxRows:r},`paths-prune: row cap reached — run again to continue`),a}async function we(e){let{defineJob:t,registerJob:n,QueueClient:r}=await import(`@murumets-ee/queue/client`),i=t({name:`content:paths-cascade`,description:`Regenerate toolkit_paths canonical rows for the descendants of a renamed routable-hierarchy ancestor (one locale). Walks the full bounded subtree in a single invocation.`,schema:Y}),a=t({name:`content:paths-rebuild`,description:`Recompute every routable document's canonical toolkit_paths row (optionally scoped to one entity/locale); dryRun reports the diff without writing. On-demand (lumi paths:rebuild).`,schema:X});n(t({name:`content:paths-prune`,description:`Delete toolkit_paths rows of entity types that are no longer routable (lost frontend.path or unregistered). dryRun reports them without deleting. On-demand (lumi paths:rebuild --orphans).`,schema:Z}),async t=>{let n={dryRun:Z.parse(t.payload).dryRun,orphans:[],found:0,deleted:0,truncated:!1,refused:!1};await R(()=>z(async()=>{let r=await Ce(e,Z.parse(t.payload));for(let e of r.orphans){let t=n.orphans.find(t=>t.entityType===e.entityType);t?t.rows+=e.rows:n.orphans.push({...e})}n.found+=r.found,n.deleted+=r.deleted,n.truncated||=r.truncated,n.refused||=r.refused,t.updateProgress(n),e.logger.info(r,`paths-prune: sweep complete`)},{app:e,label:`paths-prune`}))}),n(i,async t=>{await R(async()=>{let n=await xe(e,Y.parse(t.payload),{onProgress:e=>t.updateProgress(e)});e.logger.info(n,`paths-cascade: descendant regeneration complete`)})}),n(a,async t=>{await R(()=>z(async()=>{let n=await Se(e,X.parse(t.payload),{onProgress:e=>t.updateProgress({...e,site:F()??null})});e.logger.info({dryRun:n.dryRun,scanned:n.scanned,changed:n.changed,missing:n.missing,conflicts:n.conflicts,applied:n.applied,failed:n.failed,passes:n.passes,...n.hierarchyNote===void 0?{}:{hierarchyNote:n.hierarchyNote}},`paths-rebuild: sweep complete`)},{app:e,label:`paths-rebuild`}))}),he(async(e,t,n,a)=>{await new r({app:e,logger:e.logger}).enqueue(i,{entityType:t.name,parentId:n,locale:a})})}const Q=te({name:`toolkit_path_patterns`,columns:{id:V.uuid({primaryKey:!0,defaultRandom:!0}),entityType:V.varchar({length:100,notNull:!0,pgName:`entity_type`}),locale:V.varchar({length:10,notNull:!0}),patternHash:V.varchar({length:64,notNull:!0,pgName:`pattern_hash`}),updatedAt:V.timestamp({notNull:!0,defaultNow:!0,withTimezone:!0,pgName:`updated_at`})},unique:[{on:[`entityType`,`locale`]}]}),Te=Q.table;function Ee(e,t,n){let r=j(e,t,n);if(r===null)return null;let i=typeof r==`function`?r.toString():JSON.stringify(r);return ae(`sha256`).update(i).digest(`hex`)}async function De(e){let t=a(),n=t.defaultLocale,r=t.locales.map(e=>e.code),i=Q.makeClient(e.db.readWrite);for(let[t,a]of e.entities){let o=a.frontend?.path;if(o!==void 0)for(let a of r){let r=Ee(o,a,n);if(r===null)continue;let s=await i.findOne({entityType:t,locale:a});s!==null&&s.patternHash===r||(s!==null&&e.logger.warn({entity:t,locale:a,previousHash:s.patternHash,currentHash:r},`toolkit_paths: frontend.path pattern for '${t}' (locale '${a}') changed since last boot — stale toolkit_paths rows may exist; run \`lumi paths:rebuild --entity ${t}\``),await i.upsert({entityType:t,locale:a,patternHash:r},{target:[`entityType`,`locale`],set:{patternHash:r,updatedAt:new Date}}))}}}const Oe=async(e,t,n)=>{if(t.length===0)return new Map;let[{buildEnumerateDeps:r},{getCanonicalPaths:i}]=await Promise.all([import(`./resolve-context-DklN53BH.mjs`).then(e=>e.u),import(`./enumerate-CYHJKQz6.mjs`).then(e=>e.n)]),a=r(N()),o=await a.filterPublished(e,t,n);return o.size===0?new Map:i(e,[...o],n,a)},ke=async(e,t)=>{if(e.length===0)return new Set;let{buildEnumerateDeps:n}=await import(`./resolve-context-DklN53BH.mjs`).then(e=>e.u),r=n(N()),i=[...new Set(e)],a=i.slice(0,48);i.length>a.length&&N().logger.warn({paths:i.length,max:48},`content: publishedPathsAmong was asked for more paths than it reads; the rest count as unpublished`);let o=await r.pathsClient.findMany({where:{locale:t,isCanonical:!0,path:{in:a}},limit:a.length}),s=new Map;for(let e of o){let t=s.get(e.entityType);t===void 0&&(t=new Map,s.set(e.entityType,t)),t.set(e.entityId,e.path)}let c=new Set;for(let[e,n]of s){let i=await r.filterPublished(e,[...n.keys()],t);for(let[e,t]of n)i.has(e)&&c.add(t)}return c},Ae=async e=>{let[{buildBreadcrumbDeps:t},{resolveBreadcrumbTrail:n}]=await Promise.all([import(`./resolve-context-DklN53BH.mjs`).then(e=>e.u),import(`./breadcrumbs-BqSuMNac.mjs`).then(e=>e.t)]);return(await n(e,t(N())))?.steps};function $(e){return g(e,{name:`${e.name}_drafts`,columns:{id:V.uuid({primaryKey:!0,defaultRandom:!0}),entityId:V.uuid({notNull:!0,pgName:`entity_id`}),locale:V.varchar({length:10,notNull:!0,default:`_`}),data:V.jsonb({notNull:!0}),createdBy:V.varchar({length:255,notNull:!0,pgName:`created_by`}),createdByName:V.varchar({length:255,pgName:`created_by_name`}),createdAt:V.timestamp({notNull:!0,defaultNow:!0,withTimezone:!0,pgName:`created_at`}),updatedAt:V.timestamp({notNull:!0,defaultNow:!0,withTimezone:!0,pgName:`updated_at`})},unique:[{on:[`entityId`,`locale`]}]})}function je(e){return g(e,{name:`${e.name}_locale_status`,columns:{id:V.uuid({primaryKey:!0,defaultRandom:!0}),entityId:V.uuid({notNull:!0,pgName:`entity_id`}),locale:V.varchar({length:10,notNull:!0}),status:V.varchar({length:20,notNull:!0,default:`draft`}),publishedAt:V.timestamp({withTimezone:!0,pgName:`published_at`})},unique:[{on:[`entityId`,`locale`]}]})}function Me(e){return g(e,{name:`${e.name}_versions`,columns:{id:V.uuid({primaryKey:!0,defaultRandom:!0}),entityId:V.uuid({notNull:!0,pgName:`entity_id`}),version:V.integer({notNull:!0}),locale:V.varchar({length:10,notNull:!0,default:`_`}),data:V.jsonb({notNull:!0}),delta:V.jsonb(),status:V.varchar({length:20}),createdBy:V.varchar({length:255,pgName:`created_by`}),createdByName:V.varchar({length:255,pgName:`created_by_name`}),createdAt:V.timestamp({notNull:!0,defaultNow:!0,withTimezone:!0,pgName:`created_at`}),isAutosave:V.boolean({notNull:!0,default:!1,pgName:`is_autosave`})},unique:[{on:[`entityId`,`version`,`locale`]}]})}function Ne(e){if(!e.locales||e.locales.length===0)throw Error(`content() requires at least one locale`);if(!e.defaultLocale)throw Error(`content() requires a defaultLocale`);if(!e.locales.some(t=>t.code===e.defaultLocale))throw Error(`defaultLocale "${e.defaultLocale}" not found in locales: [${e.locales.map(e=>e.code).join(`, `)}]`);if(e.reservedPathPrefixes){for(let t of e.reservedPathPrefixes)if(typeof t!=`string`||!t.startsWith(`/`))throw Error(`content(): reservedPathPrefixes entries must be absolute paths starting with '/', got ${JSON.stringify(t)}`)}let t=e.autoTrash??!0,a=t===!1?void 0:{publishable:!0,...typeof t==`object`&&t.exclude?{exclude:t.exclude}:{}};return M({name:`@murumets-ee/content`,contributes:{"blocks.documentDraftStore":ce(),"blocks.documentVersionStore":fe(),"blocks.publishedPathResolver":Oe,"entity.writeListeners":f,"blocks.publishedPathsAmong":ke,"blocks.breadcrumbTrail":Ae,"sites.baseLocale":async()=>(await import(`./locale-registry-COsJrVZl.mjs`).then(e=>e.n)).resolveInstallBaseLocale(),...a?{"trash.autoEnable":a}:{},...e.reservedPathPrefixes?{"routing.reservedPathPrefixes":e.reservedPathPrefixes}:{}},shared:{settings:[n],features:[{resource:`redirect`,actions:[`manage`],defaultRoles:[`admin`],description:`Create, edit, and delete manual URL redirects (toolkit_redirects).`},{resource:`path`,actions:[`resolve`],defaultRoles:[`admin`,`editor`],description:`Resolve a site URL path to the CMS document that serves it.`}]},server:{entities:[r,o],tables:{toolkitContentLocks:E,toolkitPaths:b,toolkitPathPatterns:Te,toolkitRedirects:S,toolkitTranslationProvenance:u},routes:[...T(),...w()],seeders:[{name:`content:site-chrome`,description:`Create the empty site_chrome row for each placement (header, footer), as a DRAFT, so they can be edited on the page canvas. Publishing one is what makes /v1/_chrome serve it instead of the delivery template's own fallback. Idempotent — an existing row for a placement is left alone.`,available:p,bootstrap:!0,run:async()=>{let{seedSiteChrome:e}=await import(`@murumets-ee/content/seed`);return await e()}},{name:`content:detail-templates`,description:`Create the DRAFT detail template for each entity drawn by one (block-library D009), so its page layout can be edited on the canvas. Until a template is published its rows keep the plain fallback page. Idempotent — an existing template is left alone.`,available:m,bootstrap:!0,run:async()=>{let{seedDetailTemplates:e}=await import(`@murumets-ee/content/seed`);return await e()}}],init:async t=>{i(e);let n=0,r=0,a=0;for(let[e,i]of t.entities){if(i.behaviors?.some(e=>e.name===`versionable`)){let t=`${e}_versions`;if(!H.has(t)){let n=Me(i);H.register(t,n.table),s(e,{versions:n})}n++}let t=i.behaviors?.some(e=>e.name===`publishable`),o=i.allFields,c=Object.values(o).some(e=>e.translatable);if(t&&c){let t=`${e}_locale_status`;if(!H.has(t)){let n=je(i);H.register(t,n.table),s(e,{localeStatus:n})}r++}if(t){let t=`${e}_drafts`;if(!H.has(t)){let n=$(i);H.register(t,n.table),s(e,{drafts:n})}a++}}se(e.locales.map(e=>e.code)),be();try{await we(t)}catch(e){t.logger.warn({err:e},"content: failed to register routing path jobs — descendant cascade + `lumi paths:rebuild` will be unavailable (path writes still succeed)")}t.logger.info({locales:e.locales.map(e=>e.code),defaultLocale:e.defaultLocale,versionableEntities:n,localeStatusEntities:r,draftEntities:a},`Content plugin initialized`)},onReady:async e=>{try{await De(e)}catch(t){e.logger.error({err:t},"content: boot-time frontend-path pattern-drift check failed — continuing app boot without it. Inspect the logged `err` for the cause: a transient DB error can be retried (and `lumi paths:rebuild` re-derives the index if a pattern actually changed), whereas a structural cause — e.g. a missing migration leaving `toolkit_path_patterns` absent — will recur on every boot and needs `lumi migrate`")}}}})}export{q as n,Ne as t};
2
+ //# sourceMappingURL=plugin-CjgqBSFy.mjs.map