@blinkk/root-cms 1.4.6 → 1.4.8
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 +2 -2
- package/dist/{client-c_QAurxr.d.ts → client-AE0BYn69.d.ts} +147 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +285 -3
- package/dist/core.d.ts +3 -3
- package/dist/core.js +285 -3
- package/dist/functions.js +283 -3
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.js +283 -3
- package/dist/project.d.ts +1 -1
- package/dist/{schema-hlZc-G1f.d.ts → schema-NuZy-PDV.d.ts} +4 -0
- package/dist/ui/ui.js +10 -10
- package/package.json +3 -3
package/dist/core.js
CHANGED
|
@@ -396,6 +396,35 @@ var RootCMSClient = class {
|
|
|
396
396
|
}
|
|
397
397
|
return null;
|
|
398
398
|
}
|
|
399
|
+
/**
|
|
400
|
+
* Firestore path for a collection.
|
|
401
|
+
*/
|
|
402
|
+
dbCollectionDocsPath(collectionId, options) {
|
|
403
|
+
let modeCollection = "";
|
|
404
|
+
if (options.mode === "draft") {
|
|
405
|
+
modeCollection = "Drafts";
|
|
406
|
+
} else if (options.mode === "published") {
|
|
407
|
+
modeCollection = "Published";
|
|
408
|
+
} else {
|
|
409
|
+
throw new Error(`unknown mode: ${options.mode}`);
|
|
410
|
+
}
|
|
411
|
+
return `Projects/${this.projectId}/Collections/${collectionId}/${modeCollection}`;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Firestore path for a content doc.
|
|
415
|
+
*/
|
|
416
|
+
dbDocPath(collectionId, slug, options) {
|
|
417
|
+
const collectionDocsPath = this.dbCollectionDocsPath(collectionId, options);
|
|
418
|
+
const normalizedSlug = slug.replaceAll("/", "--");
|
|
419
|
+
return `${collectionDocsPath}/${normalizedSlug}`;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Firestore doc ref for a content doc.
|
|
423
|
+
*/
|
|
424
|
+
dbDocRef(collectionId, slug, options) {
|
|
425
|
+
const docPath = this.dbDocPath(collectionId, slug, options);
|
|
426
|
+
return this.db.doc(docPath);
|
|
427
|
+
}
|
|
399
428
|
/**
|
|
400
429
|
* Saves draft data to a doc.
|
|
401
430
|
*
|
|
@@ -796,6 +825,25 @@ var RootCMSClient = class {
|
|
|
796
825
|
const translationsMap = await this.loadTranslations(options);
|
|
797
826
|
return translationsForLocale(translationsMap, locale);
|
|
798
827
|
}
|
|
828
|
+
/**
|
|
829
|
+
* Firestore path for a translations file.
|
|
830
|
+
*/
|
|
831
|
+
dbTranslationsPath(translationsId, options) {
|
|
832
|
+
const mode = options.mode;
|
|
833
|
+
if (!(mode === "draft" || mode === "published")) {
|
|
834
|
+
throw new Error(`invalid mode: ${mode}`);
|
|
835
|
+
}
|
|
836
|
+
const slug = translationsId.replaceAll("/", "--");
|
|
837
|
+
const dbPath = `Projects/${this.projectId}/TranslationsManager/${mode}/Translations/${slug}`;
|
|
838
|
+
return dbPath;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Firestore doc ref for a translations file.
|
|
842
|
+
*/
|
|
843
|
+
dbTranslationsRef(translationsId, options) {
|
|
844
|
+
const dbPath = this.dbTranslationsPath(translationsId, options);
|
|
845
|
+
return this.db.doc(dbPath);
|
|
846
|
+
}
|
|
799
847
|
/**
|
|
800
848
|
* Returns a data source configuration object.
|
|
801
849
|
*/
|
|
@@ -866,7 +914,8 @@ var RootCMSClient = class {
|
|
|
866
914
|
const batch = this.db.batch();
|
|
867
915
|
batch.set(dataDocRefPublished, {
|
|
868
916
|
dataSource: updatedDataSource,
|
|
869
|
-
data: (dataRes == null ? void 0 : dataRes.data) || null
|
|
917
|
+
data: (dataRes == null ? void 0 : dataRes.data) || null,
|
|
918
|
+
...(dataRes == null ? void 0 : dataRes.headers) ? { headers: dataRes.headers } : {}
|
|
870
919
|
});
|
|
871
920
|
batch.update(dataDocRefDraft, {
|
|
872
921
|
dataSource: updatedDataSource
|
|
@@ -917,14 +966,34 @@ var RootCMSClient = class {
|
|
|
917
966
|
if (!dataSourceId || dataSourceId.includes("/")) {
|
|
918
967
|
throw new Error(`invalid data source id: ${dataSourceId}`);
|
|
919
968
|
}
|
|
920
|
-
const
|
|
921
|
-
const docRef = this.db.doc(dbPath);
|
|
969
|
+
const docRef = this.dbDataSourceDataRef(dataSourceId, { mode });
|
|
922
970
|
const doc = await docRef.get();
|
|
923
971
|
if (doc.exists) {
|
|
924
972
|
return doc.data();
|
|
925
973
|
}
|
|
926
974
|
return null;
|
|
927
975
|
}
|
|
976
|
+
/**
|
|
977
|
+
* Firestore path for a datasource data.
|
|
978
|
+
*/
|
|
979
|
+
dbDataSourceDataPath(dataSourceId, options) {
|
|
980
|
+
if (!dataSourceId || dataSourceId.includes("/")) {
|
|
981
|
+
throw new Error(`invalid data source id: ${dataSourceId}`);
|
|
982
|
+
}
|
|
983
|
+
const mode = options.mode;
|
|
984
|
+
if (!(mode === "draft" || mode === "published")) {
|
|
985
|
+
throw new Error(`invalid mode: ${mode}`);
|
|
986
|
+
}
|
|
987
|
+
const dbPath = `Projects/${this.projectId}/DataSources/${dataSourceId}/Data/${mode}`;
|
|
988
|
+
return dbPath;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Firestore doc ref for a datasource data.
|
|
992
|
+
*/
|
|
993
|
+
dbDataSourceDataRef(dataSourceId, options) {
|
|
994
|
+
const dbPath = this.dbDataSourceDataPath(dataSourceId, options);
|
|
995
|
+
return this.db.doc(dbPath);
|
|
996
|
+
}
|
|
928
997
|
/**
|
|
929
998
|
* Gets the user's role from the project's ACL.
|
|
930
999
|
*/
|
|
@@ -996,6 +1065,13 @@ var RootCMSClient = class {
|
|
|
996
1065
|
}
|
|
997
1066
|
}
|
|
998
1067
|
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Creates a batch request that is capable of fetching one or more docs,
|
|
1070
|
+
* corresponding translations, and dataSources.
|
|
1071
|
+
*/
|
|
1072
|
+
createBatchRequest(options) {
|
|
1073
|
+
return new BatchRequest(this, options);
|
|
1074
|
+
}
|
|
999
1075
|
};
|
|
1000
1076
|
function isRichTextData(data) {
|
|
1001
1077
|
return Boolean(
|
|
@@ -1141,6 +1217,210 @@ function parseDocId(docId) {
|
|
|
1141
1217
|
}
|
|
1142
1218
|
return { collection: collection2, slug };
|
|
1143
1219
|
}
|
|
1220
|
+
var BatchRequest = class {
|
|
1221
|
+
constructor(cmsClient, options) {
|
|
1222
|
+
this.docIds = [];
|
|
1223
|
+
this.dataSourceIds = [];
|
|
1224
|
+
this.queries = [];
|
|
1225
|
+
this.translationsIds = [];
|
|
1226
|
+
this.cmsClient = cmsClient;
|
|
1227
|
+
this.db = cmsClient.db;
|
|
1228
|
+
this.options = options;
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Adds a doc to the batch request.
|
|
1232
|
+
*/
|
|
1233
|
+
addDoc(docId) {
|
|
1234
|
+
this.docIds.push(docId);
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Adds a data source to the batch request.
|
|
1238
|
+
*/
|
|
1239
|
+
addDataSource(dataSourceId) {
|
|
1240
|
+
this.dataSourceIds.push(dataSourceId);
|
|
1241
|
+
}
|
|
1242
|
+
/**
|
|
1243
|
+
* Adds a collection-based query to the batch request.
|
|
1244
|
+
*/
|
|
1245
|
+
addQuery(queryId, collectionId, queryOptions) {
|
|
1246
|
+
this.queries.push({
|
|
1247
|
+
queryId,
|
|
1248
|
+
collectionId,
|
|
1249
|
+
queryOptions
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
/**
|
|
1253
|
+
* Adds a translation file to the request.
|
|
1254
|
+
*/
|
|
1255
|
+
addTranslations(translationsId) {
|
|
1256
|
+
this.translationsIds.push(translationsId);
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Fetches data from the DB.
|
|
1260
|
+
*/
|
|
1261
|
+
async fetch() {
|
|
1262
|
+
const res = new BatchResponse();
|
|
1263
|
+
const promises = [
|
|
1264
|
+
this.fetchDocs(res),
|
|
1265
|
+
this.fetchQueries(res),
|
|
1266
|
+
this.fetchDataSources(res)
|
|
1267
|
+
];
|
|
1268
|
+
if (!this.options.translate && this.translationsIds.length > 0) {
|
|
1269
|
+
promises.push(this.fetchTranslations(res));
|
|
1270
|
+
}
|
|
1271
|
+
await Promise.all(promises);
|
|
1272
|
+
if (this.translationsIds.length > 0) {
|
|
1273
|
+
await this.fetchTranslations(res);
|
|
1274
|
+
}
|
|
1275
|
+
return res;
|
|
1276
|
+
}
|
|
1277
|
+
async fetchDocs(res) {
|
|
1278
|
+
if (this.docIds.length === 0) {
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
const docRefs = this.docIds.map((docId) => {
|
|
1282
|
+
const [collectionId, slug] = docId.split("/");
|
|
1283
|
+
return this.cmsClient.dbDocRef(collectionId, slug, {
|
|
1284
|
+
mode: this.options.mode
|
|
1285
|
+
});
|
|
1286
|
+
});
|
|
1287
|
+
const docs = await this.db.getAll(...docRefs);
|
|
1288
|
+
this.docIds.forEach((docId, i) => {
|
|
1289
|
+
const doc = docs[i];
|
|
1290
|
+
if (!doc.exists) {
|
|
1291
|
+
console.warn(`doc "${docId}" does not exist`);
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
const docData = unmarshalData(doc.data());
|
|
1295
|
+
res.docs[docId] = docData;
|
|
1296
|
+
if (this.options.translate) {
|
|
1297
|
+
this.addTranslations(docId);
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
async fetchQueries(res) {
|
|
1302
|
+
if (this.queries.length === 0) {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
const mode = this.options.mode;
|
|
1306
|
+
const handleQuery = async (queryItem) => {
|
|
1307
|
+
const docsPath = this.cmsClient.dbCollectionDocsPath(
|
|
1308
|
+
queryItem.collectionId,
|
|
1309
|
+
{ mode }
|
|
1310
|
+
);
|
|
1311
|
+
const queryOptions = queryItem.queryOptions || {};
|
|
1312
|
+
let query = this.db.collection(docsPath);
|
|
1313
|
+
if (queryOptions.limit) {
|
|
1314
|
+
query = query.limit(queryOptions.limit);
|
|
1315
|
+
}
|
|
1316
|
+
if (queryOptions.offset) {
|
|
1317
|
+
query = query.offset(queryOptions.offset);
|
|
1318
|
+
}
|
|
1319
|
+
if (queryOptions.orderBy) {
|
|
1320
|
+
query = query.orderBy(
|
|
1321
|
+
queryOptions.orderBy,
|
|
1322
|
+
queryOptions.orderByDirection
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
if (queryOptions.query) {
|
|
1326
|
+
query = queryOptions.query(query);
|
|
1327
|
+
}
|
|
1328
|
+
const results = await query.get();
|
|
1329
|
+
const docs = [];
|
|
1330
|
+
results.forEach((result) => {
|
|
1331
|
+
const doc = unmarshalData(result.data());
|
|
1332
|
+
docs.push(doc);
|
|
1333
|
+
});
|
|
1334
|
+
res.queries[queryItem.queryId] = docs;
|
|
1335
|
+
};
|
|
1336
|
+
await Promise.all(this.queries.map((queryItem) => handleQuery(queryItem)));
|
|
1337
|
+
}
|
|
1338
|
+
async fetchDataSources(res) {
|
|
1339
|
+
if (this.dataSourceIds.length === 0) {
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
const docRefs = this.dataSourceIds.map((dataSourceId) => {
|
|
1343
|
+
return this.cmsClient.dbDataSourceDataRef(dataSourceId, {
|
|
1344
|
+
mode: this.options.mode
|
|
1345
|
+
});
|
|
1346
|
+
});
|
|
1347
|
+
const docs = await this.db.getAll(...docRefs);
|
|
1348
|
+
this.dataSourceIds.forEach((dataSourceId, i) => {
|
|
1349
|
+
const doc = docs[i];
|
|
1350
|
+
if (!doc.exists) {
|
|
1351
|
+
console.warn(`"data source "${dataSourceId}" does not exist`);
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
res.dataSources[dataSourceId] = doc.data();
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
async fetchTranslations(res) {
|
|
1358
|
+
if (this.translationsIds.length === 0) {
|
|
1359
|
+
return;
|
|
1360
|
+
}
|
|
1361
|
+
const docRefs = this.translationsIds.map((translationsId) => {
|
|
1362
|
+
return this.cmsClient.dbTranslationsRef(translationsId, {
|
|
1363
|
+
mode: this.options.mode
|
|
1364
|
+
});
|
|
1365
|
+
});
|
|
1366
|
+
const docs = await this.db.getAll(...docRefs);
|
|
1367
|
+
this.translationsIds.forEach((translationsId, i) => {
|
|
1368
|
+
const doc = docs[i];
|
|
1369
|
+
if (!doc.exists) {
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
res.translations[translationsId] = doc.data();
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
};
|
|
1376
|
+
var BatchResponse = class {
|
|
1377
|
+
constructor() {
|
|
1378
|
+
this.docs = {};
|
|
1379
|
+
this.queries = {};
|
|
1380
|
+
this.dataSources = {};
|
|
1381
|
+
this.translations = {};
|
|
1382
|
+
}
|
|
1383
|
+
/**
|
|
1384
|
+
* Returns a map of translations for a given locale or locale fallbacks.
|
|
1385
|
+
*
|
|
1386
|
+
* The input is either a single locale (e.g. "de") or an array of locales
|
|
1387
|
+
* representing the fallback tree, e.g. ["en-CA", "en-GB", "en"].
|
|
1388
|
+
*
|
|
1389
|
+
* TODO(stevenle): support the locale fallback tree.
|
|
1390
|
+
*
|
|
1391
|
+
* The returned value is a flat map of source string to translated string,
|
|
1392
|
+
* e.g.:
|
|
1393
|
+
* {"<source>": "<translation>"}
|
|
1394
|
+
*/
|
|
1395
|
+
getTranslations(locale) {
|
|
1396
|
+
const translationsMap = this.getTranslationsMap();
|
|
1397
|
+
const translations = translationsForLocale(translationsMap, locale);
|
|
1398
|
+
return translations;
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* Merges the strings from all translations files retrieved in the request.
|
|
1402
|
+
* The returned value is a map of string to translations, e.g.:
|
|
1403
|
+
*
|
|
1404
|
+
* {"<hash>": {"source": "<source>", "<locale>": "<translation>"}}
|
|
1405
|
+
*/
|
|
1406
|
+
getTranslationsMap() {
|
|
1407
|
+
const translationsDocs = Object.values(this.translations).reverse();
|
|
1408
|
+
const translationsMap = {};
|
|
1409
|
+
for (const translationsDoc of translationsDocs) {
|
|
1410
|
+
const strings = translationsDoc.strings || {};
|
|
1411
|
+
for (const hash in strings) {
|
|
1412
|
+
const translations = strings[hash];
|
|
1413
|
+
translationsMap[hash] ??= { source: translations.source };
|
|
1414
|
+
for (const locale in translations) {
|
|
1415
|
+
if (locale !== "source" && translations[locale]) {
|
|
1416
|
+
translationsMap[hash][locale] = translations[locale];
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
return translationsMap;
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1144
1424
|
|
|
1145
1425
|
// core/runtime.ts
|
|
1146
1426
|
import { FieldValue as FieldValue3 } from "firebase-admin/firestore";
|
|
@@ -1386,6 +1666,8 @@ function defineCollection(collection2) {
|
|
|
1386
1666
|
}
|
|
1387
1667
|
var collection = defineCollection;
|
|
1388
1668
|
export {
|
|
1669
|
+
BatchRequest,
|
|
1670
|
+
BatchResponse,
|
|
1389
1671
|
RootCMSClient,
|
|
1390
1672
|
TranslationsManager,
|
|
1391
1673
|
buildTranslationsDbPath,
|
package/dist/functions.js
CHANGED
|
@@ -395,6 +395,35 @@ var RootCMSClient = class {
|
|
|
395
395
|
}
|
|
396
396
|
return null;
|
|
397
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Firestore path for a collection.
|
|
400
|
+
*/
|
|
401
|
+
dbCollectionDocsPath(collectionId, options) {
|
|
402
|
+
let modeCollection = "";
|
|
403
|
+
if (options.mode === "draft") {
|
|
404
|
+
modeCollection = "Drafts";
|
|
405
|
+
} else if (options.mode === "published") {
|
|
406
|
+
modeCollection = "Published";
|
|
407
|
+
} else {
|
|
408
|
+
throw new Error(`unknown mode: ${options.mode}`);
|
|
409
|
+
}
|
|
410
|
+
return `Projects/${this.projectId}/Collections/${collectionId}/${modeCollection}`;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Firestore path for a content doc.
|
|
414
|
+
*/
|
|
415
|
+
dbDocPath(collectionId, slug, options) {
|
|
416
|
+
const collectionDocsPath = this.dbCollectionDocsPath(collectionId, options);
|
|
417
|
+
const normalizedSlug = slug.replaceAll("/", "--");
|
|
418
|
+
return `${collectionDocsPath}/${normalizedSlug}`;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Firestore doc ref for a content doc.
|
|
422
|
+
*/
|
|
423
|
+
dbDocRef(collectionId, slug, options) {
|
|
424
|
+
const docPath = this.dbDocPath(collectionId, slug, options);
|
|
425
|
+
return this.db.doc(docPath);
|
|
426
|
+
}
|
|
398
427
|
/**
|
|
399
428
|
* Saves draft data to a doc.
|
|
400
429
|
*
|
|
@@ -795,6 +824,25 @@ var RootCMSClient = class {
|
|
|
795
824
|
const translationsMap = await this.loadTranslations(options);
|
|
796
825
|
return translationsForLocale(translationsMap, locale);
|
|
797
826
|
}
|
|
827
|
+
/**
|
|
828
|
+
* Firestore path for a translations file.
|
|
829
|
+
*/
|
|
830
|
+
dbTranslationsPath(translationsId, options) {
|
|
831
|
+
const mode = options.mode;
|
|
832
|
+
if (!(mode === "draft" || mode === "published")) {
|
|
833
|
+
throw new Error(`invalid mode: ${mode}`);
|
|
834
|
+
}
|
|
835
|
+
const slug = translationsId.replaceAll("/", "--");
|
|
836
|
+
const dbPath = `Projects/${this.projectId}/TranslationsManager/${mode}/Translations/${slug}`;
|
|
837
|
+
return dbPath;
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Firestore doc ref for a translations file.
|
|
841
|
+
*/
|
|
842
|
+
dbTranslationsRef(translationsId, options) {
|
|
843
|
+
const dbPath = this.dbTranslationsPath(translationsId, options);
|
|
844
|
+
return this.db.doc(dbPath);
|
|
845
|
+
}
|
|
798
846
|
/**
|
|
799
847
|
* Returns a data source configuration object.
|
|
800
848
|
*/
|
|
@@ -865,7 +913,8 @@ var RootCMSClient = class {
|
|
|
865
913
|
const batch = this.db.batch();
|
|
866
914
|
batch.set(dataDocRefPublished, {
|
|
867
915
|
dataSource: updatedDataSource,
|
|
868
|
-
data: (dataRes == null ? void 0 : dataRes.data) || null
|
|
916
|
+
data: (dataRes == null ? void 0 : dataRes.data) || null,
|
|
917
|
+
...(dataRes == null ? void 0 : dataRes.headers) ? { headers: dataRes.headers } : {}
|
|
869
918
|
});
|
|
870
919
|
batch.update(dataDocRefDraft, {
|
|
871
920
|
dataSource: updatedDataSource
|
|
@@ -916,14 +965,34 @@ var RootCMSClient = class {
|
|
|
916
965
|
if (!dataSourceId || dataSourceId.includes("/")) {
|
|
917
966
|
throw new Error(`invalid data source id: ${dataSourceId}`);
|
|
918
967
|
}
|
|
919
|
-
const
|
|
920
|
-
const docRef = this.db.doc(dbPath);
|
|
968
|
+
const docRef = this.dbDataSourceDataRef(dataSourceId, { mode });
|
|
921
969
|
const doc = await docRef.get();
|
|
922
970
|
if (doc.exists) {
|
|
923
971
|
return doc.data();
|
|
924
972
|
}
|
|
925
973
|
return null;
|
|
926
974
|
}
|
|
975
|
+
/**
|
|
976
|
+
* Firestore path for a datasource data.
|
|
977
|
+
*/
|
|
978
|
+
dbDataSourceDataPath(dataSourceId, options) {
|
|
979
|
+
if (!dataSourceId || dataSourceId.includes("/")) {
|
|
980
|
+
throw new Error(`invalid data source id: ${dataSourceId}`);
|
|
981
|
+
}
|
|
982
|
+
const mode = options.mode;
|
|
983
|
+
if (!(mode === "draft" || mode === "published")) {
|
|
984
|
+
throw new Error(`invalid mode: ${mode}`);
|
|
985
|
+
}
|
|
986
|
+
const dbPath = `Projects/${this.projectId}/DataSources/${dataSourceId}/Data/${mode}`;
|
|
987
|
+
return dbPath;
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Firestore doc ref for a datasource data.
|
|
991
|
+
*/
|
|
992
|
+
dbDataSourceDataRef(dataSourceId, options) {
|
|
993
|
+
const dbPath = this.dbDataSourceDataPath(dataSourceId, options);
|
|
994
|
+
return this.db.doc(dbPath);
|
|
995
|
+
}
|
|
927
996
|
/**
|
|
928
997
|
* Gets the user's role from the project's ACL.
|
|
929
998
|
*/
|
|
@@ -995,6 +1064,13 @@ var RootCMSClient = class {
|
|
|
995
1064
|
}
|
|
996
1065
|
}
|
|
997
1066
|
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Creates a batch request that is capable of fetching one or more docs,
|
|
1069
|
+
* corresponding translations, and dataSources.
|
|
1070
|
+
*/
|
|
1071
|
+
createBatchRequest(options) {
|
|
1072
|
+
return new BatchRequest(this, options);
|
|
1073
|
+
}
|
|
998
1074
|
};
|
|
999
1075
|
function isRichTextData(data) {
|
|
1000
1076
|
return Boolean(
|
|
@@ -1129,6 +1205,210 @@ function parseDocId(docId) {
|
|
|
1129
1205
|
}
|
|
1130
1206
|
return { collection, slug };
|
|
1131
1207
|
}
|
|
1208
|
+
var BatchRequest = class {
|
|
1209
|
+
constructor(cmsClient, options) {
|
|
1210
|
+
this.docIds = [];
|
|
1211
|
+
this.dataSourceIds = [];
|
|
1212
|
+
this.queries = [];
|
|
1213
|
+
this.translationsIds = [];
|
|
1214
|
+
this.cmsClient = cmsClient;
|
|
1215
|
+
this.db = cmsClient.db;
|
|
1216
|
+
this.options = options;
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Adds a doc to the batch request.
|
|
1220
|
+
*/
|
|
1221
|
+
addDoc(docId) {
|
|
1222
|
+
this.docIds.push(docId);
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Adds a data source to the batch request.
|
|
1226
|
+
*/
|
|
1227
|
+
addDataSource(dataSourceId) {
|
|
1228
|
+
this.dataSourceIds.push(dataSourceId);
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Adds a collection-based query to the batch request.
|
|
1232
|
+
*/
|
|
1233
|
+
addQuery(queryId, collectionId, queryOptions) {
|
|
1234
|
+
this.queries.push({
|
|
1235
|
+
queryId,
|
|
1236
|
+
collectionId,
|
|
1237
|
+
queryOptions
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Adds a translation file to the request.
|
|
1242
|
+
*/
|
|
1243
|
+
addTranslations(translationsId) {
|
|
1244
|
+
this.translationsIds.push(translationsId);
|
|
1245
|
+
}
|
|
1246
|
+
/**
|
|
1247
|
+
* Fetches data from the DB.
|
|
1248
|
+
*/
|
|
1249
|
+
async fetch() {
|
|
1250
|
+
const res = new BatchResponse();
|
|
1251
|
+
const promises = [
|
|
1252
|
+
this.fetchDocs(res),
|
|
1253
|
+
this.fetchQueries(res),
|
|
1254
|
+
this.fetchDataSources(res)
|
|
1255
|
+
];
|
|
1256
|
+
if (!this.options.translate && this.translationsIds.length > 0) {
|
|
1257
|
+
promises.push(this.fetchTranslations(res));
|
|
1258
|
+
}
|
|
1259
|
+
await Promise.all(promises);
|
|
1260
|
+
if (this.translationsIds.length > 0) {
|
|
1261
|
+
await this.fetchTranslations(res);
|
|
1262
|
+
}
|
|
1263
|
+
return res;
|
|
1264
|
+
}
|
|
1265
|
+
async fetchDocs(res) {
|
|
1266
|
+
if (this.docIds.length === 0) {
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
const docRefs = this.docIds.map((docId) => {
|
|
1270
|
+
const [collectionId, slug] = docId.split("/");
|
|
1271
|
+
return this.cmsClient.dbDocRef(collectionId, slug, {
|
|
1272
|
+
mode: this.options.mode
|
|
1273
|
+
});
|
|
1274
|
+
});
|
|
1275
|
+
const docs = await this.db.getAll(...docRefs);
|
|
1276
|
+
this.docIds.forEach((docId, i) => {
|
|
1277
|
+
const doc = docs[i];
|
|
1278
|
+
if (!doc.exists) {
|
|
1279
|
+
console.warn(`doc "${docId}" does not exist`);
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
const docData = unmarshalData(doc.data());
|
|
1283
|
+
res.docs[docId] = docData;
|
|
1284
|
+
if (this.options.translate) {
|
|
1285
|
+
this.addTranslations(docId);
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
async fetchQueries(res) {
|
|
1290
|
+
if (this.queries.length === 0) {
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
const mode = this.options.mode;
|
|
1294
|
+
const handleQuery = async (queryItem) => {
|
|
1295
|
+
const docsPath = this.cmsClient.dbCollectionDocsPath(
|
|
1296
|
+
queryItem.collectionId,
|
|
1297
|
+
{ mode }
|
|
1298
|
+
);
|
|
1299
|
+
const queryOptions = queryItem.queryOptions || {};
|
|
1300
|
+
let query = this.db.collection(docsPath);
|
|
1301
|
+
if (queryOptions.limit) {
|
|
1302
|
+
query = query.limit(queryOptions.limit);
|
|
1303
|
+
}
|
|
1304
|
+
if (queryOptions.offset) {
|
|
1305
|
+
query = query.offset(queryOptions.offset);
|
|
1306
|
+
}
|
|
1307
|
+
if (queryOptions.orderBy) {
|
|
1308
|
+
query = query.orderBy(
|
|
1309
|
+
queryOptions.orderBy,
|
|
1310
|
+
queryOptions.orderByDirection
|
|
1311
|
+
);
|
|
1312
|
+
}
|
|
1313
|
+
if (queryOptions.query) {
|
|
1314
|
+
query = queryOptions.query(query);
|
|
1315
|
+
}
|
|
1316
|
+
const results = await query.get();
|
|
1317
|
+
const docs = [];
|
|
1318
|
+
results.forEach((result) => {
|
|
1319
|
+
const doc = unmarshalData(result.data());
|
|
1320
|
+
docs.push(doc);
|
|
1321
|
+
});
|
|
1322
|
+
res.queries[queryItem.queryId] = docs;
|
|
1323
|
+
};
|
|
1324
|
+
await Promise.all(this.queries.map((queryItem) => handleQuery(queryItem)));
|
|
1325
|
+
}
|
|
1326
|
+
async fetchDataSources(res) {
|
|
1327
|
+
if (this.dataSourceIds.length === 0) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
const docRefs = this.dataSourceIds.map((dataSourceId) => {
|
|
1331
|
+
return this.cmsClient.dbDataSourceDataRef(dataSourceId, {
|
|
1332
|
+
mode: this.options.mode
|
|
1333
|
+
});
|
|
1334
|
+
});
|
|
1335
|
+
const docs = await this.db.getAll(...docRefs);
|
|
1336
|
+
this.dataSourceIds.forEach((dataSourceId, i) => {
|
|
1337
|
+
const doc = docs[i];
|
|
1338
|
+
if (!doc.exists) {
|
|
1339
|
+
console.warn(`"data source "${dataSourceId}" does not exist`);
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
res.dataSources[dataSourceId] = doc.data();
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
async fetchTranslations(res) {
|
|
1346
|
+
if (this.translationsIds.length === 0) {
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
const docRefs = this.translationsIds.map((translationsId) => {
|
|
1350
|
+
return this.cmsClient.dbTranslationsRef(translationsId, {
|
|
1351
|
+
mode: this.options.mode
|
|
1352
|
+
});
|
|
1353
|
+
});
|
|
1354
|
+
const docs = await this.db.getAll(...docRefs);
|
|
1355
|
+
this.translationsIds.forEach((translationsId, i) => {
|
|
1356
|
+
const doc = docs[i];
|
|
1357
|
+
if (!doc.exists) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
res.translations[translationsId] = doc.data();
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
};
|
|
1364
|
+
var BatchResponse = class {
|
|
1365
|
+
constructor() {
|
|
1366
|
+
this.docs = {};
|
|
1367
|
+
this.queries = {};
|
|
1368
|
+
this.dataSources = {};
|
|
1369
|
+
this.translations = {};
|
|
1370
|
+
}
|
|
1371
|
+
/**
|
|
1372
|
+
* Returns a map of translations for a given locale or locale fallbacks.
|
|
1373
|
+
*
|
|
1374
|
+
* The input is either a single locale (e.g. "de") or an array of locales
|
|
1375
|
+
* representing the fallback tree, e.g. ["en-CA", "en-GB", "en"].
|
|
1376
|
+
*
|
|
1377
|
+
* TODO(stevenle): support the locale fallback tree.
|
|
1378
|
+
*
|
|
1379
|
+
* The returned value is a flat map of source string to translated string,
|
|
1380
|
+
* e.g.:
|
|
1381
|
+
* {"<source>": "<translation>"}
|
|
1382
|
+
*/
|
|
1383
|
+
getTranslations(locale) {
|
|
1384
|
+
const translationsMap = this.getTranslationsMap();
|
|
1385
|
+
const translations = translationsForLocale(translationsMap, locale);
|
|
1386
|
+
return translations;
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* Merges the strings from all translations files retrieved in the request.
|
|
1390
|
+
* The returned value is a map of string to translations, e.g.:
|
|
1391
|
+
*
|
|
1392
|
+
* {"<hash>": {"source": "<source>", "<locale>": "<translation>"}}
|
|
1393
|
+
*/
|
|
1394
|
+
getTranslationsMap() {
|
|
1395
|
+
const translationsDocs = Object.values(this.translations).reverse();
|
|
1396
|
+
const translationsMap = {};
|
|
1397
|
+
for (const translationsDoc of translationsDocs) {
|
|
1398
|
+
const strings = translationsDoc.strings || {};
|
|
1399
|
+
for (const hash in strings) {
|
|
1400
|
+
const translations = strings[hash];
|
|
1401
|
+
translationsMap[hash] ??= { source: translations.source };
|
|
1402
|
+
for (const locale in translations) {
|
|
1403
|
+
if (locale !== "source" && translations[locale]) {
|
|
1404
|
+
translationsMap[hash][locale] = translations[locale];
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
return translationsMap;
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1132
1412
|
|
|
1133
1413
|
// core/versions.ts
|
|
1134
1414
|
import path from "node:path";
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import '@blinkk/root';
|
|
2
2
|
import 'firebase-admin/app';
|
|
3
3
|
import 'firebase-admin/firestore';
|
|
4
|
-
export {
|
|
4
|
+
export { X as CMSAIConfig, _ as CMSPlugin, Z as CMSPluginOptions, Y as CMSSidebarTool, W as CMSUser, $ as cmsPlugin } from './client-AE0BYn69.js';
|