@x12i/catalox 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +35 -3
  2. package/dist/src/catalox/catalox.d.ts +17 -0
  3. package/dist/src/catalox/catalox.d.ts.map +1 -1
  4. package/dist/src/catalox/catalox.js +64 -6
  5. package/dist/src/catalox/catalox.js.map +1 -1
  6. package/dist/src/catalox/firestore-gcs-compare.d.ts +15 -0
  7. package/dist/src/catalox/firestore-gcs-compare.d.ts.map +1 -0
  8. package/dist/src/catalox/firestore-gcs-compare.js +221 -0
  9. package/dist/src/catalox/firestore-gcs-compare.js.map +1 -0
  10. package/dist/src/catalox/firestore-gcs-transfer.d.ts +24 -0
  11. package/dist/src/catalox/firestore-gcs-transfer.d.ts.map +1 -0
  12. package/dist/src/catalox/firestore-gcs-transfer.js +346 -0
  13. package/dist/src/catalox/firestore-gcs-transfer.js.map +1 -0
  14. package/dist/src/catalox/index.d.ts +2 -0
  15. package/dist/src/catalox/index.d.ts.map +1 -1
  16. package/dist/src/catalox/index.js +2 -0
  17. package/dist/src/catalox/index.js.map +1 -1
  18. package/dist/src/cli/index.js +169 -1
  19. package/dist/src/cli/index.js.map +1 -1
  20. package/dist/src/contracts/catalogs.d.ts +6 -0
  21. package/dist/src/contracts/catalogs.d.ts.map +1 -1
  22. package/dist/src/contracts/catalogs.js +18 -1
  23. package/dist/src/contracts/catalogs.js.map +1 -1
  24. package/dist/src/contracts/gcs-firestore-compare.d.ts +64 -0
  25. package/dist/src/contracts/gcs-firestore-compare.d.ts.map +1 -0
  26. package/dist/src/contracts/gcs-firestore-compare.js +2 -0
  27. package/dist/src/contracts/gcs-firestore-compare.js.map +1 -0
  28. package/dist/src/contracts/gcs-firestore-transfer.d.ts +94 -0
  29. package/dist/src/contracts/gcs-firestore-transfer.d.ts.map +1 -0
  30. package/dist/src/contracts/gcs-firestore-transfer.js +2 -0
  31. package/dist/src/contracts/gcs-firestore-transfer.js.map +1 -0
  32. package/dist/src/contracts/index.d.ts +3 -0
  33. package/dist/src/contracts/index.d.ts.map +1 -1
  34. package/dist/src/contracts/index.js +1 -0
  35. package/dist/src/contracts/index.js.map +1 -1
  36. package/dist/src/firebase/native-item-store.d.ts +6 -0
  37. package/dist/src/firebase/native-item-store.d.ts.map +1 -1
  38. package/dist/src/firebase/native-item-store.js +18 -1
  39. package/dist/src/firebase/native-item-store.js.map +1 -1
  40. package/dist/test/unit/compact-catalog-filter.test.d.ts +2 -0
  41. package/dist/test/unit/compact-catalog-filter.test.d.ts.map +1 -0
  42. package/dist/test/unit/compact-catalog-filter.test.js +18 -0
  43. package/dist/test/unit/compact-catalog-filter.test.js.map +1 -0
  44. package/dist/test/unit/gcs-firestore-compare.test.d.ts +2 -0
  45. package/dist/test/unit/gcs-firestore-compare.test.d.ts.map +1 -0
  46. package/dist/test/unit/gcs-firestore-compare.test.js +14 -0
  47. package/dist/test/unit/gcs-firestore-compare.test.js.map +1 -0
  48. package/dist/test/unit/gcs-firestore-paths.test.d.ts +2 -0
  49. package/dist/test/unit/gcs-firestore-paths.test.d.ts.map +1 -0
  50. package/dist/test/unit/gcs-firestore-paths.test.js +16 -0
  51. package/dist/test/unit/gcs-firestore-paths.test.js.map +1 -0
  52. package/package.json +4 -1
@@ -0,0 +1,221 @@
1
+ import { createHash } from "node:crypto";
2
+ import { FieldPath, Timestamp, } from "firebase-admin/firestore";
3
+ import { Storage } from "@google-cloud/storage";
4
+ import readline from "node:readline";
5
+ import { Readable } from "node:stream";
6
+ import { CATALOX_FIRESTORE_GCS_MANIFEST, collectionRefFromPath, normalizeGcsPrefix, } from "./firestore-gcs-transfer.js";
7
+ function getBucket(input) {
8
+ const storage = input.storage ?? new Storage();
9
+ return storage.bucket(input.bucket);
10
+ }
11
+ /**
12
+ * Normalizes Firestore values (including Timestamp and JSON-round-trip timestamp shapes)
13
+ * for stable equality checks between live reads and NDJSON exports.
14
+ */
15
+ export function normalizeForCompare(value) {
16
+ if (value == null)
17
+ return value;
18
+ if (typeof value !== "object")
19
+ return value;
20
+ if (value instanceof Timestamp) {
21
+ return { __cfTs: value.seconds, __cfNs: value.nanoseconds };
22
+ }
23
+ if (Array.isArray(value))
24
+ return value.map(normalizeForCompare);
25
+ const o = value;
26
+ const sec = typeof o.seconds === "number" ? o.seconds : typeof o._seconds === "number" ? o._seconds : undefined;
27
+ if (typeof sec === "number") {
28
+ const ns = (typeof o.nanoseconds === "number" ? o.nanoseconds : undefined) ??
29
+ (typeof o._nanoseconds === "number" ? o._nanoseconds : undefined) ??
30
+ 0;
31
+ const keys = Object.keys(o);
32
+ const allowed = new Set(["seconds", "_seconds", "nanoseconds", "_nanoseconds"]);
33
+ if (keys.every((k) => allowed.has(k))) {
34
+ return { __cfTs: sec, __cfNs: ns };
35
+ }
36
+ }
37
+ const out = {};
38
+ for (const k of Object.keys(o).sort()) {
39
+ out[k] = normalizeForCompare(o[k]);
40
+ }
41
+ return out;
42
+ }
43
+ export function dataFingerprint(data) {
44
+ return createHash("sha256").update(JSON.stringify(normalizeForCompare(data))).digest("hex");
45
+ }
46
+ async function loadNdjsonDataMap(bucket, objectPath) {
47
+ const map = new Map();
48
+ const [exists] = await bucket.file(objectPath).exists();
49
+ if (!exists)
50
+ throw new Error(`GCS object not found: ${objectPath}`);
51
+ const rs = bucket.file(objectPath).createReadStream();
52
+ const rl = readline.createInterface({ input: rs, crlfDelay: Infinity });
53
+ for await (const line of rl) {
54
+ const trimmed = line.trim();
55
+ if (!trimmed)
56
+ continue;
57
+ const row = JSON.parse(trimmed);
58
+ if (row.id == null || row.data === undefined)
59
+ throw new Error("Invalid NDJSON row: expected { id, data }");
60
+ map.set(String(row.id), row.data);
61
+ }
62
+ return map;
63
+ }
64
+ function pushLimited(arr, id, max) {
65
+ if (arr.length < max)
66
+ arr.push(id);
67
+ }
68
+ export async function compareFirestoreCollectionWithGcsNdjson(input) {
69
+ const issues = [];
70
+ const maxIds = input.maxListedIdsPerCategory ?? 500;
71
+ const maxFp = input.maxChangedFingerprints ?? 50;
72
+ const emptyIds = () => ({
73
+ identicalIds: [],
74
+ changedIds: [],
75
+ onlyInFirestoreIds: [],
76
+ onlyInBucketIds: [],
77
+ });
78
+ try {
79
+ const bucket = getBucket(input);
80
+ const bucketMap = await loadNdjsonDataMap(bucket, input.objectPath);
81
+ const col = collectionRefFromPath(input.firestore, input.collectionPath);
82
+ const processedFromBucket = new Set();
83
+ let firestoreDocuments = 0;
84
+ const ids = emptyIds();
85
+ const changedSamples = [];
86
+ let identical = 0;
87
+ let changed = 0;
88
+ let onlyInFirestore = 0;
89
+ let onlyInBucket = 0;
90
+ let last;
91
+ while (true) {
92
+ let q = col.orderBy(FieldPath.documentId()).limit(400);
93
+ if (last)
94
+ q = q.startAfter(last);
95
+ const snap = await q.get();
96
+ if (snap.empty)
97
+ break;
98
+ for (const d of snap.docs) {
99
+ firestoreDocuments += 1;
100
+ const fd = d.data();
101
+ if (!bucketMap.has(d.id)) {
102
+ onlyInFirestore += 1;
103
+ pushLimited(ids.onlyInFirestoreIds, d.id, maxIds);
104
+ continue;
105
+ }
106
+ processedFromBucket.add(d.id);
107
+ const bd = bucketMap.get(d.id);
108
+ const fpF = dataFingerprint(fd);
109
+ const fpB = dataFingerprint(bd);
110
+ if (fpF === fpB) {
111
+ identical += 1;
112
+ pushLimited(ids.identicalIds, d.id, maxIds);
113
+ }
114
+ else {
115
+ changed += 1;
116
+ pushLimited(ids.changedIds, d.id, maxIds);
117
+ if (changedSamples.length < maxFp) {
118
+ changedSamples.push({ id: d.id, firestoreFingerprint: fpF, bucketFingerprint: fpB });
119
+ }
120
+ }
121
+ }
122
+ last = snap.docs[snap.docs.length - 1];
123
+ }
124
+ for (const id of bucketMap.keys()) {
125
+ if (!processedFromBucket.has(id)) {
126
+ onlyInBucket += 1;
127
+ pushLimited(ids.onlyInBucketIds, id, maxIds);
128
+ }
129
+ }
130
+ return {
131
+ ok: true,
132
+ collectionPath: input.collectionPath,
133
+ objectPath: input.objectPath,
134
+ bucket: input.bucket,
135
+ counts: {
136
+ firestoreDocuments,
137
+ bucketDocuments: bucketMap.size,
138
+ identical,
139
+ changed,
140
+ onlyInFirestore,
141
+ onlyInBucket,
142
+ },
143
+ ids,
144
+ changedSamples,
145
+ issues,
146
+ };
147
+ }
148
+ catch (e) {
149
+ issues.push({
150
+ code: "compare_failed",
151
+ message: e instanceof Error ? e.message : String(e),
152
+ detail: { collectionPath: input.collectionPath, objectPath: input.objectPath },
153
+ });
154
+ return {
155
+ ok: false,
156
+ collectionPath: input.collectionPath,
157
+ objectPath: input.objectPath,
158
+ bucket: input.bucket,
159
+ counts: {
160
+ firestoreDocuments: 0,
161
+ bucketDocuments: 0,
162
+ identical: 0,
163
+ changed: 0,
164
+ onlyInFirestore: 0,
165
+ onlyInBucket: 0,
166
+ },
167
+ ids: emptyIds(),
168
+ changedSamples: [],
169
+ issues,
170
+ };
171
+ }
172
+ }
173
+ export async function compareAllFirestoreCollectionsWithGcsManifest(input) {
174
+ const issues = [];
175
+ const prefix = normalizeGcsPrefix(input.gcsPrefix);
176
+ const manifestObjectPath = input.manifestObjectPath ?? `${prefix}${CATALOX_FIRESTORE_GCS_MANIFEST}`;
177
+ const collections = [];
178
+ try {
179
+ const bucket = getBucket(input);
180
+ const [exists] = await bucket.file(manifestObjectPath).exists();
181
+ if (!exists) {
182
+ issues.push({ code: "manifest_not_found", message: `GCS object not found: ${manifestObjectPath}` });
183
+ return { ok: false, bucket: input.bucket, manifestObjectPath, collections, issues };
184
+ }
185
+ const [buf] = await bucket.file(manifestObjectPath).download();
186
+ const manifest = JSON.parse(buf.toString("utf8"));
187
+ if (manifest.catalog !== "catalox-firestore-gcs-export" || manifest.version !== 1 || !Array.isArray(manifest.entries)) {
188
+ throw new Error("Unsupported manifest format (expected catalog catalox-firestore-gcs-export version 1)");
189
+ }
190
+ for (const ent of manifest.entries) {
191
+ const one = await compareFirestoreCollectionWithGcsNdjson({
192
+ firestore: input.firestore,
193
+ bucket: input.bucket,
194
+ ...(input.gcsPrefix != null && input.gcsPrefix !== "" ? { gcsPrefix: input.gcsPrefix } : {}),
195
+ collectionPath: ent.firestorePath,
196
+ objectPath: ent.objectPath,
197
+ ...(input.maxListedIdsPerCategory != null ? { maxListedIdsPerCategory: input.maxListedIdsPerCategory } : {}),
198
+ ...(input.maxChangedFingerprints != null ? { maxChangedFingerprints: input.maxChangedFingerprints } : {}),
199
+ ...(input.storage ? { storage: input.storage } : {}),
200
+ });
201
+ collections.push(one);
202
+ if (!one.ok) {
203
+ issues.push({
204
+ code: "compare_collection_failed",
205
+ message: one.issues[0]?.message ?? "compare failed",
206
+ detail: { collectionPath: ent.firestorePath, objectPath: ent.objectPath },
207
+ });
208
+ }
209
+ }
210
+ const ok = issues.length === 0 && collections.every((c) => c.ok);
211
+ return { ok, bucket: input.bucket, manifestObjectPath, collections, issues };
212
+ }
213
+ catch (e) {
214
+ issues.push({
215
+ code: "compare_manifest_failed",
216
+ message: e instanceof Error ? e.message : String(e),
217
+ });
218
+ return { ok: false, bucket: input.bucket, manifestObjectPath, collections, issues };
219
+ }
220
+ }
221
+ //# sourceMappingURL=firestore-gcs-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firestore-gcs-compare.js","sourceRoot":"","sources":["../../../src/catalox/firestore-gcs-compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { type CollectionReference, type Firestore } from "firebase-admin/firestore";
2
+ import { Storage } from "@google-cloud/storage";
3
+ import type { ExportAllFirestoreCollectionsToGcsInput, ExportAllFirestoreCollectionsToGcsResult, ExportFirestoreCollectionToGcsInput, ExportFirestoreCollectionToGcsResult, RestoreAllFirestoreCollectionsFromGcsInput, RestoreAllFirestoreCollectionsFromGcsResult, RestoreFirestoreCollectionFromGcsInput, RestoreFirestoreCollectionFromGcsResult } from "../contracts/gcs-firestore-transfer.js";
4
+ /** Default manifest object name under `gcsPrefix` for export-all / restore-all / compare-manifest. */
5
+ export declare const CATALOX_FIRESTORE_GCS_MANIFEST = "catalox-firestore-export-manifest.json";
6
+ type GcsRuntimeInput = {
7
+ storage?: Storage;
8
+ };
9
+ export declare function normalizeGcsPrefix(prefix?: string): string;
10
+ /** Map `apps` or `a/b/c` → safe single-segment base for object names. */
11
+ export declare function firestoreCollectionPathToObjectBase(collectionPath: string): string;
12
+ export declare function ndjsonObjectPath(params: {
13
+ gcsPrefix: string;
14
+ collectionPath: string;
15
+ objectNamePostfix?: string;
16
+ }): string;
17
+ /** Parse `col` or `col/doc/subcol` into a CollectionReference (odd number of segments). */
18
+ export declare function collectionRefFromPath(fs: Firestore, collectionPath: string): CollectionReference;
19
+ export declare function exportFirestoreCollectionToGcs(input: ExportFirestoreCollectionToGcsInput & GcsRuntimeInput): Promise<ExportFirestoreCollectionToGcsResult>;
20
+ export declare function exportAllFirestoreCollectionsToGcs(input: ExportAllFirestoreCollectionsToGcsInput & GcsRuntimeInput): Promise<ExportAllFirestoreCollectionsToGcsResult>;
21
+ export declare function restoreFirestoreCollectionFromGcs(input: RestoreFirestoreCollectionFromGcsInput & GcsRuntimeInput): Promise<RestoreFirestoreCollectionFromGcsResult>;
22
+ export declare function restoreAllFirestoreCollectionsFromGcsManifest(input: RestoreAllFirestoreCollectionsFromGcsInput & GcsRuntimeInput): Promise<RestoreAllFirestoreCollectionsFromGcsResult>;
23
+ export {};
24
+ //# sourceMappingURL=firestore-gcs-transfer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firestore-gcs-transfer.d.ts","sourceRoot":"","sources":["../../../src/catalox/firestore-gcs-transfer.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,mBAAmB,EAExB,KAAK,SAAS,EAEf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,OAAO,EAA0B,MAAM,uBAAuB,CAAC;AAIxE,OAAO,KAAK,EACV,uCAAuC,EACvC,wCAAwC,EACxC,mCAAmC,EACnC,oCAAoC,EAGpC,0CAA0C,EAC1C,2CAA2C,EAC3C,sCAAsC,EACtC,uCAAuC,EACxC,MAAM,wCAAwC,CAAC;AAGhD,sGAAsG;AACtG,eAAO,MAAM,8BAA8B,2CAA2C,CAAC;AAEvF,KAAK,eAAe,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7C,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAI1D;AAED,yEAAyE;AACzE,wBAAgB,mCAAmC,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAMlF;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,MAAM,CAIT;AAOD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,GAAG,mBAAmB,CAkBhG;AAyED,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,mCAAmC,GAAG,eAAe,GAC3D,OAAO,CAAC,oCAAoC,CAAC,CAwB/C;AAED,wBAAsB,kCAAkC,CACtD,KAAK,EAAE,uCAAuC,GAAG,eAAe,GAC/D,OAAO,CAAC,wCAAwC,CAAC,CA0DnD;AAgCD,wBAAsB,iCAAiC,CACrD,KAAK,EAAE,sCAAsC,GAAG,eAAe,GAC9D,OAAO,CAAC,uCAAuC,CAAC,CA6ClD;AAED,wBAAsB,6CAA6C,CACjE,KAAK,EAAE,0CAA0C,GAAG,eAAe,GAClE,OAAO,CAAC,2CAA2C,CAAC,CA2DtD"}
@@ -0,0 +1,346 @@
1
+ import { once } from "node:events";
2
+ import { FieldPath, } from "firebase-admin/firestore";
3
+ import { Storage } from "@google-cloud/storage";
4
+ import readline from "node:readline";
5
+ import { Readable } from "node:stream";
6
+ import { deleteAllDocsInFirestoreCollection } from "./backup-data.js";
7
+ /** Default manifest object name under `gcsPrefix` for export-all / restore-all / compare-manifest. */
8
+ export const CATALOX_FIRESTORE_GCS_MANIFEST = "catalox-firestore-export-manifest.json";
9
+ export function normalizeGcsPrefix(prefix) {
10
+ const p = (prefix ?? "").trim();
11
+ if (!p)
12
+ return "";
13
+ return p.endsWith("/") ? p : `${p}/`;
14
+ }
15
+ /** Map `apps` or `a/b/c` → safe single-segment base for object names. */
16
+ export function firestoreCollectionPathToObjectBase(collectionPath) {
17
+ return collectionPath
18
+ .split("/")
19
+ .filter(Boolean)
20
+ .join("__")
21
+ .replace(/[^a-zA-Z0-9_-]/g, "_");
22
+ }
23
+ export function ndjsonObjectPath(params) {
24
+ const base = firestoreCollectionPathToObjectBase(params.collectionPath);
25
+ const sfx = params.objectNamePostfix != null && params.objectNamePostfix !== "" ? params.objectNamePostfix : "";
26
+ return `${params.gcsPrefix}${base}${sfx}.ndjson`;
27
+ }
28
+ function getBucket(input) {
29
+ const storage = input.storage ?? new Storage();
30
+ return storage.bucket(input.bucket);
31
+ }
32
+ /** Parse `col` or `col/doc/subcol` into a CollectionReference (odd number of segments). */
33
+ export function collectionRefFromPath(fs, collectionPath) {
34
+ const parts = collectionPath.split("/").filter(Boolean);
35
+ if (parts.length === 0)
36
+ throw new Error("collectionPath is empty");
37
+ if (parts.length % 2 === 0) {
38
+ throw new Error(`collectionPath must end at a collection (odd segment count); got "${collectionPath}"`);
39
+ }
40
+ let cur = fs.collection(parts[0]);
41
+ for (let i = 1; i < parts.length; i++) {
42
+ const seg = parts[i];
43
+ if (i % 2 === 1) {
44
+ cur = cur.doc(seg);
45
+ }
46
+ else {
47
+ cur = cur.collection(seg);
48
+ }
49
+ }
50
+ return cur;
51
+ }
52
+ async function* ndjsonLinesForCollection(col) {
53
+ let last;
54
+ while (true) {
55
+ let q = col.orderBy(FieldPath.documentId()).limit(400);
56
+ if (last)
57
+ q = q.startAfter(last);
58
+ const snap = await q.get();
59
+ if (snap.empty)
60
+ break;
61
+ for (const d of snap.docs) {
62
+ yield JSON.stringify({ id: d.id, data: d.data() });
63
+ }
64
+ last = snap.docs[snap.docs.length - 1];
65
+ }
66
+ }
67
+ async function uploadNdjsonFromCollection(file, col) {
68
+ const ws = file.createWriteStream({
69
+ contentType: "application/x-ndjson",
70
+ resumable: false,
71
+ });
72
+ let count = 0;
73
+ await new Promise((resolve, reject) => {
74
+ ws.on("error", reject);
75
+ ws.on("finish", resolve);
76
+ (async () => {
77
+ try {
78
+ for await (const line of ndjsonLinesForCollection(col)) {
79
+ count += 1;
80
+ const chunk = `${line}\n`;
81
+ if (!ws.write(chunk))
82
+ await once(ws, "drain");
83
+ }
84
+ }
85
+ catch (e) {
86
+ reject(e);
87
+ }
88
+ finally {
89
+ ws.end();
90
+ }
91
+ })().catch(reject);
92
+ });
93
+ return count;
94
+ }
95
+ async function discoverCollectionsForExport(fs, recursive) {
96
+ const roots = await fs.listCollections();
97
+ if (!recursive)
98
+ return roots;
99
+ const out = [];
100
+ const seen = new Set();
101
+ const queue = [...roots];
102
+ while (queue.length) {
103
+ const col = queue.shift();
104
+ if (seen.has(col.path))
105
+ continue;
106
+ seen.add(col.path);
107
+ out.push(col);
108
+ let lastDoc;
109
+ while (true) {
110
+ let q = col.orderBy(FieldPath.documentId()).limit(200);
111
+ if (lastDoc)
112
+ q = q.startAfter(lastDoc);
113
+ const snap = await q.get();
114
+ if (snap.empty)
115
+ break;
116
+ for (const d of snap.docs) {
117
+ const subs = await d.ref.listCollections();
118
+ for (const s of subs) {
119
+ if (!seen.has(s.path))
120
+ queue.push(s);
121
+ }
122
+ }
123
+ lastDoc = snap.docs[snap.docs.length - 1];
124
+ }
125
+ }
126
+ return out;
127
+ }
128
+ export async function exportFirestoreCollectionToGcs(input) {
129
+ const issues = [];
130
+ const prefix = normalizeGcsPrefix(input.gcsPrefix);
131
+ try {
132
+ const col = collectionRefFromPath(input.firestore, input.collectionPath);
133
+ const objectPath = ndjsonObjectPath({
134
+ gcsPrefix: prefix,
135
+ collectionPath: input.collectionPath,
136
+ ...(input.objectNamePostfix != null && input.objectNamePostfix !== ""
137
+ ? { objectNamePostfix: input.objectNamePostfix }
138
+ : {}),
139
+ });
140
+ const bucket = getBucket(input);
141
+ const file = bucket.file(objectPath);
142
+ const count = await uploadNdjsonFromCollection(file, col);
143
+ return { ok: true, bucket: input.bucket, objectPath, documentCount: count, issues };
144
+ }
145
+ catch (e) {
146
+ issues.push({
147
+ code: "export_failed",
148
+ message: e instanceof Error ? e.message : String(e),
149
+ detail: { collectionPath: input.collectionPath },
150
+ });
151
+ return { ok: false, bucket: input.bucket, objectPath: "", documentCount: 0, issues };
152
+ }
153
+ }
154
+ export async function exportAllFirestoreCollectionsToGcs(input) {
155
+ const issues = [];
156
+ const prefix = normalizeGcsPrefix(input.gcsPrefix);
157
+ const recursive = Boolean(input.recursive);
158
+ const bucket = getBucket(input);
159
+ const entries = [];
160
+ try {
161
+ const cols = await discoverCollectionsForExport(input.firestore, recursive);
162
+ for (const col of cols) {
163
+ const collectionPath = col.path;
164
+ const objectPath = ndjsonObjectPath({
165
+ gcsPrefix: prefix,
166
+ collectionPath,
167
+ ...(input.objectNamePostfix != null && input.objectNamePostfix !== ""
168
+ ? { objectNamePostfix: input.objectNamePostfix }
169
+ : {}),
170
+ });
171
+ try {
172
+ const file = bucket.file(objectPath);
173
+ const count = await uploadNdjsonFromCollection(file, col);
174
+ entries.push({ firestorePath: collectionPath, objectPath, documentCount: count });
175
+ }
176
+ catch (e) {
177
+ issues.push({
178
+ code: "export_collection_failed",
179
+ message: e instanceof Error ? e.message : String(e),
180
+ detail: { firestorePath: collectionPath },
181
+ });
182
+ }
183
+ }
184
+ const manifestObjectPath = `${prefix}${CATALOX_FIRESTORE_GCS_MANIFEST}`;
185
+ const manifest = {
186
+ catalog: "catalox-firestore-gcs-export",
187
+ version: 1,
188
+ exportedAt: new Date().toISOString(),
189
+ gcsPrefix: prefix,
190
+ objectNamePostfix: input.objectNamePostfix ?? "",
191
+ entries: entries.map((e) => ({
192
+ firestorePath: e.firestorePath,
193
+ objectPath: e.objectPath,
194
+ documentCount: e.documentCount,
195
+ })),
196
+ };
197
+ await bucket.file(manifestObjectPath).save(JSON.stringify(manifest, null, 2), {
198
+ contentType: "application/json",
199
+ resumable: false,
200
+ });
201
+ const ok = issues.length === 0;
202
+ return { ok, bucket: input.bucket, manifestObjectPath, entries, issues };
203
+ }
204
+ catch (e) {
205
+ issues.push({
206
+ code: "export_all_failed",
207
+ message: e instanceof Error ? e.message : String(e),
208
+ });
209
+ return { ok: false, bucket: input.bucket, manifestObjectPath: `${prefix}${CATALOX_FIRESTORE_GCS_MANIFEST}`, entries, issues };
210
+ }
211
+ }
212
+ async function restoreNdjsonStreamToCollection(fs, col, stream) {
213
+ const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
214
+ let batch = fs.batch();
215
+ let n = 0;
216
+ let inBatch = 0;
217
+ const flush = async () => {
218
+ if (inBatch === 0)
219
+ return;
220
+ await batch.commit();
221
+ batch = fs.batch();
222
+ inBatch = 0;
223
+ };
224
+ for await (const line of rl) {
225
+ const trimmed = line.trim();
226
+ if (!trimmed)
227
+ continue;
228
+ const row = JSON.parse(trimmed);
229
+ if (row.id == null || row.data == null)
230
+ throw new Error("Invalid NDJSON row: expected { id, data }");
231
+ batch.set(col.doc(String(row.id)), row.data, { merge: false });
232
+ n += 1;
233
+ inBatch += 1;
234
+ if (inBatch >= 450)
235
+ await flush();
236
+ }
237
+ await flush();
238
+ return n;
239
+ }
240
+ export async function restoreFirestoreCollectionFromGcs(input) {
241
+ const issues = [];
242
+ try {
243
+ const col = collectionRefFromPath(input.firestore, input.collectionPath);
244
+ if (input.replaceDestinationCollection) {
245
+ await deleteAllDocsInFirestoreCollection(input.firestore, col.path);
246
+ }
247
+ const bucket = getBucket(input);
248
+ const [exists] = await bucket.file(input.objectPath).exists();
249
+ if (!exists) {
250
+ issues.push({ code: "object_not_found", message: `GCS object not found: ${input.objectPath}` });
251
+ return {
252
+ ok: false,
253
+ bucket: input.bucket,
254
+ objectPath: input.objectPath,
255
+ collectionPath: input.collectionPath,
256
+ documentsWritten: 0,
257
+ issues,
258
+ };
259
+ }
260
+ const rs = bucket.file(input.objectPath).createReadStream();
261
+ const written = await restoreNdjsonStreamToCollection(input.firestore, col, rs);
262
+ return {
263
+ ok: true,
264
+ bucket: input.bucket,
265
+ objectPath: input.objectPath,
266
+ collectionPath: input.collectionPath,
267
+ documentsWritten: written,
268
+ issues,
269
+ };
270
+ }
271
+ catch (e) {
272
+ issues.push({
273
+ code: "restore_failed",
274
+ message: e instanceof Error ? e.message : String(e),
275
+ detail: { objectPath: input.objectPath, collectionPath: input.collectionPath },
276
+ });
277
+ return {
278
+ ok: false,
279
+ bucket: input.bucket,
280
+ objectPath: input.objectPath,
281
+ collectionPath: input.collectionPath,
282
+ documentsWritten: 0,
283
+ issues,
284
+ };
285
+ }
286
+ }
287
+ export async function restoreAllFirestoreCollectionsFromGcsManifest(input) {
288
+ const issues = [];
289
+ const prefix = normalizeGcsPrefix(input.gcsPrefix);
290
+ const manifestObjectPath = input.manifestObjectPath ?? `${prefix}${CATALOX_FIRESTORE_GCS_MANIFEST}`;
291
+ const restored = [];
292
+ try {
293
+ const bucket = getBucket(input);
294
+ const [exists] = await bucket.file(manifestObjectPath).exists();
295
+ if (!exists) {
296
+ issues.push({ code: "manifest_not_found", message: `GCS object not found: ${manifestObjectPath}` });
297
+ return { ok: false, bucket: input.bucket, manifestObjectPath, restored, issues };
298
+ }
299
+ const [buf] = await bucket.file(manifestObjectPath).download();
300
+ const manifest = JSON.parse(buf.toString("utf8"));
301
+ if (manifest.catalog !== "catalox-firestore-gcs-export" || manifest.version !== 1 || !Array.isArray(manifest.entries)) {
302
+ throw new Error("Unsupported manifest format (expected catalog catalox-firestore-gcs-export version 1)");
303
+ }
304
+ for (const ent of manifest.entries) {
305
+ try {
306
+ const col = collectionRefFromPath(input.firestore, ent.firestorePath);
307
+ if (input.replaceDestinationCollection) {
308
+ await deleteAllDocsInFirestoreCollection(input.firestore, col.path);
309
+ }
310
+ const [objExists] = await bucket.file(ent.objectPath).exists();
311
+ if (!objExists) {
312
+ issues.push({
313
+ code: "object_not_found",
314
+ message: `Missing NDJSON object: ${ent.objectPath}`,
315
+ detail: { firestorePath: ent.firestorePath },
316
+ });
317
+ continue;
318
+ }
319
+ const rs = bucket.file(ent.objectPath).createReadStream();
320
+ const documentsWritten = await restoreNdjsonStreamToCollection(input.firestore, col, rs);
321
+ restored.push({
322
+ firestorePath: ent.firestorePath,
323
+ objectPath: ent.objectPath,
324
+ documentsWritten,
325
+ });
326
+ }
327
+ catch (e) {
328
+ issues.push({
329
+ code: "restore_entry_failed",
330
+ message: e instanceof Error ? e.message : String(e),
331
+ detail: { firestorePath: ent.firestorePath, objectPath: ent.objectPath },
332
+ });
333
+ }
334
+ }
335
+ const ok = issues.length === 0;
336
+ return { ok, bucket: input.bucket, manifestObjectPath, restored, issues };
337
+ }
338
+ catch (e) {
339
+ issues.push({
340
+ code: "restore_all_failed",
341
+ message: e instanceof Error ? e.message : String(e),
342
+ });
343
+ return { ok: false, bucket: input.bucket, manifestObjectPath, restored, issues };
344
+ }
345
+ }
346
+ //# sourceMappingURL=firestore-gcs-transfer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firestore-gcs-transfer.js","sourceRoot":"","sources":["../../../src/catalox/firestore-gcs-transfer.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@ export * from "./authorization.js";
3
3
  export * from "./catalox.js";
4
4
  export { runBackupData, formatBackupTimestamp, discoverNativeCatalogIds, BACKUP_METADATA_SOURCE_NAMES, type BackupDataDeps, pruneMongoBackupRuns, pruneFirebaseVersionedBackups, paginatedCopyFirestoreToFirestore, deleteAllDocsInFirestoreCollection, firebaseLatestName, firebaseVersionedName, firebaseNativeLogical, firebaseSnapshotLogical, firebaseSnapshotRunLogical, } from "./backup-data.js";
5
5
  export { runRestoreFirestoreBackup, runUndoFirestoreRestore, type RestoreFirestoreDeps } from "./restore-firestore-backup.js";
6
+ export { exportFirestoreCollectionToGcs, exportAllFirestoreCollectionsToGcs, restoreFirestoreCollectionFromGcs, restoreAllFirestoreCollectionsFromGcsManifest, CATALOX_FIRESTORE_GCS_MANIFEST, normalizeGcsPrefix, firestoreCollectionPathToObjectBase, ndjsonObjectPath, collectionRefFromPath, } from "./firestore-gcs-transfer.js";
7
+ export { compareFirestoreCollectionWithGcsNdjson, compareAllFirestoreCollectionsWithGcsManifest, normalizeForCompare, dataFingerprint, } from "./firestore-gcs-compare.js";
6
8
  export { reportNativeCatalogLayoutDiagnostics, nativeCatalogFirestorePaths, type NativeCatalogLayoutDiagnosticRow, } from "./native-catalog-layout-diagnostics.js";
7
9
  export * from "./identity.js";
8
10
  export * from "./json-io.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/catalox/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,KAAK,cAAc,EACnB,oBAAoB,EACpB,6BAA6B,EAC7B,iCAAiC,EACjC,kCAAkC,EAClC,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC9H,OAAO,EACL,oCAAoC,EACpC,2BAA2B,EAC3B,KAAK,gCAAgC,GACtC,MAAM,wCAAwC,CAAC;AAChD,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/catalox/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,KAAK,cAAc,EACnB,oBAAoB,EACpB,6BAA6B,EAC7B,iCAAiC,EACjC,kCAAkC,EAClC,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC9H,OAAO,EACL,8BAA8B,EAC9B,kCAAkC,EAClC,iCAAiC,EACjC,6CAA6C,EAC7C,8BAA8B,EAC9B,kBAAkB,EAClB,mCAAmC,EACnC,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uCAAuC,EACvC,6CAA6C,EAC7C,mBAAmB,EACnB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oCAAoC,EACpC,2BAA2B,EAC3B,KAAK,gCAAgC,GACtC,MAAM,wCAAwC,CAAC;AAChD,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC"}