@murumets-ee/content 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/block-diff-H1AttKiz.mjs +2 -0
- package/dist/block-diff-H1AttKiz.mjs.map +1 -0
- package/dist/blocks/index.d.mts +197 -0
- package/dist/blocks/index.d.mts.map +1 -0
- package/dist/blocks/index.mjs +2 -0
- package/dist/blocks/index.mjs.map +1 -0
- package/dist/client.d.mts +213 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +2 -0
- package/dist/client.mjs.map +1 -0
- package/dist/define-block-D-7OpIn5.mjs +2 -0
- package/dist/define-block-D-7OpIn5.mjs.map +1 -0
- package/dist/drafts-BYyRdmiT.mjs +2 -0
- package/dist/drafts-BYyRdmiT.mjs.map +1 -0
- package/dist/index.d.mts +71 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/locale-status-CGttT38v.mjs +2 -0
- package/dist/locale-status-CGttT38v.mjs.map +1 -0
- package/dist/lock-service.d.mts +54 -0
- package/dist/lock-service.d.mts.map +1 -0
- package/dist/lock-service.mjs +2 -0
- package/dist/lock-service.mjs.map +1 -0
- package/dist/locks-CNxQJieo.mjs +2 -0
- package/dist/locks-CNxQJieo.mjs.map +1 -0
- package/dist/plugin.d.mts +15 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +2 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/query-client.d.mts +60 -0
- package/dist/query-client.d.mts.map +1 -0
- package/dist/query-client.mjs +2 -0
- package/dist/query-client.mjs.map +1 -0
- package/dist/types-nXbE5Ufa.d.mts +43 -0
- package/dist/types-nXbE5Ufa.d.mts.map +1 -0
- package/dist/types-wLHyjcWf.d.mts +95 -0
- package/dist/types-wLHyjcWf.d.mts.map +1 -0
- package/dist/versions-cotph2VG.mjs +2 -0
- package/dist/versions-cotph2VG.mjs.map +1 -0
- package/package.json +20 -20
- package/dist/blocks/index.d.ts +0 -187
- package/dist/blocks/index.js +0 -1
- package/dist/chunk-BVMZMEPV.js +0 -1
- package/dist/chunk-CULYIGZI.js +0 -1
- package/dist/client.d.ts +0 -215
- package/dist/client.js +0 -1
- package/dist/drafts-2ZRAHAUK.js +0 -1
- package/dist/index.d.ts +0 -142
- package/dist/index.js +0 -1
- package/dist/locale-status-B7B3WFXF.js +0 -1
- package/dist/lock-service.d.ts +0 -61
- package/dist/lock-service.js +0 -1
- package/dist/locks-AXFCTV7F.js +0 -1
- package/dist/plugin.d.ts +0 -33
- package/dist/plugin.js +0 -1
- package/dist/query-client.d.ts +0 -67
- package/dist/query-client.js +0 -1
- package/dist/types-BYeiE1ie.d.ts +0 -99
- package/dist/types-Cr0ifLn_.d.ts +0 -41
- package/dist/versions-4ICOJIK2.js +0 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { FieldConfig, InferEntityDTO } from "@murumets-ee/entity";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A block definition — describes a reusable content block's data shape.
|
|
6
|
+
*
|
|
7
|
+
* @typeParam F - The literal field map, inferred from the call site.
|
|
8
|
+
*/
|
|
9
|
+
interface BlockDefinition<F extends Record<string, FieldConfig> = Record<string, FieldConfig>> {
|
|
10
|
+
slug: string;
|
|
11
|
+
label: string;
|
|
12
|
+
fields: F;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Infer the data shape of a single block definition.
|
|
16
|
+
* Produces `{ _block: 'hero'; _id: string; heading: string; ... }`
|
|
17
|
+
*/
|
|
18
|
+
type InferBlockData<B extends BlockDefinition> = B extends BlockDefinition<infer F> ? {
|
|
19
|
+
_block: B['slug'];
|
|
20
|
+
_id: string;
|
|
21
|
+
} & Omit<InferEntityDTO<F>, 'id'> : never;
|
|
22
|
+
/**
|
|
23
|
+
* Infer a discriminated union from a tuple of block definitions.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* type Layout = InferBlocksUnion<typeof [HeroBlock, RichTextBlock]>
|
|
27
|
+
* // = { _block: 'hero'; ... } | { _block: 'richtext'; ... }
|
|
28
|
+
*/
|
|
29
|
+
type InferBlocksUnion<T extends readonly BlockDefinition[]> = { [K in keyof T]: T[K] extends BlockDefinition ? InferBlockData<T[K]> : never }[number];
|
|
30
|
+
interface LocaleConfig {
|
|
31
|
+
code: string;
|
|
32
|
+
label: string;
|
|
33
|
+
}
|
|
34
|
+
interface ContentConfig {
|
|
35
|
+
locales: LocaleConfig[];
|
|
36
|
+
defaultLocale: string;
|
|
37
|
+
}
|
|
38
|
+
interface VersionableOptions {
|
|
39
|
+
/** Maximum versions kept per document. Default: 50 */
|
|
40
|
+
maxPerDoc?: number;
|
|
41
|
+
/** Enable autosave (single mutable autosave version). Default: false */
|
|
42
|
+
autosave?: boolean;
|
|
43
|
+
}
|
|
44
|
+
interface VersionEntry {
|
|
45
|
+
id: string;
|
|
46
|
+
entityId: string;
|
|
47
|
+
version: number;
|
|
48
|
+
locale: string;
|
|
49
|
+
data: Record<string, unknown>;
|
|
50
|
+
delta: Record<string, unknown> | null;
|
|
51
|
+
status: string | null;
|
|
52
|
+
createdBy: string | null;
|
|
53
|
+
createdByName: string | null;
|
|
54
|
+
createdAt: Date | string;
|
|
55
|
+
isAutosave: boolean;
|
|
56
|
+
}
|
|
57
|
+
interface TranslationFieldStatus {
|
|
58
|
+
complete: boolean;
|
|
59
|
+
total: number;
|
|
60
|
+
translated: number;
|
|
61
|
+
missing: string[];
|
|
62
|
+
}
|
|
63
|
+
interface TranslationStatus {
|
|
64
|
+
[locale: string]: TranslationFieldStatus;
|
|
65
|
+
}
|
|
66
|
+
interface TranslationReport {
|
|
67
|
+
total: number;
|
|
68
|
+
complete: number;
|
|
69
|
+
partial: number;
|
|
70
|
+
missing: number;
|
|
71
|
+
}
|
|
72
|
+
interface LocalePublishStatus {
|
|
73
|
+
locale: string;
|
|
74
|
+
status: 'draft' | 'published';
|
|
75
|
+
publishedAt: Date | string | null;
|
|
76
|
+
}
|
|
77
|
+
interface DraftEntry {
|
|
78
|
+
id: string;
|
|
79
|
+
entityId: string;
|
|
80
|
+
locale: string;
|
|
81
|
+
data: Record<string, unknown>;
|
|
82
|
+
createdBy: string;
|
|
83
|
+
createdByName: string | null;
|
|
84
|
+
createdAt: Date | string;
|
|
85
|
+
updatedAt: Date | string;
|
|
86
|
+
}
|
|
87
|
+
interface LockInfo {
|
|
88
|
+
lockedBy: string;
|
|
89
|
+
lockedByName: string | null;
|
|
90
|
+
lockedAt: Date | string;
|
|
91
|
+
expiresAt: Date | string;
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { InferBlocksUnion as a, LockInfo as c, TranslationStatus as d, VersionEntry as f, InferBlockData as i, TranslationFieldStatus as l, ContentConfig as n, LocaleConfig as o, VersionableOptions as p, DraftEntry as r, LocalePublishStatus as s, BlockDefinition as t, TranslationReport as u };
|
|
95
|
+
//# sourceMappingURL=types-wLHyjcWf.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-wLHyjcWf.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;UAeiB,eAAA,WACL,MAAA,SAAe,WAAA,IAAe,MAAA,SAAe,WAAA;EAEvD,IAAA;EACA,KAAA;EACA,MAAA,EAAQ,CAAA;AAAA;;;;;KAWE,cAAA,WAAyB,eAAA,IACnC,CAAA,SAAU,eAAA;EACJ,MAAA,EAAQ,CAAA;EAAW,GAAA;AAAA,IAAgB,IAAA,CAAK,cAAA,CAAe,CAAA;;;AAF/D;;;;;KAYY,gBAAA,oBAAoC,eAAA,oBAClC,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,eAAA,GAAkB,cAAA,CAAe,CAAA,CAAE,CAAA;AAAA,UAOjD,YAAA;EACf,IAAA;EACA,KAAA;AAAA;AAAA,UAGe,aAAA;EACf,OAAA,EAAS,YAAA;EACT,aAAA;AAAA;AAAA,UAOe,kBAAA;EAhCT;EAkCN,SAAA;EAlCyB;EAoCzB,QAAA;AAAA;AAAA,UAOe,YAAA;EACf,EAAA;EACA,QAAA;EACA,OAAA;EACA,MAAA;EACA,IAAA,EAAM,MAAA;EACN,KAAA,EAAO,MAAA;EACP,MAAA;EACA,SAAA;EACA,aAAA;EACA,SAAA,EAAW,IAAA;EACX,UAAA;AAAA;AAAA,UAae,sBAAA;EACf,QAAA;EACA,KAAA;EACA,UAAA;EACA,OAAA;AAAA;AAAA,UAGe,iBAAA;EAAA,CACd,MAAA,WAAiB,sBAAA;AAAA;AAAA,UAGH,iBAAA;EACf,KAAA;EACA,QAAA;EACA,OAAA;EACA,OAAA;AAAA;AAAA,UAOe,mBAAA;EACf,MAAA;EACA,MAAA;EACA,WAAA,EAAa,IAAA;AAAA;AAAA,UAOE,UAAA;EACf,EAAA;EACA,QAAA;EACA,MAAA;EACA,IAAA,EAAM,MAAA;EACN,SAAA;EACA,aAAA;EACA,SAAA,EAAW,IAAA;EACX,SAAA,EAAW,IAAA;AAAA;AAAA,UAOI,QAAA;EACf,QAAA;EACA,YAAA;EACA,QAAA,EAAU,IAAA;EACV,SAAA,EAAW,IAAA;AAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{boolean as e,integer as t,jsonb as n,pgTable as r,timestamp as i,unique as a,uuid as o,varchar as s}from"drizzle-orm/pg-core";function c(c){return r(`${c.name}_versions`,{id:o(`id`).primaryKey().defaultRandom(),entityId:o(`entity_id`).notNull(),version:t(`version`).notNull(),locale:s(`locale`,{length:10}).notNull().default(`_`),data:n(`data`).notNull(),delta:n(`delta`),status:s(`status`,{length:20}),createdBy:s(`created_by`,{length:255}),createdByName:s(`created_by_name`,{length:255}),createdAt:i(`created_at`,{withTimezone:!0}).notNull().defaultNow(),isAutosave:e(`is_autosave`).notNull().default(!1)},e=>({uniqueEntityVersionLocale:a().on(e.entityId,e.version,e.locale)}))}export{c as generateVersionsSchema};
|
|
2
|
+
//# sourceMappingURL=versions-cotph2VG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versions-cotph2VG.mjs","names":[],"sources":["../src/schema/versions.ts"],"sourcesContent":["/**\n * Version history table schema generator\n *\n * Generates a {entity}_versions table for entities with the versionable() behavior.\n * Each version stores a full snapshot + delta (changed fields only).\n */\n\nimport type { Entity } from '@murumets-ee/entity'\nimport {\n boolean,\n integer,\n jsonb,\n pgTable,\n timestamp,\n unique,\n uuid,\n varchar,\n} from 'drizzle-orm/pg-core'\n\n/**\n * Generate versions table schema for a versionable entity.\n *\n * Schema:\n * {entity}_versions (\n * id uuid PK,\n * entity_id uuid NOT NULL,\n * version integer NOT NULL,\n * locale varchar(10) NOT NULL DEFAULT '_', -- locale this snapshot belongs to\n * data jsonb NOT NULL, -- full snapshot (locale-merged view)\n * delta jsonb, -- only changed fields\n * status varchar(20), -- 'draft' | 'published' at time of save\n * created_by uuid,\n * created_at timestamp NOT NULL DEFAULT now(),\n * is_autosave boolean NOT NULL DEFAULT false,\n * UNIQUE(entity_id, version, locale)\n * )\n *\n * Each locale has its own version sequence. The default locale uses '_'\n * as the locale value (distinguishable from actual locale codes).\n */\nexport function generateVersionsSchema(entity: Entity) {\n const tableName = `${entity.name}_versions`\n\n return pgTable(\n tableName,\n {\n id: uuid('id').primaryKey().defaultRandom(),\n entityId: uuid('entity_id').notNull(),\n version: integer('version').notNull(),\n locale: varchar('locale', { length: 10 }).notNull().default('_'),\n data: jsonb('data').notNull(),\n delta: jsonb('delta'),\n status: varchar('status', { length: 20 }),\n createdBy: varchar('created_by', { length: 255 }),\n createdByName: varchar('created_by_name', { length: 255 }),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n isAutosave: boolean('is_autosave').notNull().default(false),\n },\n (table) => ({\n uniqueEntityVersionLocale: unique().on(table.entityId, table.version, table.locale),\n }),\n )\n}\n"],"mappings":"qIAwCA,SAAgB,EAAuB,EAAgB,CAGrD,OAAO,EAFW,GAAG,EAAO,KAAK,WAI/B,CACE,GAAI,EAAK,KAAK,CAAC,YAAY,CAAC,eAAe,CAC3C,SAAU,EAAK,YAAY,CAAC,SAAS,CACrC,QAAS,EAAQ,UAAU,CAAC,SAAS,CACrC,OAAQ,EAAQ,SAAU,CAAE,OAAQ,GAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,IAAI,CAChE,KAAM,EAAM,OAAO,CAAC,SAAS,CAC7B,MAAO,EAAM,QAAQ,CACrB,OAAQ,EAAQ,SAAU,CAAE,OAAQ,GAAI,CAAC,CACzC,UAAW,EAAQ,aAAc,CAAE,OAAQ,IAAK,CAAC,CACjD,cAAe,EAAQ,kBAAmB,CAAE,OAAQ,IAAK,CAAC,CAC1D,UAAW,EAAU,aAAc,CAAE,aAAc,GAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CACjF,WAAY,EAAQ,cAAc,CAAC,SAAS,CAAC,QAAQ,GAAM,CAC5D,CACA,IAAW,CACV,0BAA2B,GAAQ,CAAC,GAAG,EAAM,SAAU,EAAM,QAAS,EAAM,OAAO,CACpF,EACF"}
|
package/package.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@murumets-ee/content",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
8
|
-
"types": "./dist/index.d.
|
|
9
|
-
"import": "./dist/index.
|
|
8
|
+
"types": "./dist/index.d.mts",
|
|
9
|
+
"import": "./dist/index.mjs"
|
|
10
10
|
},
|
|
11
11
|
"./client": {
|
|
12
|
-
"types": "./dist/client.d.
|
|
13
|
-
"import": "./dist/client.
|
|
12
|
+
"types": "./dist/client.d.mts",
|
|
13
|
+
"import": "./dist/client.mjs"
|
|
14
14
|
},
|
|
15
15
|
"./query": {
|
|
16
|
-
"types": "./dist/query-client.d.
|
|
17
|
-
"import": "./dist/query-client.
|
|
16
|
+
"types": "./dist/query-client.d.mts",
|
|
17
|
+
"import": "./dist/query-client.mjs"
|
|
18
18
|
},
|
|
19
19
|
"./plugin": {
|
|
20
|
-
"types": "./dist/plugin.d.
|
|
21
|
-
"import": "./dist/plugin.
|
|
20
|
+
"types": "./dist/plugin.d.mts",
|
|
21
|
+
"import": "./dist/plugin.mjs"
|
|
22
22
|
},
|
|
23
23
|
"./blocks": {
|
|
24
|
-
"types": "./dist/blocks/index.d.
|
|
25
|
-
"import": "./dist/blocks/index.
|
|
24
|
+
"types": "./dist/blocks/index.d.mts",
|
|
25
|
+
"import": "./dist/blocks/index.mjs"
|
|
26
26
|
},
|
|
27
27
|
"./lock": {
|
|
28
|
-
"types": "./dist/lock-service.d.
|
|
29
|
-
"import": "./dist/lock-service.
|
|
28
|
+
"types": "./dist/lock-service.d.mts",
|
|
29
|
+
"import": "./dist/lock-service.mjs"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
@@ -36,20 +36,20 @@
|
|
|
36
36
|
"drizzle-orm": "^0.45.1",
|
|
37
37
|
"server-only": "^0.0.1",
|
|
38
38
|
"zod": "^3.24.1",
|
|
39
|
-
"@murumets-ee/
|
|
40
|
-
"@murumets-ee/
|
|
41
|
-
"@murumets-ee/
|
|
42
|
-
"@murumets-ee/
|
|
39
|
+
"@murumets-ee/core": "0.1.6",
|
|
40
|
+
"@murumets-ee/logging": "0.1.6",
|
|
41
|
+
"@murumets-ee/entity": "0.2.0",
|
|
42
|
+
"@murumets-ee/db": "0.1.5"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^22.10.5",
|
|
46
|
-
"
|
|
46
|
+
"tsdown": "^0.21.7",
|
|
47
47
|
"typescript": "^5.7.3",
|
|
48
48
|
"vitest": "^2.1.8"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
|
-
"build": "
|
|
52
|
-
"dev": "
|
|
51
|
+
"build": "tsdown",
|
|
52
|
+
"dev": "tsdown --watch",
|
|
53
53
|
"test": "vitest"
|
|
54
54
|
}
|
|
55
55
|
}
|
package/dist/blocks/index.d.ts
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import { B as BlockDefinition } from '../types-BYeiE1ie.js';
|
|
2
|
-
import * as _murumets_ee_entity from '@murumets-ee/entity';
|
|
3
|
-
|
|
4
|
-
declare const CodeBlock: BlockDefinition<{
|
|
5
|
-
readonly code: _murumets_ee_entity.TextField & {
|
|
6
|
-
readonly required: true;
|
|
7
|
-
};
|
|
8
|
-
readonly language: _murumets_ee_entity.SelectField & {
|
|
9
|
-
options: readonly ["javascript", "typescript", "python", "html", "css", "json", "bash", "sql", "other"];
|
|
10
|
-
} & Omit<Partial<_murumets_ee_entity.SelectField>, "options">;
|
|
11
|
-
}>;
|
|
12
|
-
|
|
13
|
-
declare const CTABlock: BlockDefinition<{
|
|
14
|
-
readonly heading: _murumets_ee_entity.TextField & {
|
|
15
|
-
readonly required: true;
|
|
16
|
-
readonly translatable: true;
|
|
17
|
-
};
|
|
18
|
-
readonly description: _murumets_ee_entity.TextField & {
|
|
19
|
-
readonly translatable: true;
|
|
20
|
-
};
|
|
21
|
-
readonly buttonText: _murumets_ee_entity.TextField & {
|
|
22
|
-
readonly required: true;
|
|
23
|
-
readonly translatable: true;
|
|
24
|
-
};
|
|
25
|
-
readonly buttonLink: _murumets_ee_entity.TextField & {
|
|
26
|
-
readonly required: true;
|
|
27
|
-
};
|
|
28
|
-
}>;
|
|
29
|
-
|
|
30
|
-
declare const GalleryBlock: BlockDefinition<{
|
|
31
|
-
readonly images: _murumets_ee_entity.ReferenceField & {
|
|
32
|
-
cardinality: "many";
|
|
33
|
-
} & Partial<Omit<_murumets_ee_entity.ReferenceField, "entity" | "cardinality">>;
|
|
34
|
-
readonly columns: _murumets_ee_entity.SelectField & {
|
|
35
|
-
options: readonly ["2", "3", "4"];
|
|
36
|
-
} & Omit<Partial<_murumets_ee_entity.SelectField>, "options">;
|
|
37
|
-
}>;
|
|
38
|
-
|
|
39
|
-
declare const HeroBlock: BlockDefinition<{
|
|
40
|
-
readonly heading: _murumets_ee_entity.TextField & {
|
|
41
|
-
readonly required: true;
|
|
42
|
-
readonly translatable: true;
|
|
43
|
-
};
|
|
44
|
-
readonly subheading: _murumets_ee_entity.TextField & {
|
|
45
|
-
readonly translatable: true;
|
|
46
|
-
};
|
|
47
|
-
readonly background: _murumets_ee_entity.MediaField & {
|
|
48
|
-
readonly accept: ["image/*"];
|
|
49
|
-
};
|
|
50
|
-
readonly alignment: _murumets_ee_entity.SelectField & {
|
|
51
|
-
options: readonly ["left", "center", "right"];
|
|
52
|
-
} & Omit<Partial<_murumets_ee_entity.SelectField>, "options">;
|
|
53
|
-
}>;
|
|
54
|
-
|
|
55
|
-
declare const ImageBlock: BlockDefinition<{
|
|
56
|
-
readonly image: _murumets_ee_entity.MediaField & {
|
|
57
|
-
readonly accept: ["image/*"];
|
|
58
|
-
readonly required: true;
|
|
59
|
-
};
|
|
60
|
-
readonly alt: _murumets_ee_entity.TextField & {
|
|
61
|
-
readonly translatable: true;
|
|
62
|
-
};
|
|
63
|
-
readonly caption: _murumets_ee_entity.TextField & {
|
|
64
|
-
readonly translatable: true;
|
|
65
|
-
};
|
|
66
|
-
}>;
|
|
67
|
-
|
|
68
|
-
declare const QuoteBlock: BlockDefinition<{
|
|
69
|
-
readonly quote: _murumets_ee_entity.TextField & {
|
|
70
|
-
readonly required: true;
|
|
71
|
-
readonly translatable: true;
|
|
72
|
-
};
|
|
73
|
-
readonly attribution: _murumets_ee_entity.TextField & {
|
|
74
|
-
readonly translatable: true;
|
|
75
|
-
};
|
|
76
|
-
}>;
|
|
77
|
-
|
|
78
|
-
declare const RichTextBlock: BlockDefinition<{
|
|
79
|
-
readonly content: _murumets_ee_entity.RichTextField & {
|
|
80
|
-
readonly translatable: true;
|
|
81
|
-
};
|
|
82
|
-
}>;
|
|
83
|
-
|
|
84
|
-
declare const VideoBlock: BlockDefinition<{
|
|
85
|
-
readonly url: _murumets_ee_entity.TextField & {
|
|
86
|
-
readonly required: true;
|
|
87
|
-
};
|
|
88
|
-
readonly poster: _murumets_ee_entity.MediaField & {
|
|
89
|
-
readonly accept: ["image/*"];
|
|
90
|
-
};
|
|
91
|
-
readonly caption: _murumets_ee_entity.TextField & {
|
|
92
|
-
readonly translatable: true;
|
|
93
|
-
};
|
|
94
|
-
}>;
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* All common blocks shipped with the toolkit.
|
|
98
|
-
* Use as-is or pick individual blocks from the named exports.
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* import { commonBlocks } from '@murumets-ee/content/blocks'
|
|
102
|
-
* const Page = defineEntity({
|
|
103
|
-
* name: 'page',
|
|
104
|
-
* fields: {
|
|
105
|
-
* layout: field.blocks({ blocks: [...commonBlocks] }),
|
|
106
|
-
* },
|
|
107
|
-
* })
|
|
108
|
-
*/
|
|
109
|
-
declare const commonBlocks: readonly [BlockDefinition<{
|
|
110
|
-
readonly content: _murumets_ee_entity.RichTextField & {
|
|
111
|
-
readonly translatable: true;
|
|
112
|
-
};
|
|
113
|
-
}>, BlockDefinition<{
|
|
114
|
-
readonly image: _murumets_ee_entity.MediaField & {
|
|
115
|
-
readonly accept: ["image/*"];
|
|
116
|
-
readonly required: true;
|
|
117
|
-
};
|
|
118
|
-
readonly alt: _murumets_ee_entity.TextField & {
|
|
119
|
-
readonly translatable: true;
|
|
120
|
-
};
|
|
121
|
-
readonly caption: _murumets_ee_entity.TextField & {
|
|
122
|
-
readonly translatable: true;
|
|
123
|
-
};
|
|
124
|
-
}>, BlockDefinition<{
|
|
125
|
-
readonly heading: _murumets_ee_entity.TextField & {
|
|
126
|
-
readonly required: true;
|
|
127
|
-
readonly translatable: true;
|
|
128
|
-
};
|
|
129
|
-
readonly subheading: _murumets_ee_entity.TextField & {
|
|
130
|
-
readonly translatable: true;
|
|
131
|
-
};
|
|
132
|
-
readonly background: _murumets_ee_entity.MediaField & {
|
|
133
|
-
readonly accept: ["image/*"];
|
|
134
|
-
};
|
|
135
|
-
readonly alignment: _murumets_ee_entity.SelectField & {
|
|
136
|
-
options: readonly ["left", "center", "right"];
|
|
137
|
-
} & Omit<Partial<_murumets_ee_entity.SelectField>, "options">;
|
|
138
|
-
}>, BlockDefinition<{
|
|
139
|
-
readonly images: _murumets_ee_entity.ReferenceField & {
|
|
140
|
-
cardinality: "many";
|
|
141
|
-
} & Partial<Omit<_murumets_ee_entity.ReferenceField, "entity" | "cardinality">>;
|
|
142
|
-
readonly columns: _murumets_ee_entity.SelectField & {
|
|
143
|
-
options: readonly ["2", "3", "4"];
|
|
144
|
-
} & Omit<Partial<_murumets_ee_entity.SelectField>, "options">;
|
|
145
|
-
}>, BlockDefinition<{
|
|
146
|
-
readonly heading: _murumets_ee_entity.TextField & {
|
|
147
|
-
readonly required: true;
|
|
148
|
-
readonly translatable: true;
|
|
149
|
-
};
|
|
150
|
-
readonly description: _murumets_ee_entity.TextField & {
|
|
151
|
-
readonly translatable: true;
|
|
152
|
-
};
|
|
153
|
-
readonly buttonText: _murumets_ee_entity.TextField & {
|
|
154
|
-
readonly required: true;
|
|
155
|
-
readonly translatable: true;
|
|
156
|
-
};
|
|
157
|
-
readonly buttonLink: _murumets_ee_entity.TextField & {
|
|
158
|
-
readonly required: true;
|
|
159
|
-
};
|
|
160
|
-
}>, BlockDefinition<{
|
|
161
|
-
readonly url: _murumets_ee_entity.TextField & {
|
|
162
|
-
readonly required: true;
|
|
163
|
-
};
|
|
164
|
-
readonly poster: _murumets_ee_entity.MediaField & {
|
|
165
|
-
readonly accept: ["image/*"];
|
|
166
|
-
};
|
|
167
|
-
readonly caption: _murumets_ee_entity.TextField & {
|
|
168
|
-
readonly translatable: true;
|
|
169
|
-
};
|
|
170
|
-
}>, BlockDefinition<{
|
|
171
|
-
readonly quote: _murumets_ee_entity.TextField & {
|
|
172
|
-
readonly required: true;
|
|
173
|
-
readonly translatable: true;
|
|
174
|
-
};
|
|
175
|
-
readonly attribution: _murumets_ee_entity.TextField & {
|
|
176
|
-
readonly translatable: true;
|
|
177
|
-
};
|
|
178
|
-
}>, BlockDefinition<{
|
|
179
|
-
readonly code: _murumets_ee_entity.TextField & {
|
|
180
|
-
readonly required: true;
|
|
181
|
-
};
|
|
182
|
-
readonly language: _murumets_ee_entity.SelectField & {
|
|
183
|
-
options: readonly ["javascript", "typescript", "python", "html", "css", "json", "bash", "sql", "other"];
|
|
184
|
-
} & Omit<Partial<_murumets_ee_entity.SelectField>, "options">;
|
|
185
|
-
}>];
|
|
186
|
-
|
|
187
|
-
export { CTABlock, CodeBlock, GalleryBlock, HeroBlock, ImageBlock, QuoteBlock, RichTextBlock, VideoBlock, commonBlocks };
|
package/dist/blocks/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e}from"../chunk-CULYIGZI.js";import{field as d}from"@murumets-ee/entity";var r=e({slug:"code",label:"Code",fields:{code:d.text({required:!0}),language:d.select({options:["javascript","typescript","python","html","css","json","bash","sql","other"]})}});import{field as t}from"@murumets-ee/entity";var l=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})}});import{field as u}from"@murumets-ee/entity";var i=e({slug:"gallery",label:"Gallery",fields:{images:u.reference({entity:"media",cardinality:"many"}),columns:u.select({options:["2","3","4"]})}});import{field as o}from"@murumets-ee/entity";var a=e({slug:"hero",label:"Hero Section",fields:{heading:o.text({required:!0,translatable:!0}),subheading:o.text({translatable:!0}),background:o.media({accept:["image/*"]}),alignment:o.select({options:["left","center","right"]})}});import{field as c}from"@murumets-ee/entity";var m=e({slug:"image",label:"Image",fields:{image:c.media({accept:["image/*"],required:!0}),alt:c.text({translatable:!0}),caption:c.text({translatable:!0})}});import{field as x}from"@murumets-ee/entity";var n=e({slug:"quote",label:"Quote",fields:{quote:x.text({required:!0,translatable:!0}),attribution:x.text({translatable:!0})}});import{field as k}from"@murumets-ee/entity";var f=e({slug:"richtext",label:"Rich Text",fields:{content:k.richtext({translatable:!0})}});import{field as s}from"@murumets-ee/entity";var p=e({slug:"video",label:"Video",fields:{url:s.text({required:!0}),poster:s.media({accept:["image/*"]}),caption:s.text({translatable:!0})}});var X=[f,m,a,i,l,p,n,r];export{l as CTABlock,r as CodeBlock,i as GalleryBlock,a as HeroBlock,m as ImageBlock,n as QuoteBlock,f as RichTextBlock,p as VideoBlock,X as commonBlocks};
|
package/dist/chunk-BVMZMEPV.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{field as g}from"@murumets-ee/entity";var x={maxPerDoc:50,autosave:!1};function j(e){let t={...x,...e};return{name:"versionable",fields:{_version:g.number({required:!0,default:1,integer:!0}),_versionedAt:g.date()},hooks:{beforeCreate:async s=>(s._version=1,s._versionedAt=new Date,s),beforeUpdate:async(s,f)=>(f._versionedAt=new Date,f)},_versionableOptions:t}}function F(e){return e?e.find(n=>n.name==="versionable")?._versionableOptions??null:null}function h(e){return e.match(/\S+|\s+/g)??[]}function b(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=h(e),s=h(t),f=n.length,r=s.length,o=Array.from({length:f+1},()=>new Array(r+1).fill(0));for(let c=1;c<=f;c++)for(let u=1;u<=r;u++)n[c-1]===s[u-1]?o[c][u]=o[c-1][u-1]+1:o[c][u]=Math.max(o[c-1][u],o[c][u-1]);let p=[],i=f,l=r,d=[];for(;i>0||l>0;)i>0&&l>0&&n[i-1]===s[l-1]?(d.push({type:"equal",value:n[i-1]}),i--,l--):l>0&&(i===0||o[i][l-1]>=o[i-1][l])?(d.push({type:"add",value:s[l-1]}),l--):(d.push({type:"remove",value:n[i-1]}),i--);d.reverse();for(let c of d){let u=p[p.length-1];u&&u.type===c.type?u.value+=c.value:p.push({...c})}return p}function m(e){return e.replace(/<[^>]*>/g," ").replace(/\s+/g," ").trim()}function a(e){return e==null?"":e instanceof Date?e.toISOString():typeof e=="object"?JSON.stringify(e):String(e)}function D(e,t,n,s){if(JSON.stringify(t)===JSON.stringify(n))return null;switch(s?.type??O(t,n)){case"text":case"slug":{let r=b(a(t),a(n));return{field:e,type:"text",from:t,to:n,segments:r}}case"richtext":{let r=b(m(a(t)),m(a(n)));return{field:e,type:"richtext",from:t,to:n,segments:r}}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 I(e,t,n){let s=new Set([...Object.keys(e),...Object.keys(t)]),f=[];for(let r of s){if(r==="id"||r==="createdAt"||r==="updatedAt")continue;let o=D(r,e[r],t[r],n?.[r]);o&&f.push(o)}return f}function O(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 v(e,t){if(typeof e=="string"||typeof t=="string")return b(a(e),a(t))}function _(e){return typeof e=="object"&&e!==null&&"_block"in e&&"_id"in e&&typeof e._block=="string"&&typeof e._id=="string"}function B(e,t){let n=new Set([...Object.keys(e),...Object.keys(t)]),s=[];for(let f of n){if(f==="_block"||f==="_id")continue;let r=e[f],o=t[f];JSON.stringify(r)!==JSON.stringify(o)&&s.push({field:f,from:r,to:o,segments:v(r,o)})}return s}function E(e,t){let n=e.filter(_),s=t.filter(_),f=new Map,r=new Map;for(let i=0;i<n.length;i++)f.set(n[i]._id,{block:n[i],index:i});for(let i=0;i<s.length;i++)r.set(s[i]._id,{block:s[i],index:i});let o=[],p=new Set;for(let[i,{block:l,index:d}]of r){p.add(i);let c=f.get(i);if(!c){o.push({blockId:i,blockType:l._block,status:"added",toIndex:d});continue}let u=c.block,y=c.index,k=B(u,l),w=y!==d;k.length===0&&!w?o.push({blockId:i,blockType:l._block,status:"unchanged",fromIndex:y,toIndex:d}):k.length>0?o.push({blockId:i,blockType:l._block,status:"changed",fromIndex:y,toIndex:d,propDiffs:k}):o.push({blockId:i,blockType:l._block,status:"moved",fromIndex:y,toIndex:d})}for(let[i,{block:l,index:d}]of f)p.has(i)||o.push({blockId:i,blockType:l._block,status:"removed",fromIndex:d});return o}export{j as a,F as b,b as c,D as d,I as e,v as f,E as g};
|
package/dist/chunk-CULYIGZI.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function e(l){if(!l.slug||!l.slug.match(/^[a-z][a-z0-9-]*$/))throw new Error(`Block slug must be lowercase alphanumeric with hyphens, got: "${l.slug}"`);if(!l.label)throw new Error(`Block label is required for slug: "${l.slug}"`);if(!l.fields||Object.keys(l.fields).length===0)throw new Error(`Block "${l.slug}" must have at least one field`);return{slug:l.slug,label:l.label,fields:l.fields}}export{e as a};
|
package/dist/client.d.ts
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@murumets-ee/core';
|
|
2
|
-
import { Entity, FieldToTS, FieldConfig } from '@murumets-ee/entity';
|
|
3
|
-
import { FindManyOptions } from '@murumets-ee/entity/admin';
|
|
4
|
-
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
5
|
-
import { F as FieldDiff } from './types-Cr0ifLn_.js';
|
|
6
|
-
import { V as VersionEntry, D as DraftEntry, T as TranslationStatus, a as TranslationReport, L as LocalePublishStatus } from './types-BYeiE1ie.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* ContentClient — wraps AdminClient with version history and translation status.
|
|
10
|
-
*
|
|
11
|
-
* Usage:
|
|
12
|
-
* import { createContentClient } from '@murumets-ee/content/client'
|
|
13
|
-
* const pages = createContentClient(Page)
|
|
14
|
-
* await pages.create({ title: 'Hello', layout: [...] })
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/** Value type that any entity field can hold */
|
|
18
|
-
type EntityFieldValue = FieldToTS<FieldConfig> | null | undefined;
|
|
19
|
-
interface ContentClientConfig {
|
|
20
|
-
entity: Entity;
|
|
21
|
-
db: PostgresJsDatabase;
|
|
22
|
-
logger?: Logger;
|
|
23
|
-
}
|
|
24
|
-
declare class ContentClient {
|
|
25
|
-
private entity;
|
|
26
|
-
private db;
|
|
27
|
-
private logger?;
|
|
28
|
-
private admin;
|
|
29
|
-
private versionableOptions;
|
|
30
|
-
constructor(config: ContentClientConfig);
|
|
31
|
-
private getAdmin;
|
|
32
|
-
create(data: Record<string, EntityFieldValue>): Promise<{
|
|
33
|
-
id: string;
|
|
34
|
-
} & {} & {
|
|
35
|
-
[x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
|
|
36
|
-
[key: string]: unknown;
|
|
37
|
-
_block: string;
|
|
38
|
-
_id: string;
|
|
39
|
-
}[] | null | undefined;
|
|
40
|
-
}>;
|
|
41
|
-
findById(id: string, options?: {
|
|
42
|
-
locale?: string;
|
|
43
|
-
}): Promise<({
|
|
44
|
-
id: string;
|
|
45
|
-
} & {} & {
|
|
46
|
-
[x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
|
|
47
|
-
[key: string]: unknown;
|
|
48
|
-
_block: string;
|
|
49
|
-
_id: string;
|
|
50
|
-
}[] | null | undefined;
|
|
51
|
-
}) | null>;
|
|
52
|
-
findMany(options?: FindManyOptions): Promise<({
|
|
53
|
-
id: string;
|
|
54
|
-
} & {} & {
|
|
55
|
-
[x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
|
|
56
|
-
[key: string]: unknown;
|
|
57
|
-
_block: string;
|
|
58
|
-
_id: string;
|
|
59
|
-
}[] | null | undefined;
|
|
60
|
-
})[]>;
|
|
61
|
-
update(id: string, data: Record<string, EntityFieldValue>): Promise<{
|
|
62
|
-
id: string;
|
|
63
|
-
} & {} & {
|
|
64
|
-
[x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
|
|
65
|
-
[key: string]: unknown;
|
|
66
|
-
_block: string;
|
|
67
|
-
_id: string;
|
|
68
|
-
}[] | null | undefined;
|
|
69
|
-
}>;
|
|
70
|
-
delete(id: string): Promise<void>;
|
|
71
|
-
saveTranslation(entityId: string, locale: string, translations: Record<string, unknown>): Promise<void>;
|
|
72
|
-
deleteTranslation(entityId: string, locale?: string): Promise<void>;
|
|
73
|
-
/**
|
|
74
|
-
* Copy layout from one locale to another (for localized: true blocks).
|
|
75
|
-
*/
|
|
76
|
-
copyLayout(entityId: string, options: {
|
|
77
|
-
from: string;
|
|
78
|
-
to: string | string[];
|
|
79
|
-
}): Promise<void>;
|
|
80
|
-
/**
|
|
81
|
-
* List versions for an entity (newest first), filtered by locale.
|
|
82
|
-
* Uses '_' as the locale value for default-locale snapshots.
|
|
83
|
-
*/
|
|
84
|
-
getVersions(entityId: string, options?: {
|
|
85
|
-
limit?: number;
|
|
86
|
-
offset?: number;
|
|
87
|
-
locale?: string;
|
|
88
|
-
}): Promise<VersionEntry[]>;
|
|
89
|
-
/**
|
|
90
|
-
* Get a specific version snapshot.
|
|
91
|
-
*/
|
|
92
|
-
getVersion(entityId: string, version: number, locale?: string): Promise<VersionEntry | null>;
|
|
93
|
-
/**
|
|
94
|
-
* Compare two versions and return field-level diff.
|
|
95
|
-
*
|
|
96
|
-
* Returns structured diffs with word-level segments for text fields
|
|
97
|
-
* and structural block diffs for blocks fields.
|
|
98
|
-
*/
|
|
99
|
-
compareVersions(entityId: string, v1: number, v2: number, locale?: string): Promise<{
|
|
100
|
-
diffs: FieldDiff[];
|
|
101
|
-
fromVersion: VersionEntry;
|
|
102
|
-
toVersion: VersionEntry;
|
|
103
|
-
} | null>;
|
|
104
|
-
/**
|
|
105
|
-
* Compare the current draft with the live entity (or a specific version).
|
|
106
|
-
* Returns field-level diffs between the current published data and the draft.
|
|
107
|
-
*/
|
|
108
|
-
compareDraftWithCurrent(entityId: string, locale?: string): Promise<{
|
|
109
|
-
diffs: FieldDiff[];
|
|
110
|
-
current: Record<string, unknown>;
|
|
111
|
-
draft: DraftEntry;
|
|
112
|
-
} | null>;
|
|
113
|
-
/**
|
|
114
|
-
* Restore an entity to a previous version.
|
|
115
|
-
*/
|
|
116
|
-
restoreVersion(entityId: string, version: number): Promise<{
|
|
117
|
-
id: string;
|
|
118
|
-
} & {} & {
|
|
119
|
-
[x: string]: string | number | boolean | Date | Record<string, unknown> | Record<string, unknown>[] | {
|
|
120
|
-
[key: string]: unknown;
|
|
121
|
-
_block: string;
|
|
122
|
-
_id: string;
|
|
123
|
-
}[] | null | undefined;
|
|
124
|
-
}>;
|
|
125
|
-
/**
|
|
126
|
-
* Enforce maxPerDoc retention by deleting oldest versions for a locale.
|
|
127
|
-
*/
|
|
128
|
-
pruneVersions(entityId: string, locale?: string): Promise<void>;
|
|
129
|
-
/**
|
|
130
|
-
* Get translation status for an entity — per-locale completion report.
|
|
131
|
-
*/
|
|
132
|
-
getTranslationStatus(entityId: string): Promise<TranslationStatus>;
|
|
133
|
-
/**
|
|
134
|
-
* Get translation status for multiple entities in a single query.
|
|
135
|
-
* Returns a map of entityId → TranslationStatus (O(1) DB roundtrips).
|
|
136
|
-
*/
|
|
137
|
-
getTranslationStatusBatch(entityIds: string[]): Promise<Map<string, TranslationStatus>>;
|
|
138
|
-
/**
|
|
139
|
-
* Get translation report across all entities of this type.
|
|
140
|
-
*/
|
|
141
|
-
getTranslationReport(options?: {
|
|
142
|
-
locale?: string;
|
|
143
|
-
}): Promise<TranslationReport>;
|
|
144
|
-
/**
|
|
145
|
-
* Get per-locale publish status for an entity.
|
|
146
|
-
* Returns status for all non-default locales that have explicit overrides.
|
|
147
|
-
* Missing locale = inherits base entity status.
|
|
148
|
-
*/
|
|
149
|
-
getLocaleStatus(entityId: string): Promise<LocalePublishStatus[]>;
|
|
150
|
-
/**
|
|
151
|
-
* Set per-locale publish status. Upserts into locale_status table.
|
|
152
|
-
* When locale === defaultLocale, updates the base entity status instead.
|
|
153
|
-
*/
|
|
154
|
-
setLocaleStatus(entityId: string, locale: string, status: 'draft' | 'published'): Promise<void>;
|
|
155
|
-
/**
|
|
156
|
-
* Get per-locale publish status for multiple entities in a single query.
|
|
157
|
-
* Returns a map of entityId → locale → LocalePublishStatus.
|
|
158
|
-
*/
|
|
159
|
-
getLocaleStatusBatch(entityIds: string[]): Promise<Map<string, Record<string, LocalePublishStatus>>>;
|
|
160
|
-
/**
|
|
161
|
-
* Save (upsert) a draft for an entity+locale.
|
|
162
|
-
* One draft per entity+locale — overwrites any existing draft.
|
|
163
|
-
*/
|
|
164
|
-
saveDraft(entityId: string, data: Record<string, unknown>, locale?: string, user?: {
|
|
165
|
-
id: string;
|
|
166
|
-
name?: string;
|
|
167
|
-
}): Promise<DraftEntry>;
|
|
168
|
-
/**
|
|
169
|
-
* Get the draft for an entity+locale, or null if none exists.
|
|
170
|
-
*/
|
|
171
|
-
getDraft(entityId: string, locale?: string): Promise<DraftEntry | null>;
|
|
172
|
-
/**
|
|
173
|
-
* Delete (discard) a draft for an entity+locale.
|
|
174
|
-
*/
|
|
175
|
-
deleteDraft(entityId: string, locale?: string): Promise<boolean>;
|
|
176
|
-
/**
|
|
177
|
-
* Publish a draft: apply draft data to the live entity, then delete the draft.
|
|
178
|
-
* Runs in a transaction to ensure atomicity.
|
|
179
|
-
*/
|
|
180
|
-
publishDraft(entityId: string, locale?: string, user?: {
|
|
181
|
-
id: string;
|
|
182
|
-
name?: string;
|
|
183
|
-
}): Promise<Record<string, unknown>>;
|
|
184
|
-
/**
|
|
185
|
-
* Quick existence check for list badges — does a draft exist?
|
|
186
|
-
*/
|
|
187
|
-
hasDraft(entityId: string, locale?: string): Promise<boolean>;
|
|
188
|
-
/**
|
|
189
|
-
* Check draft existence for multiple entities in one query.
|
|
190
|
-
* Returns a set of entity IDs that have drafts.
|
|
191
|
-
*/
|
|
192
|
-
hasDraftBatch(entityIds: string[], locale?: string): Promise<Set<string>>;
|
|
193
|
-
/**
|
|
194
|
-
* Create a version snapshot for an entity after an external update.
|
|
195
|
-
* Use this when the update was performed by AdminClient directly
|
|
196
|
-
* (e.g., the admin API handler) rather than through ContentClient.update().
|
|
197
|
-
*
|
|
198
|
-
* @param locale - The locale being edited. Use undefined or '_' for the default locale.
|
|
199
|
-
* @param user - The user who made the change (id + name for display).
|
|
200
|
-
*/
|
|
201
|
-
createVersionSnapshot(entityId: string, currentData: Record<string, unknown>, previousData?: Record<string, unknown> | null, locale?: string, user?: {
|
|
202
|
-
id: string;
|
|
203
|
-
name?: string;
|
|
204
|
-
}): Promise<void>;
|
|
205
|
-
private saveVersionSnapshot;
|
|
206
|
-
private toDraftEntry;
|
|
207
|
-
private calculateDelta;
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Factory — creates a ContentClient for an entity.
|
|
211
|
-
* Must be called after createApp().
|
|
212
|
-
*/
|
|
213
|
-
declare function createContentClient(entity: Entity): Promise<ContentClient>;
|
|
214
|
-
|
|
215
|
-
export { ContentClient, type ContentClientConfig, createContentClient };
|
package/dist/client.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as v,e as p,g as b}from"./chunk-BVMZMEPV.js";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=v(t.entity.behaviors)}async getAdmin(){if(!this.admin){let{AdminClient:t}=await import("@murumets-ee/entity/admin");this.admin=new t({entity:this.entity,db:this.db,logger:this.logger})}return this.admin}async create(t){let i=await(await this.getAdmin()).create(t);return this.versionableOptions&&await this.saveVersionSnapshot(i.id,i,null,!1),i}async findById(t,e){return(await this.getAdmin()).findById(t,e)}async findMany(t){return(await this.getAdmin()).findMany(t)}async update(t,e){let i=await this.getAdmin(),n=null;this.versionableOptions&&(n=await i.findById(t));let o=await i.update(t,e);if(this.versionableOptions&&n){let s=this.calculateDelta(n,o),r=await this.saveVersionSnapshot(t,o,s,!1);if(r!==void 0){let{schemaRegistry:a}=await import("@murumets-ee/db"),{eq:c}=await import("drizzle-orm"),d=a.get(this.entity.name);d&&(await this.db.update(d).set({_version:r}).where(c(d.id,t)),o._version=r)}await this.pruneVersions(t)}return o}async delete(t){return(await this.getAdmin()).delete(t)}async saveTranslation(t,e,i){return(await this.getAdmin()).saveTranslation(t,e,i)}async deleteTranslation(t,e){return(await this.getAdmin()).deleteTranslation(t,e)}async copyLayout(t,e){let{schemaRegistry:i}=await import("@murumets-ee/db"),{eq:n,and:o}=await import("drizzle-orm"),s=i.get(`${this.entity.name}_layout`);if(!s)return;let r=Array.isArray(e.to)?e.to:[e.to],a=await this.db.select().from(s).where(o(n(s.entityId,t),n(s.locale,e.from))).orderBy(s.sortOrder);if(a.length!==0){for(let c of r){await this.db.delete(s).where(o(n(s.entityId,t),n(s.locale,c)));for(let d of a)await this.db.insert(s).values({entityId:d.entityId,fieldName:d.fieldName,blockType:d.blockType,sortOrder:d.sortOrder,data:d.data,locale:c})}this.logger?.debug({entityId:t,from:e.from,to:r},"Layout copied between locales")}}async getVersions(t,e){let{schemaRegistry:i}=await import("@murumets-ee/db"),{eq:n,and:o,desc:s}=await import("drizzle-orm"),r=i.get(`${this.entity.name}_versions`);if(!r)return[];let a=e?.locale??"_",c=this.db.select().from(r).where(o(n(r.entityId,t),n(r.locale,a))).orderBy(s(r.version)).$dynamic();return e?.limit&&(c=c.limit(e.limit)),e?.offset&&(c=c.offset(e.offset)),c}async getVersion(t,e,i="_"){let{schemaRegistry:n}=await import("@murumets-ee/db"),{eq:o,and:s}=await import("drizzle-orm"),r=n.get(`${this.entity.name}_versions`);return r?(await this.db.select().from(r).where(s(o(r.entityId,t),o(r.version,e),o(r.locale,i))).limit(1))[0]??null:null}async compareVersions(t,e,i,n="_"){let[o,s]=await Promise.all([this.getVersion(t,e,n),this.getVersion(t,i,n)]);if(!o||!s)return null;let r=o.data,a=s.data,c=this.entity.allFields,d=p(r,a,c);for(let l of d)l.type==="blocks"&&Array.isArray(l.from)&&Array.isArray(l.to)&&(l.blockDiffs=b(l.from,l.to));return{diffs:d,fromVersion:o,toVersion:s}}async compareDraftWithCurrent(t,e="_"){let i=await this.getDraft(t,e);if(!i)return null;let n=await this.getAdmin(),{getContentConfig:o}=await import("./plugin.js"),r=o().defaultLocale,a=e==="_"?{defaultLocale:r}:{locale:e,defaultLocale:r},c=await n.findById(t,a);if(!c)return null;let d=this.entity.allFields,l={};for(let f of Object.keys(i.data))l[f]=c[f];let u=p(l,i.data,d);for(let f of u)f.type==="blocks"&&Array.isArray(f.from)&&Array.isArray(f.to)&&(f.blockDiffs=b(f.from,f.to));return{diffs:u,current:c,draft:i}}async restoreVersion(t,e){let i=await this.getVersion(t,e);if(!i)throw new Error(`Version ${e} not found for entity ${t}`);let n=i.data,{id:o,createdAt:s,createdBy:r,_version:a,_versionedAt:c,...d}=n;return(await this.getAdmin()).update(t,d)}async pruneVersions(t,e="_"){if(!this.versionableOptions)return;let{schemaRegistry:i}=await import("@murumets-ee/db"),{eq:n,and:o,desc:s,sql:r}=await import("drizzle-orm"),a=i.get(`${this.entity.name}_versions`);if(!a)return;let c=this.versionableOptions.maxPerDoc,d=await this.db.select({id:a.id}).from(a).where(o(n(a.entityId,t),n(a.locale,e))).orderBy(s(a.version)).limit(c);if(d.length<c)return;let l=d.map(u=>u.id);await this.db.delete(a).where(r`${a.entityId} = ${t} AND ${a.locale} = ${e} AND ${a.id} NOT IN (${r.join(l.map(u=>r`${u}`),r`, `)})`)}async getTranslationStatus(t){let{getContentConfig:e}=await import("./plugin.js"),i=e(),n=Object.entries(this.entity.allFields).filter(([l,u])=>u.translatable).map(([l])=>l);if(n.length===0)return{};let{schemaRegistry:o}=await import("@murumets-ee/db"),{eq:s}=await import("drizzle-orm"),r=o.get(`${this.entity.name}_translations`);if(!r)return{};let a=await this.db.select().from(r).where(s(r.entityId,t)),c=new Map;for(let l of a){let u=l,f={};for(let g of n)f[g]=u[g];c.set(u.locale,f)}let d={};for(let l of i.locales){if(l.code===i.defaultLocale)continue;let u=c.get(l.code)??{},f=[];for(let m of n)(u[m]===void 0||u[m]===null)&&f.push(m);let g=n.length-f.length;d[l.code]={complete:f.length===0,total:n.length,translated:g,missing:f}}return d}async getTranslationStatusBatch(t){let e=new Map;if(t.length===0)return e;let{getContentConfig:i}=await import("./plugin.js"),n=i(),o=Object.entries(this.entity.allFields).filter(([l,u])=>u.translatable).map(([l])=>l);if(o.length===0)return e;let{schemaRegistry:s}=await import("@murumets-ee/db"),{inArray:r}=await import("drizzle-orm"),a=s.get(`${this.entity.name}_translations`);if(!a)return e;let c=await this.db.select().from(a).where(r(a.entityId,t)),d=new Map;for(let l of c){let u=l,f=u.entityId,g=u.locale,m={};for(let h of o)m[h]=u[h];d.has(f)||d.set(f,new Map),d.get(f).set(g,m)}for(let l of t){let u=d.get(l),f={};for(let g of n.locales){if(g.code===n.defaultLocale)continue;let m=u?.get(g.code)??{},h=[];for(let w of o)(m[w]===void 0||m[w]===null)&&h.push(w);let A=o.length-h.length;f[g.code]={complete:h.length===0,total:o.length,translated:A,missing:h}}e.set(l,f)}return e}async getTranslationReport(t){let{getContentConfig:e}=await import("./plugin.js"),i=e(),n=t?.locale??i.locales.find(d=>d.code!==i.defaultLocale)?.code;if(!n)return{total:0,complete:0,partial:0,missing:0};let s=await(await this.getAdmin()).findMany(),r=0,a=0,c=0;for(let d of s){let u=(await this.getTranslationStatus(d.id))[n];!u||u.translated===0?c++:u.complete?r++:a++}return{total:s.length,complete:r,partial:a,missing:c}}async getLocaleStatus(t){let{schemaRegistry:e}=await import("@murumets-ee/db"),{eq:i}=await import("drizzle-orm"),n=e.get(`${this.entity.name}_locale_status`);return n?(await this.db.select().from(n).where(i(n.entityId,t))).map(s=>({locale:s.locale,status:s.status,publishedAt:s.publishedAt??null})):[]}async setLocaleStatus(t,e,i){let{getContentConfig:n}=await import("./plugin.js"),o=n();if(e===o.defaultLocale){let u=await this.getAdmin(),f={status:i};i==="published"&&(f.publishedAt=new Date),await u.update(t,f);return}let{schemaRegistry:s}=await import("@murumets-ee/db"),{eq:r,and:a}=await import("drizzle-orm"),c=s.get(`${this.entity.name}_locale_status`);if(!c)return;let d=i==="published"?new Date:null,[l]=await this.db.select({id:c.id}).from(c).where(a(r(c.entityId,t),r(c.locale,e))).limit(1);l?await this.db.update(c).set({status:i,publishedAt:d}).where(r(c.id,l.id)):await this.db.insert(c).values({entityId:t,locale:e,status:i,publishedAt:d})}async getLocaleStatusBatch(t){let e=new Map;if(t.length===0)return e;let{schemaRegistry:i}=await import("@murumets-ee/db"),{inArray:n}=await import("drizzle-orm"),o=i.get(`${this.entity.name}_locale_status`);if(!o)return e;let s=await this.db.select().from(o).where(n(o.entityId,t));for(let r of s){let a=r.entityId,c=r.locale;e.has(a)||e.set(a,{}),e.get(a)[c]={locale:c,status:r.status,publishedAt:r.publishedAt??null}}return e}async saveDraft(t,e,i="_",n){let{schemaRegistry:o}=await import("@murumets-ee/db"),{eq:s,and:r}=await import("drizzle-orm"),a=o.get(`${this.entity.name}_drafts`);if(!a)throw new Error(`Drafts table not found for entity "${this.entity.name}". Is the content plugin initialized?`);let c=new Date,d=n?.id??"",l=n?.name??null,[u]=await this.db.select().from(a).where(r(s(a.entityId,t),s(a.locale,i))).limit(1);if(u){let[g]=await this.db.update(a).set({data:e,updatedAt:c}).where(s(a.id,u.id)).returning();return this.toDraftEntry(g)}let[f]=await this.db.insert(a).values({entityId:t,locale:i,data:e,createdBy:d,createdByName:l,createdAt:c,updatedAt:c}).returning();return this.toDraftEntry(f)}async getDraft(t,e="_"){let{schemaRegistry:i}=await import("@murumets-ee/db"),{eq:n,and:o}=await import("drizzle-orm"),s=i.get(`${this.entity.name}_drafts`);if(!s)return null;let[r]=await this.db.select().from(s).where(o(n(s.entityId,t),n(s.locale,e))).limit(1);return r?this.toDraftEntry(r):null}async deleteDraft(t,e="_"){let{schemaRegistry:i}=await import("@murumets-ee/db"),{eq:n,and:o}=await import("drizzle-orm"),s=i.get(`${this.entity.name}_drafts`);return s?(await this.db.delete(s).where(o(n(s.entityId,t),n(s.locale,e))).returning({id:s.id})).length>0:!1}async publishDraft(t,e="_",i){let n=await this.getDraft(t,e);if(!n)throw new Error(`No draft found for entity ${t} locale ${e}`);let o=await this.getAdmin(),s=null;this.versionableOptions&&(s=await o.findById(t));let r=n.data,{id:a,createdAt:c,createdBy:d,_version:l,_versionedAt:u,...f}=r,g=await o.update(t,f);return await this.deleteDraft(t,e),this.versionableOptions&&await this.createVersionSnapshot(t,g,s,e,i),g}async hasDraft(t,e="_"){let{schemaRegistry:i}=await import("@murumets-ee/db"),{eq:n,and:o}=await import("drizzle-orm"),s=i.get(`${this.entity.name}_drafts`);if(!s)return!1;let[r]=await this.db.select({id:s.id}).from(s).where(o(n(s.entityId,t),n(s.locale,e))).limit(1);return!!r}async hasDraftBatch(t,e="_"){let i=new Set;if(t.length===0)return i;let{schemaRegistry:n}=await import("@murumets-ee/db"),{inArray:o,eq:s,and:r}=await import("drizzle-orm"),a=n.get(`${this.entity.name}_drafts`);if(!a)return i;let c=await this.db.select({entityId:a.entityId}).from(a).where(r(o(a.entityId,t),s(a.locale,e)));for(let d of c)i.add(d.entityId);return i}async createVersionSnapshot(t,e,i,n,o){if(!this.versionableOptions)return;let s=n??"_",r=i?this.calculateDelta(i,e):null,a=await this.saveVersionSnapshot(t,e,r,!1,s,o);if(a!==void 0&&s==="_"){let{schemaRegistry:c}=await import("@murumets-ee/db"),{eq:d}=await import("drizzle-orm"),l=c.get(this.entity.name);l&&await this.db.update(l).set({_version:a}).where(d(l.id,t))}await this.pruneVersions(t,s)}async saveVersionSnapshot(t,e,i,n,o="_",s){let{schemaRegistry:r}=await import("@murumets-ee/db"),{eq:a,and:c,sql:d}=await import("drizzle-orm"),l=r.get(`${this.entity.name}_versions`);if(!l)return;let[u]=await this.db.select({maxVersion:d`coalesce(max(${l.version}), 0)`}).from(l).where(c(a(l.entityId,t),a(l.locale,o))),f=(u?.maxVersion??0)+1,g=e.status??null;if(n){let[m]=await this.db.select().from(l).where(c(a(l.entityId,t),a(l.isAutosave,!0),a(l.version,f),a(l.locale,o))).limit(1);if(m)return await this.db.update(l).set({data:e,delta:i,status:g,createdAt:new Date}).where(a(l.id,m.id)),f}return await this.db.insert(l).values({entityId:t,version:f,locale:o,data:e,delta:i,status:g,createdBy:s?.id??e.updatedBy??e.createdBy??null,createdByName:s?.name??null,isAutosave:n}),f}toDraftEntry(t){return{id:t.id,entityId:t.entityId,locale:t.locale,data:t.data,createdBy:t.createdBy,createdByName:t.createdByName??null,createdAt:t.createdAt,updatedAt:t.updatedAt}}calculateDelta(t,e){let i={};for(let n of Object.keys(e))n==="id"||n.startsWith("_")||JSON.stringify(t[n])!==JSON.stringify(e[n])&&(i[n]=e[n]);return i}};async function T(y){let{getApp:t}=await import("@murumets-ee/core"),e=t();return new R({entity:y,db:e.db.readWrite,logger:e.logger.child({content:y.name})})}export{R as ContentClient,T as createContentClient};
|
package/dist/drafts-2ZRAHAUK.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{jsonb as o,pgTable as u,timestamp as a,unique as r,uuid as n,varchar as t}from"drizzle-orm/pg-core";function m(l){let d=`${l.name}_drafts`;return u(d,{id:n("id").primaryKey().defaultRandom(),entityId:n("entity_id").notNull(),locale:t("locale",{length:10}).notNull().default("_"),data:o("data").notNull(),createdBy:t("created_by",{length:255}).notNull(),createdByName:t("created_by_name",{length:255}),createdAt:a("created_at",{withTimezone:!0}).notNull().defaultNow(),updatedAt:a("updated_at",{withTimezone:!0}).notNull().defaultNow()},e=>({uniqueEntityLocale:r().on(e.entityId,e.locale)}))}export{m as generateDraftsSchema};
|