@hot-updater/firebase 1.0.0-rc.0 → 1.0.0-rc.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/dist/firebase/functions/index.cjs +1255 -841
- package/dist/firebase/public/firestore.indexes.json +27 -37
- package/dist/iac/index.cjs +374 -173
- package/dist/iac/index.d.cts +1 -5
- package/dist/iac/index.d.mts +1 -5
- package/dist/iac/index.mjs +368 -167
- package/dist/index.cjs +183 -43
- package/dist/index.d.cts +2 -4
- package/dist/index.d.mts +1 -3
- package/dist/index.mjs +184 -44
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -6,6 +6,7 @@ let firebase_admin_firestore = require("firebase-admin/firestore");
|
|
|
6
6
|
let firebase_admin_storage = require("firebase-admin/storage");
|
|
7
7
|
//#region src/firebaseDatabaseParserShared.ts
|
|
8
8
|
var FirebaseDatabaseDataError = class extends Error {
|
|
9
|
+
source;
|
|
9
10
|
name = "FirebaseDatabaseDataError";
|
|
10
11
|
constructor(source) {
|
|
11
12
|
super(`Invalid Firebase database data at "${source}".`);
|
|
@@ -117,6 +118,24 @@ const parseFirebaseBundleEventRow = (value, source) => {
|
|
|
117
118
|
received_at_ms: number(property(input, "received_at_ms"), source)
|
|
118
119
|
};
|
|
119
120
|
};
|
|
121
|
+
const parseFirebaseInsightsInstallationRow = (value, source) => {
|
|
122
|
+
const input = record(value, source);
|
|
123
|
+
const type = string(property(input, "type"), source);
|
|
124
|
+
if (type !== "UPDATE_APPLIED" && type !== "RECOVERED" && type !== "RELEASE_ADOPTED" && type !== "UNCHANGED") throw new FirebaseDatabaseDataError(source);
|
|
125
|
+
return {
|
|
126
|
+
id: string(property(input, "id"), source),
|
|
127
|
+
type,
|
|
128
|
+
install_id: string(property(input, "install_id"), source),
|
|
129
|
+
user_id: nullableString(property(input, "user_id"), source),
|
|
130
|
+
username: nullableString(property(input, "username"), source),
|
|
131
|
+
to_bundle_id: string(property(input, "to_bundle_id"), source),
|
|
132
|
+
platform: platform(property(input, "platform"), source),
|
|
133
|
+
app_version: string(property(input, "app_version"), source),
|
|
134
|
+
channel: string(property(input, "channel"), source),
|
|
135
|
+
cohort: string(property(input, "cohort"), source),
|
|
136
|
+
received_at_ms: number(property(input, "received_at_ms"), source)
|
|
137
|
+
};
|
|
138
|
+
};
|
|
120
139
|
const parseFirebaseApiKeyRow = (value, source) => {
|
|
121
140
|
const input = record(value, source);
|
|
122
141
|
const role = string(property(input, "role"), source);
|
|
@@ -197,13 +216,15 @@ const matchesCondition = (row, condition) => {
|
|
|
197
216
|
switch (condition.operator ?? "eq") {
|
|
198
217
|
case "eq": {
|
|
199
218
|
if (typeof expected !== "string") return actual === expected;
|
|
200
|
-
const
|
|
219
|
+
const mode = "mode" in condition ? condition.mode : void 0;
|
|
220
|
+
const comparison = normalizeStringComparison(actual, expected, mode);
|
|
201
221
|
return comparison !== null && comparison[0] === comparison[1];
|
|
202
222
|
}
|
|
203
223
|
case "ne": {
|
|
204
224
|
if (actual === null || actual === void 0) return false;
|
|
205
225
|
if (typeof expected !== "string") return actual !== expected;
|
|
206
|
-
const
|
|
226
|
+
const mode = "mode" in condition ? condition.mode : void 0;
|
|
227
|
+
const comparison = normalizeStringComparison(actual, expected, mode);
|
|
207
228
|
return comparison === null || comparison[0] !== comparison[1];
|
|
208
229
|
}
|
|
209
230
|
case "gt":
|
|
@@ -228,17 +249,20 @@ const matchesCondition = (row, condition) => {
|
|
|
228
249
|
}
|
|
229
250
|
case "contains": {
|
|
230
251
|
if (typeof expected !== "string") return false;
|
|
231
|
-
const
|
|
252
|
+
const mode = "mode" in condition ? condition.mode : void 0;
|
|
253
|
+
const comparison = normalizeStringComparison(actual, expected, mode);
|
|
232
254
|
return comparison?.[0].includes(comparison[1]) ?? false;
|
|
233
255
|
}
|
|
234
256
|
case "starts_with": {
|
|
235
257
|
if (typeof expected !== "string") return false;
|
|
236
|
-
const
|
|
258
|
+
const mode = "mode" in condition ? condition.mode : void 0;
|
|
259
|
+
const comparison = normalizeStringComparison(actual, expected, mode);
|
|
237
260
|
return comparison?.[0].startsWith(comparison[1]) ?? false;
|
|
238
261
|
}
|
|
239
262
|
case "ends_with": {
|
|
240
263
|
if (typeof expected !== "string") return false;
|
|
241
|
-
const
|
|
264
|
+
const mode = "mode" in condition ? condition.mode : void 0;
|
|
265
|
+
const comparison = normalizeStringComparison(actual, expected, mode);
|
|
242
266
|
return comparison?.[0].endsWith(comparison[1]) ?? false;
|
|
243
267
|
}
|
|
244
268
|
}
|
|
@@ -283,6 +307,7 @@ const queryFirebaseDatabaseRows = (rows, input) => {
|
|
|
283
307
|
//#endregion
|
|
284
308
|
//#region src/firebaseDatabaseState.ts
|
|
285
309
|
var FirebaseDatabaseConstraintError = class extends Error {
|
|
310
|
+
constraint;
|
|
286
311
|
name = "FirebaseDatabaseConstraintError";
|
|
287
312
|
constructor(constraint) {
|
|
288
313
|
super(`Firebase database constraint failed: ${constraint}`);
|
|
@@ -293,6 +318,7 @@ const cloneFirebaseDatabaseSnapshot = (snapshot) => ({
|
|
|
293
318
|
bundles: new Map(snapshot.bundles),
|
|
294
319
|
bundlePatches: new Map(snapshot.bundlePatches),
|
|
295
320
|
bundleEvents: new Map(snapshot.bundleEvents),
|
|
321
|
+
bundleInstallations: new Map(snapshot.bundleInstallations),
|
|
296
322
|
channels: new Map(snapshot.channels),
|
|
297
323
|
apiKeys: new Map(snapshot.apiKeys),
|
|
298
324
|
releaseCatalogs: new Map(snapshot.releaseCatalogs),
|
|
@@ -322,6 +348,13 @@ const createFirebaseDatabaseState = (snapshot) => ({
|
|
|
322
348
|
requireUnique(snapshot.bundleEvents, input.data.id, input.model);
|
|
323
349
|
snapshot.bundleEvents.set(input.data.id, input.data);
|
|
324
350
|
return input.data;
|
|
351
|
+
case "bundle_installations": {
|
|
352
|
+
const current = snapshot.bundleInstallations.get(input.data.install_id);
|
|
353
|
+
if (current && input.onConflict === "ignore") return current;
|
|
354
|
+
if (current) throw new FirebaseDatabaseConstraintError("bundle_installations.install_id.unique");
|
|
355
|
+
snapshot.bundleInstallations.set(input.data.install_id, input.data);
|
|
356
|
+
return input.data;
|
|
357
|
+
}
|
|
325
358
|
case "releases":
|
|
326
359
|
requireUnique(snapshot.releases, input.data.id, input.model);
|
|
327
360
|
if (!snapshot.channels.has(input.data.channel_id)) throw new FirebaseDatabaseConstraintError("releases.channel_id.foreign-key");
|
|
@@ -351,6 +384,16 @@ const createFirebaseDatabaseState = (snapshot) => ({
|
|
|
351
384
|
}
|
|
352
385
|
},
|
|
353
386
|
async update(input) {
|
|
387
|
+
if (input.model === "bundle_installations") {
|
|
388
|
+
const current = [...snapshot.bundleInstallations.values()].find((row) => matchesFirebaseDatabaseWhere(row, input.where));
|
|
389
|
+
if (!current) return null;
|
|
390
|
+
const updated = {
|
|
391
|
+
...current,
|
|
392
|
+
...input.update
|
|
393
|
+
};
|
|
394
|
+
snapshot.bundleInstallations.set(current.install_id, updated);
|
|
395
|
+
return updated;
|
|
396
|
+
}
|
|
354
397
|
if (input.model === "api_keys") {
|
|
355
398
|
const current = [...snapshot.apiKeys.values()].find((row) => matchesFirebaseDatabaseWhere(row, input.where));
|
|
356
399
|
if (!current) return null;
|
|
@@ -412,6 +455,8 @@ const createFirebaseDatabaseState = (snapshot) => ({
|
|
|
412
455
|
case "bundles": return distinctCount([...snapshot.bundles.values()].filter((row) => matchesFirebaseDatabaseWhere(row, input.where)), input.distinct);
|
|
413
456
|
case "bundle_patches": return distinctCount([...snapshot.bundlePatches.values()].filter((row) => matchesFirebaseDatabaseWhere(row, input.where)), input.distinct);
|
|
414
457
|
case "releases": return distinctCount([...snapshot.releases.values()].filter((row) => matchesFirebaseDatabaseWhere(row, input.where)), input.distinct);
|
|
458
|
+
case "bundle_installations": return distinctCount([...snapshot.bundleInstallations.values()].filter((row) => matchesFirebaseDatabaseWhere(row, input.where)), input.distinct);
|
|
459
|
+
case "bundle_events": return distinctCount([...snapshot.bundleEvents.values()].filter((row) => matchesFirebaseDatabaseWhere(row, input.where)), input.distinct);
|
|
415
460
|
}
|
|
416
461
|
},
|
|
417
462
|
async findOne(input) {
|
|
@@ -422,6 +467,7 @@ const createFirebaseDatabaseState = (snapshot) => ({
|
|
|
422
467
|
case "bundle_patches": return [...snapshot.bundlePatches.values()].find((row) => matchesFirebaseDatabaseWhere(row, input.where)) ?? null;
|
|
423
468
|
case "releases": return [...snapshot.releases.values()].find((row) => matchesFirebaseDatabaseWhere(row, input.where)) ?? null;
|
|
424
469
|
case "release_catalogs": return [...snapshot.releaseCatalogs.values()].find((row) => matchesFirebaseDatabaseWhere(row, input.where)) ?? null;
|
|
470
|
+
case "bundle_installations": return [...snapshot.bundleInstallations.values()].find((row) => matchesFirebaseDatabaseWhere(row, input.where)) ?? null;
|
|
425
471
|
}
|
|
426
472
|
},
|
|
427
473
|
async findMany(input) {
|
|
@@ -429,6 +475,7 @@ const createFirebaseDatabaseState = (snapshot) => ({
|
|
|
429
475
|
case "bundles": return queryFirebaseDatabaseRows([...snapshot.bundles.values()], input);
|
|
430
476
|
case "bundle_patches": return queryFirebaseDatabaseRows([...snapshot.bundlePatches.values()], input);
|
|
431
477
|
case "bundle_events": return queryFirebaseDatabaseRows([...snapshot.bundleEvents.values()], input);
|
|
478
|
+
case "bundle_installations": return queryFirebaseDatabaseRows([...snapshot.bundleInstallations.values()], input);
|
|
432
479
|
case "channels": return queryFirebaseDatabaseRows([...snapshot.channels.values()], input);
|
|
433
480
|
case "api_keys": return queryFirebaseDatabaseRows([...snapshot.apiKeys.values()], input);
|
|
434
481
|
case "releases": return queryFirebaseDatabaseRows([...snapshot.releases.values()], input);
|
|
@@ -441,6 +488,7 @@ const createFirebaseDatabaseState = (snapshot) => ({
|
|
|
441
488
|
const FIREBASE_V1_COLLECTION_NAMES = {
|
|
442
489
|
apiKeys: "hot_updater_v1_api_keys",
|
|
443
490
|
bundleEvents: "hot_updater_v1_bundle_events",
|
|
491
|
+
bundleInstallations: "hot_updater_v1_bundle_installations",
|
|
444
492
|
bundlePatches: "hot_updater_v1_bundle_patches",
|
|
445
493
|
bundles: "hot_updater_v1_bundles",
|
|
446
494
|
channels: "hot_updater_v1_channels",
|
|
@@ -451,6 +499,7 @@ const FIREBASE_V1_COLLECTION_NAMES = {
|
|
|
451
499
|
//#endregion
|
|
452
500
|
//#region src/firebaseDatabasePersistence.ts
|
|
453
501
|
var FirebaseDatabaseAdapterVersionError = class extends Error {
|
|
502
|
+
version;
|
|
454
503
|
name = "FirebaseDatabaseAdapterVersionError";
|
|
455
504
|
constructor(version) {
|
|
456
505
|
super(`Unsupported Firebase database adapter version: ${String(version)}`);
|
|
@@ -461,6 +510,7 @@ const createFirebaseDatabaseCollections = (db) => ({
|
|
|
461
510
|
bundles: db.collection(FIREBASE_V1_COLLECTION_NAMES.bundles),
|
|
462
511
|
bundlePatches: db.collection(FIREBASE_V1_COLLECTION_NAMES.bundlePatches),
|
|
463
512
|
bundleEvents: db.collection(FIREBASE_V1_COLLECTION_NAMES.bundleEvents),
|
|
513
|
+
bundleInstallations: db.collection(FIREBASE_V1_COLLECTION_NAMES.bundleInstallations),
|
|
464
514
|
channels: db.collection(FIREBASE_V1_COLLECTION_NAMES.channels),
|
|
465
515
|
apiKeys: db.collection(FIREBASE_V1_COLLECTION_NAMES.apiKeys),
|
|
466
516
|
releaseCatalogs: db.collection(FIREBASE_V1_COLLECTION_NAMES.releaseCatalogs),
|
|
@@ -469,14 +519,15 @@ const createFirebaseDatabaseCollections = (db) => ({
|
|
|
469
519
|
});
|
|
470
520
|
const firebaseChannelDocumentId = (name) => `name_${Buffer.from(name, "utf8").toString("base64url")}`;
|
|
471
521
|
const firebaseChannelIdDocumentId = (id) => `channel_id_${Buffer.from(id, "utf8").toString("base64url")}`;
|
|
522
|
+
const firebaseInstallationDocumentId = (id) => `install_${Buffer.from(id, "utf8").toString("base64url")}`;
|
|
472
523
|
const requireFirebaseDocumentKey = (model, documentId, row) => {
|
|
473
|
-
if (documentId !== ("id" in row ? row.id : row.scope_key)) throw new FirebaseDatabaseConstraintError(`${model}.id.document-key`);
|
|
524
|
+
if (documentId !== (model === "bundle_installations" ? firebaseInstallationDocumentId(row.install_id) : "id" in row ? row.id : row.scope_key)) throw new FirebaseDatabaseConstraintError(`${model}.id.document-key`);
|
|
474
525
|
return row;
|
|
475
526
|
};
|
|
476
527
|
const documentMap = (model, documents) => {
|
|
477
528
|
const rows = /* @__PURE__ */ new Map();
|
|
478
529
|
for (const { row } of documents) {
|
|
479
|
-
const key = "id" in row ? row.id : row.scope_key;
|
|
530
|
+
const key = model === "bundle_installations" ? row.install_id : "id" in row ? row.id : row.scope_key;
|
|
480
531
|
if (rows.has(key)) throw new FirebaseDatabaseConstraintError(`${model}.id.unique`);
|
|
481
532
|
rows.set(key, row);
|
|
482
533
|
}
|
|
@@ -491,10 +542,6 @@ const patchMap = (snapshot) => documentMap("bundle_patches", snapshot.docs.map((
|
|
|
491
542
|
document,
|
|
492
543
|
row: parseFirebasePatchRow(document.data(), `bundle_patches/${document.id}`)
|
|
493
544
|
})));
|
|
494
|
-
const eventMap = (snapshot) => documentMap("bundle_events", snapshot.docs.map((document) => ({
|
|
495
|
-
document,
|
|
496
|
-
row: parseFirebaseBundleEventRow(document.data(), `bundle_events/${document.id}`)
|
|
497
|
-
})));
|
|
498
545
|
const channelMap = (snapshot) => {
|
|
499
546
|
const rows = /* @__PURE__ */ new Map();
|
|
500
547
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -525,18 +572,18 @@ const toSnapshot = (documents) => {
|
|
|
525
572
|
return {
|
|
526
573
|
bundles: bundleMap(documents[0]),
|
|
527
574
|
bundlePatches: patchMap(documents[1]),
|
|
528
|
-
bundleEvents:
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
575
|
+
bundleEvents: /* @__PURE__ */ new Map(),
|
|
576
|
+
bundleInstallations: /* @__PURE__ */ new Map(),
|
|
577
|
+
channels: channelMap(documents[2]),
|
|
578
|
+
apiKeys: apiKeyMap(documents[3]),
|
|
579
|
+
releases: releaseMap(documents[4]),
|
|
580
|
+
releaseCatalogs: releaseCatalogMap(documents[5])
|
|
533
581
|
};
|
|
534
582
|
};
|
|
535
583
|
const loadFirebaseDatabaseSnapshot = async (collections) => {
|
|
536
|
-
const [bundles, patches,
|
|
584
|
+
const [bundles, patches, channels, apiKeys, releases, releaseCatalogs] = await Promise.all([
|
|
537
585
|
collections.bundles.get(),
|
|
538
586
|
collections.bundlePatches.get(),
|
|
539
|
-
collections.bundleEvents.get(),
|
|
540
587
|
collections.channels.get(),
|
|
541
588
|
collections.apiKeys.get(),
|
|
542
589
|
collections.releases.get(),
|
|
@@ -545,7 +592,6 @@ const loadFirebaseDatabaseSnapshot = async (collections) => {
|
|
|
545
592
|
return toSnapshot([
|
|
546
593
|
bundles,
|
|
547
594
|
patches,
|
|
548
|
-
events,
|
|
549
595
|
channels,
|
|
550
596
|
apiKeys,
|
|
551
597
|
releases,
|
|
@@ -553,10 +599,9 @@ const loadFirebaseDatabaseSnapshot = async (collections) => {
|
|
|
553
599
|
]);
|
|
554
600
|
};
|
|
555
601
|
const loadFirebaseTransactionSnapshot = async (transaction, collections) => {
|
|
556
|
-
const [bundles, patches,
|
|
602
|
+
const [bundles, patches, channels, apiKeys, releases, releaseCatalogs] = await Promise.all([
|
|
557
603
|
transaction.get(collections.bundles),
|
|
558
604
|
transaction.get(collections.bundlePatches),
|
|
559
|
-
transaction.get(collections.bundleEvents),
|
|
560
605
|
transaction.get(collections.channels),
|
|
561
606
|
transaction.get(collections.apiKeys),
|
|
562
607
|
transaction.get(collections.releases),
|
|
@@ -565,7 +610,6 @@ const loadFirebaseTransactionSnapshot = async (transaction, collections) => {
|
|
|
565
610
|
return toSnapshot([
|
|
566
611
|
bundles,
|
|
567
612
|
patches,
|
|
568
|
-
events,
|
|
569
613
|
channels,
|
|
570
614
|
apiKeys,
|
|
571
615
|
releases,
|
|
@@ -591,13 +635,6 @@ const persistFirebaseDatabaseSnapshot = ({ transaction, collections, before, aft
|
|
|
591
635
|
after: after.bundlePatches,
|
|
592
636
|
documentId: (row) => row.id
|
|
593
637
|
});
|
|
594
|
-
persistCollection({
|
|
595
|
-
transaction,
|
|
596
|
-
collection: collections.bundleEvents,
|
|
597
|
-
before: before.bundleEvents,
|
|
598
|
-
after: after.bundleEvents,
|
|
599
|
-
documentId: (row) => row.id
|
|
600
|
-
});
|
|
601
638
|
persistCollection({
|
|
602
639
|
transaction,
|
|
603
640
|
collection: collections.channels,
|
|
@@ -629,7 +666,7 @@ const persistFirebaseDatabaseSnapshot = ({ transaction, collections, before, aft
|
|
|
629
666
|
documentId: (row) => row.scope_key
|
|
630
667
|
});
|
|
631
668
|
};
|
|
632
|
-
const migrateFirebaseDatabase = async (
|
|
669
|
+
const migrateFirebaseDatabase = async (collections) => {
|
|
633
670
|
const versionDocument = collections.settings.doc("database_adapter_version");
|
|
634
671
|
const version = await versionDocument.get();
|
|
635
672
|
const adapterVersion = version.data()?.version;
|
|
@@ -640,7 +677,9 @@ const migrateFirebaseDatabase = async (_db, collections) => {
|
|
|
640
677
|
collections.bundlePatches.limit(1).get(),
|
|
641
678
|
collections.channels.limit(1).get(),
|
|
642
679
|
collections.releases.limit(1).get(),
|
|
643
|
-
collections.releaseCatalogs.limit(1).get()
|
|
680
|
+
collections.releaseCatalogs.limit(1).get(),
|
|
681
|
+
collections.bundleInstallations.limit(1).get(),
|
|
682
|
+
collections.bundleEvents.limit(1).get()
|
|
644
683
|
])).some((snapshot) => !snapshot.empty)) throw new FirebaseDatabaseAdapterVersionError("v0");
|
|
645
684
|
try {
|
|
646
685
|
await versionDocument.create({ version: 4 });
|
|
@@ -655,13 +694,40 @@ const exactId = (input) => {
|
|
|
655
694
|
const [condition] = input.where;
|
|
656
695
|
return condition.field === "id" && (condition.operator === void 0 || condition.operator === "eq") && typeof condition.value === "string" ? condition.value : void 0;
|
|
657
696
|
};
|
|
697
|
+
const exactInstallId = (input) => {
|
|
698
|
+
const condition = input.where?.find(({ field, operator }) => field === "install_id" && (operator === void 0 || operator === "eq"));
|
|
699
|
+
return typeof condition?.value === "string" ? condition.value : void 0;
|
|
700
|
+
};
|
|
701
|
+
const firestoreOperator = (operator) => {
|
|
702
|
+
switch (operator ?? "eq") {
|
|
703
|
+
case "eq": return "==";
|
|
704
|
+
case "ne": return "!=";
|
|
705
|
+
case "gt": return ">";
|
|
706
|
+
case "gte": return ">=";
|
|
707
|
+
case "lt": return "<";
|
|
708
|
+
case "lte": return "<=";
|
|
709
|
+
case "in": return "in";
|
|
710
|
+
case "not_in": return "not-in";
|
|
711
|
+
default: return;
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
const applyFirebaseWhere = (initial, where) => {
|
|
715
|
+
let query = initial;
|
|
716
|
+
for (const condition of where) {
|
|
717
|
+
const operator = firestoreOperator(condition.operator);
|
|
718
|
+
if (condition.connector === "OR" || operator === void 0) throw new FirebaseDatabaseConstraintError("query.unsupported");
|
|
719
|
+
query = query.where(condition.field, operator, condition.value);
|
|
720
|
+
}
|
|
721
|
+
return query;
|
|
722
|
+
};
|
|
658
723
|
const firebaseDatabase = (config) => {
|
|
659
|
-
const
|
|
660
|
-
const
|
|
724
|
+
const implementation = (() => {
|
|
725
|
+
const app = (0, firebase_admin_app.getApps)().length ? (0, firebase_admin_app.getApp)() : (0, firebase_admin_app.initializeApp)(config);
|
|
726
|
+
const db = (0, firebase_admin_firestore.getFirestore)(app);
|
|
661
727
|
const collections = createFirebaseDatabaseCollections(db);
|
|
662
728
|
let migration;
|
|
663
729
|
const ensureMigrated = () => {
|
|
664
|
-
migration ??= migrateFirebaseDatabase(
|
|
730
|
+
migration ??= migrateFirebaseDatabase(collections).catch((error) => {
|
|
665
731
|
migration = void 0;
|
|
666
732
|
throw error;
|
|
667
733
|
});
|
|
@@ -684,14 +750,74 @@ const firebaseDatabase = (config) => {
|
|
|
684
750
|
};
|
|
685
751
|
const read = async (operation) => {
|
|
686
752
|
await ensureMigrated();
|
|
687
|
-
|
|
753
|
+
const snapshot = await loadFirebaseDatabaseSnapshot(collections);
|
|
754
|
+
return operation(createFirebaseDatabaseState(snapshot));
|
|
688
755
|
};
|
|
689
756
|
return {
|
|
690
|
-
|
|
691
|
-
|
|
757
|
+
recordInsights: async ({ event, installation }) => {
|
|
758
|
+
await ensureMigrated();
|
|
759
|
+
await db.runTransaction(async (transaction) => {
|
|
760
|
+
const eventReference = collections.bundleEvents.doc(event.id);
|
|
761
|
+
const installationReference = collections.bundleInstallations.doc(firebaseInstallationDocumentId(installation.install_id));
|
|
762
|
+
const [storedEvent, storedInstallation] = await transaction.getAll(eventReference, installationReference);
|
|
763
|
+
if (storedEvent.exists) return;
|
|
764
|
+
const current = storedInstallation.exists ? requireFirebaseDocumentKey("bundle_installations", storedInstallation.id, parseFirebaseInsightsInstallationRow(storedInstallation.data(), `bundle_installations/${storedInstallation.id}`)) : null;
|
|
765
|
+
transaction.create(eventReference, event);
|
|
766
|
+
if (current === null || installation.received_at_ms > current.received_at_ms || installation.received_at_ms === current.received_at_ms && (0, _hot_updater_plugin_core.compareInsightsText)(installation.id, current.id) > 0) transaction.set(installationReference, installation);
|
|
767
|
+
});
|
|
768
|
+
},
|
|
769
|
+
create: async (input) => {
|
|
770
|
+
if (input.model !== "bundle_events" && input.model !== "bundle_installations") return mutate((database) => database.create(input));
|
|
771
|
+
await ensureMigrated();
|
|
772
|
+
return db.runTransaction(async (transaction) => {
|
|
773
|
+
const collection = input.model === "bundle_events" ? collections.bundleEvents : collections.bundleInstallations;
|
|
774
|
+
const documentId = input.model === "bundle_events" ? input.data.id : firebaseInstallationDocumentId(input.data.install_id);
|
|
775
|
+
const reference = collection.doc(documentId);
|
|
776
|
+
const document = await transaction.get(reference);
|
|
777
|
+
if (document.exists) {
|
|
778
|
+
const row = input.model === "bundle_events" ? requireFirebaseDocumentKey("bundle_events", document.id, parseFirebaseBundleEventRow(document.data(), `bundle_events/${document.id}`)) : requireFirebaseDocumentKey("bundle_installations", document.id, parseFirebaseInsightsInstallationRow(document.data(), `bundle_installations/${document.id}`));
|
|
779
|
+
if (input.onConflict === "ignore") return row;
|
|
780
|
+
throw new FirebaseDatabaseConstraintError(`${input.model}.id.unique`);
|
|
781
|
+
}
|
|
782
|
+
transaction.create(reference, input.data);
|
|
783
|
+
return input.data;
|
|
784
|
+
});
|
|
785
|
+
},
|
|
786
|
+
update: async (input) => {
|
|
787
|
+
if (input.model !== "bundle_installations") return mutate((database) => database.update(input));
|
|
788
|
+
const installId = exactInstallId(input);
|
|
789
|
+
if (installId === void 0) return mutate((database) => database.update(input));
|
|
790
|
+
await ensureMigrated();
|
|
791
|
+
return db.runTransaction(async (transaction) => {
|
|
792
|
+
const reference = collections.bundleInstallations.doc(firebaseInstallationDocumentId(installId));
|
|
793
|
+
const document = await transaction.get(reference);
|
|
794
|
+
if (!document.exists) return null;
|
|
795
|
+
const current = requireFirebaseDocumentKey("bundle_installations", document.id, parseFirebaseInsightsInstallationRow(document.data(), `bundle_installations/${document.id}`));
|
|
796
|
+
if (!matchesFirebaseDatabaseWhere(current, input.where)) return null;
|
|
797
|
+
const updated = {
|
|
798
|
+
...current,
|
|
799
|
+
...input.update
|
|
800
|
+
};
|
|
801
|
+
transaction.set(reference, updated, { merge: true });
|
|
802
|
+
return updated;
|
|
803
|
+
});
|
|
804
|
+
},
|
|
692
805
|
delete: (input) => mutate((database) => database.delete(input)),
|
|
693
|
-
count: (input) =>
|
|
806
|
+
count: async (input) => {
|
|
807
|
+
if (input.model !== "bundle_installations" && input.model !== "bundle_events") return read((database) => database.count(input));
|
|
808
|
+
await ensureMigrated();
|
|
809
|
+
let query = applyFirebaseWhere(input.model === "bundle_events" ? collections.bundleEvents : collections.bundleInstallations, input.where ?? []);
|
|
810
|
+
if (input.model === "bundle_events") query = query.orderBy("received_at_ms", "desc").orderBy("id", "desc");
|
|
811
|
+
return (await query.count().get()).data().count;
|
|
812
|
+
},
|
|
694
813
|
findOne: async (input) => {
|
|
814
|
+
if (input.model === "bundle_installations") {
|
|
815
|
+
const installId = exactInstallId(input);
|
|
816
|
+
if (installId === void 0) return read((database) => database.findOne(input));
|
|
817
|
+
await ensureMigrated();
|
|
818
|
+
const document = await collections.bundleInstallations.doc(firebaseInstallationDocumentId(installId)).get();
|
|
819
|
+
return document.exists ? requireFirebaseDocumentKey("bundle_installations", document.id, parseFirebaseInsightsInstallationRow(document.data(), `bundle_installations/${document.id}`)) : null;
|
|
820
|
+
}
|
|
695
821
|
const id = exactId(input);
|
|
696
822
|
if (id === void 0) return read((database) => database.findOne(input));
|
|
697
823
|
await ensureMigrated();
|
|
@@ -712,9 +838,21 @@ const firebaseDatabase = (config) => {
|
|
|
712
838
|
}
|
|
713
839
|
},
|
|
714
840
|
findMany: async (input) => {
|
|
715
|
-
if (input.model
|
|
716
|
-
|
|
717
|
-
|
|
841
|
+
if (input.model === "bundle_events" || input.model === "bundle_installations") {
|
|
842
|
+
await ensureMigrated();
|
|
843
|
+
const collection = input.model === "bundle_events" ? collections.bundleEvents : collections.bundleInstallations;
|
|
844
|
+
let query = applyFirebaseWhere(collection, input.where ?? []);
|
|
845
|
+
for (const order of input.orderBy ?? []) {
|
|
846
|
+
if (order.nulls !== void 0) throw new FirebaseDatabaseConstraintError("query.unsupported");
|
|
847
|
+
query = query.orderBy(order.field, order.direction);
|
|
848
|
+
}
|
|
849
|
+
return (await query.offset(input.offset).limit(input.limit).get()).docs.map((document) => input.model === "bundle_events" ? requireFirebaseDocumentKey("bundle_events", document.id, parseFirebaseBundleEventRow(document.data(), `bundle_events/${document.id}`)) : requireFirebaseDocumentKey("bundle_installations", document.id, parseFirebaseInsightsInstallationRow(document.data(), `bundle_installations/${document.id}`)));
|
|
850
|
+
}
|
|
851
|
+
if (input.model === "channels") {
|
|
852
|
+
await ensureMigrated();
|
|
853
|
+
return queryFirebaseDatabaseRows(await loadFirebaseChannels(collections), input);
|
|
854
|
+
}
|
|
855
|
+
return read((database) => database.findMany(input));
|
|
718
856
|
},
|
|
719
857
|
insertChannel: async (input) => {
|
|
720
858
|
await ensureMigrated();
|
|
@@ -766,7 +904,8 @@ const firebaseDatabase = (config) => {
|
|
|
766
904
|
},
|
|
767
905
|
transaction: (callback) => mutate(callback)
|
|
768
906
|
};
|
|
769
|
-
})()
|
|
907
|
+
})();
|
|
908
|
+
const adapter = (0, _hot_updater_plugin_core_internal.createDatabasePluginAdapter)("firebaseDatabase", implementation);
|
|
770
909
|
return (0, _hot_updater_plugin_core.createDatabasePlugin)({
|
|
771
910
|
name: "firebaseDatabase",
|
|
772
911
|
models: adapter.models,
|
|
@@ -776,7 +915,8 @@ const firebaseDatabase = (config) => {
|
|
|
776
915
|
//#endregion
|
|
777
916
|
//#region src/firebaseStorage.ts
|
|
778
917
|
const firebaseStorage = (config) => {
|
|
779
|
-
const
|
|
918
|
+
const app = (0, firebase_admin_app.getApps)().length ? (0, firebase_admin_app.getApp)() : (0, firebase_admin_app.initializeApp)(config);
|
|
919
|
+
const bucket = (0, firebase_admin_storage.getStorage)(app).bucket(config.storageBucket);
|
|
780
920
|
const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
|
|
781
921
|
const parseAndValidate = (storageUri) => {
|
|
782
922
|
const parsed = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "gs");
|
package/dist/index.d.cts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
|
|
2
|
-
import { StoragePluginWith } from "@hot-updater/plugin-core";
|
|
3
1
|
import { AppOptions } from "firebase-admin/app";
|
|
4
|
-
|
|
2
|
+
import { StoragePluginWith } from "@hot-updater/plugin-core";
|
|
5
3
|
//#region src/firebaseDatabase.d.ts
|
|
6
4
|
type FirebaseDatabaseConfig = AppOptions;
|
|
7
|
-
declare const firebaseDatabase: (config: FirebaseDatabaseConfig) =>
|
|
5
|
+
declare const firebaseDatabase: (config: FirebaseDatabaseConfig) => import("@hot-updater/plugin-core").DatabasePlugin;
|
|
8
6
|
//#endregion
|
|
9
7
|
//#region src/firebaseStorage.d.ts
|
|
10
8
|
interface FirebaseStorageConfig extends AppOptions {
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
|
|
2
1
|
import { StoragePluginWith } from "@hot-updater/plugin-core";
|
|
3
2
|
import { AppOptions } from "firebase-admin/app";
|
|
4
|
-
|
|
5
3
|
//#region src/firebaseDatabase.d.ts
|
|
6
4
|
type FirebaseDatabaseConfig = AppOptions;
|
|
7
|
-
declare const firebaseDatabase: (config: FirebaseDatabaseConfig) =>
|
|
5
|
+
declare const firebaseDatabase: (config: FirebaseDatabaseConfig) => import("@hot-updater/plugin-core").DatabasePlugin;
|
|
8
6
|
//#endregion
|
|
9
7
|
//#region src/firebaseStorage.d.ts
|
|
10
8
|
interface FirebaseStorageConfig extends AppOptions {
|