@murumets-ee/content 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -17
- package/dist/blocks/index.cjs +0 -1
- package/dist/blocks/index.d.cts +0 -187
- package/dist/blocks/index.d.ts +0 -187
- package/dist/client.cjs +0 -1
- package/dist/client.d.cts +0 -215
- package/dist/client.d.ts +0 -215
- package/dist/index.cjs +0 -1
- package/dist/index.d.cts +0 -142
- package/dist/index.d.ts +0 -142
- package/dist/lock-service.cjs +0 -1
- package/dist/lock-service.d.cts +0 -61
- package/dist/lock-service.d.ts +0 -61
- package/dist/plugin.cjs +0 -1
- package/dist/plugin.d.cts +0 -33
- package/dist/plugin.d.ts +0 -33
- package/dist/query-client.cjs +0 -1
- package/dist/query-client.d.cts +0 -67
- package/dist/query-client.d.ts +0 -67
- package/dist/types-BYeiE1ie.d.cts +0 -99
- package/dist/types-BYeiE1ie.d.ts +0 -99
- package/dist/types-Cr0ifLn_.d.cts +0 -41
- package/dist/types-Cr0ifLn_.d.ts +0 -41
package/dist/client.d.cts
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_.cjs';
|
|
6
|
-
import { V as VersionEntry, D as DraftEntry, T as TranslationStatus, a as TranslationReport, L as LocalePublishStatus } from './types-BYeiE1ie.cjs';
|
|
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.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/index.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";var m=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var I=Object.prototype.hasOwnProperty;var R=(e,n)=>{for(var t in n)m(e,t,{get:n[t],enumerable:!0})},W=(e,n,t,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of E(n))!I.call(e,o)&&o!==t&&m(e,o,{get:()=>n[o],enumerable:!(i=q(n,o))||i.enumerable});return e};var C=e=>W(m({},"__esModule",{value:!0}),e);var K={};R(K,{WORKFLOW_STATES:()=>x,defineBlock:()=>D,diffBlocks:()=>A,diffField:()=>_,diffFields:()=>T,diffStringValues:()=>g,diffText:()=>p,getVersionableOptions:()=>S,versionable:()=>F,workflowable:()=>v});module.exports=C(K);var h=require("@murumets-ee/entity"),L={maxPerDoc:50,autosave:!1};function F(e){let n={...L,...e};return{name:"versionable",fields:{_version:h.field.number({required:!0,default:1,integer:!0}),_versionedAt:h.field.date()},hooks:{beforeCreate:async i=>(i._version=1,i._versionedAt=new Date,i),beforeUpdate:async(i,o)=>(o._versionedAt=new Date,o)},_versionableOptions:n}}function S(e){return e?e.find(t=>t.name==="versionable")?._versionableOptions??null:null}var y=require("@murumets-ee/entity"),x=["draft","in_review","approved","rejected","published"];function v(){return{name:"workflowable",fields:{_workflowStatus:y.field.select({options:x,default:"draft",indexed:!0,required:!0}),_workflowAssignee:y.field.text({required:!1}),_workflowNote:y.field.text({required:!1}),_workflowUpdatedAt:y.field.date()},hooks:{beforeCreate:async e=>(e._workflowStatus="draft",e._workflowUpdatedAt=new Date,e)}}}function D(e){if(!e.slug||!e.slug.match(/^[a-z][a-z0-9-]*$/))throw new Error(`Block slug must be lowercase alphanumeric with hyphens, got: "${e.slug}"`);if(!e.label)throw new Error(`Block label is required for slug: "${e.slug}"`);if(!e.fields||Object.keys(e.fields).length===0)throw new Error(`Block "${e.slug}" must have at least one field`);return{slug:e.slug,label:e.label,fields:e.fields}}function B(e){return e.match(/\S+|\s+/g)??[]}function p(e,n){if(e===n)return e?[{type:"equal",value:e}]:[];if(!e)return[{type:"add",value:n}];if(!n)return[{type:"remove",value:e}];let t=B(e),i=B(n),o=t.length,s=i.length,l=Array.from({length:o+1},()=>new Array(s+1).fill(0));for(let u=1;u<=o;u++)for(let c=1;c<=s;c++)t[u-1]===i[c-1]?l[u][c]=l[u-1][c-1]+1:l[u][c]=Math.max(l[u-1][c],l[u][c-1]);let a=[],r=o,f=s,d=[];for(;r>0||f>0;)r>0&&f>0&&t[r-1]===i[f-1]?(d.push({type:"equal",value:t[r-1]}),r--,f--):f>0&&(r===0||l[r][f-1]>=l[r-1][f])?(d.push({type:"add",value:i[f-1]}),f--):(d.push({type:"remove",value:t[r-1]}),r--);d.reverse();for(let u of d){let c=a[a.length-1];c&&c.type===u.type?c.value+=u.value:a.push({...u})}return a}function O(e){return e.replace(/<[^>]*>/g," ").replace(/\s+/g," ").trim()}function k(e){return e==null?"":e instanceof Date?e.toISOString():typeof e=="object"?JSON.stringify(e):String(e)}function _(e,n,t,i){if(JSON.stringify(n)===JSON.stringify(t))return null;switch(i?.type??U(n,t)){case"text":case"slug":{let s=p(k(n),k(t));return{field:e,type:"text",from:n,to:t,segments:s}}case"richtext":{let s=p(O(k(n)),O(k(t)));return{field:e,type:"richtext",from:n,to:t,segments:s}}case"number":return{field:e,type:"number",from:n,to:t};case"boolean":return{field:e,type:"boolean",from:n,to:t};case"date":return{field:e,type:"date",from:n,to:t};case"select":return{field:e,type:"select",from:n,to:t};case"media":return{field:e,type:"media",from:n,to:t};case"json":return{field:e,type:"json",from:n,to:t};case"blocks":return{field:e,type:"blocks",from:n,to:t};default:return{field:e,type:"unknown",from:n,to:t}}}function T(e,n,t){let i=new Set([...Object.keys(e),...Object.keys(n)]),o=[];for(let s of i){if(s==="id"||s==="createdAt"||s==="updatedAt")continue;let l=_(s,e[s],n[s],t?.[s]);l&&o.push(l)}return o}function U(e,n){let t=e??n;return typeof t=="number"?"number":typeof t=="boolean"?"boolean":t instanceof Date?"date":typeof t=="string"?/^\d{4}-\d{2}-\d{2}/.test(t)?"date":"text":Array.isArray(t)?t.length>0&&typeof t[0]=="object"&&t[0]!==null&&"_block"in t[0]?"blocks":"json":typeof t=="object"?"json":"unknown"}function g(e,n){if(typeof e=="string"||typeof n=="string")return p(k(e),k(n))}function j(e){return typeof e=="object"&&e!==null&&"_block"in e&&"_id"in e&&typeof e._block=="string"&&typeof e._id=="string"}function J(e,n){let t=new Set([...Object.keys(e),...Object.keys(n)]),i=[];for(let o of t){if(o==="_block"||o==="_id")continue;let s=e[o],l=n[o];JSON.stringify(s)!==JSON.stringify(l)&&i.push({field:o,from:s,to:l,segments:g(s,l)})}return i}function A(e,n){let t=e.filter(j),i=n.filter(j),o=new Map,s=new Map;for(let r=0;r<t.length;r++)o.set(t[r]._id,{block:t[r],index:r});for(let r=0;r<i.length;r++)s.set(i[r]._id,{block:i[r],index:r});let l=[],a=new Set;for(let[r,{block:f,index:d}]of s){a.add(r);let u=o.get(r);if(!u){l.push({blockId:r,blockType:f._block,status:"added",toIndex:d});continue}let c=u.block,b=u.index,w=J(c,f),V=b!==d;w.length===0&&!V?l.push({blockId:r,blockType:f._block,status:"unchanged",fromIndex:b,toIndex:d}):w.length>0?l.push({blockId:r,blockType:f._block,status:"changed",fromIndex:b,toIndex:d,propDiffs:w}):l.push({blockId:r,blockType:f._block,status:"moved",fromIndex:b,toIndex:d})}for(let[r,{block:f,index:d}]of o)a.has(r)||l.push({blockId:r,blockType:f._block,status:"removed",fromIndex:d});return l}0&&(module.exports={WORKFLOW_STATES,defineBlock,diffBlocks,diffField,diffFields,diffStringValues,diffText,getVersionableOptions,versionable,workflowable});
|
package/dist/index.d.cts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { Behavior, NumberField, DateField, SelectField, TextField, FieldConfig } from '@murumets-ee/entity';
|
|
2
|
-
import { b as VersionableOptions, B as BlockDefinition } from './types-BYeiE1ie.cjs';
|
|
3
|
-
export { C as ContentConfig, D as DraftEntry, I as InferBlockData, c as InferBlocksUnion, d as LocaleConfig, e as LockInfo, f as TranslationFieldStatus, a as TranslationReport, T as TranslationStatus, V as VersionEntry } from './types-BYeiE1ie.cjs';
|
|
4
|
-
import { B as BlockDiffEntry, F as FieldDiff, D as DiffSegment } from './types-Cr0ifLn_.cjs';
|
|
5
|
-
export { a as BlockDiffStatus, P as PropDiff } from './types-Cr0ifLn_.cjs';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Versionable behavior — full version history with snapshots.
|
|
9
|
-
*
|
|
10
|
-
* Extends the concept of revisionable() (which only tracks a counter)
|
|
11
|
-
* with actual version snapshots stored in {entity}_versions table.
|
|
12
|
-
*
|
|
13
|
-
* The behavior itself adds fields + hooks for version tracking.
|
|
14
|
-
* Actual snapshot persistence happens in ContentClient (which has DB access).
|
|
15
|
-
*
|
|
16
|
-
* Options:
|
|
17
|
-
* - maxPerDoc: Maximum versions kept per document (default: 50)
|
|
18
|
-
* - autosave: Enable smart autosave (default: false)
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
type VersionableFields = {
|
|
22
|
-
_version: NumberField & {
|
|
23
|
-
required: true;
|
|
24
|
-
};
|
|
25
|
-
_versionedAt: DateField;
|
|
26
|
-
};
|
|
27
|
-
declare function versionable(options?: VersionableOptions): Behavior<VersionableFields>;
|
|
28
|
-
/**
|
|
29
|
-
* Extract versionable options from an entity's behaviors
|
|
30
|
-
*/
|
|
31
|
-
declare function getVersionableOptions(behaviors?: Behavior[]): Required<VersionableOptions> | null;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Workflowable behavior — editorial workflow with approval gates.
|
|
35
|
-
*
|
|
36
|
-
* Adds workflow status tracking fields to an entity. Works alongside
|
|
37
|
-
* `publishable()` — the workflow status tracks the editorial pipeline,
|
|
38
|
-
* while publishable's `status` remains the public-facing state.
|
|
39
|
-
*
|
|
40
|
-
* Key invariant: `status` can only transition to 'published' when
|
|
41
|
-
* `_workflowStatus === 'approved'` (unless the user has direct `publish`
|
|
42
|
-
* permission, which bypasses the workflow).
|
|
43
|
-
*
|
|
44
|
-
* Workflow states:
|
|
45
|
-
* - draft → in_review (submit for review, requires 'update')
|
|
46
|
-
* - in_review → approved (approve, requires 'publish')
|
|
47
|
-
* - in_review → rejected (reject with note, requires 'publish')
|
|
48
|
-
* - approved → published (publish, requires 'publish')
|
|
49
|
-
* - rejected → in_review (resubmit, requires 'update')
|
|
50
|
-
* - published → draft (unpublish, requires 'publish')
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
declare const WORKFLOW_STATES: readonly ["draft", "in_review", "approved", "rejected", "published"];
|
|
54
|
-
type WorkflowState = (typeof WORKFLOW_STATES)[number];
|
|
55
|
-
type WorkflowableFields = {
|
|
56
|
-
_workflowStatus: SelectField & {
|
|
57
|
-
required: true;
|
|
58
|
-
};
|
|
59
|
-
_workflowAssignee: TextField;
|
|
60
|
-
_workflowNote: TextField;
|
|
61
|
-
_workflowUpdatedAt: DateField;
|
|
62
|
-
};
|
|
63
|
-
declare function workflowable(): Behavior<WorkflowableFields>;
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Block definition API
|
|
67
|
-
*
|
|
68
|
-
* defineBlock() creates a reusable content block with typed fields.
|
|
69
|
-
* Uses `const F` generic to preserve literal field types for inference.
|
|
70
|
-
*
|
|
71
|
-
* Blocks are NOT entities — they lack independent identity, CRUD, and access control.
|
|
72
|
-
* They exist only as embedded data within a parent entity's blocks field.
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* const HeroBlock = defineBlock({
|
|
76
|
-
* slug: 'hero',
|
|
77
|
-
* label: 'Hero Section',
|
|
78
|
-
* fields: {
|
|
79
|
-
* heading: field.text({ required: true, translatable: true }),
|
|
80
|
-
* background: field.media({ accept: ['image/*'] }),
|
|
81
|
-
* },
|
|
82
|
-
* })
|
|
83
|
-
*/
|
|
84
|
-
|
|
85
|
-
declare function defineBlock<const F extends Record<string, FieldConfig>>(definition: {
|
|
86
|
-
slug: string;
|
|
87
|
-
label: string;
|
|
88
|
-
fields: F;
|
|
89
|
-
}): BlockDefinition<F>;
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Structural diff for Puck block arrays.
|
|
93
|
-
*
|
|
94
|
-
* Blocks are identified by `_id`. The algorithm detects:
|
|
95
|
-
* - Added blocks (new _id in target)
|
|
96
|
-
* - Removed blocks (missing _id in target)
|
|
97
|
-
* - Moved blocks (same _id, different position)
|
|
98
|
-
* - Changed blocks (same _id, different prop values)
|
|
99
|
-
* - Unchanged blocks
|
|
100
|
-
*/
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Compute structural diff between two block arrays.
|
|
104
|
-
*
|
|
105
|
-
* Each block is identified by its `_id` field. Position changes,
|
|
106
|
-
* additions, removals, and prop-level changes are all detected.
|
|
107
|
-
*/
|
|
108
|
-
declare function diffBlocks(fromBlocks: unknown[], toBlocks: unknown[]): BlockDiffEntry[];
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Field-level diff — dispatches to the appropriate diff strategy per field type.
|
|
112
|
-
*/
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Compute diff for a single field, using the field's type to determine
|
|
116
|
-
* the best diff strategy.
|
|
117
|
-
*/
|
|
118
|
-
declare function diffField(fieldName: string, from: unknown, to: unknown, fieldConfig?: FieldConfig): FieldDiff | null;
|
|
119
|
-
/**
|
|
120
|
-
* Diff all fields between two version snapshots.
|
|
121
|
-
* Pass fieldConfigs to get type-aware diffs; without them, types are inferred.
|
|
122
|
-
*/
|
|
123
|
-
declare function diffFields(from: Record<string, unknown>, to: Record<string, unknown>, fieldConfigs?: Record<string, FieldConfig>): FieldDiff[];
|
|
124
|
-
/** Diff two string values and return segments (used by block-diff for string props). */
|
|
125
|
-
declare function diffStringValues(from: unknown, to: unknown): DiffSegment[] | undefined;
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Word-level text diff using a simplified Myers algorithm.
|
|
129
|
-
*
|
|
130
|
-
* Splits text into words (preserving whitespace), computes the longest common
|
|
131
|
-
* subsequence, and returns an array of diff segments.
|
|
132
|
-
*/
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Compute word-level diff between two strings.
|
|
136
|
-
*
|
|
137
|
-
* Uses a simple LCS (dynamic programming) approach which is fine for
|
|
138
|
-
* the text sizes we deal with (entity field values, not source code).
|
|
139
|
-
*/
|
|
140
|
-
declare function diffText(from: string, to: string): DiffSegment[];
|
|
141
|
-
|
|
142
|
-
export { BlockDefinition, BlockDiffEntry, DiffSegment, FieldDiff, VersionableOptions, WORKFLOW_STATES, type WorkflowState, type WorkflowableFields, defineBlock, diffBlocks, diffField, diffFields, diffStringValues, diffText, getVersionableOptions, versionable, workflowable };
|