@blinkk/root-cms 1.4.4 → 1.4.6
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/app.js +8 -3
- package/dist/cli.js +15 -0
- package/dist/{client-98Le1XxF.d.ts → client-c_QAurxr.d.ts} +209 -2
- package/dist/client.d.ts +1 -1
- package/dist/client.js +397 -22
- package/dist/core.d.ts +3 -3
- package/dist/core.js +405 -27
- package/dist/functions.js +401 -26
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.js +401 -26
- package/dist/project.d.ts +1 -1
- package/dist/{schema--Xq_zQlv.d.ts → schema-hlZc-G1f.d.ts} +11 -0
- package/dist/ui/ui.css +1 -1
- package/dist/ui/ui.js +44 -44
- package/package.json +5 -3
package/dist/client.js
CHANGED
|
@@ -1,9 +1,360 @@
|
|
|
1
1
|
// core/client.ts
|
|
2
2
|
import crypto from "node:crypto";
|
|
3
|
+
import {
|
|
4
|
+
FieldValue as FieldValue2,
|
|
5
|
+
Timestamp as Timestamp2
|
|
6
|
+
} from "firebase-admin/firestore";
|
|
7
|
+
|
|
8
|
+
// core/translations-manager.ts
|
|
3
9
|
import {
|
|
4
10
|
FieldValue,
|
|
5
11
|
Timestamp
|
|
6
12
|
} from "firebase-admin/firestore";
|
|
13
|
+
|
|
14
|
+
// shared/strings.ts
|
|
15
|
+
import fnv from "fnv-plus";
|
|
16
|
+
function normalizeStr(str) {
|
|
17
|
+
const lines = str.trim().split("\n").map((line) => removeTrailingWhitespace(line));
|
|
18
|
+
return lines.join("\n");
|
|
19
|
+
}
|
|
20
|
+
function removeTrailingWhitespace(str) {
|
|
21
|
+
return str.trimEnd().replace(/ $/, "");
|
|
22
|
+
}
|
|
23
|
+
function hashStr(str) {
|
|
24
|
+
if (!str || typeof str !== "string") {
|
|
25
|
+
throw new Error("input string is invalid");
|
|
26
|
+
}
|
|
27
|
+
return fnv.fast1a52hex(normalizeStr(str));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// core/translations-manager.ts
|
|
31
|
+
var TRANSLATIONS_DB_PATH_FORMAT = "/Projects/{project}/TranslationsManager/{mode}/Translations";
|
|
32
|
+
var TRANSLATIONS_LOCALE_DOC_DB_PATH_FORMAT = `${TRANSLATIONS_DB_PATH_FORMAT}/{id}:{locale}`;
|
|
33
|
+
var TranslationsManager = class {
|
|
34
|
+
constructor(cmsClient) {
|
|
35
|
+
this.cmsClient = cmsClient;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Saves draft translations for a translations doc id.
|
|
39
|
+
*
|
|
40
|
+
* Example:
|
|
41
|
+
* ```
|
|
42
|
+
* const strings = {
|
|
43
|
+
* 'one': {es: 'uno', fr: 'un'},
|
|
44
|
+
* 'two': {es: 'dos', fr: 'deux'},
|
|
45
|
+
* };
|
|
46
|
+
* await tm.saveTranslations('Pages/index', strings);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
async saveTranslations(id, strings, options) {
|
|
50
|
+
const mode = "draft";
|
|
51
|
+
const localesSet = /* @__PURE__ */ new Set();
|
|
52
|
+
Object.values(strings).forEach((entry) => {
|
|
53
|
+
Object.keys(entry).forEach((locale) => {
|
|
54
|
+
if (locale !== "source") {
|
|
55
|
+
localesSet.add(locale);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
const batch = this.cmsClient.db.batch();
|
|
60
|
+
const locales = Array.from(localesSet);
|
|
61
|
+
locales.forEach((locale) => {
|
|
62
|
+
const updates = {
|
|
63
|
+
id,
|
|
64
|
+
locale,
|
|
65
|
+
sys: {
|
|
66
|
+
modifiedAt: Timestamp.now(),
|
|
67
|
+
modifiedBy: (options == null ? void 0 : options.modifiedBy) || "root-cms-client"
|
|
68
|
+
},
|
|
69
|
+
strings: {}
|
|
70
|
+
};
|
|
71
|
+
if ((options == null ? void 0 : options.tags) && options.tags.length > 0) {
|
|
72
|
+
updates.tags = FieldValue.arrayUnion(...options.tags);
|
|
73
|
+
}
|
|
74
|
+
let numUpdates = 0;
|
|
75
|
+
const hashMap = this.toLocaleDocHashMap(strings, locale);
|
|
76
|
+
Object.entries(hashMap).forEach(([hash, translations]) => {
|
|
77
|
+
Object.entries(translations).forEach(([locale2, translation]) => {
|
|
78
|
+
if (translation) {
|
|
79
|
+
updates.strings[hash] ??= {};
|
|
80
|
+
updates.strings[hash][locale2] = translation;
|
|
81
|
+
numUpdates += 1;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
if (numUpdates > 0) {
|
|
86
|
+
const localeDocPath = buildTranslationsLocaleDocDbPath({
|
|
87
|
+
project: this.cmsClient.projectId,
|
|
88
|
+
mode,
|
|
89
|
+
id,
|
|
90
|
+
locale
|
|
91
|
+
});
|
|
92
|
+
const localeDocRef = this.cmsClient.db.doc(localeDocPath);
|
|
93
|
+
batch.set(localeDocRef, updates, { merge: true });
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
await batch.commit();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Publishes a translations doc.
|
|
100
|
+
*/
|
|
101
|
+
async publishTranslations(id, options) {
|
|
102
|
+
const db = this.cmsClient.db;
|
|
103
|
+
const project = this.cmsClient.projectId;
|
|
104
|
+
const draftPath = buildTranslationsDbPath({ project, mode: "draft" });
|
|
105
|
+
const query = db.collection(draftPath).where("id", "==", id);
|
|
106
|
+
const res = await query.get();
|
|
107
|
+
if (res.size === 0) {
|
|
108
|
+
console.warn(`no translations to publish for ${id}`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const batch = (options == null ? void 0 : options.batch) || db.batch();
|
|
112
|
+
res.docs.forEach((doc) => {
|
|
113
|
+
const translationsLocaleDoc = doc.data();
|
|
114
|
+
const sys = {
|
|
115
|
+
...translationsLocaleDoc.sys,
|
|
116
|
+
publishedAt: Timestamp.now(),
|
|
117
|
+
publishedBy: (options == null ? void 0 : options.publishedBy) || "root-cms-client"
|
|
118
|
+
};
|
|
119
|
+
batch.update(doc.ref, { sys });
|
|
120
|
+
const publishedDocPath = buildTranslationsLocaleDocDbPath({
|
|
121
|
+
project,
|
|
122
|
+
mode: "published",
|
|
123
|
+
id: translationsLocaleDoc.id,
|
|
124
|
+
locale: translationsLocaleDoc.locale
|
|
125
|
+
});
|
|
126
|
+
const publishedDocRef = db.doc(publishedDocPath);
|
|
127
|
+
batch.set(publishedDocRef, { ...translationsLocaleDoc, sys });
|
|
128
|
+
});
|
|
129
|
+
const shouldCommitBatch = !(options == null ? void 0 : options.batch);
|
|
130
|
+
if (shouldCommitBatch) {
|
|
131
|
+
await batch.commit();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Fetches translations from one or more translations docs in the translations
|
|
136
|
+
* manager.
|
|
137
|
+
*
|
|
138
|
+
* Example:
|
|
139
|
+
* ```
|
|
140
|
+
* await tm.loadTranslations();
|
|
141
|
+
* // =>
|
|
142
|
+
* // {
|
|
143
|
+
* // "one": {"es": "uno", "fr": "un"},
|
|
144
|
+
* // "two": {"es": "dos", "fr": "deux"}
|
|
145
|
+
* // }
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* To load a specific set of translations docs by id:
|
|
149
|
+
* ```
|
|
150
|
+
* const translationsToLoad = ['Global/strings', 'Global/header', 'Global/footer', 'Pages/index'];
|
|
151
|
+
* await tm.loadTranslations({ids: translationsToLoad});
|
|
152
|
+
* // =>
|
|
153
|
+
* // {
|
|
154
|
+
* // "one": {"es": "uno", "fr": "un"},
|
|
155
|
+
* // "two": {"es": "dos", "fr": "deux"}
|
|
156
|
+
* // }
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* To load a subset of locales (more performant):
|
|
160
|
+
* ```
|
|
161
|
+
* await tm.loadTranslations({locales: ['es']});
|
|
162
|
+
* // =>
|
|
163
|
+
* // {
|
|
164
|
+
* // "one": {"es": "uno"},
|
|
165
|
+
* // "two": {"es": "dos"}
|
|
166
|
+
* // }
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
async loadTranslations(options) {
|
|
170
|
+
const mode = (options == null ? void 0 : options.mode) || "published";
|
|
171
|
+
const dbPath = buildTranslationsDbPath({
|
|
172
|
+
project: this.cmsClient.projectId,
|
|
173
|
+
mode
|
|
174
|
+
});
|
|
175
|
+
let query = this.cmsClient.db.collection(dbPath);
|
|
176
|
+
if ((options == null ? void 0 : options.ids) && options.ids.length > 0) {
|
|
177
|
+
query = query.where("id", "in", options.ids);
|
|
178
|
+
}
|
|
179
|
+
if ((options == null ? void 0 : options.tags) && options.tags.length > 0) {
|
|
180
|
+
query = query.where("tags", "array-contains", options.tags);
|
|
181
|
+
}
|
|
182
|
+
if ((options == null ? void 0 : options.locales) && options.locales.length > 0) {
|
|
183
|
+
query = query.where("locale", "in", options.locales);
|
|
184
|
+
}
|
|
185
|
+
const results = await query.get();
|
|
186
|
+
const strings = {};
|
|
187
|
+
results.forEach((result) => {
|
|
188
|
+
const localeDoc = result.data();
|
|
189
|
+
Object.values(localeDoc.strings || {}).forEach((item) => {
|
|
190
|
+
strings[item.source] ??= { source: item.source };
|
|
191
|
+
strings[item.source][localeDoc.locale] = item.translation;
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
return strings;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Fetches translations for a given locale, with optional fallbacks.
|
|
198
|
+
* The return value is a map of source string to translated string.
|
|
199
|
+
*
|
|
200
|
+
* Example:
|
|
201
|
+
* ```
|
|
202
|
+
* await translationsDoc.loadTranslationsForLocale('es');
|
|
203
|
+
* // =>
|
|
204
|
+
* // {
|
|
205
|
+
* // "one": "uno",
|
|
206
|
+
* // "two": "dos",
|
|
207
|
+
* // }
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
async loadTranslationsForLocale(locale, options) {
|
|
211
|
+
const localeSet = /* @__PURE__ */ new Set([
|
|
212
|
+
locale,
|
|
213
|
+
...(options == null ? void 0 : options.fallbackLocales) || []
|
|
214
|
+
]);
|
|
215
|
+
const fallbackLocales = Array.from(localeSet);
|
|
216
|
+
const multiLocaleStrings = await this.loadTranslations({
|
|
217
|
+
mode: options == null ? void 0 : options.mode,
|
|
218
|
+
locales: fallbackLocales
|
|
219
|
+
});
|
|
220
|
+
return this.toSingleLocaleMap(multiLocaleStrings, fallbackLocales);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Converts a multi-locale translations map to a flat single-locale map,
|
|
224
|
+
* with optional support for fallback locales.
|
|
225
|
+
*
|
|
226
|
+
* ```
|
|
227
|
+
* const multiLocaleStrings = {
|
|
228
|
+
* 'one': {es: 'uno', fr: 'un'},
|
|
229
|
+
* 'two': {es: 'dos', fr: 'deux'}
|
|
230
|
+
* };
|
|
231
|
+
* translationsDoc.toSingleLocaleMap(multiLocaleStrings, ['es']);
|
|
232
|
+
* // =>
|
|
233
|
+
* // {
|
|
234
|
+
* // "one": "uno",
|
|
235
|
+
* // "two": "dos",
|
|
236
|
+
* // }
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
toSingleLocaleMap(multiLocaleStrings, fallbackLocales) {
|
|
240
|
+
const singleLocaleStrings = {};
|
|
241
|
+
Object.entries(multiLocaleStrings).forEach(([source, translations]) => {
|
|
242
|
+
let translation = source;
|
|
243
|
+
for (const locale of fallbackLocales) {
|
|
244
|
+
if (translations[locale]) {
|
|
245
|
+
translation = translations[locale];
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
singleLocaleStrings[source] = translation;
|
|
250
|
+
});
|
|
251
|
+
return singleLocaleStrings;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Converts a multi-locale translations map to a single-locale hashed version,
|
|
255
|
+
* used for storage in in the DB.
|
|
256
|
+
*
|
|
257
|
+
* ```
|
|
258
|
+
* const multiLocaleStrings = {
|
|
259
|
+
* 'one': {es: 'uno', fr: 'un'},
|
|
260
|
+
* 'two': {es: 'dos', fr: 'deux'}
|
|
261
|
+
* };
|
|
262
|
+
* translationsDoc.toLocaleDocHashMap(multiLocaleStrings, 'es');
|
|
263
|
+
* // =>
|
|
264
|
+
* // {
|
|
265
|
+
* // "<hash1>": {"source": "one", "translation": "uno"},
|
|
266
|
+
* // "<hash2>": {"source": "two", "translation": "dos"},
|
|
267
|
+
* // }
|
|
268
|
+
* ```
|
|
269
|
+
*
|
|
270
|
+
* One reason for using hashes is because the DB has limits on the number of
|
|
271
|
+
* chars that can be used as the "key" in a object map.
|
|
272
|
+
*/
|
|
273
|
+
toLocaleDocHashMap(multiLocaleStrings, locale) {
|
|
274
|
+
const hashMap = {};
|
|
275
|
+
Object.entries(multiLocaleStrings).forEach(([source, translations]) => {
|
|
276
|
+
const translation = translations[locale];
|
|
277
|
+
if (translation) {
|
|
278
|
+
const hash = hashStr(source);
|
|
279
|
+
hashMap[hash] = { source, translation };
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
return hashMap;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Import translations from the v1 system to the TranslationsManager.
|
|
286
|
+
*/
|
|
287
|
+
async importTranslationsFromV1() {
|
|
288
|
+
var _a;
|
|
289
|
+
const projectId = this.cmsClient.projectId;
|
|
290
|
+
const db = this.cmsClient.db;
|
|
291
|
+
const dbPath = `Projects/${projectId}/Translations`;
|
|
292
|
+
const query = db.collection(dbPath);
|
|
293
|
+
const querySnapshot = await query.get();
|
|
294
|
+
if (querySnapshot.size === 0) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
console.log(
|
|
298
|
+
"[root cms] importing v1 Translations to v2 TranslationsManager"
|
|
299
|
+
);
|
|
300
|
+
const translationsDocs = {};
|
|
301
|
+
querySnapshot.forEach((doc) => {
|
|
302
|
+
const translation = doc.data();
|
|
303
|
+
const source = this.cmsClient.normalizeString(translation.source);
|
|
304
|
+
delete translation.source;
|
|
305
|
+
const tags = translation.tags || [];
|
|
306
|
+
delete translation.tags;
|
|
307
|
+
for (const tag of tags) {
|
|
308
|
+
if (tag.includes("/")) {
|
|
309
|
+
const translationsId = tag;
|
|
310
|
+
translationsDocs[translationsId] ??= {
|
|
311
|
+
id: translationsId,
|
|
312
|
+
tags,
|
|
313
|
+
strings: {}
|
|
314
|
+
};
|
|
315
|
+
translationsDocs[translationsId].strings[source] = translation;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
if (Object.keys(translationsDocs).length === 0) {
|
|
320
|
+
console.log("[root cms] no v1 translations to save");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
for (const docId in translationsDocs) {
|
|
324
|
+
const [collection, slug] = docId.split("/");
|
|
325
|
+
if (collection && slug) {
|
|
326
|
+
const doc = await this.cmsClient.getDoc(collection, slug, {
|
|
327
|
+
mode: "draft"
|
|
328
|
+
});
|
|
329
|
+
const linkedSheet = (_a = doc == null ? void 0 : doc.sys) == null ? void 0 : _a.l10nSheet;
|
|
330
|
+
if (linkedSheet) {
|
|
331
|
+
translationsDocs[docId].sys.linkedSheet = linkedSheet;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
Object.entries(translationsDocs).forEach(([translationsId, data]) => {
|
|
336
|
+
const len = Object.keys(data.strings).length;
|
|
337
|
+
console.log(`[root cms] saving ${len} string(s) to ${translationsId}...`);
|
|
338
|
+
this.saveTranslations(translationsId, data.strings, {
|
|
339
|
+
tags: data.tags || [translationsId]
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
function buildTranslationsDbPath(options) {
|
|
345
|
+
return TRANSLATIONS_DB_PATH_FORMAT.replace(
|
|
346
|
+
"{project}",
|
|
347
|
+
options.project
|
|
348
|
+
).replace("{mode}", options.mode);
|
|
349
|
+
}
|
|
350
|
+
function buildTranslationsLocaleDocDbPath(options) {
|
|
351
|
+
return TRANSLATIONS_LOCALE_DOC_DB_PATH_FORMAT.replace(
|
|
352
|
+
"{project}",
|
|
353
|
+
options.project
|
|
354
|
+
).replace("{mode}", options.mode).replace("{id}", options.id.replaceAll("/", "--")).replace("{locale}", options.locale);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// core/client.ts
|
|
7
358
|
var RootCMSClient = class {
|
|
8
359
|
constructor(rootConfig) {
|
|
9
360
|
this.rootConfig = rootConfig;
|
|
@@ -57,9 +408,9 @@ var RootCMSClient = class {
|
|
|
57
408
|
slug,
|
|
58
409
|
sys: {
|
|
59
410
|
...draftSys,
|
|
60
|
-
createdAt: draftSys.createdAt ??
|
|
411
|
+
createdAt: draftSys.createdAt ?? Timestamp2.now(),
|
|
61
412
|
createdBy: draftSys.createdBy ?? modifiedBy,
|
|
62
|
-
modifiedAt:
|
|
413
|
+
modifiedAt: Timestamp2.now(),
|
|
63
414
|
modifiedBy,
|
|
64
415
|
locales: (options == null ? void 0 : options.locales) ?? draftSys.locales ?? ["en"]
|
|
65
416
|
},
|
|
@@ -167,7 +518,7 @@ var RootCMSClient = class {
|
|
|
167
518
|
const publishedRef = this.db.doc(
|
|
168
519
|
`${projectCollectionsPath}/${collection}/Published/${slug}`
|
|
169
520
|
);
|
|
170
|
-
const firstPublishedAt = sys.firstPublishedAt ??
|
|
521
|
+
const firstPublishedAt = sys.firstPublishedAt ?? FieldValue2.serverTimestamp();
|
|
171
522
|
const firstPublishedBy = sys.firstPublishedBy ?? publishedBy;
|
|
172
523
|
batch.set(publishedRef, {
|
|
173
524
|
id,
|
|
@@ -178,7 +529,7 @@ var RootCMSClient = class {
|
|
|
178
529
|
...sys,
|
|
179
530
|
firstPublishedAt,
|
|
180
531
|
firstPublishedBy,
|
|
181
|
-
publishedAt:
|
|
532
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
182
533
|
publishedBy
|
|
183
534
|
}
|
|
184
535
|
});
|
|
@@ -186,11 +537,11 @@ var RootCMSClient = class {
|
|
|
186
537
|
batch.delete(scheduledRef);
|
|
187
538
|
batchCount += 1;
|
|
188
539
|
batch.update(draftRef, {
|
|
189
|
-
"sys.scheduledAt":
|
|
190
|
-
"sys.scheduledBy":
|
|
540
|
+
"sys.scheduledAt": FieldValue2.delete(),
|
|
541
|
+
"sys.scheduledBy": FieldValue2.delete(),
|
|
191
542
|
"sys.firstPublishedAt": firstPublishedAt,
|
|
192
543
|
"sys.firstPublishedBy": firstPublishedBy,
|
|
193
|
-
"sys.publishedAt":
|
|
544
|
+
"sys.publishedAt": FieldValue2.serverTimestamp(),
|
|
194
545
|
"sys.publishedBy": publishedBy
|
|
195
546
|
});
|
|
196
547
|
batchCount += 1;
|
|
@@ -264,7 +615,7 @@ var RootCMSClient = class {
|
|
|
264
615
|
...sys,
|
|
265
616
|
firstPublishedAt,
|
|
266
617
|
firstPublishedBy,
|
|
267
|
-
publishedAt:
|
|
618
|
+
publishedAt: FieldValue2.serverTimestamp(),
|
|
268
619
|
publishedBy: scheduledBy || ""
|
|
269
620
|
}
|
|
270
621
|
});
|
|
@@ -272,11 +623,11 @@ var RootCMSClient = class {
|
|
|
272
623
|
batch.delete(scheduledRef);
|
|
273
624
|
batchCount += 1;
|
|
274
625
|
batch.update(draftRef, {
|
|
275
|
-
"sys.scheduledAt":
|
|
276
|
-
"sys.scheduledBy":
|
|
626
|
+
"sys.scheduledAt": FieldValue2.delete(),
|
|
627
|
+
"sys.scheduledBy": FieldValue2.delete(),
|
|
277
628
|
"sys.firstPublishedAt": firstPublishedAt,
|
|
278
629
|
"sys.firstPublishedBy": firstPublishedBy,
|
|
279
|
-
"sys.publishedAt":
|
|
630
|
+
"sys.publishedAt": FieldValue2.serverTimestamp(),
|
|
280
631
|
"sys.publishedBy": scheduledBy || "root-cms-client"
|
|
281
632
|
});
|
|
282
633
|
batchCount += 1;
|
|
@@ -299,17 +650,17 @@ var RootCMSClient = class {
|
|
|
299
650
|
async publishScheduledReleases() {
|
|
300
651
|
const releasesPath = `Projects/${this.projectId}/Releases`;
|
|
301
652
|
const now = Math.ceil((/* @__PURE__ */ new Date()).getTime());
|
|
302
|
-
const query = this.db.collection(releasesPath).where("scheduledAt", "<=",
|
|
653
|
+
const query = this.db.collection(releasesPath).where("scheduledAt", "<=", Timestamp2.fromMillis(now));
|
|
303
654
|
const querySnapshot = await query.get();
|
|
304
655
|
for (const snapshot of querySnapshot.docs) {
|
|
305
656
|
const release = snapshot.data();
|
|
306
657
|
const batch = this.db.batch();
|
|
307
658
|
const publishedBy = release.scheduledBy || "root-cms-client";
|
|
308
659
|
batch.update(snapshot.ref, {
|
|
309
|
-
publishedAt:
|
|
660
|
+
publishedAt: Timestamp2.now(),
|
|
310
661
|
publishedBy,
|
|
311
|
-
scheduledAt:
|
|
312
|
-
scheduledBy:
|
|
662
|
+
scheduledAt: FieldValue2.delete(),
|
|
663
|
+
scheduledBy: FieldValue2.delete()
|
|
313
664
|
});
|
|
314
665
|
await this.publishDocs(release.docIds || [], { publishedBy, batch });
|
|
315
666
|
}
|
|
@@ -321,7 +672,7 @@ var RootCMSClient = class {
|
|
|
321
672
|
var _a;
|
|
322
673
|
if ((_a = doc.sys) == null ? void 0 : _a.publishingLocked) {
|
|
323
674
|
if (doc.sys.publishingLocked.until) {
|
|
324
|
-
const now =
|
|
675
|
+
const now = Timestamp2.now().toMillis();
|
|
325
676
|
const until = doc.sys.publishingLocked.until.toMillis();
|
|
326
677
|
return now < until;
|
|
327
678
|
}
|
|
@@ -329,6 +680,30 @@ var RootCMSClient = class {
|
|
|
329
680
|
}
|
|
330
681
|
return false;
|
|
331
682
|
}
|
|
683
|
+
/**
|
|
684
|
+
* Returns a `TranslationsManager` object for managing translations.
|
|
685
|
+
*
|
|
686
|
+
* To get translations:
|
|
687
|
+
* ```
|
|
688
|
+
* await tm.loadTranslations({
|
|
689
|
+
* ids: ['Global/strings', 'Pages/index'],
|
|
690
|
+
* locales: ['es'],
|
|
691
|
+
* });
|
|
692
|
+
* ```
|
|
693
|
+
*
|
|
694
|
+
* NOTE: The `TranslationsManager` is a v2 feature that will eventually
|
|
695
|
+
* replace the v1 translations system.
|
|
696
|
+
*/
|
|
697
|
+
getTranslationsManager() {
|
|
698
|
+
var _a;
|
|
699
|
+
const cmsPluginOptions = this.cmsPlugin.getConfig();
|
|
700
|
+
if ((_a = cmsPluginOptions.experiments) == null ? void 0 : _a.v2TranslationsManager) {
|
|
701
|
+
throw new Error(
|
|
702
|
+
"`v2TranslationsManager` is not enabled. update root.config.ts and add: `{experiments: {v2TranslationsManager: true}}`"
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
return new TranslationsManager(this);
|
|
706
|
+
}
|
|
332
707
|
/**
|
|
333
708
|
* Loads translations saved in the translations collection, optionally
|
|
334
709
|
* filtered by tag.
|
|
@@ -374,7 +749,7 @@ var RootCMSClient = class {
|
|
|
374
749
|
source: this.normalizeString(source)
|
|
375
750
|
};
|
|
376
751
|
if (tags) {
|
|
377
|
-
data.tags =
|
|
752
|
+
data.tags = FieldValue2.arrayUnion(...tags);
|
|
378
753
|
}
|
|
379
754
|
batch.set(translationRef, data, { merge: true });
|
|
380
755
|
batchCount += 1;
|
|
@@ -445,7 +820,7 @@ var RootCMSClient = class {
|
|
|
445
820
|
const syncedBy = (options == null ? void 0 : options.syncedBy) || "root-cms-client";
|
|
446
821
|
const updatedDataSource = {
|
|
447
822
|
...dataSource,
|
|
448
|
-
syncedAt:
|
|
823
|
+
syncedAt: Timestamp2.now(),
|
|
449
824
|
syncedBy
|
|
450
825
|
};
|
|
451
826
|
const batch = this.db.batch();
|
|
@@ -454,7 +829,7 @@ var RootCMSClient = class {
|
|
|
454
829
|
data
|
|
455
830
|
});
|
|
456
831
|
batch.update(dataSourceDocRef, {
|
|
457
|
-
syncedAt:
|
|
832
|
+
syncedAt: Timestamp2.now(),
|
|
458
833
|
syncedBy
|
|
459
834
|
});
|
|
460
835
|
await batch.commit();
|
|
@@ -479,7 +854,7 @@ var RootCMSClient = class {
|
|
|
479
854
|
const publishedBy = (options == null ? void 0 : options.publishedBy) || "root-cms-client";
|
|
480
855
|
const updatedDataSource = {
|
|
481
856
|
...dataSource,
|
|
482
|
-
publishedAt:
|
|
857
|
+
publishedAt: Timestamp2.now(),
|
|
483
858
|
publishedBy
|
|
484
859
|
};
|
|
485
860
|
const batch = this.db.batch();
|
|
@@ -491,7 +866,7 @@ var RootCMSClient = class {
|
|
|
491
866
|
dataSource: updatedDataSource
|
|
492
867
|
});
|
|
493
868
|
batch.update(dataSourceDocRef, {
|
|
494
|
-
publishedAt:
|
|
869
|
+
publishedAt: Timestamp2.now(),
|
|
495
870
|
publishedBy
|
|
496
871
|
});
|
|
497
872
|
await batch.commit();
|
|
@@ -598,7 +973,7 @@ var RootCMSClient = class {
|
|
|
598
973
|
}
|
|
599
974
|
const data = {
|
|
600
975
|
action,
|
|
601
|
-
timestamp:
|
|
976
|
+
timestamp: Timestamp2.now(),
|
|
602
977
|
by: (options == null ? void 0 : options.by) || "system",
|
|
603
978
|
metadata: (options == null ? void 0 : options.metadata) || {}
|
|
604
979
|
};
|
package/dist/core.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { L as LoadTranslationsOptions, T as TranslationsMap, a as LocaleTranslations } from './client-
|
|
2
|
-
export { A as Action, p as ArrayObject, c as DataSource, d as DataSourceData, e as DataSourceMode, D as Doc, b as DocMode, h as GetCountOptions, G as GetDocOptions, H as HttpMethod, j as ListActionsOptions, g as ListDocsOptions, R as Release, k as RootCMSClient, f as SaveDraftOptions, S as SetDocOptions, i as Translation, U as UserRole, m as getCmsPlugin, l as isRichTextData, q as marshalArray, n as marshalData, o as normalizeData, v as parseDocId, t as toArrayObject, s as translationsForLocale, r as unmarshalArray, u as unmarshalData } from './client-
|
|
1
|
+
import { L as LoadTranslationsOptions, T as TranslationsMap, a as LocaleTranslations } from './client-c_QAurxr.js';
|
|
2
|
+
export { A as Action, p as ArrayObject, c as DataSource, d as DataSourceData, e as DataSourceMode, D as Doc, b as DocMode, h as GetCountOptions, G as GetDocOptions, H as HttpMethod, j as ListActionsOptions, g as ListDocsOptions, w as Locale, M as MultiLocaleTranslationsMap, R as Release, k as RootCMSClient, f as SaveDraftOptions, S as SetDocOptions, E as SingleLocaleTranslationsMap, x as SourceString, y as TranslatedString, i as Translation, z as TranslationsDocMode, C as TranslationsLocaleDocEntry, B as TranslationsLocaleDocHashMap, F as TranslationsManager, U as UserRole, I as buildTranslationsDbPath, J as buildTranslationsLocaleDocDbPath, m as getCmsPlugin, l as isRichTextData, q as marshalArray, n as marshalData, o as normalizeData, v as parseDocId, t as toArrayObject, s as translationsForLocale, r as unmarshalArray, u as unmarshalData } from './client-c_QAurxr.js';
|
|
3
3
|
import { RootConfig } from '@blinkk/root';
|
|
4
4
|
import { Query } from 'firebase-admin/firestore';
|
|
5
|
-
export { s as schema } from './schema
|
|
5
|
+
export { s as schema } from './schema-hlZc-G1f.js';
|
|
6
6
|
import 'firebase-admin/app';
|
|
7
7
|
import 'preact';
|
|
8
8
|
|