fires2rest 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -10
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Fires2REST (Firestore REST with Transactions) is a TypeScript library that provides a simple and efficient way to perform transactions and other operations on Firestore documents using the REST API.
|
|
4
4
|
|
|
5
|
+
It's a drop-in replacement for the official Firebase Admin SDK (the Firestore part), see [the comparison](./ref).
|
|
6
|
+
|
|
5
7
|
## Why "Fires2REST"
|
|
6
8
|
|
|
7
9
|
Firestore REST with Transactions → Firestore RES**T** → FirestoREST → Fires2REST
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/references.ts","../src/transaction.ts","../src/client.ts","../src/field-value.ts","../src/value.ts","../src/auth.ts"],"sourcesContent":[],"mappings":";;AAYA;AAKA;AAKA;AAKA;AAKA;AAKA;AAKiB,UA9BA,SAAA,CA8BA;EAKjB,SAAiB,EAAA,IAAA;AAKjB;AAQA;AAOiB,UAlDA,YAAA,CAoDe;EAKhC,YAAY,EAAA,OAAA;;;AAGN,UAvDW,YAAA,CAuDX;EACA,YAAA,EAAA,MAAA;;;AAGA,UAtDW,WAAA,CAsDX;EACA,WAAA,EAAA,MAAA;;;AAGA,UArDW,cAAA,CAqDX;EAAA,cAAA,EAAA,MAAA;AAON;AAgBA;AAQiB,UA/EA,WAAA,CA+EA;EAMD,WAAA,EAAA,MAAA;;;AAMY,UAtFX,UAAA,CAsFW;EAEH,UAAA,EAAA,MAAA;;AAIzB;AAQiB,UA/FA,cAAA,CA+FA;EAEJ,cAAA,EAAA,MAAA;;;AAUS,UAtGL,aAAA,CAsGK;EAAA,aAAA,EAAA;IAItB,QAAiB,EAAA,MAAA;IAYjB,SAAiB,EAAA,MAAA;EAkBjB,CAAA;AAMA;AAQA;AAgBiB,UA9JA,UAAA,CA8JA;EAUjB,UAAY,EAAA;IAOZ,MAAiB,CAAA,EA7KA,cA6KA,EAAA;EAAqB,CAAA;;;AAcZ,UAtLT,QAAA,CAsLS;EAAA,QAAA,EAAA;aApLT,eAAe;;;ACjDhC;AACQ,KDqDI,cAAA,GACN,SCtDE,GDuDF,YCvDE,GDwDF,YCxDE,GDyDF,WCzDE,GD0DF,cC1DE,GD2DF,WC3DE,GD4DF,UC5DE,GD6DF,cC7DE,GD8DF,aC9DE,GD+DF,UC/DE,GDgEF,QChEE;;AAKkB,UDkET,iBAAA,CClES;EACA;EAIL,IAAA,CAAA,EAAA,MAAA;EAmBT;EA5BC,MAAA,CAAA,ED0EA,MC1EA,CAAA,MAAA,ED0Ee,cC1Ef,CAAA;EAAA;EAiDb,UAAiB,CAAA,EAAA,MAAA;EAIF;EAAR,UAAA,CAAA,EAAA,MAAA;;;AAMA,UD2BU,YAAA,CC3BV;EAGO;EACC,MAAA,CAAA,EAAA,OAAA;EAAR;EAC4B,UAAA,CAAA,EAAA,MAAA;;AAMnC;AAAmC,UDwBlB,cAAA,CCxBkB;EAKE;EAUC,SAAA,EAAA,MAAA;EAApB;EAQsB,gBAAA,CAAA,EAAA,cAAA;EAUE;EAAjB,SAAA,CAAA,EDHT,cCGS;EAAR;EAQG,OAAA,CAAA,EDTN,cCSM;EAA2C;EAAR,OAAA,CAAA,EDPzC,cCOyC;EAWxB;EAAR,qBAAA,CAAA,EDhBK,UCgBL,CAAA,YAAA,CAAA;EAAqB;EAAR,kBAAA,CAAA,EDdX,UCcW,CAAA,YAAA,CAAA;;;AAkBvB,UD5BI,iBAAA,CC4BJ;EAAwB;EAKA,QAAA,EAAA,MAAA;EAYW;EAAlB,eAAA,EDzCT,cCyCS,EAAA;;;AAWE,UDhDf,KAAA,CCgDe;EAAR;EAAA,MAAA,CAAA,ED9CX,iBC8CW;;;;ECnKxB,SAAa,CAAA,EFyHG,iBEzHH;EAIwB;EAId,UAAA,CAAA,EAAA;IAAR,UAAA,EAAA,MAAA,EAAA;EAQG,CAAA;EACa;EAAlB,gBAAA,CAAA,EF4GU,cE5GV,EAAA;EACmB;EAAjB,eAAA,CAAA,EF6GO,YE7GP;;;AAYgB,UFqGd,WAAA,CErGc;EAAlB;EACC,UAAA,CAAA,EAAA,MAAA;EAEP;EAoCQ,gBAAA,CAAA,EFkEQ,cElER,EAAA;;;AAEO,UFwEL,kBAAA,CExEK;EAAR;EACP,QAAA,CAAA,EAAA;IAyCS;IAAoB,QAAA,CAAA,EAAA,MAAA;EASlB,CAAA;EAAA;;;;EC/GlB,CAAA;;;AAqB+B,UHiId,wBAAA,CGjIc;EAQC;EAAwB,WAAA,EAAA,MAAA;;;AAEjD,UH6HU,cAAA,CG7HV;EAgDgB;EA0BR,YAAA,CAAA,EHqDI,WGrDJ,EAAA;EAAR;EA+BO,UAAA,EAAA,MAAA;;;AAoDA,UHxBG,gBAAA,CGwBH;EACC;EAAR,KAAA,CAAA,EHvBK,iBGuBL;EAiFkC;EA4Be,OAAA,CAAA,EAAA,MAAA;EAkCxC;EACD,QAAA,CAAA,EAAA,MAAA;EAAR;EA7U2B,WAAA,CAAA,EAAA,MAAA;;;UHoLjB,UAAA;;WIhNF,EAAA,MAAA;EAMf;EAKA,UAAa,EAAA,MAAA;EAKb;EAQA,WAAa,EAAA,MAAA;AAQb;AAQA;AACM,KJiLM,YAAA,GAAe,MIjLrB,CAAA,MAAA,EAAA,OAAA,CAAA;;AAEA,UJsLW,gBItLX,CAAA,IJsLgC,YItLhC,CAAA,CAAA;EACA;EACA,SAAA,MAAA,EAAA,OAAA;EAAA;EAKN,SAAa,EAAA,EAAA,MAAA;EAIU;EAOT,SAAA,IAAA,EAAA,MAAA;EAOiB;EAQS,IAAA,EAAA,EJ6J5B,CI7J4B,GAAA,SAAA;EAOC;EAAA,GAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EAAA,OAAA;EAQzC;EAYA,SAAgB,UAAA,CAAA,EJsIU,IItIV;EAShB;EAOA,SAAgB,UAAA,CAAA,EJwHU,IIxHV;AAOhB;;;AJ7GA;AAKA;AAKA;AAKiB,cCtBJ,oBDsBI,CAAA,ICrBT,YDqBS,CAAA,YCpBJ,gBDoBI,CCpBa,CDoBb,CAAA,CAAA;EAKjB,SAAiB,MAAA,EAAA,OAAA;EAKjB,SAAiB,EAAA,EAAA,MAAA;EAQjB,SAAiB,IAAA,EAAA,MAAA;EAOjB,SAAiB,UAAA,CAAA,ECzCS,ID2CM;EAKhC,SAAY,UAAA,CAAA,EC/Cc,ID+Cd;EACN,iBAAA,KAAA;EACA,WAAA,CAAA,GAAA,EC7Ce,iBD6Cf,GAAA,IAAA,EAAA,IAAA,EAAA,MAAA;EACA,IAAA,CAAA,CAAA,EC3BM,CD2BN,GAAA,SAAA;EACA,GAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EAAA,OAAA;;AAEA,UCTW,wBAAA,CDSX;EACA,YAAA,CAAA,IAAA,EAAA,MAAA,EAAA,aAAA,CAAA,EAAA,MAAA,CAAA,ECNC,ODMD,CCNS,iBDMT,GAAA,IAAA,CAAA;EACA,gBAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;EACA,YAAA,CAAA,IAAA,EAAA,MAAA,EAAA,IAAA,ECJQ,MDIR,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAEA,CAFA,EAAA;IACA,KAAA,CAAA,EAAA,OAAA;EACA,CAAA,CAAA,ECJC,ODID,CCJS,WDIT,CAAA;EAAA,eAAA,CAAA,IAAA,EAAA,MAAA,EAAA,IAAA,ECDQ,MDCR,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,ECAC,ODAD,CCAS,WDAT,CAAA;EAON,eAAiB,CAAA,IAAA,EAAA,MAAA,CAAA,ECNkB,ODUP,CAAA,IAAA,CAAA;AAY5B;AAQA;;;AAUc,cClCD,iBDkCC,CAAA,IClCqB,YDkCrB,CAAA,CAAA;EAEc,iBAAA,UAAA;EAEH,SAAA,EAAA,EAAA,MAAA;EAAA,SAAA,IAAA,EAAA,MAAA;EAIzB,WAAiB,CAAA,UAAA,ECrCoB,wBDyChB,EAAA,IAAA,EAAA,MAAA;EAIrB;;;EAUuB,IAAA,MAAA,CAAA,CAAA,EC7CL,mBD6CK,CC7Ce,CD6Cf,CAAA;EAED;;AAItB;EAYA,UAAiB,CAAA,cAAA,EAAA,MAAA,CAAA,ECvDuB,mBDuDvB;EAkBjB;AAMA;AAQA;EAgBA,GAAiB,CAAA,CAAA,EC7FA,OD6FA,CC7FQ,gBD6FR,CC7FyB,CD6FzB,CAAA,CAAA;EAUjB;AAOA;;EAQY,GAAA,CAAA,IAAA,EC9GQ,CD8GR,EAAA,OAMc,CANd,EAAA;IAIc,KAAA,CAAA,EAAA,OAAA;EAEA,CAAA,CAAA,ECpH6B,ODoH7B,CCpHqC,WDoHrC,CAAA;EAAA;;;eCzGH,QAAQ,KAAK,QAAQ;EA5H5C;;;EAM0B,MAAA,CAAA,CAAA,EAgIN,OAhIM,CAAA,IAAA,CAAA;;;;;AAJb,cA4IA,mBA5IA,CAAA,IA4IwB,YA5IxB,CAAA,CAAA;EAiDb,iBAAiB,UAAA;EAIF,SAAA,EAAA,EAAA,MAAA;EAAR,SAAA,IAAA,EAAA,MAAA;EAIO,WAAA,CAAA,UAAA,EAwFuB,wBAxFvB,EAAA,IAAA,EAAA,MAAA;EAEC;;;;EAIR,GAAA,CAAA,UAAA,CAAA,EAAA,MAAA,CAAA,EA8FuB,iBA9FvB,CA8FyC,CA9FzC,CAAA;EAC4B;;AAMnC;EAAmC,GAAA,CAAA,IAAA,EAkGf,CAlGe,CAAA,EAkGX,OAlGW,CAkGH,iBAlGG,CAkGe,CAlGf,CAAA,CAAA;;;;AD5DnC;AAKA;AAKA;AAKA;AAKiB,cEzBJ,WAAA,CFyBI;EAQjB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/references.ts","../src/transaction.ts","../src/client.ts","../src/field-value.ts","../src/value.ts","../src/auth.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,6 @@ async function createJWT(config) {
|
|
|
18
18
|
typ: "JWT"
|
|
19
19
|
}).sign(privateKey);
|
|
20
20
|
} catch (error) {
|
|
21
|
-
console.error("Error creating JWT:", error);
|
|
22
21
|
throw error;
|
|
23
22
|
}
|
|
24
23
|
}
|
|
@@ -38,6 +37,27 @@ async function getFirestoreToken(config) {
|
|
|
38
37
|
//#endregion
|
|
39
38
|
//#region src/utils.ts
|
|
40
39
|
/**
|
|
40
|
+
* Regular expression for valid unquoted Firestore field path segments.
|
|
41
|
+
* Unquoted segments must start with a letter or underscore, followed by
|
|
42
|
+
* letters, underscores, or digits.
|
|
43
|
+
*/
|
|
44
|
+
const SIMPLE_FIELD_PATH_REGEX = /^[a-zA-Z_][a-zA-Z_0-9]*$/;
|
|
45
|
+
/**
|
|
46
|
+
* Quote a field path segment if it contains special characters.
|
|
47
|
+
* Segments that don't match the simple identifier pattern must be quoted with backticks.
|
|
48
|
+
*/
|
|
49
|
+
function quoteFieldPathSegment(segment) {
|
|
50
|
+
if (SIMPLE_FIELD_PATH_REGEX.test(segment)) return segment;
|
|
51
|
+
return `\`${segment.replace(/\\/g, "\\\\").replace(/`/g, "\\`")}\``;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Quote a full field path, handling each segment individually.
|
|
55
|
+
* Splits the path by dots and quotes each segment if needed.
|
|
56
|
+
*/
|
|
57
|
+
function quoteFieldPath(path) {
|
|
58
|
+
return path.split(".").map(quoteFieldPathSegment).join(".");
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
41
61
|
* Generate a random document ID (20 characters, alphanumeric)
|
|
42
62
|
*/
|
|
43
63
|
function generateDocumentId() {
|
|
@@ -69,12 +89,15 @@ function extractDocumentId(name) {
|
|
|
69
89
|
*/
|
|
70
90
|
function getFieldPaths(obj, prefix = "", isFieldValue$1) {
|
|
71
91
|
const paths = [];
|
|
72
|
-
for (const key of Object.keys(obj))
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
92
|
+
for (const key of Object.keys(obj)) {
|
|
93
|
+
const quotedKey = quoteFieldPathSegment(key);
|
|
94
|
+
if (key.includes(".")) paths.push(quoteFieldPath(key));
|
|
95
|
+
else {
|
|
96
|
+
const fullPath = prefix ? `${prefix}.${quotedKey}` : quotedKey;
|
|
97
|
+
const value = obj[key];
|
|
98
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) && !isFieldValue$1(value) && Object.keys(value).length > 0 && !("latitude" in value && "longitude" in value)) paths.push(...getFieldPaths(value, fullPath, isFieldValue$1));
|
|
99
|
+
else paths.push(fullPath);
|
|
100
|
+
}
|
|
78
101
|
}
|
|
79
102
|
return paths;
|
|
80
103
|
}
|
|
@@ -323,7 +346,8 @@ function toFirestoreFields(data) {
|
|
|
323
346
|
function extractFieldTransforms(data, pathPrefix = "") {
|
|
324
347
|
const transforms = [];
|
|
325
348
|
for (const [key, value] of Object.entries(data)) {
|
|
326
|
-
const
|
|
349
|
+
const quotedKey = key.includes(".") ? quoteFieldPath(key) : quoteFieldPathSegment(key);
|
|
350
|
+
const fieldPath = pathPrefix ? `${pathPrefix}.${quotedKey}` : quotedKey;
|
|
327
351
|
if (isFieldValue(value)) {
|
|
328
352
|
const transform = fieldValueToTransform(value, fieldPath);
|
|
329
353
|
if (transform) transforms.push(transform);
|
|
@@ -360,7 +384,8 @@ function fieldValueToTransform(fieldValue, fieldPath) {
|
|
|
360
384
|
function extractDeleteFields(data, pathPrefix = "") {
|
|
361
385
|
const deletePaths = [];
|
|
362
386
|
for (const [key, value] of Object.entries(data)) {
|
|
363
|
-
const
|
|
387
|
+
const quotedKey = key.includes(".") ? quoteFieldPath(key) : quoteFieldPathSegment(key);
|
|
388
|
+
const fieldPath = pathPrefix ? `${pathPrefix}.${quotedKey}` : quotedKey;
|
|
364
389
|
if (isFieldValue(value) && isDeleteField(value)) deletePaths.push(fieldPath);
|
|
365
390
|
else if (typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof Timestamp) && !(value instanceof GeoPoint) && !(value instanceof Uint8Array)) deletePaths.push(...extractDeleteFields(value, fieldPath));
|
|
366
391
|
}
|
|
@@ -373,7 +398,8 @@ function extractDeleteFields(data, pathPrefix = "") {
|
|
|
373
398
|
function extractTransformFields(data, pathPrefix = "") {
|
|
374
399
|
const transformPaths = [];
|
|
375
400
|
for (const [key, value] of Object.entries(data)) {
|
|
376
|
-
const
|
|
401
|
+
const quotedKey = key.includes(".") ? quoteFieldPath(key) : quoteFieldPathSegment(key);
|
|
402
|
+
const fieldPath = pathPrefix ? `${pathPrefix}.${quotedKey}` : quotedKey;
|
|
377
403
|
if (isFieldValue(value) && !isDeleteField(value)) transformPaths.push(fieldPath);
|
|
378
404
|
else if (typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof Timestamp) && !(value instanceof GeoPoint) && !(value instanceof Uint8Array)) transformPaths.push(...extractTransformFields(value, fieldPath));
|
|
379
405
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["isFieldValue","toFirestoreValue"],"sources":["../src/auth.ts","../src/utils.ts","../src/field-value.ts","../src/value.ts","../src/references.ts","../src/transaction.ts","../src/client.ts"],"sourcesContent":["import { importPKCS8, SignJWT } from \"jose\";\nimport type { AuthConfig } from \"./types.js\";\n\nexport async function createJWT(config: AuthConfig): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n const payload = {\n iss: config.clientEmail,\n sub: config.clientEmail,\n aud: \"https://oauth2.googleapis.com/token\",\n iat: now,\n exp: now + 3600,\n scope: \"https://www.googleapis.com/auth/datastore\",\n };\n\n try {\n const privateKey = await importPKCS8(config.privateKey, \"RS256\");\n\n const token = await new SignJWT(payload)\n .setProtectedHeader({\n alg: \"RS256\",\n typ: \"JWT\",\n })\n .sign(privateKey);\n\n return token;\n } catch (error) {\n console.error(\"Error creating JWT:\", error);\n throw error;\n }\n}\n\nexport async function getFirestoreToken(config: AuthConfig): Promise<string> {\n const response = await fetch(\"https://oauth2.googleapis.com/token\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"urn:ietf:params:oauth:grant-type:jwt-bearer\",\n assertion: await createJWT(config),\n }),\n });\n\n const data = (await response.json()) as { access_token: unknown };\n if (typeof data.access_token !== \"string\") {\n throw new Error(\"Invalid access token\");\n }\n\n return data.access_token;\n}\n","/**\n * Firestore Utility Functions\n */\n\nimport type { FirestoreValue } from \"./types.js\";\n\n/**\n * Generate a random document ID (20 characters, alphanumeric)\n */\nexport function generateDocumentId(): string {\n const chars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n let result = \"\";\n for (let i = 0; i < 20; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n\n/**\n * Parse a document path into collection and document ID\n */\nexport function parseDocumentPath(path: string): {\n collection: string;\n docId: string;\n} {\n const parts = path.split(\"/\");\n if (parts.length < 2 || parts.length % 2 !== 0) {\n throw new Error(`Invalid document path: ${path}`);\n }\n return {\n collection: parts.slice(0, -1).join(\"/\"),\n docId: parts[parts.length - 1],\n };\n}\n\n/**\n * Extract document ID from full resource name\n */\nexport function extractDocumentId(name: string): string {\n const parts = name.split(\"/\");\n return parts[parts.length - 1];\n}\n\n/**\n * Extract document path from full resource name\n */\nexport function extractDocumentPath(name: string): string {\n // Format: projects/{project}/databases/{db}/documents/{path}\n const match = name.match(/documents\\/(.+)$/);\n return match ? match[1] : name;\n}\n\n/**\n * Get all field paths from an object.\n */\nexport function getFieldPaths(\n obj: Record<string, unknown>,\n prefix = \"\",\n isFieldValue: (v: unknown) => boolean,\n): string[] {\n const paths: string[] = [];\n for (const key of Object.keys(obj)) {\n // Check if key contains dots (dot-notation path)\n if (key.includes(\".\")) {\n // For dot-notation keys, the entire key is the path\n paths.push(key);\n } else {\n const fullPath = prefix ? `${prefix}.${key}` : key;\n const value = obj[key];\n if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !isFieldValue(value) &&\n Object.keys(value).length > 0 &&\n !(\"latitude\" in value && \"longitude\" in value)\n ) {\n paths.push(\n ...getFieldPaths(\n value as Record<string, unknown>,\n fullPath,\n isFieldValue,\n ),\n );\n } else {\n paths.push(fullPath);\n }\n }\n }\n return paths;\n}\n\n/**\n * Build Firestore fields from update data, handling dot-notation paths.\n */\nexport function buildUpdateFields(\n data: Record<string, unknown>,\n toFirestoreValue: (v: unknown) => FirestoreValue,\n isFieldValue: (v: unknown) => boolean,\n): Record<string, FirestoreValue> {\n const fields: Record<string, FirestoreValue> = {};\n\n for (const [key, value] of Object.entries(data)) {\n // Skip FieldValue sentinels\n if (isFieldValue(value)) {\n continue;\n }\n\n // Handle dot-notation paths like \"user.age\"\n if (key.includes(\".\")) {\n const parts = key.split(\".\");\n let current = fields;\n\n // Navigate/create nested structure\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (!current[part]) {\n current[part] = {\n mapValue: { fields: {} },\n };\n }\n const mapVal = current[part] as {\n mapValue: { fields: Record<string, FirestoreValue> };\n };\n if (!mapVal.mapValue.fields) {\n mapVal.mapValue.fields = {};\n }\n current = mapVal.mapValue.fields;\n }\n\n // Set the final value\n current[parts[parts.length - 1]] = toFirestoreValue(value);\n } else {\n // Regular field\n fields[key] = toFirestoreValue(value);\n }\n }\n\n return fields;\n}\n","/**\n * FieldValue Sentinels\n *\n * Sentinel values for special Firestore operations.\n */\n\n/** Property name to identify FieldValue instances */\nconst FIELD_VALUE_MARKER = \"__isFieldValue__\" as const;\n\n/** Base class for FieldValue sentinels */\nabstract class FieldValueBase {\n readonly __isFieldValue__: true = true;\n abstract readonly _type: string;\n}\n\n/** Server timestamp sentinel */\nexport class ServerTimestampValue extends FieldValueBase {\n readonly _type = \"serverTimestamp\";\n}\n\n/** Delete field sentinel */\nexport class DeleteFieldValue extends FieldValueBase {\n readonly _type = \"delete\";\n}\n\n/** Increment sentinel */\nexport class IncrementValue extends FieldValueBase {\n readonly _type = \"increment\";\n constructor(readonly amount: number) {\n super();\n }\n}\n\n/** Array union sentinel */\nexport class ArrayUnionValue extends FieldValueBase {\n readonly _type = \"arrayUnion\";\n constructor(readonly elements: unknown[]) {\n super();\n }\n}\n\n/** Array remove sentinel */\nexport class ArrayRemoveValue extends FieldValueBase {\n readonly _type = \"arrayRemove\";\n constructor(readonly elements: unknown[]) {\n super();\n }\n}\n\n/** FieldValue sentinel type */\nexport type FieldValueType =\n | ServerTimestampValue\n | DeleteFieldValue\n | IncrementValue\n | ArrayUnionValue\n | ArrayRemoveValue;\n\n/**\n * FieldValue factory for creating sentinel values\n */\nexport const FieldValue = {\n /**\n * Returns a sentinel to include a server-generated timestamp in the written data.\n */\n serverTimestamp(): FieldValueType {\n return new ServerTimestampValue();\n },\n\n /**\n * Returns a sentinel to delete a field.\n */\n delete(): FieldValueType {\n return new DeleteFieldValue();\n },\n\n /**\n * Returns a sentinel to increment a numeric field by the given amount.\n */\n increment(amount: number): FieldValueType {\n return new IncrementValue(amount);\n },\n\n /**\n * Returns a sentinel to union elements into an array field.\n * Only adds elements not already present.\n */\n arrayUnion(...elements: unknown[]): FieldValueType {\n return new ArrayUnionValue(elements);\n },\n\n /**\n * Returns a sentinel to remove elements from an array field.\n */\n arrayRemove(...elements: unknown[]): FieldValueType {\n return new ArrayRemoveValue(elements);\n },\n};\n\n/**\n * Check if a value is a FieldValue sentinel\n */\nexport function isFieldValue(value: unknown): value is FieldValueType {\n return (\n typeof value === \"object\" &&\n value !== null &&\n FIELD_VALUE_MARKER in value &&\n (value as Record<string, unknown>)[FIELD_VALUE_MARKER] === true\n );\n}\n\n/**\n * Check if a value is a ServerTimestamp sentinel\n */\nexport function isServerTimestamp(\n value: unknown,\n): value is ServerTimestampValue {\n return value instanceof ServerTimestampValue;\n}\n\n/**\n * Check if a value is a Delete sentinel\n */\nexport function isDeleteField(value: unknown): value is DeleteFieldValue {\n return value instanceof DeleteFieldValue;\n}\n\n/**\n * Check if a value is an Increment sentinel\n */\nexport function isIncrement(value: unknown): value is IncrementValue {\n return value instanceof IncrementValue;\n}\n\n/**\n * Get increment amount if value is an increment sentinel\n */\nexport function getIncrementAmount(value: unknown): number | undefined {\n if (value instanceof IncrementValue) {\n return value.amount;\n }\n return undefined;\n}\n\n/**\n * Check if a value is an ArrayUnion sentinel\n */\nexport function isArrayUnion(value: unknown): value is ArrayUnionValue {\n return value instanceof ArrayUnionValue;\n}\n\n/**\n * Get array union elements if value is an array union sentinel\n */\nexport function getArrayUnionElements(value: unknown): unknown[] | undefined {\n if (value instanceof ArrayUnionValue) {\n return value.elements;\n }\n return undefined;\n}\n\n/**\n * Check if a value is an ArrayRemove sentinel\n */\nexport function isArrayRemove(value: unknown): value is ArrayRemoveValue {\n return value instanceof ArrayRemoveValue;\n}\n\n/**\n * Get array remove elements if value is an array remove sentinel\n */\nexport function getArrayRemoveElements(value: unknown): unknown[] | undefined {\n if (value instanceof ArrayRemoveValue) {\n return value.elements;\n }\n return undefined;\n}\n","/**\n * Value Conversion Utilities\n *\n * Bidirectional conversion between JavaScript values and Firestore REST format.\n */\n\nimport {\n type FieldValueType,\n getArrayRemoveElements,\n getArrayUnionElements,\n getIncrementAmount,\n isArrayRemove,\n isArrayUnion,\n isDeleteField,\n isFieldValue,\n isIncrement,\n isServerTimestamp,\n} from \"./field-value.js\";\nimport type {\n ArrayValue,\n FieldTransform,\n FirestoreValue,\n MapValue,\n} from \"./types.js\";\n\n// Re-export from field-value\nexport {\n FieldValue,\n isFieldValue,\n type FieldValueType,\n} from \"./field-value.js\";\n\n// ============================================================================\n// GeoPoint Class\n// ============================================================================\n\n/**\n * Represents a geographic point (latitude/longitude).\n */\nexport class GeoPoint {\n constructor(\n readonly latitude: number,\n readonly longitude: number,\n ) {\n if (latitude < -90 || latitude > 90) {\n throw new Error(\"Latitude must be between -90 and 90\");\n }\n if (longitude < -180 || longitude > 180) {\n throw new Error(\"Longitude must be between -180 and 180\");\n }\n }\n\n isEqual(other: GeoPoint): boolean {\n return (\n this.latitude === other.latitude &&\n this.longitude === other.longitude\n );\n }\n}\n\n// ============================================================================\n// Timestamp Class\n// ============================================================================\n\n/**\n * Represents a Firestore timestamp with nanosecond precision.\n */\nexport class Timestamp {\n constructor(\n readonly seconds: number,\n readonly nanoseconds: number,\n ) {}\n\n static now(): Timestamp {\n const now = Date.now();\n return new Timestamp(Math.floor(now / 1000), (now % 1000) * 1_000_000);\n }\n\n static fromDate(date: Date): Timestamp {\n const ms = date.getTime();\n return new Timestamp(Math.floor(ms / 1000), (ms % 1000) * 1_000_000);\n }\n\n static fromMillis(milliseconds: number): Timestamp {\n return new Timestamp(\n Math.floor(milliseconds / 1000),\n (milliseconds % 1000) * 1_000_000,\n );\n }\n\n toDate(): Date {\n return new Date(this.seconds * 1000 + this.nanoseconds / 1_000_000);\n }\n\n toMillis(): number {\n return this.seconds * 1000 + this.nanoseconds / 1_000_000;\n }\n\n isEqual(other: Timestamp): boolean {\n return (\n this.seconds === other.seconds &&\n this.nanoseconds === other.nanoseconds\n );\n }\n}\n\n// ============================================================================\n// JavaScript to Firestore Conversion\n// ============================================================================\n\n/**\n * Convert a JavaScript value to Firestore REST format.\n */\nexport function toFirestoreValue(value: unknown): FirestoreValue {\n // null\n if (value === null) {\n return { nullValue: null };\n }\n\n // undefined -> null\n if (value === undefined) {\n return { nullValue: null };\n }\n\n // boolean\n if (typeof value === \"boolean\") {\n return { booleanValue: value };\n }\n\n // number\n if (typeof value === \"number\") {\n if (Number.isInteger(value)) {\n return { integerValue: String(value) };\n }\n return { doubleValue: value };\n }\n\n // string\n if (typeof value === \"string\") {\n return { stringValue: value };\n }\n\n // Date\n if (value instanceof Date) {\n return { timestampValue: value.toISOString() };\n }\n\n // Timestamp\n if (value instanceof Timestamp) {\n return { timestampValue: value.toDate().toISOString() };\n }\n\n // GeoPoint\n if (value instanceof GeoPoint) {\n return {\n geoPointValue: {\n latitude: value.latitude,\n longitude: value.longitude,\n },\n };\n }\n\n // Uint8Array (bytes)\n if (value instanceof Uint8Array) {\n // Convert to base64\n const binary = Array.from(value, (byte) =>\n String.fromCharCode(byte),\n ).join(\"\");\n return { bytesValue: btoa(binary) };\n }\n\n // Array\n if (Array.isArray(value)) {\n return {\n arrayValue: {\n values: value.map(toFirestoreValue),\n },\n };\n }\n\n // Object (map)\n if (typeof value === \"object\") {\n const fields: Record<string, FirestoreValue> = {};\n for (const [key, val] of Object.entries(value)) {\n // Skip FieldValue sentinels - they're handled separately as transforms\n if (!isFieldValue(val)) {\n fields[key] = toFirestoreValue(val);\n }\n }\n return {\n mapValue: {\n fields,\n },\n };\n }\n\n throw new Error(`Unsupported value type: ${typeof value}`);\n}\n\n/**\n * Convert document data to Firestore fields format.\n */\nexport function toFirestoreFields(\n data: Record<string, unknown>,\n): Record<string, FirestoreValue> {\n const fields: Record<string, FirestoreValue> = {};\n for (const [key, value] of Object.entries(data)) {\n if (!isFieldValue(value)) {\n fields[key] = toFirestoreValue(value);\n }\n }\n return fields;\n}\n\n/**\n * Extract field transforms from document data.\n */\nexport function extractFieldTransforms(\n data: Record<string, unknown>,\n pathPrefix = \"\",\n): FieldTransform[] {\n const transforms: FieldTransform[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n const fieldPath = pathPrefix ? `${pathPrefix}.${key}` : key;\n\n if (isFieldValue(value)) {\n const transform = fieldValueToTransform(value, fieldPath);\n if (transform) {\n transforms.push(transform);\n }\n } else if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !(value instanceof Timestamp) &&\n !(value instanceof GeoPoint) &&\n !(value instanceof Uint8Array)\n ) {\n // Recurse into nested objects\n transforms.push(\n ...extractFieldTransforms(\n value as Record<string, unknown>,\n fieldPath,\n ),\n );\n }\n }\n\n return transforms;\n}\n\n/**\n * Convert a FieldValue sentinel to a FieldTransform.\n */\nfunction fieldValueToTransform(\n fieldValue: FieldValueType,\n fieldPath: string,\n): FieldTransform | null {\n if (isServerTimestamp(fieldValue)) {\n return {\n fieldPath,\n setToServerValue: \"REQUEST_TIME\",\n };\n }\n\n if (isDeleteField(fieldValue)) {\n // Delete is handled differently - not a transform\n return null;\n }\n\n if (isIncrement(fieldValue)) {\n return {\n fieldPath,\n increment: toFirestoreValue(getIncrementAmount(fieldValue)),\n };\n }\n\n if (isArrayUnion(fieldValue)) {\n const elements = getArrayUnionElements(fieldValue) ?? [];\n return {\n fieldPath,\n appendMissingElements: {\n values: elements.map(toFirestoreValue),\n },\n };\n }\n\n if (isArrayRemove(fieldValue)) {\n const elements = getArrayRemoveElements(fieldValue) ?? [];\n return {\n fieldPath,\n removeAllFromArray: {\n values: elements.map(toFirestoreValue),\n },\n };\n }\n\n return null;\n}\n\n/**\n * Extract delete field paths from document data.\n */\nexport function extractDeleteFields(\n data: Record<string, unknown>,\n pathPrefix = \"\",\n): string[] {\n const deletePaths: string[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n const fieldPath = pathPrefix ? `${pathPrefix}.${key}` : key;\n\n if (isFieldValue(value) && isDeleteField(value)) {\n deletePaths.push(fieldPath);\n } else if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !(value instanceof Timestamp) &&\n !(value instanceof GeoPoint) &&\n !(value instanceof Uint8Array)\n ) {\n deletePaths.push(\n ...extractDeleteFields(\n value as Record<string, unknown>,\n fieldPath,\n ),\n );\n }\n }\n\n return deletePaths;\n}\n\n/**\n * Extract transform field paths from document data.\n * These are fields with FieldValue sentinels that become transforms (not delete).\n */\nexport function extractTransformFields(\n data: Record<string, unknown>,\n pathPrefix = \"\",\n): string[] {\n const transformPaths: string[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n const fieldPath = pathPrefix ? `${pathPrefix}.${key}` : key;\n\n if (isFieldValue(value) && !isDeleteField(value)) {\n transformPaths.push(fieldPath);\n } else if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !(value instanceof Timestamp) &&\n !(value instanceof GeoPoint) &&\n !(value instanceof Uint8Array)\n ) {\n transformPaths.push(\n ...extractTransformFields(\n value as Record<string, unknown>,\n fieldPath,\n ),\n );\n }\n }\n\n return transformPaths;\n}\n\n// ============================================================================\n// Firestore to JavaScript Conversion\n// ============================================================================\n\n/**\n * Convert a Firestore REST value to JavaScript.\n */\nexport function fromFirestoreValue(value: FirestoreValue): unknown {\n if (\"nullValue\" in value) {\n return null;\n }\n\n if (\"booleanValue\" in value) {\n return value.booleanValue;\n }\n\n if (\"integerValue\" in value) {\n return parseInt(value.integerValue, 10);\n }\n\n if (\"doubleValue\" in value) {\n return value.doubleValue;\n }\n\n if (\"timestampValue\" in value) {\n return new Date(value.timestampValue);\n }\n\n if (\"stringValue\" in value) {\n return value.stringValue;\n }\n\n if (\"bytesValue\" in value) {\n // Decode base64\n const binary = atob(value.bytesValue);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n\n if (\"referenceValue\" in value) {\n return value.referenceValue;\n }\n\n if (\"geoPointValue\" in value) {\n return new GeoPoint(\n value.geoPointValue.latitude,\n value.geoPointValue.longitude,\n );\n }\n\n if (\"arrayValue\" in value) {\n const arr = value as ArrayValue;\n return (arr.arrayValue.values ?? []).map(fromFirestoreValue);\n }\n\n if (\"mapValue\" in value) {\n const map = value as MapValue;\n return fromFirestoreFields(map.mapValue.fields ?? {});\n }\n\n throw new Error(\"Unknown Firestore value type\");\n}\n\n/**\n * Convert Firestore fields to JavaScript object.\n */\nexport function fromFirestoreFields(\n fields: Record<string, FirestoreValue>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(fields)) {\n result[key] = fromFirestoreValue(value);\n }\n return result;\n}\n","/**\n * Document and Collection References\n */\n\nimport type {\n DocumentData,\n DocumentSnapshot,\n FirestoreDocument,\n WriteResult,\n} from \"./types.js\";\nimport {\n extractDocumentId,\n generateDocumentId,\n parseDocumentPath,\n} from \"./utils.js\";\nimport { fromFirestoreFields } from \"./value.js\";\n\n/**\n * Document snapshot implementation.\n */\nexport class DocumentSnapshotImpl<\n T = DocumentData,\n> implements DocumentSnapshot<T> {\n readonly exists: boolean;\n readonly id: string;\n readonly path: string;\n readonly createTime?: Date;\n readonly updateTime?: Date;\n\n private readonly _data?: T;\n\n constructor(doc: FirestoreDocument | null, path: string) {\n if (doc && doc.fields) {\n this.exists = true;\n this._data = fromFirestoreFields(doc.fields) as T;\n this.createTime = doc.createTime\n ? new Date(doc.createTime)\n : undefined;\n this.updateTime = doc.updateTime\n ? new Date(doc.updateTime)\n : undefined;\n } else {\n this.exists = false;\n this._data = undefined;\n }\n\n this.path = path;\n this.id = extractDocumentId(path);\n }\n\n data(): T | undefined {\n return this._data;\n }\n\n get(fieldPath: string): unknown {\n if (!this._data) return undefined;\n\n const parts = fieldPath.split(\".\");\n let current: unknown = this._data;\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n }\n}\n\n// Type for the Firestore client interface needed by references\nexport interface FirestoreClientInterface {\n _getDocument(\n path: string,\n transactionId?: string,\n ): Promise<FirestoreDocument | null>;\n _getDocumentName(path: string): string;\n _setDocument(\n path: string,\n data: Record<string, unknown>,\n options?: { merge?: boolean },\n ): Promise<WriteResult>;\n _updateDocument(\n path: string,\n data: Record<string, unknown>,\n ): Promise<WriteResult>;\n _deleteDocument(path: string): Promise<void>;\n}\n\n/**\n * A reference to a Firestore document.\n */\nexport class DocumentReference<T = DocumentData> {\n readonly id: string;\n readonly path: string;\n\n constructor(\n private readonly _firestore: FirestoreClientInterface,\n path: string,\n ) {\n this.path = path;\n this.id = extractDocumentId(path);\n }\n\n /**\n * Get the parent collection reference.\n */\n get parent(): CollectionReference<T> {\n const { collection } = parseDocumentPath(this.path);\n return new CollectionReference<T>(this._firestore, collection);\n }\n\n /**\n * Get a subcollection of this document.\n */\n collection(collectionPath: string): CollectionReference {\n return new CollectionReference(\n this._firestore,\n `${this.path}/${collectionPath}`,\n );\n }\n\n /**\n * Get the document.\n */\n async get(): Promise<DocumentSnapshot<T>> {\n const doc = await this._firestore._getDocument(this.path);\n return new DocumentSnapshotImpl<T>(doc, this.path);\n }\n\n /**\n * Set the document data.\n */\n async set(data: T, options?: { merge?: boolean }): Promise<WriteResult> {\n return this._firestore._setDocument(\n this.path,\n data as Record<string, unknown>,\n options,\n );\n }\n\n /**\n * Update the document data.\n */\n async update(data: Partial<T>): Promise<WriteResult> {\n return this._firestore._updateDocument(\n this.path,\n data as Record<string, unknown>,\n );\n }\n\n /**\n * Delete the document.\n */\n async delete(): Promise<void> {\n await this._firestore._deleteDocument(this.path);\n }\n}\n\n/**\n * A reference to a Firestore collection.\n */\nexport class CollectionReference<T = DocumentData> {\n readonly id: string;\n readonly path: string;\n\n constructor(\n private readonly _firestore: FirestoreClientInterface,\n path: string,\n ) {\n this.path = path;\n const parts = path.split(\"/\");\n this.id = parts[parts.length - 1];\n }\n\n /**\n * Get a document reference in this collection.\n * If no ID is provided, a random one will be generated.\n */\n doc(documentId?: string): DocumentReference<T> {\n const docId = documentId ?? generateDocumentId();\n return new DocumentReference<T>(\n this._firestore,\n `${this.path}/${docId}`,\n );\n }\n\n /**\n * Add a new document with an auto-generated ID.\n */\n async add(data: T): Promise<DocumentReference<T>> {\n const ref = this.doc();\n await ref.set(data);\n return ref;\n }\n}\n","/**\n * Firestore Transaction\n */\n\nimport {\n DocumentReference,\n DocumentSnapshotImpl,\n type FirestoreClientInterface,\n} from \"./references.js\";\nimport type {\n DocumentData,\n DocumentSnapshot,\n FirestoreDocument,\n Write,\n} from \"./types.js\";\nimport { getFieldPaths } from \"./utils.js\";\nimport {\n extractDeleteFields,\n extractFieldTransforms,\n isFieldValue,\n toFirestoreFields,\n} from \"./value.js\";\n\n/**\n * A Firestore transaction.\n * All reads must happen before any writes.\n */\nexport class Transaction {\n private readonly _writes: Write[] = [];\n\n constructor(\n private readonly _firestore: FirestoreClientInterface & {\n _getDocument(\n path: string,\n transactionId?: string,\n ): Promise<FirestoreDocument | null>;\n },\n private readonly _transactionId: string,\n ) {}\n\n /**\n * Get a document within this transaction.\n */\n async get<T = DocumentData>(\n ref: DocumentReference<T>,\n ): Promise<DocumentSnapshot<T>> {\n const doc = await this._firestore._getDocument(\n ref.path,\n this._transactionId,\n );\n return new DocumentSnapshotImpl<T>(doc, ref.path);\n }\n\n /**\n * Queue a set operation.\n */\n set<T = DocumentData>(\n ref: DocumentReference<T>,\n data: T,\n options?: { merge?: boolean },\n ): Transaction {\n const docName = this._firestore._getDocumentName(ref.path);\n const fields = toFirestoreFields(data as Record<string, unknown>);\n const transforms = extractFieldTransforms(\n data as Record<string, unknown>,\n );\n\n const write: Write = {\n update: {\n name: docName,\n fields,\n },\n };\n\n // Handle merge option\n if (options?.merge) {\n const fieldPaths = getFieldPaths(\n data as Record<string, unknown>,\n \"\",\n isFieldValue,\n );\n write.updateMask = { fieldPaths };\n }\n\n // Add transforms if any\n if (transforms.length > 0) {\n write.updateTransforms = transforms;\n }\n\n this._writes.push(write);\n return this;\n }\n\n /**\n * Queue an update operation.\n */\n update<T = DocumentData>(\n ref: DocumentReference<T>,\n data: Partial<T>,\n ): Transaction {\n const docName = this._firestore._getDocumentName(ref.path);\n\n // Filter out FieldValue.delete() fields for the update mask\n const deleteFields = extractDeleteFields(\n data as Record<string, unknown>,\n );\n const transforms = extractFieldTransforms(\n data as Record<string, unknown>,\n );\n\n // Get all field paths that are being set (not deleted or transformed)\n const fieldPaths = getFieldPaths(\n data as Record<string, unknown>,\n \"\",\n isFieldValue,\n ).filter((p) => !deleteFields.includes(p));\n\n // Build fields, excluding FieldValue sentinels\n const fields = toFirestoreFields(data as Record<string, unknown>);\n\n const write: Write = {\n update: {\n name: docName,\n fields,\n },\n updateMask: { fieldPaths: [...fieldPaths, ...deleteFields] },\n currentDocument: { exists: true },\n };\n\n if (transforms.length > 0) {\n write.updateTransforms = transforms;\n }\n\n this._writes.push(write);\n return this;\n }\n\n /**\n * Queue a delete operation.\n */\n delete(ref: DocumentReference): Transaction {\n const docName = this._firestore._getDocumentName(ref.path);\n this._writes.push({\n delete: docName,\n });\n return this;\n }\n\n /** @internal */\n _getWrites(): Write[] {\n return this._writes;\n }\n\n /** @internal */\n _getTransactionId(): string {\n return this._transactionId;\n }\n}\n","/**\n * Firestore REST Client\n *\n * Main client implementation for Firestore REST API with transaction support.\n */\n\nimport { getFirestoreToken } from \"./auth.js\";\nimport {\n CollectionReference,\n DocumentReference,\n type FirestoreClientInterface,\n} from \"./references.js\";\nimport { Transaction } from \"./transaction.js\";\nimport type {\n AuthConfig,\n BeginTransactionResponse,\n CommitResponse,\n FirestoreDocument,\n TransactionOptions,\n Write,\n WriteResult,\n} from \"./types.js\";\nimport { buildUpdateFields, getFieldPaths } from \"./utils.js\";\nimport {\n extractDeleteFields,\n extractFieldTransforms,\n extractTransformFields,\n isFieldValue,\n toFirestoreFields,\n toFirestoreValue,\n} from \"./value.js\";\n\nconst API_BASE = \"https://firestore.googleapis.com/v1\";\nconst DEFAULT_DATABASE = \"(default)\";\n\n/**\n * Firestore REST API client.\n */\nexport class Firestore implements FirestoreClientInterface {\n private readonly _config: AuthConfig;\n private readonly _databaseId: string;\n private _token: string | null = null;\n private _tokenExpiry: number = 0;\n\n constructor(config: AuthConfig, databaseId: string = DEFAULT_DATABASE) {\n this._config = config;\n this._databaseId = databaseId;\n }\n\n /**\n * Get a collection reference.\n */\n collection(collectionPath: string): CollectionReference {\n return new CollectionReference(this, collectionPath);\n }\n\n /**\n * Get a document reference.\n */\n doc(documentPath: string): DocumentReference {\n return new DocumentReference(this, documentPath);\n }\n\n /**\n * Run a transaction.\n */\n async runTransaction<R>(\n updateFn: (transaction: Transaction) => Promise<R>,\n options?: { maxAttempts?: number },\n ): Promise<R> {\n const maxAttempts = options?.maxAttempts ?? 5;\n let lastError: Error | null = null;\n let retryTransaction: string | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n // Begin transaction\n const transactionId =\n await this._beginTransaction(retryTransaction);\n const transaction = new Transaction(this, transactionId);\n\n // Run user function\n const result = await updateFn(transaction);\n\n // Commit transaction\n await this._commitTransaction(\n transactionId,\n transaction._getWrites(),\n );\n\n return result;\n } catch (error) {\n lastError = error as Error;\n\n // Check if this is a contention error that should be retried\n if (\n error instanceof Error &&\n error.message.includes(\"ABORTED\")\n ) {\n // Use the failed transaction ID for retry\n retryTransaction = undefined; // Will create new transaction\n continue;\n }\n\n // Non-retryable error\n throw error;\n }\n }\n\n throw lastError ?? new Error(\"Transaction failed after max attempts\");\n }\n\n // ========================================================================\n // Internal Methods\n // ========================================================================\n\n /** @internal */\n async _getToken(): Promise<string> {\n // Check if we have a valid token\n if (this._token && Date.now() < this._tokenExpiry - 60000) {\n return this._token;\n }\n\n // Get new token\n this._token = await getFirestoreToken(this._config);\n this._tokenExpiry = Date.now() + 3600 * 1000; // 1 hour\n return this._token;\n }\n\n /** @internal */\n _getDatabasePath(): string {\n return `projects/${this._config.projectId}/databases/${this._databaseId}`;\n }\n\n /** @internal */\n _getDocumentName(path: string): string {\n return `${this._getDatabasePath()}/documents/${path}`;\n }\n\n /** @internal */\n async _getDocument(\n path: string,\n transactionId?: string,\n ): Promise<FirestoreDocument | null> {\n const token = await this._getToken();\n const docName = this._getDocumentName(path);\n\n let url = `${API_BASE}/${docName}`;\n if (transactionId) {\n url += `?transaction=${encodeURIComponent(transactionId)}`;\n }\n\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n if (response.status === 404) {\n return null;\n }\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(`Failed to get document: ${JSON.stringify(error)}`);\n }\n\n return response.json();\n }\n\n /** @internal */\n async _setDocument(\n path: string,\n data: Record<string, unknown>,\n options?: { merge?: boolean },\n ): Promise<WriteResult> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n const docName = this._getDocumentName(path);\n\n const fields = toFirestoreFields(data);\n const transforms = extractFieldTransforms(data);\n\n const writes: Write[] = [\n {\n update: {\n name: docName,\n fields,\n },\n },\n ];\n\n if (options?.merge) {\n const fieldPaths = getFieldPaths(data, \"\", isFieldValue);\n writes[0].updateMask = { fieldPaths };\n }\n\n if (transforms.length > 0) {\n writes[0].updateTransforms = transforms;\n }\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:commit`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ writes }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(`Failed to set document: ${JSON.stringify(error)}`);\n }\n\n const result: CommitResponse = await response.json();\n return result.writeResults?.[0] ?? {};\n }\n\n /** @internal */\n async _updateDocument(\n path: string,\n data: Record<string, unknown>,\n ): Promise<WriteResult> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n const docName = this._getDocumentName(path);\n\n const deleteFields = extractDeleteFields(data);\n const transforms = extractFieldTransforms(data);\n const transformFields = extractTransformFields(data);\n\n // Get all field paths, excluding delete fields and transform fields\n const fieldPaths = getFieldPaths(data, \"\", isFieldValue).filter(\n (p) => !deleteFields.includes(p) && !transformFields.includes(p),\n );\n\n // Build fields for non-FieldValue data, also handling dot-notation\n const fields = buildUpdateFields(data, toFirestoreValue, isFieldValue);\n\n // Combine updateMask: regular fields + delete fields (transforms are NOT in mask)\n const updateMaskPaths = [...fieldPaths, ...deleteFields];\n\n const writes: Write[] = [];\n\n // If we have regular fields or delete fields, create an update write\n if (updateMaskPaths.length > 0) {\n const write: Write = {\n update: {\n name: docName,\n fields,\n },\n updateMask: { fieldPaths: updateMaskPaths },\n currentDocument: { exists: true },\n };\n writes.push(write);\n }\n\n // If we have transforms, add them\n if (transforms.length > 0) {\n if (writes.length > 0) {\n // Add transforms to the existing update write\n writes[0].updateTransforms = transforms;\n } else {\n // Transform-only: use a transform write\n writes.push({\n transform: {\n document: docName,\n fieldTransforms: transforms,\n },\n currentDocument: { exists: true },\n });\n }\n }\n\n if (writes.length === 0) {\n // Nothing to write\n return {};\n }\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:commit`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ writes }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n `Failed to update document: ${JSON.stringify(error)}`,\n );\n }\n\n const result: CommitResponse = await response.json();\n return result.writeResults?.[0] ?? {};\n }\n\n /** @internal */\n async _deleteDocument(path: string): Promise<void> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n const docName = this._getDocumentName(path);\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:commit`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n writes: [{ delete: docName }],\n }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n `Failed to delete document: ${JSON.stringify(error)}`,\n );\n }\n }\n\n /** @internal */\n async _beginTransaction(retryTransaction?: string): Promise<string> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n\n const options: TransactionOptions = {\n readWrite: retryTransaction ? { retryTransaction } : {},\n };\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:beginTransaction`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ options }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n `Failed to begin transaction: ${JSON.stringify(error)}`,\n );\n }\n\n const result: BeginTransactionResponse = await response.json();\n return result.transaction;\n }\n\n /** @internal */\n async _commitTransaction(\n transactionId: string,\n writes: Write[],\n ): Promise<CommitResponse> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:commit`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n writes,\n transaction: transactionId,\n }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n `Failed to commit transaction: ${JSON.stringify(error)}`,\n );\n }\n\n return response.json();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["isFieldValue","toFirestoreValue"],"sources":["../src/auth.ts","../src/utils.ts","../src/field-value.ts","../src/value.ts","../src/references.ts","../src/transaction.ts","../src/client.ts"],"sourcesContent":["import { importPKCS8, SignJWT } from \"jose\";\nimport type { AuthConfig } from \"./types.js\";\n\nexport async function createJWT(config: AuthConfig): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n const payload = {\n iss: config.clientEmail,\n sub: config.clientEmail,\n aud: \"https://oauth2.googleapis.com/token\",\n iat: now,\n exp: now + 3600,\n scope: \"https://www.googleapis.com/auth/datastore\",\n };\n\n try {\n const privateKey = await importPKCS8(config.privateKey, \"RS256\");\n\n const token = await new SignJWT(payload)\n .setProtectedHeader({\n alg: \"RS256\",\n typ: \"JWT\",\n })\n .sign(privateKey);\n\n return token;\n } catch (error) {\n throw error;\n }\n}\n\nexport async function getFirestoreToken(config: AuthConfig): Promise<string> {\n const response = await fetch(\"https://oauth2.googleapis.com/token\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"urn:ietf:params:oauth:grant-type:jwt-bearer\",\n assertion: await createJWT(config),\n }),\n });\n\n const data = (await response.json()) as { access_token: unknown };\n if (typeof data.access_token !== \"string\") {\n throw new Error(\"Invalid access token\");\n }\n\n return data.access_token;\n}\n","/**\n * Firestore Utility Functions\n */\n\nimport type { FirestoreValue } from \"./types.js\";\n\n/**\n * Regular expression for valid unquoted Firestore field path segments.\n * Unquoted segments must start with a letter or underscore, followed by\n * letters, underscores, or digits.\n */\nconst SIMPLE_FIELD_PATH_REGEX = /^[a-zA-Z_][a-zA-Z_0-9]*$/;\n\n/**\n * Quote a field path segment if it contains special characters.\n * Segments that don't match the simple identifier pattern must be quoted with backticks.\n */\nexport function quoteFieldPathSegment(segment: string): string {\n if (SIMPLE_FIELD_PATH_REGEX.test(segment)) {\n return segment;\n }\n // Escape backticks and backslashes in the segment\n const escaped = segment.replace(/\\\\/g, \"\\\\\\\\\").replace(/`/g, \"\\\\`\");\n return `\\`${escaped}\\``;\n}\n\n/**\n * Quote a full field path, handling each segment individually.\n * Splits the path by dots and quotes each segment if needed.\n */\nexport function quoteFieldPath(path: string): string {\n return path.split(\".\").map(quoteFieldPathSegment).join(\".\");\n}\n\n/**\n * Generate a random document ID (20 characters, alphanumeric)\n */\nexport function generateDocumentId(): string {\n const chars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n let result = \"\";\n for (let i = 0; i < 20; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n}\n\n/**\n * Parse a document path into collection and document ID\n */\nexport function parseDocumentPath(path: string): {\n collection: string;\n docId: string;\n} {\n const parts = path.split(\"/\");\n if (parts.length < 2 || parts.length % 2 !== 0) {\n throw new Error(`Invalid document path: ${path}`);\n }\n return {\n collection: parts.slice(0, -1).join(\"/\"),\n docId: parts[parts.length - 1],\n };\n}\n\n/**\n * Extract document ID from full resource name\n */\nexport function extractDocumentId(name: string): string {\n const parts = name.split(\"/\");\n return parts[parts.length - 1];\n}\n\n/**\n * Extract document path from full resource name\n */\nexport function extractDocumentPath(name: string): string {\n // Format: projects/{project}/databases/{db}/documents/{path}\n const match = name.match(/documents\\/(.+)$/);\n return match ? match[1] : name;\n}\n\n/**\n * Get all field paths from an object.\n */\nexport function getFieldPaths(\n obj: Record<string, unknown>,\n prefix = \"\",\n isFieldValue: (v: unknown) => boolean,\n): string[] {\n const paths: string[] = [];\n for (const key of Object.keys(obj)) {\n const quotedKey = quoteFieldPathSegment(key);\n // Check if key contains dots (dot-notation path)\n if (key.includes(\".\")) {\n // For dot-notation keys, quote each segment\n paths.push(quoteFieldPath(key));\n } else {\n const fullPath = prefix ? `${prefix}.${quotedKey}` : quotedKey;\n const value = obj[key];\n if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !isFieldValue(value) &&\n Object.keys(value).length > 0 &&\n !(\"latitude\" in value && \"longitude\" in value)\n ) {\n paths.push(\n ...getFieldPaths(\n value as Record<string, unknown>,\n fullPath,\n isFieldValue,\n ),\n );\n } else {\n paths.push(fullPath);\n }\n }\n }\n return paths;\n}\n\n/**\n * Build Firestore fields from update data, handling dot-notation paths.\n */\nexport function buildUpdateFields(\n data: Record<string, unknown>,\n toFirestoreValue: (v: unknown) => FirestoreValue,\n isFieldValue: (v: unknown) => boolean,\n): Record<string, FirestoreValue> {\n const fields: Record<string, FirestoreValue> = {};\n\n for (const [key, value] of Object.entries(data)) {\n // Skip FieldValue sentinels\n if (isFieldValue(value)) {\n continue;\n }\n\n // Handle dot-notation paths like \"user.age\"\n if (key.includes(\".\")) {\n const parts = key.split(\".\");\n let current = fields;\n\n // Navigate/create nested structure\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (!current[part]) {\n current[part] = {\n mapValue: { fields: {} },\n };\n }\n const mapVal = current[part] as {\n mapValue: { fields: Record<string, FirestoreValue> };\n };\n if (!mapVal.mapValue.fields) {\n mapVal.mapValue.fields = {};\n }\n current = mapVal.mapValue.fields;\n }\n\n // Set the final value\n current[parts[parts.length - 1]] = toFirestoreValue(value);\n } else {\n // Regular field\n fields[key] = toFirestoreValue(value);\n }\n }\n\n return fields;\n}\n","/**\n * FieldValue Sentinels\n *\n * Sentinel values for special Firestore operations.\n */\n\n/** Property name to identify FieldValue instances */\nconst FIELD_VALUE_MARKER = \"__isFieldValue__\" as const;\n\n/** Base class for FieldValue sentinels */\nabstract class FieldValueBase {\n readonly __isFieldValue__: true = true;\n abstract readonly _type: string;\n}\n\n/** Server timestamp sentinel */\nexport class ServerTimestampValue extends FieldValueBase {\n readonly _type = \"serverTimestamp\";\n}\n\n/** Delete field sentinel */\nexport class DeleteFieldValue extends FieldValueBase {\n readonly _type = \"delete\";\n}\n\n/** Increment sentinel */\nexport class IncrementValue extends FieldValueBase {\n readonly _type = \"increment\";\n constructor(readonly amount: number) {\n super();\n }\n}\n\n/** Array union sentinel */\nexport class ArrayUnionValue extends FieldValueBase {\n readonly _type = \"arrayUnion\";\n constructor(readonly elements: unknown[]) {\n super();\n }\n}\n\n/** Array remove sentinel */\nexport class ArrayRemoveValue extends FieldValueBase {\n readonly _type = \"arrayRemove\";\n constructor(readonly elements: unknown[]) {\n super();\n }\n}\n\n/** FieldValue sentinel type */\nexport type FieldValueType =\n | ServerTimestampValue\n | DeleteFieldValue\n | IncrementValue\n | ArrayUnionValue\n | ArrayRemoveValue;\n\n/**\n * FieldValue factory for creating sentinel values\n */\nexport const FieldValue = {\n /**\n * Returns a sentinel to include a server-generated timestamp in the written data.\n */\n serverTimestamp(): FieldValueType {\n return new ServerTimestampValue();\n },\n\n /**\n * Returns a sentinel to delete a field.\n */\n delete(): FieldValueType {\n return new DeleteFieldValue();\n },\n\n /**\n * Returns a sentinel to increment a numeric field by the given amount.\n */\n increment(amount: number): FieldValueType {\n return new IncrementValue(amount);\n },\n\n /**\n * Returns a sentinel to union elements into an array field.\n * Only adds elements not already present.\n */\n arrayUnion(...elements: unknown[]): FieldValueType {\n return new ArrayUnionValue(elements);\n },\n\n /**\n * Returns a sentinel to remove elements from an array field.\n */\n arrayRemove(...elements: unknown[]): FieldValueType {\n return new ArrayRemoveValue(elements);\n },\n};\n\n/**\n * Check if a value is a FieldValue sentinel\n */\nexport function isFieldValue(value: unknown): value is FieldValueType {\n return (\n typeof value === \"object\" &&\n value !== null &&\n FIELD_VALUE_MARKER in value &&\n (value as Record<string, unknown>)[FIELD_VALUE_MARKER] === true\n );\n}\n\n/**\n * Check if a value is a ServerTimestamp sentinel\n */\nexport function isServerTimestamp(\n value: unknown,\n): value is ServerTimestampValue {\n return value instanceof ServerTimestampValue;\n}\n\n/**\n * Check if a value is a Delete sentinel\n */\nexport function isDeleteField(value: unknown): value is DeleteFieldValue {\n return value instanceof DeleteFieldValue;\n}\n\n/**\n * Check if a value is an Increment sentinel\n */\nexport function isIncrement(value: unknown): value is IncrementValue {\n return value instanceof IncrementValue;\n}\n\n/**\n * Get increment amount if value is an increment sentinel\n */\nexport function getIncrementAmount(value: unknown): number | undefined {\n if (value instanceof IncrementValue) {\n return value.amount;\n }\n return undefined;\n}\n\n/**\n * Check if a value is an ArrayUnion sentinel\n */\nexport function isArrayUnion(value: unknown): value is ArrayUnionValue {\n return value instanceof ArrayUnionValue;\n}\n\n/**\n * Get array union elements if value is an array union sentinel\n */\nexport function getArrayUnionElements(value: unknown): unknown[] | undefined {\n if (value instanceof ArrayUnionValue) {\n return value.elements;\n }\n return undefined;\n}\n\n/**\n * Check if a value is an ArrayRemove sentinel\n */\nexport function isArrayRemove(value: unknown): value is ArrayRemoveValue {\n return value instanceof ArrayRemoveValue;\n}\n\n/**\n * Get array remove elements if value is an array remove sentinel\n */\nexport function getArrayRemoveElements(value: unknown): unknown[] | undefined {\n if (value instanceof ArrayRemoveValue) {\n return value.elements;\n }\n return undefined;\n}\n","/**\n * Value Conversion Utilities\n *\n * Bidirectional conversion between JavaScript values and Firestore REST format.\n */\n\nimport {\n type FieldValueType,\n getArrayRemoveElements,\n getArrayUnionElements,\n getIncrementAmount,\n isArrayRemove,\n isArrayUnion,\n isDeleteField,\n isFieldValue,\n isIncrement,\n isServerTimestamp,\n} from \"./field-value.js\";\nimport type {\n ArrayValue,\n FieldTransform,\n FirestoreValue,\n MapValue,\n} from \"./types.js\";\nimport { quoteFieldPath, quoteFieldPathSegment } from \"./utils.js\";\n\n// Re-export from field-value\nexport {\n FieldValue,\n isFieldValue,\n type FieldValueType,\n} from \"./field-value.js\";\n\n// ============================================================================\n// GeoPoint Class\n// ============================================================================\n\n/**\n * Represents a geographic point (latitude/longitude).\n */\nexport class GeoPoint {\n constructor(\n readonly latitude: number,\n readonly longitude: number,\n ) {\n if (latitude < -90 || latitude > 90) {\n throw new Error(\"Latitude must be between -90 and 90\");\n }\n if (longitude < -180 || longitude > 180) {\n throw new Error(\"Longitude must be between -180 and 180\");\n }\n }\n\n isEqual(other: GeoPoint): boolean {\n return (\n this.latitude === other.latitude &&\n this.longitude === other.longitude\n );\n }\n}\n\n// ============================================================================\n// Timestamp Class\n// ============================================================================\n\n/**\n * Represents a Firestore timestamp with nanosecond precision.\n */\nexport class Timestamp {\n constructor(\n readonly seconds: number,\n readonly nanoseconds: number,\n ) {}\n\n static now(): Timestamp {\n const now = Date.now();\n return new Timestamp(Math.floor(now / 1000), (now % 1000) * 1_000_000);\n }\n\n static fromDate(date: Date): Timestamp {\n const ms = date.getTime();\n return new Timestamp(Math.floor(ms / 1000), (ms % 1000) * 1_000_000);\n }\n\n static fromMillis(milliseconds: number): Timestamp {\n return new Timestamp(\n Math.floor(milliseconds / 1000),\n (milliseconds % 1000) * 1_000_000,\n );\n }\n\n toDate(): Date {\n return new Date(this.seconds * 1000 + this.nanoseconds / 1_000_000);\n }\n\n toMillis(): number {\n return this.seconds * 1000 + this.nanoseconds / 1_000_000;\n }\n\n isEqual(other: Timestamp): boolean {\n return (\n this.seconds === other.seconds &&\n this.nanoseconds === other.nanoseconds\n );\n }\n}\n\n// ============================================================================\n// JavaScript to Firestore Conversion\n// ============================================================================\n\n/**\n * Convert a JavaScript value to Firestore REST format.\n */\nexport function toFirestoreValue(value: unknown): FirestoreValue {\n // null\n if (value === null) {\n return { nullValue: null };\n }\n\n // undefined -> null\n if (value === undefined) {\n return { nullValue: null };\n }\n\n // boolean\n if (typeof value === \"boolean\") {\n return { booleanValue: value };\n }\n\n // number\n if (typeof value === \"number\") {\n if (Number.isInteger(value)) {\n return { integerValue: String(value) };\n }\n return { doubleValue: value };\n }\n\n // string\n if (typeof value === \"string\") {\n return { stringValue: value };\n }\n\n // Date\n if (value instanceof Date) {\n return { timestampValue: value.toISOString() };\n }\n\n // Timestamp\n if (value instanceof Timestamp) {\n return { timestampValue: value.toDate().toISOString() };\n }\n\n // GeoPoint\n if (value instanceof GeoPoint) {\n return {\n geoPointValue: {\n latitude: value.latitude,\n longitude: value.longitude,\n },\n };\n }\n\n // Uint8Array (bytes)\n if (value instanceof Uint8Array) {\n // Convert to base64\n const binary = Array.from(value, (byte) =>\n String.fromCharCode(byte),\n ).join(\"\");\n return { bytesValue: btoa(binary) };\n }\n\n // Array\n if (Array.isArray(value)) {\n return {\n arrayValue: {\n values: value.map(toFirestoreValue),\n },\n };\n }\n\n // Object (map)\n if (typeof value === \"object\") {\n const fields: Record<string, FirestoreValue> = {};\n for (const [key, val] of Object.entries(value)) {\n // Skip FieldValue sentinels - they're handled separately as transforms\n if (!isFieldValue(val)) {\n fields[key] = toFirestoreValue(val);\n }\n }\n return {\n mapValue: {\n fields,\n },\n };\n }\n\n throw new Error(`Unsupported value type: ${typeof value}`);\n}\n\n/**\n * Convert document data to Firestore fields format.\n */\nexport function toFirestoreFields(\n data: Record<string, unknown>,\n): Record<string, FirestoreValue> {\n const fields: Record<string, FirestoreValue> = {};\n for (const [key, value] of Object.entries(data)) {\n if (!isFieldValue(value)) {\n fields[key] = toFirestoreValue(value);\n }\n }\n return fields;\n}\n\n/**\n * Extract field transforms from document data.\n */\nexport function extractFieldTransforms(\n data: Record<string, unknown>,\n pathPrefix = \"\",\n): FieldTransform[] {\n const transforms: FieldTransform[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n const quotedKey = key.includes(\".\")\n ? quoteFieldPath(key)\n : quoteFieldPathSegment(key);\n const fieldPath = pathPrefix ? `${pathPrefix}.${quotedKey}` : quotedKey;\n\n if (isFieldValue(value)) {\n const transform = fieldValueToTransform(value, fieldPath);\n if (transform) {\n transforms.push(transform);\n }\n } else if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !(value instanceof Timestamp) &&\n !(value instanceof GeoPoint) &&\n !(value instanceof Uint8Array)\n ) {\n // Recurse into nested objects\n transforms.push(\n ...extractFieldTransforms(\n value as Record<string, unknown>,\n fieldPath,\n ),\n );\n }\n }\n\n return transforms;\n}\n\n/**\n * Convert a FieldValue sentinel to a FieldTransform.\n */\nfunction fieldValueToTransform(\n fieldValue: FieldValueType,\n fieldPath: string,\n): FieldTransform | null {\n if (isServerTimestamp(fieldValue)) {\n return {\n fieldPath,\n setToServerValue: \"REQUEST_TIME\",\n };\n }\n\n if (isDeleteField(fieldValue)) {\n // Delete is handled differently - not a transform\n return null;\n }\n\n if (isIncrement(fieldValue)) {\n return {\n fieldPath,\n increment: toFirestoreValue(getIncrementAmount(fieldValue)),\n };\n }\n\n if (isArrayUnion(fieldValue)) {\n const elements = getArrayUnionElements(fieldValue) ?? [];\n return {\n fieldPath,\n appendMissingElements: {\n values: elements.map(toFirestoreValue),\n },\n };\n }\n\n if (isArrayRemove(fieldValue)) {\n const elements = getArrayRemoveElements(fieldValue) ?? [];\n return {\n fieldPath,\n removeAllFromArray: {\n values: elements.map(toFirestoreValue),\n },\n };\n }\n\n return null;\n}\n\n/**\n * Extract delete field paths from document data.\n */\nexport function extractDeleteFields(\n data: Record<string, unknown>,\n pathPrefix = \"\",\n): string[] {\n const deletePaths: string[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n const quotedKey = key.includes(\".\")\n ? quoteFieldPath(key)\n : quoteFieldPathSegment(key);\n const fieldPath = pathPrefix ? `${pathPrefix}.${quotedKey}` : quotedKey;\n\n if (isFieldValue(value) && isDeleteField(value)) {\n deletePaths.push(fieldPath);\n } else if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !(value instanceof Timestamp) &&\n !(value instanceof GeoPoint) &&\n !(value instanceof Uint8Array)\n ) {\n deletePaths.push(\n ...extractDeleteFields(\n value as Record<string, unknown>,\n fieldPath,\n ),\n );\n }\n }\n\n return deletePaths;\n}\n\n/**\n * Extract transform field paths from document data.\n * These are fields with FieldValue sentinels that become transforms (not delete).\n */\nexport function extractTransformFields(\n data: Record<string, unknown>,\n pathPrefix = \"\",\n): string[] {\n const transformPaths: string[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n const quotedKey = key.includes(\".\")\n ? quoteFieldPath(key)\n : quoteFieldPathSegment(key);\n const fieldPath = pathPrefix ? `${pathPrefix}.${quotedKey}` : quotedKey;\n\n if (isFieldValue(value) && !isDeleteField(value)) {\n transformPaths.push(fieldPath);\n } else if (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Date) &&\n !(value instanceof Timestamp) &&\n !(value instanceof GeoPoint) &&\n !(value instanceof Uint8Array)\n ) {\n transformPaths.push(\n ...extractTransformFields(\n value as Record<string, unknown>,\n fieldPath,\n ),\n );\n }\n }\n\n return transformPaths;\n}\n\n// ============================================================================\n// Firestore to JavaScript Conversion\n// ============================================================================\n\n/**\n * Convert a Firestore REST value to JavaScript.\n */\nexport function fromFirestoreValue(value: FirestoreValue): unknown {\n if (\"nullValue\" in value) {\n return null;\n }\n\n if (\"booleanValue\" in value) {\n return value.booleanValue;\n }\n\n if (\"integerValue\" in value) {\n return parseInt(value.integerValue, 10);\n }\n\n if (\"doubleValue\" in value) {\n return value.doubleValue;\n }\n\n if (\"timestampValue\" in value) {\n return new Date(value.timestampValue);\n }\n\n if (\"stringValue\" in value) {\n return value.stringValue;\n }\n\n if (\"bytesValue\" in value) {\n // Decode base64\n const binary = atob(value.bytesValue);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n\n if (\"referenceValue\" in value) {\n return value.referenceValue;\n }\n\n if (\"geoPointValue\" in value) {\n return new GeoPoint(\n value.geoPointValue.latitude,\n value.geoPointValue.longitude,\n );\n }\n\n if (\"arrayValue\" in value) {\n const arr = value as ArrayValue;\n return (arr.arrayValue.values ?? []).map(fromFirestoreValue);\n }\n\n if (\"mapValue\" in value) {\n const map = value as MapValue;\n return fromFirestoreFields(map.mapValue.fields ?? {});\n }\n\n throw new Error(\"Unknown Firestore value type\");\n}\n\n/**\n * Convert Firestore fields to JavaScript object.\n */\nexport function fromFirestoreFields(\n fields: Record<string, FirestoreValue>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(fields)) {\n result[key] = fromFirestoreValue(value);\n }\n return result;\n}\n","/**\n * Document and Collection References\n */\n\nimport type {\n DocumentData,\n DocumentSnapshot,\n FirestoreDocument,\n WriteResult,\n} from \"./types.js\";\nimport {\n extractDocumentId,\n generateDocumentId,\n parseDocumentPath,\n} from \"./utils.js\";\nimport { fromFirestoreFields } from \"./value.js\";\n\n/**\n * Document snapshot implementation.\n */\nexport class DocumentSnapshotImpl<\n T = DocumentData,\n> implements DocumentSnapshot<T> {\n readonly exists: boolean;\n readonly id: string;\n readonly path: string;\n readonly createTime?: Date;\n readonly updateTime?: Date;\n\n private readonly _data?: T;\n\n constructor(doc: FirestoreDocument | null, path: string) {\n if (doc && doc.fields) {\n this.exists = true;\n this._data = fromFirestoreFields(doc.fields) as T;\n this.createTime = doc.createTime\n ? new Date(doc.createTime)\n : undefined;\n this.updateTime = doc.updateTime\n ? new Date(doc.updateTime)\n : undefined;\n } else {\n this.exists = false;\n this._data = undefined;\n }\n\n this.path = path;\n this.id = extractDocumentId(path);\n }\n\n data(): T | undefined {\n return this._data;\n }\n\n get(fieldPath: string): unknown {\n if (!this._data) return undefined;\n\n const parts = fieldPath.split(\".\");\n let current: unknown = this._data;\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n if (typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n }\n}\n\n// Type for the Firestore client interface needed by references\nexport interface FirestoreClientInterface {\n _getDocument(\n path: string,\n transactionId?: string,\n ): Promise<FirestoreDocument | null>;\n _getDocumentName(path: string): string;\n _setDocument(\n path: string,\n data: Record<string, unknown>,\n options?: { merge?: boolean },\n ): Promise<WriteResult>;\n _updateDocument(\n path: string,\n data: Record<string, unknown>,\n ): Promise<WriteResult>;\n _deleteDocument(path: string): Promise<void>;\n}\n\n/**\n * A reference to a Firestore document.\n */\nexport class DocumentReference<T = DocumentData> {\n readonly id: string;\n readonly path: string;\n\n constructor(\n private readonly _firestore: FirestoreClientInterface,\n path: string,\n ) {\n this.path = path;\n this.id = extractDocumentId(path);\n }\n\n /**\n * Get the parent collection reference.\n */\n get parent(): CollectionReference<T> {\n const { collection } = parseDocumentPath(this.path);\n return new CollectionReference<T>(this._firestore, collection);\n }\n\n /**\n * Get a subcollection of this document.\n */\n collection(collectionPath: string): CollectionReference {\n return new CollectionReference(\n this._firestore,\n `${this.path}/${collectionPath}`,\n );\n }\n\n /**\n * Get the document.\n */\n async get(): Promise<DocumentSnapshot<T>> {\n const doc = await this._firestore._getDocument(this.path);\n return new DocumentSnapshotImpl<T>(doc, this.path);\n }\n\n /**\n * Set the document data.\n */\n async set(data: T, options?: { merge?: boolean }): Promise<WriteResult> {\n return this._firestore._setDocument(\n this.path,\n data as Record<string, unknown>,\n options,\n );\n }\n\n /**\n * Update the document data.\n */\n async update(data: Partial<T>): Promise<WriteResult> {\n return this._firestore._updateDocument(\n this.path,\n data as Record<string, unknown>,\n );\n }\n\n /**\n * Delete the document.\n */\n async delete(): Promise<void> {\n await this._firestore._deleteDocument(this.path);\n }\n}\n\n/**\n * A reference to a Firestore collection.\n */\nexport class CollectionReference<T = DocumentData> {\n readonly id: string;\n readonly path: string;\n\n constructor(\n private readonly _firestore: FirestoreClientInterface,\n path: string,\n ) {\n this.path = path;\n const parts = path.split(\"/\");\n this.id = parts[parts.length - 1];\n }\n\n /**\n * Get a document reference in this collection.\n * If no ID is provided, a random one will be generated.\n */\n doc(documentId?: string): DocumentReference<T> {\n const docId = documentId ?? generateDocumentId();\n return new DocumentReference<T>(\n this._firestore,\n `${this.path}/${docId}`,\n );\n }\n\n /**\n * Add a new document with an auto-generated ID.\n */\n async add(data: T): Promise<DocumentReference<T>> {\n const ref = this.doc();\n await ref.set(data);\n return ref;\n }\n}\n","/**\n * Firestore Transaction\n */\n\nimport {\n DocumentReference,\n DocumentSnapshotImpl,\n type FirestoreClientInterface,\n} from \"./references.js\";\nimport type {\n DocumentData,\n DocumentSnapshot,\n FirestoreDocument,\n Write,\n} from \"./types.js\";\nimport { getFieldPaths } from \"./utils.js\";\nimport {\n extractDeleteFields,\n extractFieldTransforms,\n isFieldValue,\n toFirestoreFields,\n} from \"./value.js\";\n\n/**\n * A Firestore transaction.\n * All reads must happen before any writes.\n */\nexport class Transaction {\n private readonly _writes: Write[] = [];\n\n constructor(\n private readonly _firestore: FirestoreClientInterface & {\n _getDocument(\n path: string,\n transactionId?: string,\n ): Promise<FirestoreDocument | null>;\n },\n private readonly _transactionId: string,\n ) {}\n\n /**\n * Get a document within this transaction.\n */\n async get<T = DocumentData>(\n ref: DocumentReference<T>,\n ): Promise<DocumentSnapshot<T>> {\n const doc = await this._firestore._getDocument(\n ref.path,\n this._transactionId,\n );\n return new DocumentSnapshotImpl<T>(doc, ref.path);\n }\n\n /**\n * Queue a set operation.\n */\n set<T = DocumentData>(\n ref: DocumentReference<T>,\n data: T,\n options?: { merge?: boolean },\n ): Transaction {\n const docName = this._firestore._getDocumentName(ref.path);\n const fields = toFirestoreFields(data as Record<string, unknown>);\n const transforms = extractFieldTransforms(\n data as Record<string, unknown>,\n );\n\n const write: Write = {\n update: {\n name: docName,\n fields,\n },\n };\n\n // Handle merge option\n if (options?.merge) {\n const fieldPaths = getFieldPaths(\n data as Record<string, unknown>,\n \"\",\n isFieldValue,\n );\n write.updateMask = { fieldPaths };\n }\n\n // Add transforms if any\n if (transforms.length > 0) {\n write.updateTransforms = transforms;\n }\n\n this._writes.push(write);\n return this;\n }\n\n /**\n * Queue an update operation.\n */\n update<T = DocumentData>(\n ref: DocumentReference<T>,\n data: Partial<T>,\n ): Transaction {\n const docName = this._firestore._getDocumentName(ref.path);\n\n // Filter out FieldValue.delete() fields for the update mask\n const deleteFields = extractDeleteFields(\n data as Record<string, unknown>,\n );\n const transforms = extractFieldTransforms(\n data as Record<string, unknown>,\n );\n\n // Get all field paths that are being set (not deleted or transformed)\n const fieldPaths = getFieldPaths(\n data as Record<string, unknown>,\n \"\",\n isFieldValue,\n ).filter((p) => !deleteFields.includes(p));\n\n // Build fields, excluding FieldValue sentinels\n const fields = toFirestoreFields(data as Record<string, unknown>);\n\n const write: Write = {\n update: {\n name: docName,\n fields,\n },\n updateMask: { fieldPaths: [...fieldPaths, ...deleteFields] },\n currentDocument: { exists: true },\n };\n\n if (transforms.length > 0) {\n write.updateTransforms = transforms;\n }\n\n this._writes.push(write);\n return this;\n }\n\n /**\n * Queue a delete operation.\n */\n delete(ref: DocumentReference): Transaction {\n const docName = this._firestore._getDocumentName(ref.path);\n this._writes.push({\n delete: docName,\n });\n return this;\n }\n\n /** @internal */\n _getWrites(): Write[] {\n return this._writes;\n }\n\n /** @internal */\n _getTransactionId(): string {\n return this._transactionId;\n }\n}\n","/**\n * Firestore REST Client\n *\n * Main client implementation for Firestore REST API with transaction support.\n */\n\nimport { getFirestoreToken } from \"./auth.js\";\nimport {\n CollectionReference,\n DocumentReference,\n type FirestoreClientInterface,\n} from \"./references.js\";\nimport { Transaction } from \"./transaction.js\";\nimport type {\n AuthConfig,\n BeginTransactionResponse,\n CommitResponse,\n FirestoreDocument,\n TransactionOptions,\n Write,\n WriteResult,\n} from \"./types.js\";\nimport { buildUpdateFields, getFieldPaths } from \"./utils.js\";\nimport {\n extractDeleteFields,\n extractFieldTransforms,\n extractTransformFields,\n isFieldValue,\n toFirestoreFields,\n toFirestoreValue,\n} from \"./value.js\";\n\nconst API_BASE = \"https://firestore.googleapis.com/v1\";\nconst DEFAULT_DATABASE = \"(default)\";\n\n/**\n * Firestore REST API client.\n */\nexport class Firestore implements FirestoreClientInterface {\n private readonly _config: AuthConfig;\n private readonly _databaseId: string;\n private _token: string | null = null;\n private _tokenExpiry: number = 0;\n\n constructor(config: AuthConfig, databaseId: string = DEFAULT_DATABASE) {\n this._config = config;\n this._databaseId = databaseId;\n }\n\n /**\n * Get a collection reference.\n */\n collection(collectionPath: string): CollectionReference {\n return new CollectionReference(this, collectionPath);\n }\n\n /**\n * Get a document reference.\n */\n doc(documentPath: string): DocumentReference {\n return new DocumentReference(this, documentPath);\n }\n\n /**\n * Run a transaction.\n */\n async runTransaction<R>(\n updateFn: (transaction: Transaction) => Promise<R>,\n options?: { maxAttempts?: number },\n ): Promise<R> {\n const maxAttempts = options?.maxAttempts ?? 5;\n let lastError: Error | null = null;\n let retryTransaction: string | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n // Begin transaction\n const transactionId =\n await this._beginTransaction(retryTransaction);\n const transaction = new Transaction(this, transactionId);\n\n // Run user function\n const result = await updateFn(transaction);\n\n // Commit transaction\n await this._commitTransaction(\n transactionId,\n transaction._getWrites(),\n );\n\n return result;\n } catch (error) {\n lastError = error as Error;\n\n // Check if this is a contention error that should be retried\n if (\n error instanceof Error &&\n error.message.includes(\"ABORTED\")\n ) {\n // Use the failed transaction ID for retry\n retryTransaction = undefined; // Will create new transaction\n continue;\n }\n\n // Non-retryable error\n throw error;\n }\n }\n\n throw lastError ?? new Error(\"Transaction failed after max attempts\");\n }\n\n // ========================================================================\n // Internal Methods\n // ========================================================================\n\n /** @internal */\n async _getToken(): Promise<string> {\n // Check if we have a valid token\n if (this._token && Date.now() < this._tokenExpiry - 60000) {\n return this._token;\n }\n\n // Get new token\n this._token = await getFirestoreToken(this._config);\n this._tokenExpiry = Date.now() + 3600 * 1000; // 1 hour\n return this._token;\n }\n\n /** @internal */\n _getDatabasePath(): string {\n return `projects/${this._config.projectId}/databases/${this._databaseId}`;\n }\n\n /** @internal */\n _getDocumentName(path: string): string {\n return `${this._getDatabasePath()}/documents/${path}`;\n }\n\n /** @internal */\n async _getDocument(\n path: string,\n transactionId?: string,\n ): Promise<FirestoreDocument | null> {\n const token = await this._getToken();\n const docName = this._getDocumentName(path);\n\n let url = `${API_BASE}/${docName}`;\n if (transactionId) {\n url += `?transaction=${encodeURIComponent(transactionId)}`;\n }\n\n const response = await fetch(url, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n if (response.status === 404) {\n return null;\n }\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(`Failed to get document: ${JSON.stringify(error)}`);\n }\n\n return response.json();\n }\n\n /** @internal */\n async _setDocument(\n path: string,\n data: Record<string, unknown>,\n options?: { merge?: boolean },\n ): Promise<WriteResult> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n const docName = this._getDocumentName(path);\n\n const fields = toFirestoreFields(data);\n const transforms = extractFieldTransforms(data);\n\n const writes: Write[] = [\n {\n update: {\n name: docName,\n fields,\n },\n },\n ];\n\n if (options?.merge) {\n const fieldPaths = getFieldPaths(data, \"\", isFieldValue);\n writes[0].updateMask = { fieldPaths };\n }\n\n if (transforms.length > 0) {\n writes[0].updateTransforms = transforms;\n }\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:commit`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ writes }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(`Failed to set document: ${JSON.stringify(error)}`);\n }\n\n const result: CommitResponse = await response.json();\n return result.writeResults?.[0] ?? {};\n }\n\n /** @internal */\n async _updateDocument(\n path: string,\n data: Record<string, unknown>,\n ): Promise<WriteResult> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n const docName = this._getDocumentName(path);\n\n const deleteFields = extractDeleteFields(data);\n const transforms = extractFieldTransforms(data);\n const transformFields = extractTransformFields(data);\n\n // Get all field paths, excluding delete fields and transform fields\n const fieldPaths = getFieldPaths(data, \"\", isFieldValue).filter(\n (p) => !deleteFields.includes(p) && !transformFields.includes(p),\n );\n\n // Build fields for non-FieldValue data, also handling dot-notation\n const fields = buildUpdateFields(data, toFirestoreValue, isFieldValue);\n\n // Combine updateMask: regular fields + delete fields (transforms are NOT in mask)\n const updateMaskPaths = [...fieldPaths, ...deleteFields];\n\n const writes: Write[] = [];\n\n // If we have regular fields or delete fields, create an update write\n if (updateMaskPaths.length > 0) {\n const write: Write = {\n update: {\n name: docName,\n fields,\n },\n updateMask: { fieldPaths: updateMaskPaths },\n currentDocument: { exists: true },\n };\n writes.push(write);\n }\n\n // If we have transforms, add them\n if (transforms.length > 0) {\n if (writes.length > 0) {\n // Add transforms to the existing update write\n writes[0].updateTransforms = transforms;\n } else {\n // Transform-only: use a transform write\n writes.push({\n transform: {\n document: docName,\n fieldTransforms: transforms,\n },\n currentDocument: { exists: true },\n });\n }\n }\n\n if (writes.length === 0) {\n // Nothing to write\n return {};\n }\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:commit`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ writes }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n `Failed to update document: ${JSON.stringify(error)}`,\n );\n }\n\n const result: CommitResponse = await response.json();\n return result.writeResults?.[0] ?? {};\n }\n\n /** @internal */\n async _deleteDocument(path: string): Promise<void> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n const docName = this._getDocumentName(path);\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:commit`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n writes: [{ delete: docName }],\n }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n `Failed to delete document: ${JSON.stringify(error)}`,\n );\n }\n }\n\n /** @internal */\n async _beginTransaction(retryTransaction?: string): Promise<string> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n\n const options: TransactionOptions = {\n readWrite: retryTransaction ? { retryTransaction } : {},\n };\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:beginTransaction`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ options }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n `Failed to begin transaction: ${JSON.stringify(error)}`,\n );\n }\n\n const result: BeginTransactionResponse = await response.json();\n return result.transaction;\n }\n\n /** @internal */\n async _commitTransaction(\n transactionId: string,\n writes: Write[],\n ): Promise<CommitResponse> {\n const token = await this._getToken();\n const database = this._getDatabasePath();\n\n const response = await fetch(\n `${API_BASE}/${database}/documents:commit`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n writes,\n transaction: transactionId,\n }),\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n `Failed to commit transaction: ${JSON.stringify(error)}`,\n );\n }\n\n return response.json();\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fires2rest",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Lightweight Firestore REST API client with full transaction support for serverless environments",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@changesets/changelog-github": "^0.5.2",
|
|
43
43
|
"@changesets/cli": "^2.29.8",
|
|
44
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
44
45
|
"dotenv": "^17.2.3",
|
|
45
46
|
"firebase-admin": "^13.6.0",
|
|
46
47
|
"prettier": "^3.7.4",
|