@murumets-ee/content 0.3.0 → 0.4.5

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 (48) hide show
  1. package/LICENSE +94 -0
  2. package/dist/{block-diff-H1AttKiz.mjs → block-diff-BBH6FoFT.mjs} +1 -1
  3. package/dist/{block-diff-H1AttKiz.mjs.map → block-diff-BBH6FoFT.mjs.map} +1 -1
  4. package/dist/blocks/index.d.mts +1 -1
  5. package/dist/blocks/index.mjs +1 -1
  6. package/dist/client.d.mts +160 -18
  7. package/dist/client.d.mts.map +1 -1
  8. package/dist/client.mjs +1 -1
  9. package/dist/client.mjs.map +1 -1
  10. package/dist/{define-block-D-7OpIn5.mjs → define-block-DpMPEEdA.mjs} +1 -1
  11. package/dist/{define-block-D-7OpIn5.mjs.map → define-block-DpMPEEdA.mjs.map} +1 -1
  12. package/dist/drafts-CyOivEtr.mjs +2 -0
  13. package/dist/drafts-CyOivEtr.mjs.map +1 -0
  14. package/dist/index.d.mts +2 -2
  15. package/dist/index.mjs +1 -1
  16. package/dist/locale-status-DTyv4wcn.mjs +2 -0
  17. package/dist/locale-status-DTyv4wcn.mjs.map +1 -0
  18. package/dist/lock-service.d.mts +3 -4
  19. package/dist/lock-service.d.mts.map +1 -1
  20. package/dist/lock-service.mjs +1 -1
  21. package/dist/lock-service.mjs.map +1 -1
  22. package/dist/locks-BkO2qMfm.mjs +2 -0
  23. package/dist/locks-BkO2qMfm.mjs.map +1 -0
  24. package/dist/plugin.d.mts +1 -1
  25. package/dist/plugin.mjs +1 -1
  26. package/dist/plugin.mjs.map +1 -1
  27. package/dist/query-client.d.mts +80 -14
  28. package/dist/query-client.d.mts.map +1 -1
  29. package/dist/query-client.mjs +1 -1
  30. package/dist/query-client.mjs.map +1 -1
  31. package/dist/registry-BJSOGFEN.mjs +2 -0
  32. package/dist/registry-BJSOGFEN.mjs.map +1 -0
  33. package/dist/rolldown-runtime-DR3Ue2cl.mjs +1 -0
  34. package/dist/{types-nXbE5Ufa.d.mts → types-COcneY5H.d.mts} +1 -1
  35. package/dist/{types-nXbE5Ufa.d.mts.map → types-COcneY5H.d.mts.map} +1 -1
  36. package/dist/{types-wLHyjcWf.d.mts → types-D-ATlx7t.d.mts} +1 -1
  37. package/dist/{types-wLHyjcWf.d.mts.map → types-D-ATlx7t.d.mts.map} +1 -1
  38. package/dist/versions-CO6oDyet.mjs +2 -0
  39. package/dist/versions-CO6oDyet.mjs.map +1 -0
  40. package/package.json +12 -12
  41. package/dist/drafts-BYyRdmiT.mjs +0 -2
  42. package/dist/drafts-BYyRdmiT.mjs.map +0 -1
  43. package/dist/locale-status-CGttT38v.mjs +0 -2
  44. package/dist/locale-status-CGttT38v.mjs.map +0 -1
  45. package/dist/locks-CNxQJieo.mjs +0 -2
  46. package/dist/locks-CNxQJieo.mjs.map +0 -1
  47. package/dist/versions-cotph2VG.mjs +0 -2
  48. package/dist/versions-cotph2VG.mjs.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,94 @@
1
+ Elastic License 2.0 (ELv2)
2
+
3
+ URL: https://www.elastic.co/licensing/elastic-license
4
+
5
+ ## Acceptance
6
+
7
+ By using the software, you agree to all of the terms and conditions below.
8
+
9
+ ## Copyright License
10
+
11
+ The licensor grants you a non-exclusive, royalty-free, worldwide,
12
+ non-sublicensable, non-transferable license to use, copy, distribute, make
13
+ available, and prepare derivative works of the software, in each case subject
14
+ to the limitations and conditions below.
15
+
16
+ ## Limitations
17
+
18
+ You may not provide the software to third parties as a hosted or managed
19
+ service, where the service provides users with access to any substantial set
20
+ of the features or functionality of the software.
21
+
22
+ You may not move, change, disable, or circumvent the license key functionality
23
+ in the software, and you may not remove or obscure any functionality in the
24
+ software that is protected by the license key.
25
+
26
+ You may not alter, remove, or obscure any licensing, copyright, or other
27
+ notices of the licensor in the software. Any use of the licensor's trademarks
28
+ is subject to applicable law.
29
+
30
+ ## Patents
31
+
32
+ The licensor grants you a license, under any patent claims the licensor can
33
+ license, or becomes able to license, to make, have made, use, sell, offer for
34
+ sale, import and have imported the software, in each case subject to the
35
+ limitations and conditions in this license. This license does not cover any
36
+ patent claims that you cause to be infringed by modifications or additions to
37
+ the software. If you or your company make any written claim that the software
38
+ infringes or contributes to infringement of any patent, your patent license
39
+ for the software granted under these terms ends immediately. If your company
40
+ makes such a claim, your patent license ends immediately for work on behalf
41
+ of your company.
42
+
43
+ ## Notices
44
+
45
+ You must ensure that anyone who gets a copy of any part of the software from
46
+ you also gets a copy of these terms.
47
+
48
+ If you modify the software, you must include in any modified copies of the
49
+ software prominent notices stating that you have modified the software.
50
+
51
+ ## No Other Rights
52
+
53
+ These terms do not imply any licenses other than those expressly granted in
54
+ these terms.
55
+
56
+ ## Termination
57
+
58
+ If you use the software in violation of these terms, such use is not licensed,
59
+ and your licenses will automatically terminate. If the licensor provides you
60
+ with a notice of your violation, and you cease all violation of this license
61
+ no later than 30 days after you receive that notice, your licenses will be
62
+ reinstated retroactively. However, if you violate these terms after such
63
+ reinstatement, any additional violation of these terms will cause your
64
+ licenses to terminate automatically and permanently.
65
+
66
+ ## No Liability
67
+
68
+ As far as the law allows, the software comes as is, without any warranty or
69
+ condition, and the licensor will not be liable to you for any damages arising
70
+ out of these terms or the use or nature of the software, under any kind of
71
+ legal claim.
72
+
73
+ ## Definitions
74
+
75
+ The **licensor** is the entity offering these terms, and the **software** is
76
+ the software the licensor makes available under these terms, including any
77
+ portion of it.
78
+
79
+ **you** refers to the individual or entity agreeing to these terms.
80
+
81
+ **your company** is any legal entity, sole proprietorship, or other kind of
82
+ organization that you work for, plus all organizations that have control over,
83
+ are under the control of, or are under common control with that organization.
84
+ **control** means ownership of substantially all the assets of an entity, or
85
+ the power to direct the management and policies of an entity (for example, by
86
+ voting right, contract, or otherwise). Control can be direct or indirect.
87
+
88
+ **your licenses** are all the licenses granted to you for the software under
89
+ these terms.
90
+
91
+ **use** means anything you do with the software requiring one of your
92
+ licenses.
93
+
94
+ **trademark** means trademarks, service marks, and similar rights.
@@ -1,2 +1,2 @@
1
1
  import{field as e}from"@murumets-ee/entity";const t={maxPerDoc:50,autosave:!1};function n(n){let r={...t,...n};return{name:`versionable`,fields:{_version:e.number({required:!0,default:1,integer:!0}),_versionedAt:e.date()},hooks:{beforeCreate:async e=>(e._version=1,e._versionedAt=new Date,e),beforeUpdate:async(e,t)=>(t._versionedAt=new Date,t)},_versionableOptions:r}}function r(e){return e?e.find(e=>e.name===`versionable`)?._versionableOptions??null:null}function i(e){return e.match(/\S+|\s+/g)??[]}function a(e,t){if(e===t)return e?[{type:`equal`,value:e}]:[];if(!e)return[{type:`add`,value:t}];if(!t)return[{type:`remove`,value:e}];let n=i(e),r=i(t),a=n.length,o=r.length,s=Array.from({length:a+1},()=>Array(o+1).fill(0));for(let e=1;e<=a;e++)for(let t=1;t<=o;t++)n[e-1]===r[t-1]?s[e][t]=s[e-1][t-1]+1:s[e][t]=Math.max(s[e-1][t],s[e][t-1]);let c=[],l=a,u=o,d=[];for(;l>0||u>0;)l>0&&u>0&&n[l-1]===r[u-1]?(d.push({type:`equal`,value:n[l-1]}),l--,u--):u>0&&(l===0||s[l][u-1]>=s[l-1][u])?(d.push({type:`add`,value:r[u-1]}),u--):(d.push({type:`remove`,value:n[l-1]}),l--);d.reverse();for(let e of d){let t=c[c.length-1];t&&t.type===e.type?t.value+=e.value:c.push({...e})}return c}function o(e){return e.replace(/<[^>]*>/g,` `).replace(/\s+/g,` `).trim()}function s(e){return e==null?``:e instanceof Date?e.toISOString():typeof e==`object`?JSON.stringify(e):String(e)}function c(e,t,n,r){if(JSON.stringify(t)===JSON.stringify(n))return null;switch(r?.type??u(t,n)){case`text`:case`slug`:return{field:e,type:`text`,from:t,to:n,segments:a(s(t),s(n))};case`richtext`:return{field:e,type:`richtext`,from:t,to:n,segments:a(o(s(t)),o(s(n)))};case`number`:return{field:e,type:`number`,from:t,to:n};case`boolean`:return{field:e,type:`boolean`,from:t,to:n};case`date`:return{field:e,type:`date`,from:t,to:n};case`select`:return{field:e,type:`select`,from:t,to:n};case`media`:return{field:e,type:`media`,from:t,to:n};case`json`:return{field:e,type:`json`,from:t,to:n};case`blocks`:return{field:e,type:`blocks`,from:t,to:n};default:return{field:e,type:`unknown`,from:t,to:n}}}function l(e,t,n){let r=new Set([...Object.keys(e),...Object.keys(t)]),i=[];for(let a of r){if(a===`id`||a===`createdAt`||a===`updatedAt`)continue;let r=c(a,e[a],t[a],n?.[a]);r&&i.push(r)}return i}function u(e,t){let n=e??t;return typeof n==`number`?`number`:typeof n==`boolean`?`boolean`:n instanceof Date?`date`:typeof n==`string`?/^\d{4}-\d{2}-\d{2}/.test(n)?`date`:`text`:Array.isArray(n)?n.length>0&&typeof n[0]==`object`&&n[0]!==null&&`_block`in n[0]?`blocks`:`json`:typeof n==`object`?`json`:`unknown`}function d(e,t){if(typeof e==`string`||typeof t==`string`)return a(s(e),s(t))}function f(e){return typeof e==`object`&&!!e&&`_block`in e&&`_id`in e&&typeof e._block==`string`&&typeof e._id==`string`}function p(e,t){let n=new Set([...Object.keys(e),...Object.keys(t)]),r=[];for(let i of n){if(i===`_block`||i===`_id`)continue;let n=e[i],a=t[i];JSON.stringify(n)!==JSON.stringify(a)&&r.push({field:i,from:n,to:a,segments:d(n,a)})}return r}function m(e,t){let n=e.filter(f),r=t.filter(f),i=new Map,a=new Map;for(let e=0;e<n.length;e++)i.set(n[e]._id,{block:n[e],index:e});for(let e=0;e<r.length;e++)a.set(r[e]._id,{block:r[e],index:e});let o=[],s=new Set;for(let[e,{block:t,index:n}]of a){s.add(e);let r=i.get(e);if(!r){o.push({blockId:e,blockType:t._block,status:`added`,toIndex:n});continue}let a=r.block,c=r.index,l=p(a,t),u=c!==n;l.length===0&&!u?o.push({blockId:e,blockType:t._block,status:`unchanged`,fromIndex:c,toIndex:n}):l.length>0?o.push({blockId:e,blockType:t._block,status:`changed`,fromIndex:c,toIndex:n,propDiffs:l}):o.push({blockId:e,blockType:t._block,status:`moved`,fromIndex:c,toIndex:n})}for(let[e,{block:t,index:n}]of i)s.has(e)||o.push({blockId:e,blockType:t._block,status:`removed`,fromIndex:n});return o}export{a,d as i,c as n,r as o,l as r,n as s,m as t};
2
- //# sourceMappingURL=block-diff-H1AttKiz.mjs.map
2
+ //# sourceMappingURL=block-diff-BBH6FoFT.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"block-diff-H1AttKiz.mjs","names":[],"sources":["../src/behaviors/versionable.ts","../src/diff/text-diff.ts","../src/diff/field-diff.ts","../src/diff/block-diff.ts"],"sourcesContent":["/**\n * Versionable behavior — full version history with snapshots.\n *\n * Extends the concept of revisionable() (which only tracks a counter)\n * with actual version snapshots stored in {entity}_versions table.\n *\n * The behavior itself adds fields + hooks for version tracking.\n * Actual snapshot persistence happens in ContentClient (which has DB access).\n *\n * Options:\n * - maxPerDoc: Maximum versions kept per document (default: 50)\n * - autosave: Enable smart autosave (default: false)\n */\n\nimport type { Behavior, DateField, NumberField } from '@murumets-ee/entity'\n\nimport { field } from '@murumets-ee/entity'\nimport type { VersionableOptions } from '../types.js'\n\nexport type VersionableFields = {\n _version: NumberField & { required: true }\n _versionedAt: DateField\n}\n\nconst DEFAULT_OPTIONS: Required<VersionableOptions> = {\n maxPerDoc: 50,\n autosave: false,\n}\n\nexport function versionable(options?: VersionableOptions): Behavior<VersionableFields> {\n const opts = { ...DEFAULT_OPTIONS, ...options }\n\n // Attach options to the behavior for ContentClient to read\n const behavior: Behavior<VersionableFields> & {\n _versionableOptions: Required<VersionableOptions>\n } = {\n name: 'versionable',\n fields: {\n _version: field.number({ required: true, default: 1, integer: true }),\n _versionedAt: field.date(),\n },\n hooks: {\n beforeCreate: async (data) => {\n data._version = 1\n data._versionedAt = new Date()\n return data\n },\n beforeUpdate: async (_id, data) => {\n // Only update _versionedAt here. The _version increment is handled by\n // createVersionSnapshot which reads the current version from the DB.\n // The beforeUpdate hook only receives partial data (the PATCH payload),\n // so it can't reliably increment _version without the current value.\n data._versionedAt = new Date()\n return data\n },\n },\n _versionableOptions: opts,\n }\n\n return behavior as Behavior<VersionableFields>\n}\n\n/**\n * Extract versionable options from an entity's behaviors\n */\nexport function getVersionableOptions(behaviors?: Behavior[]): Required<VersionableOptions> | null {\n if (!behaviors) return null\n const vBehavior = behaviors.find((b) => b.name === 'versionable') as\n | (Behavior & { _versionableOptions?: Required<VersionableOptions> })\n | undefined\n return vBehavior?._versionableOptions ?? null\n}\n","/**\n * Word-level text diff using a simplified Myers algorithm.\n *\n * Splits text into words (preserving whitespace), computes the longest common\n * subsequence, and returns an array of diff segments.\n */\n\nimport type { DiffSegment } from './types.js'\n\n/**\n * Split text into tokens — words and whitespace runs — so diffs are\n * human-readable (\"Changed *this* word\") rather than character-level.\n */\nfunction tokenize(text: string): string[] {\n return text.match(/\\S+|\\s+/g) ?? []\n}\n\n/**\n * Compute word-level diff between two strings.\n *\n * Uses a simple LCS (dynamic programming) approach which is fine for\n * the text sizes we deal with (entity field values, not source code).\n */\nexport function diffText(from: string, to: string): DiffSegment[] {\n if (from === to) {\n return from ? [{ type: 'equal', value: from }] : []\n }\n if (!from) {\n return [{ type: 'add', value: to }]\n }\n if (!to) {\n return [{ type: 'remove', value: from }]\n }\n\n const fromTokens = tokenize(from)\n const toTokens = tokenize(to)\n\n // Build LCS table\n const m = fromTokens.length\n const n = toTokens.length\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (fromTokens[i - 1] === toTokens[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1\n } else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])\n }\n }\n }\n\n // Backtrack to build diff segments\n const segments: DiffSegment[] = []\n let i = m\n let j = n\n\n // Collect in reverse, then flip\n const reversed: DiffSegment[] = []\n\n while (i > 0 || j > 0) {\n if (i > 0 && j > 0 && fromTokens[i - 1] === toTokens[j - 1]) {\n reversed.push({ type: 'equal', value: fromTokens[i - 1] })\n i--\n j--\n } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {\n reversed.push({ type: 'add', value: toTokens[j - 1] })\n j--\n } else {\n reversed.push({ type: 'remove', value: fromTokens[i - 1] })\n i--\n }\n }\n\n reversed.reverse()\n\n // Merge consecutive segments of the same type\n for (const seg of reversed) {\n const last = segments[segments.length - 1]\n if (last && last.type === seg.type) {\n last.value += seg.value\n } else {\n segments.push({ ...seg })\n }\n }\n\n return segments\n}\n","/**\n * Field-level diff — dispatches to the appropriate diff strategy per field type.\n */\n\nimport type { FieldConfig } from '@murumets-ee/entity'\nimport { diffText } from './text-diff.js'\nimport type { DiffSegment, FieldDiff } from './types.js'\n\n/** Strip HTML tags for diffing richtext content as plain text. */\nfunction stripHtml(html: string): string {\n return html\n .replace(/<[^>]*>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/** Stringify a value for display (dates, objects, etc.). */\nfunction stringify(value: unknown): string {\n if (value === null || value === undefined) return ''\n if (value instanceof Date) return value.toISOString()\n if (typeof value === 'object') return JSON.stringify(value)\n return String(value)\n}\n\n/**\n * Compute diff for a single field, using the field's type to determine\n * the best diff strategy.\n */\nexport function diffField(\n fieldName: string,\n from: unknown,\n to: unknown,\n fieldConfig?: FieldConfig,\n): FieldDiff | null {\n // No change\n if (JSON.stringify(from) === JSON.stringify(to)) return null\n\n const type = fieldConfig?.type ?? inferType(from, to)\n\n switch (type) {\n case 'text':\n case 'slug': {\n const segments = diffText(stringify(from), stringify(to))\n return { field: fieldName, type: 'text', from, to, segments }\n }\n\n case 'richtext': {\n // Diff on stripped HTML so users see word changes, not tag noise\n const segments = diffText(stripHtml(stringify(from)), stripHtml(stringify(to)))\n return { field: fieldName, type: 'richtext', from, to, segments }\n }\n\n case 'number':\n return { field: fieldName, type: 'number', from, to }\n\n case 'boolean':\n return { field: fieldName, type: 'boolean', from, to }\n\n case 'date':\n return { field: fieldName, type: 'date', from, to }\n\n case 'select':\n return { field: fieldName, type: 'select', from, to }\n\n case 'media':\n return { field: fieldName, type: 'media', from, to }\n\n case 'json':\n return { field: fieldName, type: 'json', from, to }\n\n case 'blocks':\n // Blocks are handled separately by block-diff.ts — just mark the field\n return { field: fieldName, type: 'blocks', from, to }\n\n default:\n return { field: fieldName, type: 'unknown', from, to }\n }\n}\n\n/**\n * Diff all fields between two version snapshots.\n * Pass fieldConfigs to get type-aware diffs; without them, types are inferred.\n */\nexport function diffFields(\n from: Record<string, unknown>,\n to: Record<string, unknown>,\n fieldConfigs?: Record<string, FieldConfig>,\n): FieldDiff[] {\n const allKeys = new Set([...Object.keys(from), ...Object.keys(to)])\n const diffs: FieldDiff[] = []\n\n for (const key of allKeys) {\n // Skip internal/auto-generated fields\n if (key === 'id' || key === 'createdAt' || key === 'updatedAt') continue\n\n const diff = diffField(key, from[key], to[key], fieldConfigs?.[key])\n if (diff) diffs.push(diff)\n }\n\n return diffs\n}\n\n/** Best-effort type inference when no FieldConfig is available. */\nfunction inferType(from: unknown, to: unknown): string {\n const val = from ?? to\n if (typeof val === 'number') return 'number'\n if (typeof val === 'boolean') return 'boolean'\n if (val instanceof Date) return 'date'\n if (typeof val === 'string') {\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(val)) return 'date'\n return 'text'\n }\n if (Array.isArray(val)) {\n // Check if it looks like a blocks array\n if (val.length > 0 && typeof val[0] === 'object' && val[0] !== null && '_block' in val[0]) {\n return 'blocks'\n }\n return 'json'\n }\n if (typeof val === 'object') return 'json'\n return 'unknown'\n}\n\n/** Diff two string values and return segments (used by block-diff for string props). */\nexport function diffStringValues(from: unknown, to: unknown): DiffSegment[] | undefined {\n if (typeof from === 'string' || typeof to === 'string') {\n return diffText(stringify(from), stringify(to))\n }\n return undefined\n}\n","/**\n * Structural diff for Puck block arrays.\n *\n * Blocks are identified by `_id`. The algorithm detects:\n * - Added blocks (new _id in target)\n * - Removed blocks (missing _id in target)\n * - Moved blocks (same _id, different position)\n * - Changed blocks (same _id, different prop values)\n * - Unchanged blocks\n */\n\nimport { diffStringValues } from './field-diff.js'\nimport type { BlockDiffEntry, PropDiff } from './types.js'\n\ninterface Block {\n _block: string\n _id: string\n [key: string]: unknown\n}\n\nfunction isBlock(val: unknown): val is Block {\n return (\n typeof val === 'object' &&\n val !== null &&\n '_block' in val &&\n '_id' in val &&\n typeof (val as Block)._block === 'string' &&\n typeof (val as Block)._id === 'string'\n )\n}\n\n/**\n * Diff two prop objects within a single block, returning per-prop diffs.\n */\nfunction diffProps(\n fromProps: Record<string, unknown>,\n toProps: Record<string, unknown>,\n): PropDiff[] {\n const allKeys = new Set([...Object.keys(fromProps), ...Object.keys(toProps)])\n const diffs: PropDiff[] = []\n\n for (const key of allKeys) {\n // Skip block metadata\n if (key === '_block' || key === '_id') continue\n\n const fromVal = fromProps[key]\n const toVal = toProps[key]\n\n if (JSON.stringify(fromVal) !== JSON.stringify(toVal)) {\n diffs.push({\n field: key,\n from: fromVal,\n to: toVal,\n segments: diffStringValues(fromVal, toVal),\n })\n }\n }\n\n return diffs\n}\n\n/**\n * Compute structural diff between two block arrays.\n *\n * Each block is identified by its `_id` field. Position changes,\n * additions, removals, and prop-level changes are all detected.\n */\nexport function diffBlocks(fromBlocks: unknown[], toBlocks: unknown[]): BlockDiffEntry[] {\n const from = fromBlocks.filter(isBlock)\n const to = toBlocks.filter(isBlock)\n\n const fromMap = new Map<string, { block: Block; index: number }>()\n const toMap = new Map<string, { block: Block; index: number }>()\n\n for (let i = 0; i < from.length; i++) {\n fromMap.set(from[i]._id, { block: from[i], index: i })\n }\n for (let i = 0; i < to.length; i++) {\n toMap.set(to[i]._id, { block: to[i], index: i })\n }\n\n const entries: BlockDiffEntry[] = []\n const processedIds = new Set<string>()\n\n // Walk the \"to\" array to preserve target order\n for (const [id, { block: toBlock, index: toIndex }] of toMap) {\n processedIds.add(id)\n const fromEntry = fromMap.get(id)\n\n if (!fromEntry) {\n // Added\n entries.push({\n blockId: id,\n blockType: toBlock._block,\n status: 'added',\n toIndex,\n })\n continue\n }\n\n const fromBlock = fromEntry.block\n const fromIndex = fromEntry.index\n const propDiffs = diffProps(fromBlock, toBlock)\n const moved = fromIndex !== toIndex\n\n if (propDiffs.length === 0 && !moved) {\n entries.push({\n blockId: id,\n blockType: toBlock._block,\n status: 'unchanged',\n fromIndex,\n toIndex,\n })\n } else if (propDiffs.length > 0) {\n entries.push({\n blockId: id,\n blockType: toBlock._block,\n status: 'changed',\n fromIndex,\n toIndex,\n propDiffs,\n })\n } else {\n entries.push({\n blockId: id,\n blockType: toBlock._block,\n status: 'moved',\n fromIndex,\n toIndex,\n })\n }\n }\n\n // Removed blocks (in \"from\" but not in \"to\")\n for (const [id, { block, index }] of fromMap) {\n if (!processedIds.has(id)) {\n entries.push({\n blockId: id,\n blockType: block._block,\n status: 'removed',\n fromIndex: index,\n })\n }\n }\n\n return entries\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"block-diff-BBH6FoFT.mjs","names":[],"sources":["../src/behaviors/versionable.ts","../src/diff/text-diff.ts","../src/diff/field-diff.ts","../src/diff/block-diff.ts"],"sourcesContent":["/**\n * Versionable behavior — full version history with snapshots.\n *\n * Extends the concept of revisionable() (which only tracks a counter)\n * with actual version snapshots stored in {entity}_versions table.\n *\n * The behavior itself adds fields + hooks for version tracking.\n * Actual snapshot persistence happens in ContentClient (which has DB access).\n *\n * Options:\n * - maxPerDoc: Maximum versions kept per document (default: 50)\n * - autosave: Enable smart autosave (default: false)\n */\n\nimport type { Behavior, DateField, NumberField } from '@murumets-ee/entity'\n\nimport { field } from '@murumets-ee/entity'\nimport type { VersionableOptions } from '../types.js'\n\nexport type VersionableFields = {\n _version: NumberField & { required: true }\n _versionedAt: DateField\n}\n\nconst DEFAULT_OPTIONS: Required<VersionableOptions> = {\n maxPerDoc: 50,\n autosave: false,\n}\n\nexport function versionable(options?: VersionableOptions): Behavior<VersionableFields> {\n const opts = { ...DEFAULT_OPTIONS, ...options }\n\n // Attach options to the behavior for ContentClient to read\n const behavior: Behavior<VersionableFields> & {\n _versionableOptions: Required<VersionableOptions>\n } = {\n name: 'versionable',\n fields: {\n _version: field.number({ required: true, default: 1, integer: true }),\n _versionedAt: field.date(),\n },\n hooks: {\n beforeCreate: async (data) => {\n data._version = 1\n data._versionedAt = new Date()\n return data\n },\n beforeUpdate: async (_id, data) => {\n // Only update _versionedAt here. The _version increment is handled by\n // createVersionSnapshot which reads the current version from the DB.\n // The beforeUpdate hook only receives partial data (the PATCH payload),\n // so it can't reliably increment _version without the current value.\n data._versionedAt = new Date()\n return data\n },\n },\n _versionableOptions: opts,\n }\n\n return behavior as Behavior<VersionableFields>\n}\n\n/**\n * Extract versionable options from an entity's behaviors\n */\nexport function getVersionableOptions(behaviors?: Behavior[]): Required<VersionableOptions> | null {\n if (!behaviors) return null\n const vBehavior = behaviors.find((b) => b.name === 'versionable') as\n | (Behavior & { _versionableOptions?: Required<VersionableOptions> })\n | undefined\n return vBehavior?._versionableOptions ?? null\n}\n","/**\n * Word-level text diff using a simplified Myers algorithm.\n *\n * Splits text into words (preserving whitespace), computes the longest common\n * subsequence, and returns an array of diff segments.\n */\n\nimport type { DiffSegment } from './types.js'\n\n/**\n * Split text into tokens — words and whitespace runs — so diffs are\n * human-readable (\"Changed *this* word\") rather than character-level.\n */\nfunction tokenize(text: string): string[] {\n return text.match(/\\S+|\\s+/g) ?? []\n}\n\n/**\n * Compute word-level diff between two strings.\n *\n * Uses a simple LCS (dynamic programming) approach which is fine for\n * the text sizes we deal with (entity field values, not source code).\n */\nexport function diffText(from: string, to: string): DiffSegment[] {\n if (from === to) {\n return from ? [{ type: 'equal', value: from }] : []\n }\n if (!from) {\n return [{ type: 'add', value: to }]\n }\n if (!to) {\n return [{ type: 'remove', value: from }]\n }\n\n const fromTokens = tokenize(from)\n const toTokens = tokenize(to)\n\n // Build LCS table\n const m = fromTokens.length\n const n = toTokens.length\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (fromTokens[i - 1] === toTokens[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1\n } else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])\n }\n }\n }\n\n // Backtrack to build diff segments\n const segments: DiffSegment[] = []\n let i = m\n let j = n\n\n // Collect in reverse, then flip\n const reversed: DiffSegment[] = []\n\n while (i > 0 || j > 0) {\n if (i > 0 && j > 0 && fromTokens[i - 1] === toTokens[j - 1]) {\n reversed.push({ type: 'equal', value: fromTokens[i - 1] })\n i--\n j--\n } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {\n reversed.push({ type: 'add', value: toTokens[j - 1] })\n j--\n } else {\n reversed.push({ type: 'remove', value: fromTokens[i - 1] })\n i--\n }\n }\n\n reversed.reverse()\n\n // Merge consecutive segments of the same type\n for (const seg of reversed) {\n const last = segments[segments.length - 1]\n if (last && last.type === seg.type) {\n last.value += seg.value\n } else {\n segments.push({ ...seg })\n }\n }\n\n return segments\n}\n","/**\n * Field-level diff — dispatches to the appropriate diff strategy per field type.\n */\n\nimport type { FieldConfig } from '@murumets-ee/entity'\nimport { diffText } from './text-diff.js'\nimport type { DiffSegment, FieldDiff } from './types.js'\n\n/** Strip HTML tags for diffing richtext content as plain text. */\nfunction stripHtml(html: string): string {\n return html\n .replace(/<[^>]*>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/** Stringify a value for display (dates, objects, etc.). */\nfunction stringify(value: unknown): string {\n if (value === null || value === undefined) return ''\n if (value instanceof Date) return value.toISOString()\n if (typeof value === 'object') return JSON.stringify(value)\n return String(value)\n}\n\n/**\n * Compute diff for a single field, using the field's type to determine\n * the best diff strategy.\n */\nexport function diffField(\n fieldName: string,\n from: unknown,\n to: unknown,\n fieldConfig?: FieldConfig,\n): FieldDiff | null {\n // No change\n if (JSON.stringify(from) === JSON.stringify(to)) return null\n\n const type = fieldConfig?.type ?? inferType(from, to)\n\n switch (type) {\n case 'text':\n case 'slug': {\n const segments = diffText(stringify(from), stringify(to))\n return { field: fieldName, type: 'text', from, to, segments }\n }\n\n case 'richtext': {\n // Diff on stripped HTML so users see word changes, not tag noise\n const segments = diffText(stripHtml(stringify(from)), stripHtml(stringify(to)))\n return { field: fieldName, type: 'richtext', from, to, segments }\n }\n\n case 'number':\n return { field: fieldName, type: 'number', from, to }\n\n case 'boolean':\n return { field: fieldName, type: 'boolean', from, to }\n\n case 'date':\n return { field: fieldName, type: 'date', from, to }\n\n case 'select':\n return { field: fieldName, type: 'select', from, to }\n\n case 'media':\n return { field: fieldName, type: 'media', from, to }\n\n case 'json':\n return { field: fieldName, type: 'json', from, to }\n\n case 'blocks':\n // Blocks are handled separately by block-diff.ts — just mark the field\n return { field: fieldName, type: 'blocks', from, to }\n\n default:\n return { field: fieldName, type: 'unknown', from, to }\n }\n}\n\n/**\n * Diff all fields between two version snapshots.\n * Pass fieldConfigs to get type-aware diffs; without them, types are inferred.\n */\nexport function diffFields(\n from: Record<string, unknown>,\n to: Record<string, unknown>,\n fieldConfigs?: Record<string, FieldConfig>,\n): FieldDiff[] {\n const allKeys = new Set([...Object.keys(from), ...Object.keys(to)])\n const diffs: FieldDiff[] = []\n\n for (const key of allKeys) {\n // Skip internal/auto-generated fields\n if (key === 'id' || key === 'createdAt' || key === 'updatedAt') continue\n\n const diff = diffField(key, from[key], to[key], fieldConfigs?.[key])\n if (diff) diffs.push(diff)\n }\n\n return diffs\n}\n\n/** Best-effort type inference when no FieldConfig is available. */\nfunction inferType(from: unknown, to: unknown): string {\n const val = from ?? to\n if (typeof val === 'number') return 'number'\n if (typeof val === 'boolean') return 'boolean'\n if (val instanceof Date) return 'date'\n if (typeof val === 'string') {\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(val)) return 'date'\n return 'text'\n }\n if (Array.isArray(val)) {\n // Check if it looks like a blocks array\n if (val.length > 0 && typeof val[0] === 'object' && val[0] !== null && '_block' in val[0]) {\n return 'blocks'\n }\n return 'json'\n }\n if (typeof val === 'object') return 'json'\n return 'unknown'\n}\n\n/** Diff two string values and return segments (used by block-diff for string props). */\nexport function diffStringValues(from: unknown, to: unknown): DiffSegment[] | undefined {\n if (typeof from === 'string' || typeof to === 'string') {\n return diffText(stringify(from), stringify(to))\n }\n return undefined\n}\n","/**\n * Structural diff for Puck block arrays.\n *\n * Blocks are identified by `_id`. The algorithm detects:\n * - Added blocks (new _id in target)\n * - Removed blocks (missing _id in target)\n * - Moved blocks (same _id, different position)\n * - Changed blocks (same _id, different prop values)\n * - Unchanged blocks\n */\n\nimport { diffStringValues } from './field-diff.js'\nimport type { BlockDiffEntry, PropDiff } from './types.js'\n\ninterface Block {\n _block: string\n _id: string\n [key: string]: unknown\n}\n\nfunction isBlock(val: unknown): val is Block {\n return (\n typeof val === 'object' &&\n val !== null &&\n '_block' in val &&\n '_id' in val &&\n typeof (val as Block)._block === 'string' &&\n typeof (val as Block)._id === 'string'\n )\n}\n\n/**\n * Diff two prop objects within a single block, returning per-prop diffs.\n */\nfunction diffProps(\n fromProps: Record<string, unknown>,\n toProps: Record<string, unknown>,\n): PropDiff[] {\n const allKeys = new Set([...Object.keys(fromProps), ...Object.keys(toProps)])\n const diffs: PropDiff[] = []\n\n for (const key of allKeys) {\n // Skip block metadata\n if (key === '_block' || key === '_id') continue\n\n const fromVal = fromProps[key]\n const toVal = toProps[key]\n\n if (JSON.stringify(fromVal) !== JSON.stringify(toVal)) {\n diffs.push({\n field: key,\n from: fromVal,\n to: toVal,\n segments: diffStringValues(fromVal, toVal),\n })\n }\n }\n\n return diffs\n}\n\n/**\n * Compute structural diff between two block arrays.\n *\n * Each block is identified by its `_id` field. Position changes,\n * additions, removals, and prop-level changes are all detected.\n */\nexport function diffBlocks(fromBlocks: unknown[], toBlocks: unknown[]): BlockDiffEntry[] {\n const from = fromBlocks.filter(isBlock)\n const to = toBlocks.filter(isBlock)\n\n const fromMap = new Map<string, { block: Block; index: number }>()\n const toMap = new Map<string, { block: Block; index: number }>()\n\n for (let i = 0; i < from.length; i++) {\n fromMap.set(from[i]._id, { block: from[i], index: i })\n }\n for (let i = 0; i < to.length; i++) {\n toMap.set(to[i]._id, { block: to[i], index: i })\n }\n\n const entries: BlockDiffEntry[] = []\n const processedIds = new Set<string>()\n\n // Walk the \"to\" array to preserve target order\n for (const [id, { block: toBlock, index: toIndex }] of toMap) {\n processedIds.add(id)\n const fromEntry = fromMap.get(id)\n\n if (!fromEntry) {\n // Added\n entries.push({\n blockId: id,\n blockType: toBlock._block,\n status: 'added',\n toIndex,\n })\n continue\n }\n\n const fromBlock = fromEntry.block\n const fromIndex = fromEntry.index\n const propDiffs = diffProps(fromBlock, toBlock)\n const moved = fromIndex !== toIndex\n\n if (propDiffs.length === 0 && !moved) {\n entries.push({\n blockId: id,\n blockType: toBlock._block,\n status: 'unchanged',\n fromIndex,\n toIndex,\n })\n } else if (propDiffs.length > 0) {\n entries.push({\n blockId: id,\n blockType: toBlock._block,\n status: 'changed',\n fromIndex,\n toIndex,\n propDiffs,\n })\n } else {\n entries.push({\n blockId: id,\n blockType: toBlock._block,\n status: 'moved',\n fromIndex,\n toIndex,\n })\n }\n }\n\n // Removed blocks (in \"from\" but not in \"to\")\n for (const [id, { block, index }] of fromMap) {\n if (!processedIds.has(id)) {\n entries.push({\n blockId: id,\n blockType: block._block,\n status: 'removed',\n fromIndex: index,\n })\n }\n }\n\n return entries\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as BlockDefinition } from "../types-wLHyjcWf.mjs";
1
+ import { t as BlockDefinition } from "../types-D-ATlx7t.mjs";
2
2
  import * as _$_murumets_ee_entity0 from "@murumets-ee/entity";
3
3
 
4
4
  //#region src/blocks/code.d.ts
@@ -1,2 +1,2 @@
1
- import{t as e}from"../define-block-D-7OpIn5.mjs";import{field as t}from"@murumets-ee/entity";const n=e({slug:`code`,label:`Code`,fields:{code:t.text({required:!0}),language:t.select({options:[`javascript`,`typescript`,`python`,`html`,`css`,`json`,`bash`,`sql`,`other`]})}}),r=e({slug:`cta`,label:`Call to Action`,fields:{heading:t.text({required:!0,translatable:!0}),description:t.text({translatable:!0}),buttonText:t.text({required:!0,translatable:!0}),buttonLink:t.text({required:!0})}}),i=e({slug:`gallery`,label:`Gallery`,fields:{images:t.reference({entity:`media`,cardinality:`many`}),columns:t.select({options:[`2`,`3`,`4`]})}}),a=e({slug:`hero`,label:`Hero Section`,fields:{heading:t.text({required:!0,translatable:!0}),subheading:t.text({translatable:!0}),background:t.media({accept:[`image/*`]}),alignment:t.select({options:[`left`,`center`,`right`]})}}),o=e({slug:`image`,label:`Image`,fields:{image:t.media({accept:[`image/*`],required:!0}),alt:t.text({translatable:!0}),caption:t.text({translatable:!0})}}),s=e({slug:`quote`,label:`Quote`,fields:{quote:t.text({required:!0,translatable:!0}),attribution:t.text({translatable:!0})}}),c=e({slug:`richtext`,label:`Rich Text`,fields:{content:t.richtext({translatable:!0})}}),l=e({slug:`video`,label:`Video`,fields:{url:t.text({required:!0}),poster:t.media({accept:[`image/*`]}),caption:t.text({translatable:!0})}}),u=[c,o,a,i,r,l,s,n];export{r as CTABlock,n as CodeBlock,i as GalleryBlock,a as HeroBlock,o as ImageBlock,s as QuoteBlock,c as RichTextBlock,l as VideoBlock,u as commonBlocks};
1
+ import{t as e}from"../define-block-DpMPEEdA.mjs";import{field as t}from"@murumets-ee/entity";const n=e({slug:`code`,label:`Code`,fields:{code:t.text({required:!0}),language:t.select({options:[`javascript`,`typescript`,`python`,`html`,`css`,`json`,`bash`,`sql`,`other`]})}}),r=e({slug:`cta`,label:`Call to Action`,fields:{heading:t.text({required:!0,translatable:!0}),description:t.text({translatable:!0}),buttonText:t.text({required:!0,translatable:!0}),buttonLink:t.text({required:!0})}}),i=e({slug:`gallery`,label:`Gallery`,fields:{images:t.reference({entity:`media`,cardinality:`many`}),columns:t.select({options:[`2`,`3`,`4`]})}}),a=e({slug:`hero`,label:`Hero Section`,fields:{heading:t.text({required:!0,translatable:!0}),subheading:t.text({translatable:!0}),background:t.media({accept:[`image/*`]}),alignment:t.select({options:[`left`,`center`,`right`]})}}),o=e({slug:`image`,label:`Image`,fields:{image:t.media({accept:[`image/*`],required:!0}),alt:t.text({translatable:!0}),caption:t.text({translatable:!0})}}),s=e({slug:`quote`,label:`Quote`,fields:{quote:t.text({required:!0,translatable:!0}),attribution:t.text({translatable:!0})}}),c=e({slug:`richtext`,label:`Rich Text`,fields:{content:t.richtext({translatable:!0})}}),l=e({slug:`video`,label:`Video`,fields:{url:t.text({required:!0}),poster:t.media({accept:[`image/*`]}),caption:t.text({translatable:!0})}}),u=[c,o,a,i,r,l,s,n];export{r as CTABlock,n as CodeBlock,i as GalleryBlock,a as HeroBlock,o as ImageBlock,s as QuoteBlock,c as RichTextBlock,l as VideoBlock,u as commonBlocks};
2
2
  //# sourceMappingURL=index.mjs.map
package/dist/client.d.mts CHANGED
@@ -1,69 +1,177 @@
1
- import { d as TranslationStatus, f as VersionEntry, r as DraftEntry, s as LocalePublishStatus, u as TranslationReport } from "./types-wLHyjcWf.mjs";
2
- import { i as FieldDiff } from "./types-nXbE5Ufa.mjs";
1
+ import { d as TranslationStatus, f as VersionEntry, r as DraftEntry, s as LocalePublishStatus, u as TranslationReport } from "./types-D-ATlx7t.mjs";
2
+ import { i as FieldDiff } from "./types-COcneY5H.mjs";
3
3
  import { Entity, FieldConfig, FieldToTS } from "@murumets-ee/entity";
4
4
  import { Logger } from "@murumets-ee/core";
5
- import { FindManyOptions } from "@murumets-ee/entity/admin";
6
- import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
5
+ import { AdminClient, FindManyOptions } from "@murumets-ee/entity/admin";
7
6
 
8
7
  //#region src/client.d.ts
9
8
  /** Value type that any entity field can hold */
10
9
  type EntityFieldValue = FieldToTS<FieldConfig> | null | undefined;
11
10
  interface ContentClientConfig {
11
+ admin: AdminClient;
12
12
  entity: Entity;
13
- db: PostgresJsDatabase;
14
13
  logger?: Logger;
15
14
  }
16
15
  declare class ContentClient {
17
16
  private entity;
18
- private db;
19
- private logger?;
20
17
  private admin;
18
+ private logger?;
21
19
  private versionableOptions;
22
20
  constructor(config: ContentClientConfig);
23
- private getAdmin;
21
+ /** Database handle inherited from the injected AdminClient. */
22
+ private get db();
23
+ /** Lazy TableClient for the drafts table. Returns null if the entity has no drafts table. */
24
+ private getDraftsClient;
25
+ /** Lazy TableClient for the versions table. Returns null if the entity has no versions table. */
26
+ private getVersionsClient;
27
+ /** Lazy TableClient for the locale_status table. Returns null if the entity has no locale_status table. */
28
+ private getLocaleStatusClient;
24
29
  create(data: Record<string, EntityFieldValue>): Promise<{
25
30
  id: string;
26
31
  } & {} & {
27
- [x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
32
+ [x: string]: Date | Record<string, unknown>[] | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | {
33
+ [key: string]: string | number | boolean | /*elided*/any | /*elided*/any | null;
34
+ } | null)[] | {
35
+ [key: string]: string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null;
36
+ } | null)[] | {
37
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
38
+ } | null)[] | {
39
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
40
+ } | null)[] | {
41
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
42
+ } | null)[] | {
43
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
44
+ } | null)[] | {
45
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
46
+ } | null)[] | {
47
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
48
+ } | null)[] | {
49
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
50
+ } | null)[] | {
51
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
52
+ } | null)[] | {
53
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
54
+ } | null)[] | {
55
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
56
+ } | null) | {
28
57
  [key: string]: unknown;
29
58
  _block: string;
30
59
  _id: string;
31
- }[] | null | undefined;
60
+ }[] | undefined;
32
61
  }>;
33
62
  findById(id: string, options?: {
34
63
  locale?: string;
35
64
  }): Promise<({
36
65
  id: string;
37
66
  } & {} & {
38
- [x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
67
+ [x: string]: Date | Record<string, unknown>[] | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | {
68
+ [key: string]: string | number | boolean | /*elided*/any | /*elided*/any | null;
69
+ } | null)[] | {
70
+ [key: string]: string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null;
71
+ } | null)[] | {
72
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
73
+ } | null)[] | {
74
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
75
+ } | null)[] | {
76
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
77
+ } | null)[] | {
78
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
79
+ } | null)[] | {
80
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
81
+ } | null)[] | {
82
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
83
+ } | null)[] | {
84
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
85
+ } | null)[] | {
86
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
87
+ } | null)[] | {
88
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
89
+ } | null)[] | {
90
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
91
+ } | null) | {
39
92
  [key: string]: unknown;
40
93
  _block: string;
41
94
  _id: string;
42
- }[] | null | undefined;
95
+ }[] | undefined;
43
96
  }) | null>;
44
97
  findMany(options?: FindManyOptions): Promise<({
45
98
  id: string;
46
99
  } & {} & {
47
- [x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
100
+ [x: string]: Date | Record<string, unknown>[] | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | {
101
+ [key: string]: string | number | boolean | /*elided*/any | /*elided*/any | null;
102
+ } | null)[] | {
103
+ [key: string]: string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null;
104
+ } | null)[] | {
105
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
106
+ } | null)[] | {
107
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
108
+ } | null)[] | {
109
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
110
+ } | null)[] | {
111
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
112
+ } | null)[] | {
113
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
114
+ } | null)[] | {
115
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
116
+ } | null)[] | {
117
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
118
+ } | null)[] | {
119
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
120
+ } | null)[] | {
121
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
122
+ } | null)[] | {
123
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
124
+ } | null) | {
48
125
  [key: string]: unknown;
49
126
  _block: string;
50
127
  _id: string;
51
- }[] | null | undefined;
128
+ }[] | undefined;
52
129
  })[]>;
53
130
  update(id: string, data: Record<string, EntityFieldValue>): Promise<{
54
131
  id: string;
55
132
  } & {} & {
56
- [x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
133
+ [x: string]: Date | Record<string, unknown>[] | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | {
134
+ [key: string]: string | number | boolean | /*elided*/any | /*elided*/any | null;
135
+ } | null)[] | {
136
+ [key: string]: string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null;
137
+ } | null)[] | {
138
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
139
+ } | null)[] | {
140
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
141
+ } | null)[] | {
142
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
143
+ } | null)[] | {
144
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
145
+ } | null)[] | {
146
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
147
+ } | null)[] | {
148
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
149
+ } | null)[] | {
150
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
151
+ } | null)[] | {
152
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
153
+ } | null)[] | {
154
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
155
+ } | null)[] | {
156
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
157
+ } | null) | {
57
158
  [key: string]: unknown;
58
159
  _block: string;
59
160
  _id: string;
60
- }[] | null | undefined;
161
+ }[] | undefined;
61
162
  }>;
62
163
  delete(id: string): Promise<void>;
63
164
  saveTranslation(entityId: string, locale: string, translations: Record<string, unknown>): Promise<void>;
64
165
  deleteTranslation(entityId: string, locale?: string): Promise<void>;
65
166
  /**
66
167
  * Copy layout from one locale to another (for localized: true blocks).
168
+ *
169
+ * NOTE: Layout tables are generated in `@murumets-ee/entity` (they need
170
+ * FK references to the parent entity table, which `defineTable` does not
171
+ * currently support). So this method uses direct Drizzle queries against
172
+ * the layout pgTable via `schemaRegistry` — it is the one remaining
173
+ * escape valve in ContentClient. If `defineTable` gains FK support in the
174
+ * future, migrate this to a TableClient pattern like drafts/versions.
67
175
  */
68
176
  copyLayout(entityId: string, options: {
69
177
  from: string;
@@ -108,11 +216,35 @@ declare class ContentClient {
108
216
  restoreVersion(entityId: string, version: number): Promise<{
109
217
  id: string;
110
218
  } & {} & {
111
- [x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
219
+ [x: string]: Date | Record<string, unknown>[] | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | {
220
+ [key: string]: string | number | boolean | /*elided*/any | /*elided*/any | null;
221
+ } | null)[] | {
222
+ [key: string]: string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null;
223
+ } | null)[] | {
224
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
225
+ } | null)[] | {
226
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
227
+ } | null)[] | {
228
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
229
+ } | null)[] | {
230
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
231
+ } | null)[] | {
232
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
233
+ } | null)[] | {
234
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
235
+ } | null)[] | {
236
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
237
+ } | null)[] | {
238
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
239
+ } | null)[] | {
240
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
241
+ } | null)[] | {
242
+ [key: string]: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | /*elided*/any | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null)[] | /*elided*/any | null;
243
+ } | null) | {
112
244
  [key: string]: unknown;
113
245
  _block: string;
114
246
  _id: string;
115
- }[] | null | undefined;
247
+ }[] | undefined;
116
248
  }>;
117
249
  /**
118
250
  * Enforce maxPerDoc retention by deleting oldest versions for a locale.
@@ -199,6 +331,16 @@ declare class ContentClient {
199
331
  id: string;
200
332
  name?: string;
201
333
  }): Promise<void>;
334
+ /**
335
+ * Write the `_version` column on the entity row.
336
+ *
337
+ * KNOWN EXCEPTION: this bypasses AdminClient and goes straight to the
338
+ * entity pgTable via `schemaRegistry` + direct Drizzle. Using
339
+ * `admin.update()` would retrigger the `versionable.beforeUpdate` hook
340
+ * and loop indefinitely. This is the only ContentClient path that still
341
+ * writes to an entity table directly.
342
+ */
343
+ private writeVersionColumn;
202
344
  private saveVersionSnapshot;
203
345
  private toDraftEntry;
204
346
  private calculateDelta;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":"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"}
1
+ {"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":"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"}
package/dist/client.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{o as e,r as t,t as n}from"./block-diff-H1AttKiz.mjs";import"server-only";var r=class{entity;db;logger;admin=null;versionableOptions;constructor(t){this.entity=t.entity,this.db=t.db,this.logger=t.logger,this.versionableOptions=e(t.entity.behaviors)}async getAdmin(){if(!this.admin){let{AdminClient:e}=await import(`@murumets-ee/entity/admin`);this.admin=new e({entity:this.entity,db:this.db,logger:this.logger})}return this.admin}async create(e){let t=await(await this.getAdmin()).create(e);return this.versionableOptions&&await this.saveVersionSnapshot(t.id,t,null,!1),t}async findById(e,t){return(await this.getAdmin()).findById(e,t)}async findMany(e){return(await this.getAdmin()).findMany(e)}async update(e,t){let n=await this.getAdmin(),r=null;this.versionableOptions&&(r=await n.findById(e));let i=await n.update(e,t);if(this.versionableOptions&&r){let t=this.calculateDelta(r,i),n=await this.saveVersionSnapshot(e,i,t,!1);if(n!==void 0){let{schemaRegistry:t}=await import(`@murumets-ee/db`),{eq:r}=await import(`drizzle-orm`),a=t.get(this.entity.name);a&&(await this.db.update(a).set({_version:n}).where(r(a.id,e)),i._version=n)}await this.pruneVersions(e)}return i}async delete(e){return(await this.getAdmin()).delete(e)}async saveTranslation(e,t,n){return(await this.getAdmin()).saveTranslation(e,t,n)}async deleteTranslation(e,t){return(await this.getAdmin()).deleteTranslation(e,t)}async copyLayout(e,t){let{schemaRegistry:n}=await import(`@murumets-ee/db`),{eq:r,and:i}=await import(`drizzle-orm`),a=n.get(`${this.entity.name}_layout`);if(!a)return;let o=Array.isArray(t.to)?t.to:[t.to],s=await this.db.select().from(a).where(i(r(a.entityId,e),r(a.locale,t.from))).orderBy(a.sortOrder);if(s.length!==0){for(let t of o){await this.db.delete(a).where(i(r(a.entityId,e),r(a.locale,t)));for(let e of s)await this.db.insert(a).values({entityId:e.entityId,fieldName:e.fieldName,blockType:e.blockType,sortOrder:e.sortOrder,data:e.data,locale:t})}this.logger?.debug({entityId:e,from:t.from,to:o},`Layout copied between locales`)}}async getVersions(e,t){let{schemaRegistry:n}=await import(`@murumets-ee/db`),{eq:r,and:i,desc:a}=await import(`drizzle-orm`),o=n.get(`${this.entity.name}_versions`);if(!o)return[];let s=t?.locale??`_`,c=this.db.select().from(o).where(i(r(o.entityId,e),r(o.locale,s))).orderBy(a(o.version)).$dynamic();return t?.limit&&(c=c.limit(t.limit)),t?.offset&&(c=c.offset(t.offset)),c}async getVersion(e,t,n=`_`){let{schemaRegistry:r}=await import(`@murumets-ee/db`),{eq:i,and:a}=await import(`drizzle-orm`),o=r.get(`${this.entity.name}_versions`);return o?(await this.db.select().from(o).where(a(i(o.entityId,e),i(o.version,t),i(o.locale,n))).limit(1))[0]??null:null}async compareVersions(e,r,i,a=`_`){let[o,s]=await Promise.all([this.getVersion(e,r,a),this.getVersion(e,i,a)]);if(!o||!s)return null;let c=o.data,l=s.data,u=this.entity.allFields,d=t(c,l,u);for(let e of d)e.type===`blocks`&&Array.isArray(e.from)&&Array.isArray(e.to)&&(e.blockDiffs=n(e.from,e.to));return{diffs:d,fromVersion:o,toVersion:s}}async compareDraftWithCurrent(e,r=`_`){let i=await this.getDraft(e,r);if(!i)return null;let a=await this.getAdmin(),{getContentConfig:o}=await import(`./plugin.mjs`),s=o().defaultLocale,c=r===`_`?{defaultLocale:s}:{locale:r,defaultLocale:s},l=await a.findById(e,c);if(!l)return null;let u=this.entity.allFields,d={};for(let e of Object.keys(i.data))d[e]=l[e];let f=t(d,i.data,u);for(let e of f)e.type===`blocks`&&Array.isArray(e.from)&&Array.isArray(e.to)&&(e.blockDiffs=n(e.from,e.to));return{diffs:f,current:l,draft:i}}async restoreVersion(e,t){let n=await this.getVersion(e,t);if(!n)throw Error(`Version ${t} not found for entity ${e}`);let{id:r,createdAt:i,createdBy:a,_version:o,_versionedAt:s,...c}=n.data;return(await this.getAdmin()).update(e,c)}async pruneVersions(e,t=`_`){if(!this.versionableOptions)return;let{schemaRegistry:n}=await import(`@murumets-ee/db`),{eq:r,and:i,desc:a,sql:o}=await import(`drizzle-orm`),s=n.get(`${this.entity.name}_versions`);if(!s)return;let c=this.versionableOptions.maxPerDoc,l=await this.db.select({id:s.id}).from(s).where(i(r(s.entityId,e),r(s.locale,t))).orderBy(a(s.version)).limit(c);if(l.length<c)return;let u=l.map(e=>e.id);await this.db.delete(s).where(o`${s.entityId} = ${e} AND ${s.locale} = ${t} AND ${s.id} NOT IN (${o.join(u.map(e=>o`${e}`),o`, `)})`)}async getTranslationStatus(e){let{getContentConfig:t}=await import(`./plugin.mjs`),n=t(),r=Object.entries(this.entity.allFields).filter(([e,t])=>t.translatable).map(([e])=>e);if(r.length===0)return{};let{schemaRegistry:i}=await import(`@murumets-ee/db`),{eq:a}=await import(`drizzle-orm`),o=i.get(`${this.entity.name}_translations`);if(!o)return{};let s=await this.db.select().from(o).where(a(o.entityId,e)),c=new Map;for(let e of s){let t=e,n={};for(let e of r)n[e]=t[e];c.set(t.locale,n)}let l={};for(let e of n.locales){if(e.code===n.defaultLocale)continue;let t=c.get(e.code)??{},i=[];for(let e of r)(t[e]===void 0||t[e]===null)&&i.push(e);let a=r.length-i.length;l[e.code]={complete:i.length===0,total:r.length,translated:a,missing:i}}return l}async getTranslationStatusBatch(e){let t=new Map;if(e.length===0)return t;let{getContentConfig:n}=await import(`./plugin.mjs`),r=n(),i=Object.entries(this.entity.allFields).filter(([e,t])=>t.translatable).map(([e])=>e);if(i.length===0)return t;let{schemaRegistry:a}=await import(`@murumets-ee/db`),{inArray:o}=await import(`drizzle-orm`),s=a.get(`${this.entity.name}_translations`);if(!s)return t;let c=await this.db.select().from(s).where(o(s.entityId,e)),l=new Map;for(let e of c){let t=e,n=t.entityId,r=t.locale,a={};for(let e of i)a[e]=t[e];l.has(n)||l.set(n,new Map),l.get(n).set(r,a)}for(let n of e){let e=l.get(n),a={};for(let t of r.locales){if(t.code===r.defaultLocale)continue;let n=e?.get(t.code)??{},o=[];for(let e of i)(n[e]===void 0||n[e]===null)&&o.push(e);let s=i.length-o.length;a[t.code]={complete:o.length===0,total:i.length,translated:s,missing:o}}t.set(n,a)}return t}async getTranslationReport(e){let{getContentConfig:t}=await import(`./plugin.mjs`),n=t(),r=e?.locale??n.locales.find(e=>e.code!==n.defaultLocale)?.code;if(!r)return{total:0,complete:0,partial:0,missing:0};let i=await(await this.getAdmin()).findMany(),a=0,o=0,s=0;for(let e of i){let t=(await this.getTranslationStatus(e.id))[r];!t||t.translated===0?s++:t.complete?a++:o++}return{total:i.length,complete:a,partial:o,missing:s}}async getLocaleStatus(e){let{schemaRegistry:t}=await import(`@murumets-ee/db`),{eq:n}=await import(`drizzle-orm`),r=t.get(`${this.entity.name}_locale_status`);return r?(await this.db.select().from(r).where(n(r.entityId,e))).map(e=>({locale:e.locale,status:e.status,publishedAt:e.publishedAt??null})):[]}async setLocaleStatus(e,t,n){let{getContentConfig:r}=await import(`./plugin.mjs`);if(t===r().defaultLocale){let t=await this.getAdmin(),r={status:n};n===`published`&&(r.publishedAt=new Date),await t.update(e,r);return}let{schemaRegistry:i}=await import(`@murumets-ee/db`),{eq:a,and:o}=await import(`drizzle-orm`),s=i.get(`${this.entity.name}_locale_status`);if(!s)return;let c=n===`published`?new Date:null,[l]=await this.db.select({id:s.id}).from(s).where(o(a(s.entityId,e),a(s.locale,t))).limit(1);l?await this.db.update(s).set({status:n,publishedAt:c}).where(a(s.id,l.id)):await this.db.insert(s).values({entityId:e,locale:t,status:n,publishedAt:c})}async getLocaleStatusBatch(e){let t=new Map;if(e.length===0)return t;let{schemaRegistry:n}=await import(`@murumets-ee/db`),{inArray:r}=await import(`drizzle-orm`),i=n.get(`${this.entity.name}_locale_status`);if(!i)return t;let a=await this.db.select().from(i).where(r(i.entityId,e));for(let e of a){let n=e.entityId,r=e.locale;t.has(n)||t.set(n,{}),t.get(n)[r]={locale:r,status:e.status,publishedAt:e.publishedAt??null}}return t}async saveDraft(e,t,n=`_`,r){let{schemaRegistry:i}=await import(`@murumets-ee/db`),{eq:a,and:o}=await import(`drizzle-orm`),s=i.get(`${this.entity.name}_drafts`);if(!s)throw Error(`Drafts table not found for entity "${this.entity.name}". Is the content plugin initialized?`);let c=new Date,l=r?.id??``,u=r?.name??null,[d]=await this.db.select().from(s).where(o(a(s.entityId,e),a(s.locale,n))).limit(1);if(d){let[e]=await this.db.update(s).set({data:t,updatedAt:c}).where(a(s.id,d.id)).returning();return this.toDraftEntry(e)}let[f]=await this.db.insert(s).values({entityId:e,locale:n,data:t,createdBy:l,createdByName:u,createdAt:c,updatedAt:c}).returning();return this.toDraftEntry(f)}async getDraft(e,t=`_`){let{schemaRegistry:n}=await import(`@murumets-ee/db`),{eq:r,and:i}=await import(`drizzle-orm`),a=n.get(`${this.entity.name}_drafts`);if(!a)return null;let[o]=await this.db.select().from(a).where(i(r(a.entityId,e),r(a.locale,t))).limit(1);return o?this.toDraftEntry(o):null}async deleteDraft(e,t=`_`){let{schemaRegistry:n}=await import(`@murumets-ee/db`),{eq:r,and:i}=await import(`drizzle-orm`),a=n.get(`${this.entity.name}_drafts`);return a?(await this.db.delete(a).where(i(r(a.entityId,e),r(a.locale,t))).returning({id:a.id})).length>0:!1}async publishDraft(e,t=`_`,n){let r=await this.getDraft(e,t);if(!r)throw Error(`No draft found for entity ${e} locale ${t}`);let i=await this.getAdmin(),a=null;this.versionableOptions&&(a=await i.findById(e));let{id:o,createdAt:s,createdBy:c,_version:l,_versionedAt:u,...d}=r.data,f=await i.update(e,d);return await this.deleteDraft(e,t),this.versionableOptions&&await this.createVersionSnapshot(e,f,a,t,n),f}async hasDraft(e,t=`_`){let{schemaRegistry:n}=await import(`@murumets-ee/db`),{eq:r,and:i}=await import(`drizzle-orm`),a=n.get(`${this.entity.name}_drafts`);if(!a)return!1;let[o]=await this.db.select({id:a.id}).from(a).where(i(r(a.entityId,e),r(a.locale,t))).limit(1);return!!o}async countDrafts(e=`_`){let{schemaRegistry:t}=await import(`@murumets-ee/db`),{eq:n,sql:r}=await import(`drizzle-orm`),i=t.get(`${this.entity.name}_drafts`);if(!i)return 0;let[a]=await this.db.select({count:r`count(*)::int`}).from(i).where(n(i.locale,e));return a?.count??0}async hasDraftBatch(e,t=`_`){let n=new Set;if(e.length===0)return n;let{schemaRegistry:r}=await import(`@murumets-ee/db`),{inArray:i,eq:a,and:o}=await import(`drizzle-orm`),s=r.get(`${this.entity.name}_drafts`);if(!s)return n;let c=await this.db.select({entityId:s.entityId}).from(s).where(o(i(s.entityId,e),a(s.locale,t)));for(let e of c)n.add(e.entityId);return n}async createVersionSnapshot(e,t,n,r,i){if(!this.versionableOptions)return;let a=r??`_`,o=n?this.calculateDelta(n,t):null,s=await this.saveVersionSnapshot(e,t,o,!1,a,i);if(s!==void 0&&a===`_`){let{schemaRegistry:t}=await import(`@murumets-ee/db`),{eq:n}=await import(`drizzle-orm`),r=t.get(this.entity.name);r&&await this.db.update(r).set({_version:s}).where(n(r.id,e))}await this.pruneVersions(e,a)}async saveVersionSnapshot(e,t,n,r,i=`_`,a){let{schemaRegistry:o}=await import(`@murumets-ee/db`),{eq:s,and:c,sql:l}=await import(`drizzle-orm`),u=o.get(`${this.entity.name}_versions`);if(!u)return;let[d]=await this.db.select({maxVersion:l`coalesce(max(${u.version}), 0)`}).from(u).where(c(s(u.entityId,e),s(u.locale,i))),f=(d?.maxVersion??0)+1,p=t.status??null;if(r){let[r]=await this.db.select().from(u).where(c(s(u.entityId,e),s(u.isAutosave,!0),s(u.version,f),s(u.locale,i))).limit(1);if(r)return await this.db.update(u).set({data:t,delta:n,status:p,createdAt:new Date}).where(s(u.id,r.id)),f}return await this.db.insert(u).values({entityId:e,version:f,locale:i,data:t,delta:n,status:p,createdBy:a?.id??t.updatedBy??t.createdBy??null,createdByName:a?.name??null,isAutosave:r}),f}toDraftEntry(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}}calculateDelta(e,t){let n={};for(let r of Object.keys(t))r===`id`||r.startsWith(`_`)||JSON.stringify(e[r])!==JSON.stringify(t[r])&&(n[r]=t[r]);return n}};async function i(e){let{getApp:t}=await import(`@murumets-ee/core`),n=t();return new r({entity:e,db:n.db.readWrite,logger:n.logger.child({content:e.name})})}export{r as ContentClient,i as createContentClient};
1
+ import{o as e,r as t,t as n}from"./block-diff-BBH6FoFT.mjs";import{t as r}from"./registry-BJSOGFEN.mjs";import"server-only";var i=class{entity;admin;logger;versionableOptions;constructor(t){this.entity=t.entity,this.admin=t.admin,this.logger=t.logger,this.versionableOptions=e(t.entity.behaviors)}get db(){return this.admin.getDb()}getDraftsClient(){let{drafts:e}=r(this.entity.name);return e?e.makeClient(this.db):null}getVersionsClient(){let{versions:e}=r(this.entity.name);return e?e.makeClient(this.db):null}getLocaleStatusClient(){let{localeStatus:e}=r(this.entity.name);return e?e.makeClient(this.db):null}async create(e){let t=await this.admin.create(e);return this.versionableOptions&&await this.saveVersionSnapshot(t.id,t,null,!1),t}async findById(e,t){return this.admin.findById(e,t)}async findMany(e){return this.admin.findMany(e)}async update(e,t){let n=this.admin,r=null;this.versionableOptions&&(r=await n.findById(e));let i=await n.update(e,t);if(this.versionableOptions&&r){let t=this.calculateDelta(r,i),n=await this.saveVersionSnapshot(e,i,t,!1);n!==void 0&&(await this.writeVersionColumn(e,n),i._version=n),await this.pruneVersions(e)}return i}async delete(e){return this.admin.delete(e)}async saveTranslation(e,t,n){return this.admin.saveTranslation(e,t,n)}async deleteTranslation(e,t){return this.admin.deleteTranslation(e,t)}async copyLayout(e,t){let{schemaRegistry:n}=await import(`@murumets-ee/db`),{eq:r,and:i}=await import(`drizzle-orm`),a=n.get(`${this.entity.name}_layout`);if(!a)return;let o=Array.isArray(t.to)?t.to:[t.to],s=await this.db.select().from(a).where(i(r(a.entityId,e),r(a.locale,t.from))).orderBy(a.sortOrder);if(s.length!==0){for(let t of o){await this.db.delete(a).where(i(r(a.entityId,e),r(a.locale,t)));for(let e of s)await this.db.insert(a).values({entityId:e.entityId,fieldName:e.fieldName,blockType:e.blockType,sortOrder:e.sortOrder,data:e.data,locale:t})}this.logger?.debug({entityId:e,from:t.from,to:o},`Layout copied between locales`)}}async getVersions(e,t){let n=this.getVersionsClient();return n?await n.findMany({where:{entityId:e,locale:t?.locale??`_`},orderBy:[{column:`version`,dir:`desc`}],...t?.limit===void 0?{}:{limit:t.limit},...t?.offset===void 0?{}:{offset:t.offset}}):[]}async getVersion(e,t,n=`_`){let r=this.getVersionsClient();return r?await r.findOne({entityId:e,version:t,locale:n})??null:null}async compareVersions(e,r,i,a=`_`){let[o,s]=await Promise.all([this.getVersion(e,r,a),this.getVersion(e,i,a)]);if(!o||!s)return null;let c=o.data,l=s.data,u=this.entity.allFields,d=t(c,l,u);for(let e of d)e.type===`blocks`&&Array.isArray(e.from)&&Array.isArray(e.to)&&(e.blockDiffs=n(e.from,e.to));return{diffs:d,fromVersion:o,toVersion:s}}async compareDraftWithCurrent(e,r=`_`){let i=await this.getDraft(e,r);if(!i)return null;let a=this.admin,{getContentConfig:o}=await import(`./plugin.mjs`),s=o().defaultLocale,c=r===`_`?{defaultLocale:s}:{locale:r,defaultLocale:s},l=await a.findById(e,c);if(!l)return null;let u=this.entity.allFields,d={};for(let e of Object.keys(i.data))d[e]=l[e];let f=t(d,i.data,u);for(let e of f)e.type===`blocks`&&Array.isArray(e.from)&&Array.isArray(e.to)&&(e.blockDiffs=n(e.from,e.to));return{diffs:f,current:l,draft:i}}async restoreVersion(e,t){let n=await this.getVersion(e,t);if(!n)throw Error(`Version ${t} not found for entity ${e}`);let{id:r,createdAt:i,createdBy:a,_version:o,_versionedAt:s,...c}=n.data;return this.admin.update(e,c)}async pruneVersions(e,t=`_`){if(!this.versionableOptions)return;let n=this.getVersionsClient();if(!n)return;let r=this.versionableOptions.maxPerDoc,i=await n.findMany({where:{entityId:e,locale:t},orderBy:[{column:`version`,dir:`desc`}],limit:r});if(i.length<r)return;let a=i.map(e=>e.id);await n.deleteMany({entityId:e,locale:t,id:{notIn:a}})}async getTranslationStatus(e){let{getContentConfig:t}=await import(`./plugin.mjs`),n=t(),r=Object.entries(this.entity.allFields).filter(([e,t])=>t.translatable).map(([e])=>e);if(r.length===0)return{};let{schemaRegistry:i}=await import(`@murumets-ee/db`),{eq:a}=await import(`drizzle-orm`),o=i.get(`${this.entity.name}_translations`);if(!o)return{};let s=await this.db.select().from(o).where(a(o.entityId,e)),c=new Map;for(let e of s){let t=e,n={};for(let e of r)n[e]=t[e];c.set(t.locale,n)}let l={};for(let e of n.locales){if(e.code===n.defaultLocale)continue;let t=c.get(e.code)??{},i=[];for(let e of r)(t[e]===void 0||t[e]===null)&&i.push(e);let a=r.length-i.length;l[e.code]={complete:i.length===0,total:r.length,translated:a,missing:i}}return l}async getTranslationStatusBatch(e){let t=new Map;if(e.length===0)return t;let{getContentConfig:n}=await import(`./plugin.mjs`),r=n(),i=Object.entries(this.entity.allFields).filter(([e,t])=>t.translatable).map(([e])=>e);if(i.length===0)return t;let{schemaRegistry:a}=await import(`@murumets-ee/db`),{inArray:o}=await import(`drizzle-orm`),s=a.get(`${this.entity.name}_translations`);if(!s)return t;let c=await this.db.select().from(s).where(o(s.entityId,e)),l=new Map;for(let e of c){let t=e,n=t.entityId,r=t.locale,a={};for(let e of i)a[e]=t[e];l.has(n)||l.set(n,new Map),l.get(n).set(r,a)}for(let n of e){let e=l.get(n),a={};for(let t of r.locales){if(t.code===r.defaultLocale)continue;let n=e?.get(t.code)??{},o=[];for(let e of i)(n[e]===void 0||n[e]===null)&&o.push(e);let s=i.length-o.length;a[t.code]={complete:o.length===0,total:i.length,translated:s,missing:o}}t.set(n,a)}return t}async getTranslationReport(e){let{getContentConfig:t}=await import(`./plugin.mjs`),n=t(),r=e?.locale??n.locales.find(e=>e.code!==n.defaultLocale)?.code;if(!r)return{total:0,complete:0,partial:0,missing:0};let i=await this.admin.findMany(),a=0,o=0,s=0;for(let e of i){let t=(await this.getTranslationStatus(e.id))[r];!t||t.translated===0?s++:t.complete?a++:o++}return{total:i.length,complete:a,partial:o,missing:s}}async getLocaleStatus(e){let t=this.getLocaleStatusClient();return t?(await t.findMany({where:{entityId:e}})).map(e=>({locale:e.locale,status:e.status,publishedAt:e.publishedAt??null})):[]}async setLocaleStatus(e,t,n){let{getContentConfig:r}=await import(`./plugin.mjs`);if(t===r().defaultLocale){let t=this.admin,r={status:n};n===`published`&&(r.publishedAt=new Date),await t.update(e,r);return}let i=this.getLocaleStatusClient();if(!i)return;let a=n===`published`?new Date:null;await i.upsert({entityId:e,locale:t,status:n,publishedAt:a},{target:[`entityId`,`locale`],set:{status:n,publishedAt:a}})}async getLocaleStatusBatch(e){let t=new Map;if(e.length===0)return t;let n=this.getLocaleStatusClient();if(!n)return t;let r=await n.findMany({where:{entityId:{in:e}}});for(let e of r){let n=e.entityId,r=e.locale;t.has(n)||t.set(n,{}),t.get(n)[r]={locale:r,status:e.status,publishedAt:e.publishedAt??null}}return t}async saveDraft(e,t,n=`_`,r){let i=this.getDraftsClient();if(!i)throw Error(`Drafts table not found for entity "${this.entity.name}". Is the content plugin initialized?`);let a=new Date,o=r?.id??``,s=r?.name??null,c=await i.upsert({entityId:e,locale:n,data:t,createdBy:o,createdByName:s,createdAt:a,updatedAt:a},{target:[`entityId`,`locale`],set:{data:t,updatedAt:a}});return this.toDraftEntry(c)}async getDraft(e,t=`_`){let n=this.getDraftsClient();if(!n)return null;let r=await n.findOne({entityId:e,locale:t});return r?this.toDraftEntry(r):null}async deleteDraft(e,t=`_`){let n=this.getDraftsClient();return n?(await n.deleteMany({entityId:e,locale:t})).length>0:!1}async publishDraft(e,t=`_`,n){let r=await this.getDraft(e,t);if(!r)throw Error(`No draft found for entity ${e} locale ${t}`);let i=this.admin,a=null;this.versionableOptions&&(a=await i.findById(e));let{id:o,createdAt:s,createdBy:c,_version:l,_versionedAt:u,...d}=r.data,f=await i.update(e,d);return await this.deleteDraft(e,t),this.versionableOptions&&await this.createVersionSnapshot(e,f,a,t,n),f}async hasDraft(e,t=`_`){let n=this.getDraftsClient();return n?n.exists({entityId:e,locale:t}):!1}async countDrafts(e=`_`){let t=this.getDraftsClient();return t?t.count({locale:e}):0}async hasDraftBatch(e,t=`_`){let n=new Set;if(e.length===0)return n;let r=this.getDraftsClient();if(!r)return n;let i=await r.findMany({where:{entityId:{in:e},locale:t}});for(let e of i)n.add(e.entityId);return n}async createVersionSnapshot(e,t,n,r,i){if(!this.versionableOptions)return;let a=r??`_`,o=n?this.calculateDelta(n,t):null,s=await this.saveVersionSnapshot(e,t,o,!1,a,i);s!==void 0&&a===`_`&&await this.writeVersionColumn(e,s),await this.pruneVersions(e,a)}async writeVersionColumn(e,t){let{schemaRegistry:n}=await import(`@murumets-ee/db`),{eq:r}=await import(`drizzle-orm`),i=n.get(this.entity.name);i&&await this.db.update(i).set({_version:t}).where(r(i.id,e))}async saveVersionSnapshot(e,t,n,r,i=`_`,a){let o=this.getVersionsClient();if(!o)return;let[s]=await o.aggregate({select:{maxVersion:{fn:`max`,column:`version`}},where:{entityId:e,locale:i}}),c=Number(s?.maxVersion??0)+1,l=t.status??null;if(r){let r=await o.findOne({entityId:e,isAutosave:!0,version:c,locale:i});if(r)return await o.update({id:r.id},{data:t,delta:n,status:l,createdAt:new Date}),c}return await o.insert({entityId:e,version:c,locale:i,data:t,delta:n,status:l,createdBy:a?.id??t.updatedBy??t.createdBy??null,createdByName:a?.name??null,isAutosave:r}),c}toDraftEntry(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}}calculateDelta(e,t){let n={};for(let r of Object.keys(t))r===`id`||r.startsWith(`_`)||JSON.stringify(e[r])!==JSON.stringify(t[r])&&(n[r]=t[r]);return n}};async function a(e){let{createAdminClient:t}=await import(`@murumets-ee/core/clients`),{getApp:n}=await import(`@murumets-ee/core`);return new i({admin:t(e),entity:e,logger:n().logger.child({content:e.name})})}export{i as ContentClient,a as createContentClient};
2
2
  //# sourceMappingURL=client.mjs.map