firebase-rest-firestore 1.2.0 → 1.6.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.
- package/README.md +37 -0
- package/dist/cjs/client.d.ts +454 -0
- package/dist/cjs/client.js +1192 -0
- package/dist/cjs/field-value.d.ts +22 -0
- package/dist/cjs/field-value.js +31 -0
- package/dist/{index.d.ts → cjs/index.d.ts} +2 -1
- package/dist/{index.js → cjs/index.js} +4 -2
- package/dist/cjs/types.d.ts +146 -0
- package/dist/cjs/types.js +75 -0
- package/dist/cjs/utils/auth.d.ts +13 -0
- package/dist/{utils → cjs/utils}/auth.js +14 -10
- package/dist/cjs/utils/config.d.ts +6 -0
- package/dist/{utils → cjs/utils}/config.js +0 -12
- package/dist/cjs/utils/converter.d.ts +57 -0
- package/dist/cjs/utils/converter.js +224 -0
- package/dist/cjs/utils/path.d.ts +73 -0
- package/dist/cjs/utils/path.js +176 -0
- package/dist/esm/client.d.ts +454 -0
- package/dist/esm/client.js +1180 -0
- package/dist/esm/field-value.d.ts +22 -0
- package/dist/esm/field-value.js +27 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +13 -0
- package/dist/esm/types.d.ts +146 -0
- package/dist/esm/types.js +70 -0
- package/dist/esm/utils/auth.d.ts +13 -0
- package/dist/esm/utils/auth.js +57 -0
- package/dist/esm/utils/config.d.ts +6 -0
- package/dist/esm/utils/config.js +11 -0
- package/dist/esm/utils/converter.d.ts +57 -0
- package/dist/esm/utils/converter.js +216 -0
- package/dist/esm/utils/path.d.ts +73 -0
- package/dist/esm/utils/path.js +169 -0
- package/dist/types/client.d.ts +454 -0
- package/dist/types/field-value.d.ts +22 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/types.d.ts +146 -0
- package/dist/types/utils/auth.d.ts +13 -0
- package/dist/types/utils/config.d.ts +6 -0
- package/dist/types/utils/converter.d.ts +57 -0
- package/dist/types/utils/path.d.ts +73 -0
- package/package.json +19 -5
- package/dist/client.d.ts +0 -381
- package/dist/client.js +0 -915
- package/dist/types.d.ts +0 -65
- package/dist/types.js +0 -2
- package/dist/utils/auth.d.ts +0 -13
- package/dist/utils/config.d.ts +0 -13
- package/dist/utils/converter.d.ts +0 -27
- package/dist/utils/converter.js +0 -113
- package/dist/utils/path.d.ts +0 -14
- package/dist/utils/path.js +0 -27
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertToFirestoreValue = convertToFirestoreValue;
|
|
4
|
+
exports.convertFromFirestoreValue = convertFromFirestoreValue;
|
|
5
|
+
exports.convertToFirestoreDocument = convertToFirestoreDocument;
|
|
6
|
+
exports.extractFieldTransforms = extractFieldTransforms;
|
|
7
|
+
exports.buildCommitWrite = buildCommitWrite;
|
|
8
|
+
exports.convertFromFirestoreDocument = convertFromFirestoreDocument;
|
|
9
|
+
const client_1 = require("../client");
|
|
10
|
+
const field_value_1 = require("../field-value");
|
|
11
|
+
const types_1 = require("../types");
|
|
12
|
+
const path_1 = require("./path");
|
|
13
|
+
/**
|
|
14
|
+
* JSの値をFirestore形式に変換する
|
|
15
|
+
* @param value 変換する値
|
|
16
|
+
* @returns Firestore形式の値
|
|
17
|
+
*/
|
|
18
|
+
function convertToFirestoreValue(value) {
|
|
19
|
+
if (value instanceof field_value_1.FieldValue) {
|
|
20
|
+
// Sentinels (e.g. serverTimestamp) must be extracted into field transforms
|
|
21
|
+
// before conversion. Reaching here means one was used where Firestore
|
|
22
|
+
// cannot express a transform (such as inside an array).
|
|
23
|
+
throw new Error("FieldValue (e.g. serverTimestamp()) can only be used as a top-level or nested document field value, not inside an array.");
|
|
24
|
+
}
|
|
25
|
+
if (value instanceof Date) {
|
|
26
|
+
return { timestampValue: value.toISOString() };
|
|
27
|
+
}
|
|
28
|
+
else if (value instanceof client_1.DocumentReference) {
|
|
29
|
+
return { referenceValue: value.referenceValue };
|
|
30
|
+
}
|
|
31
|
+
else if (value instanceof types_1.LiteralDocumentReference) {
|
|
32
|
+
return { referenceValue: value.referenceValue };
|
|
33
|
+
}
|
|
34
|
+
else if (value instanceof types_1.LiteralGeoPointValue) {
|
|
35
|
+
return { geoPointValue: value.geoPointValue };
|
|
36
|
+
}
|
|
37
|
+
else if (typeof value === "string") {
|
|
38
|
+
return { stringValue: value };
|
|
39
|
+
}
|
|
40
|
+
else if (typeof value === "number") {
|
|
41
|
+
return Number.isInteger(value)
|
|
42
|
+
? { integerValue: value }
|
|
43
|
+
: { doubleValue: value };
|
|
44
|
+
}
|
|
45
|
+
else if (typeof value === "boolean") {
|
|
46
|
+
return { booleanValue: value };
|
|
47
|
+
}
|
|
48
|
+
else if (value === null || value === undefined) {
|
|
49
|
+
return { nullValue: null };
|
|
50
|
+
}
|
|
51
|
+
else if (Array.isArray(value)) {
|
|
52
|
+
return {
|
|
53
|
+
arrayValue: {
|
|
54
|
+
values: value.map(item => convertToFirestoreValue(item)),
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
else if (typeof value === "object") {
|
|
59
|
+
const fields = Object.entries(value).reduce((acc, [key, val]) => ({
|
|
60
|
+
...acc,
|
|
61
|
+
[key]: convertToFirestoreValue(val),
|
|
62
|
+
}), {});
|
|
63
|
+
return { mapValue: { fields } };
|
|
64
|
+
}
|
|
65
|
+
// デフォルトは文字列化
|
|
66
|
+
return { stringValue: String(value) };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Firestore形式からJSの値に変換する
|
|
70
|
+
* @param firestoreValue Firestore形式の値
|
|
71
|
+
* @returns JS形式の値
|
|
72
|
+
*/
|
|
73
|
+
function convertFromFirestoreValue(firestoreValue) {
|
|
74
|
+
if ("stringValue" in firestoreValue) {
|
|
75
|
+
return firestoreValue.stringValue;
|
|
76
|
+
}
|
|
77
|
+
else if ("integerValue" in firestoreValue) {
|
|
78
|
+
return Number(firestoreValue.integerValue);
|
|
79
|
+
}
|
|
80
|
+
else if ("doubleValue" in firestoreValue) {
|
|
81
|
+
return firestoreValue.doubleValue;
|
|
82
|
+
}
|
|
83
|
+
else if ("booleanValue" in firestoreValue) {
|
|
84
|
+
return firestoreValue.booleanValue;
|
|
85
|
+
}
|
|
86
|
+
else if ("nullValue" in firestoreValue) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
else if ("timestampValue" in firestoreValue) {
|
|
90
|
+
return new Date(firestoreValue.timestampValue);
|
|
91
|
+
}
|
|
92
|
+
else if ("geoPointValue" in firestoreValue) {
|
|
93
|
+
return new types_1.LiteralGeoPointValue(firestoreValue);
|
|
94
|
+
}
|
|
95
|
+
else if ("referenceValue" in firestoreValue) {
|
|
96
|
+
return new types_1.LiteralDocumentReference(firestoreValue);
|
|
97
|
+
}
|
|
98
|
+
else if ("mapValue" in firestoreValue && firestoreValue.mapValue.fields) {
|
|
99
|
+
return Object.entries(firestoreValue.mapValue.fields).reduce((acc, [key, val]) => ({
|
|
100
|
+
...acc,
|
|
101
|
+
[key]: convertFromFirestoreValue(val),
|
|
102
|
+
}), {});
|
|
103
|
+
}
|
|
104
|
+
else if ("arrayValue" in firestoreValue) {
|
|
105
|
+
// The `values` field can be undefined, meaning that this is an empty array
|
|
106
|
+
return (firestoreValue.arrayValue.values ?? []).map(convertFromFirestoreValue);
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* オブジェクトをFirestoreドキュメント形式に変換
|
|
112
|
+
* @param data 変換するオブジェクト
|
|
113
|
+
* @returns Firestoreドキュメント
|
|
114
|
+
*/
|
|
115
|
+
function convertToFirestoreDocument(data) {
|
|
116
|
+
return {
|
|
117
|
+
fields: Object.entries(data).reduce((acc, [key, value]) => ({
|
|
118
|
+
...acc,
|
|
119
|
+
[key]: convertToFirestoreValue(value),
|
|
120
|
+
}), {}),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Whether a value is a plain JS object (`{}` / `Object.create(null)`), as
|
|
125
|
+
* opposed to a class instance such as `Date`, `DocumentReference`,
|
|
126
|
+
* `LiteralGeoPointValue`, `LiteralDocumentReference`, `FieldValue`, or an array.
|
|
127
|
+
* Only plain objects are recursed into when extracting field transforms.
|
|
128
|
+
*/
|
|
129
|
+
function isPlainObject(value) {
|
|
130
|
+
if (value === null || typeof value !== "object")
|
|
131
|
+
return false;
|
|
132
|
+
const proto = Object.getPrototypeOf(value);
|
|
133
|
+
return proto === Object.prototype || proto === null;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Escape a single field name for use in a Firestore field path. Simple names
|
|
137
|
+
* (`[A-Za-z_][A-Za-z0-9_]*`) are used as-is; anything else (dashes, dots,
|
|
138
|
+
* leading digits, spaces, ...) is wrapped in backticks with `\` and `` ` ``
|
|
139
|
+
* escaped, so a literal dot in a key is treated as part of the name rather than
|
|
140
|
+
* a path separator.
|
|
141
|
+
* See: https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents#Document
|
|
142
|
+
*/
|
|
143
|
+
function escapeFieldPathSegment(segment) {
|
|
144
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(segment)) {
|
|
145
|
+
return segment;
|
|
146
|
+
}
|
|
147
|
+
return "`" + segment.replace(/\\/g, "\\\\").replace(/`/g, "\\`") + "`";
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Split write data into plain field values and Firestore field transforms.
|
|
151
|
+
*
|
|
152
|
+
* `FieldValue` sentinels (e.g. `serverTimestamp()`) are pulled out into
|
|
153
|
+
* transforms keyed by their (escaped, dot-separated) field path; everything
|
|
154
|
+
* else is left untouched in `fields`. Recursion only descends into plain
|
|
155
|
+
* objects, so class instances (Date / references / geo points) are treated as
|
|
156
|
+
* leaves.
|
|
157
|
+
*
|
|
158
|
+
* @param data Write data (JS values, may contain FieldValue sentinels)
|
|
159
|
+
* @param prefix Field-path prefix used while recursing (internal, pre-escaped)
|
|
160
|
+
*/
|
|
161
|
+
function extractFieldTransforms(data, prefix = "") {
|
|
162
|
+
const fields = {};
|
|
163
|
+
const transforms = [];
|
|
164
|
+
for (const [key, value] of Object.entries(data)) {
|
|
165
|
+
const escapedKey = escapeFieldPathSegment(key);
|
|
166
|
+
const fieldPath = prefix ? `${prefix}.${escapedKey}` : escapedKey;
|
|
167
|
+
if (value instanceof field_value_1.FieldValue) {
|
|
168
|
+
if (value.methodName === "serverTimestamp") {
|
|
169
|
+
transforms.push({ fieldPath, setToServerValue: "REQUEST_TIME" });
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
throw new Error(`Unsupported FieldValue: ${value.methodName}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else if (isPlainObject(value)) {
|
|
176
|
+
const nested = extractFieldTransforms(value, fieldPath);
|
|
177
|
+
fields[key] = nested.fields;
|
|
178
|
+
transforms.push(...nested.transforms);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
fields[key] = value;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return { fields, transforms };
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build a single `documents:commit` write that updates a document and applies
|
|
188
|
+
* field transforms. `updateTransforms` / `currentDocument` are only included
|
|
189
|
+
* when relevant.
|
|
190
|
+
*
|
|
191
|
+
* @param documentName Full resource name (projects/.../documents/<path>)
|
|
192
|
+
* @param fields Already-converted Firestore field values
|
|
193
|
+
* @param transforms Field transforms to apply after the update
|
|
194
|
+
* @param currentDocument Optional precondition (e.g. `{ exists: false }`)
|
|
195
|
+
*/
|
|
196
|
+
function buildCommitWrite(documentName, fields, transforms, currentDocument) {
|
|
197
|
+
const write = {
|
|
198
|
+
update: { name: documentName, fields },
|
|
199
|
+
};
|
|
200
|
+
if (transforms.length > 0) {
|
|
201
|
+
write.updateTransforms = transforms;
|
|
202
|
+
}
|
|
203
|
+
if (currentDocument) {
|
|
204
|
+
write.currentDocument = currentDocument;
|
|
205
|
+
}
|
|
206
|
+
return write;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Firestoreドキュメントをオブジェクトに変換
|
|
210
|
+
* @param doc Firestoreレスポンス
|
|
211
|
+
* @returns 変換されたオブジェクト(idプロパティ付き)
|
|
212
|
+
*/
|
|
213
|
+
function convertFromFirestoreDocument(doc) {
|
|
214
|
+
if (!doc.fields)
|
|
215
|
+
return { id: (0, path_1.getDocumentId)(doc.name) };
|
|
216
|
+
const result = Object.entries(doc.fields).reduce((acc, [key, value]) => ({
|
|
217
|
+
...acc,
|
|
218
|
+
[key]: convertFromFirestoreValue(value),
|
|
219
|
+
}), {});
|
|
220
|
+
return {
|
|
221
|
+
...result,
|
|
222
|
+
id: (0, path_1.getDocumentId)(doc.name),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { FirestoreConfig } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Utility class for constructing Firestore URIs
|
|
4
|
+
* Consistently handles different types of paths and operations
|
|
5
|
+
*/
|
|
6
|
+
export declare class FirestorePath {
|
|
7
|
+
private projectId;
|
|
8
|
+
private databaseId;
|
|
9
|
+
private useEmulator;
|
|
10
|
+
private emulatorHost;
|
|
11
|
+
private emulatorPort;
|
|
12
|
+
private debug;
|
|
13
|
+
/**
|
|
14
|
+
* Constructor
|
|
15
|
+
*/
|
|
16
|
+
constructor(config: FirestoreConfig, debug?: boolean);
|
|
17
|
+
/**
|
|
18
|
+
* Get Firestore base URL (without document path)
|
|
19
|
+
*/
|
|
20
|
+
getBasePath(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Get base URL + collection path for a collection root
|
|
23
|
+
* @param path Collection path (ex: "users" or "users/uid/posts")
|
|
24
|
+
*/
|
|
25
|
+
getCollectionPath(path: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Get the complete URL for a document
|
|
28
|
+
* @param collectionPath Collection path
|
|
29
|
+
* @param documentId Document ID
|
|
30
|
+
*/
|
|
31
|
+
getDocumentPath(collectionPath: string, documentId: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Get URL for query execution
|
|
34
|
+
* @param path Collection path (ex: "users" or "users/uid/posts")
|
|
35
|
+
* @returns URL for query execution, collection ID, and parent path (if needed)
|
|
36
|
+
*/
|
|
37
|
+
getQueryPath(path: string): {
|
|
38
|
+
url: string;
|
|
39
|
+
collectionId: string;
|
|
40
|
+
parentPath?: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Get reference path for parent document (for query construction)
|
|
44
|
+
* @param parentPath Parent document path
|
|
45
|
+
*/
|
|
46
|
+
getParentReference(parentPath: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Get URL for runQuery
|
|
49
|
+
* @param collectionPath Collection path
|
|
50
|
+
* @returns URL for executing runQuery
|
|
51
|
+
*/
|
|
52
|
+
getRunQueryPath(collectionPath: string): string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create an instance of FirestorePath class
|
|
56
|
+
* @param config Firestore configuration
|
|
57
|
+
* @param debug Debug mode
|
|
58
|
+
*/
|
|
59
|
+
export declare function createFirestorePath(config: FirestoreConfig, debug?: boolean): FirestorePath;
|
|
60
|
+
/**
|
|
61
|
+
* Get Firestore base path URL (without path)
|
|
62
|
+
* @param projectId Project ID
|
|
63
|
+
* @param databaseId Database ID (defaults to default)
|
|
64
|
+
* @param config Firestore configuration (for emulator settings)
|
|
65
|
+
* @returns Firestore base path URL (without path)
|
|
66
|
+
*/
|
|
67
|
+
export declare function getFirestoreBasePath(projectId: string, databaseId?: string, config?: FirestoreConfig): string;
|
|
68
|
+
/**
|
|
69
|
+
* Extract document ID from document path
|
|
70
|
+
* @param path Document path
|
|
71
|
+
* @returns Document ID
|
|
72
|
+
*/
|
|
73
|
+
export declare function getDocumentId(path: string): string;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FirestorePath = void 0;
|
|
4
|
+
exports.createFirestorePath = createFirestorePath;
|
|
5
|
+
exports.getFirestoreBasePath = getFirestoreBasePath;
|
|
6
|
+
exports.getDocumentId = getDocumentId;
|
|
7
|
+
/**
|
|
8
|
+
* Utility class for constructing Firestore URIs
|
|
9
|
+
* Consistently handles different types of paths and operations
|
|
10
|
+
*/
|
|
11
|
+
class FirestorePath {
|
|
12
|
+
/**
|
|
13
|
+
* Constructor
|
|
14
|
+
*/
|
|
15
|
+
constructor(config, debug = false) {
|
|
16
|
+
this.useEmulator = false;
|
|
17
|
+
this.emulatorHost = "localhost";
|
|
18
|
+
this.emulatorPort = 8080;
|
|
19
|
+
this.debug = false;
|
|
20
|
+
this.projectId = config.projectId;
|
|
21
|
+
this.databaseId = config.databaseId || "(default)";
|
|
22
|
+
this.debug = debug;
|
|
23
|
+
if (config.useEmulator) {
|
|
24
|
+
this.useEmulator = true;
|
|
25
|
+
this.emulatorHost = config.emulatorHost || "localhost";
|
|
26
|
+
this.emulatorPort = config.emulatorPort || 8080;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get Firestore base URL (without document path)
|
|
31
|
+
*/
|
|
32
|
+
getBasePath() {
|
|
33
|
+
const baseUrl = this.useEmulator
|
|
34
|
+
? `http://${this.emulatorHost}:${this.emulatorPort}/v1`
|
|
35
|
+
: "https://firestore.googleapis.com/v1";
|
|
36
|
+
const path = `${baseUrl}/projects/${this.projectId}/databases/${this.databaseId}/documents`;
|
|
37
|
+
if (this.debug) {
|
|
38
|
+
console.log(`Generated base path: ${path}`);
|
|
39
|
+
}
|
|
40
|
+
return path;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get base URL + collection path for a collection root
|
|
44
|
+
* @param path Collection path (ex: "users" or "users/uid/posts")
|
|
45
|
+
*/
|
|
46
|
+
getCollectionPath(path) {
|
|
47
|
+
// Remove leading and trailing slashes
|
|
48
|
+
const cleanPath = path.replace(/^\/+|\/+$/g, '');
|
|
49
|
+
const fullPath = `${this.getBasePath()}/${cleanPath}`;
|
|
50
|
+
if (this.debug) {
|
|
51
|
+
console.log(`Generated collection path: ${fullPath}`);
|
|
52
|
+
}
|
|
53
|
+
return fullPath;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the complete URL for a document
|
|
57
|
+
* @param collectionPath Collection path
|
|
58
|
+
* @param documentId Document ID
|
|
59
|
+
*/
|
|
60
|
+
getDocumentPath(collectionPath, documentId) {
|
|
61
|
+
const cleanCollectionPath = collectionPath.replace(/^\/+|\/+$/g, '');
|
|
62
|
+
const path = `${this.getBasePath()}/${cleanCollectionPath}/${documentId}`;
|
|
63
|
+
if (this.debug) {
|
|
64
|
+
console.log(`Generated document path: ${path}`);
|
|
65
|
+
}
|
|
66
|
+
return path;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get URL for query execution
|
|
70
|
+
* @param path Collection path (ex: "users" or "users/uid/posts")
|
|
71
|
+
* @returns URL for query execution, collection ID, and parent path (if needed)
|
|
72
|
+
*/
|
|
73
|
+
getQueryPath(path) {
|
|
74
|
+
// パスをセグメントに分割
|
|
75
|
+
const segments = path.replace(/^\/+|\/+$/g, '').split('/');
|
|
76
|
+
// 単一コレクションの場合
|
|
77
|
+
if (segments.length === 1) {
|
|
78
|
+
const url = `${this.getBasePath()}:runQuery`;
|
|
79
|
+
if (this.debug) {
|
|
80
|
+
console.log(`Generated query URL (single collection): ${url}`);
|
|
81
|
+
console.log(`Collection ID: ${segments[0]}`);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
url,
|
|
85
|
+
collectionId: segments[0]
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// ネストしたコレクションパスの場合 (例: "users/uid/posts")
|
|
89
|
+
const collectionId = segments[segments.length - 1];
|
|
90
|
+
const parentSegments = segments.slice(0, -1);
|
|
91
|
+
const parentPath = parentSegments.join('/');
|
|
92
|
+
// ベースURLでネストしたドキュメントまでのパスを取得
|
|
93
|
+
const url = `${this.getBasePath()}:runQuery`;
|
|
94
|
+
if (this.debug) {
|
|
95
|
+
console.log(`Generated query URL (nested collection): ${url}`);
|
|
96
|
+
console.log(`Collection ID: ${collectionId}`);
|
|
97
|
+
console.log(`Parent path: ${parentPath}`);
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
url,
|
|
101
|
+
collectionId,
|
|
102
|
+
parentPath
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get reference path for parent document (for query construction)
|
|
107
|
+
* @param parentPath Parent document path
|
|
108
|
+
*/
|
|
109
|
+
getParentReference(parentPath) {
|
|
110
|
+
return `projects/${this.projectId}/databases/${this.databaseId}/documents/${parentPath}`;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get URL for runQuery
|
|
114
|
+
* @param collectionPath Collection path
|
|
115
|
+
* @returns URL for executing runQuery
|
|
116
|
+
*/
|
|
117
|
+
getRunQueryPath(collectionPath) {
|
|
118
|
+
// コレクションパス情報を取得
|
|
119
|
+
const { collectionId, parentPath } = this.getQueryPath(collectionPath);
|
|
120
|
+
// parentPathがある場合は、親ドキュメントパスを使用してURLを作成
|
|
121
|
+
if (parentPath) {
|
|
122
|
+
// getBasePathからベースURLを取得
|
|
123
|
+
const baseUrl = this.getBasePath().replace(/\/documents$/, '');
|
|
124
|
+
// 親ドキュメントパスを含むrunQueryのURL
|
|
125
|
+
const runQueryUrl = `${baseUrl}/documents/${parentPath}:runQuery`;
|
|
126
|
+
if (this.debug) {
|
|
127
|
+
console.log(`Generated runQuery URL for nested collection: ${runQueryUrl}`);
|
|
128
|
+
console.log(`Collection ID: ${collectionId}`);
|
|
129
|
+
}
|
|
130
|
+
return runQueryUrl;
|
|
131
|
+
}
|
|
132
|
+
// トップレベルコレクションの場合は、ベースパスを使用
|
|
133
|
+
const baseUrl = this.getBasePath();
|
|
134
|
+
const runQueryUrl = `${baseUrl}:runQuery`;
|
|
135
|
+
if (this.debug) {
|
|
136
|
+
console.log(`Generated runQuery URL for top-level collection: ${runQueryUrl}`);
|
|
137
|
+
console.log(`Collection ID: ${collectionId}`);
|
|
138
|
+
}
|
|
139
|
+
return runQueryUrl;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.FirestorePath = FirestorePath;
|
|
143
|
+
/**
|
|
144
|
+
* Create an instance of FirestorePath class
|
|
145
|
+
* @param config Firestore configuration
|
|
146
|
+
* @param debug Debug mode
|
|
147
|
+
*/
|
|
148
|
+
function createFirestorePath(config, debug = false) {
|
|
149
|
+
return new FirestorePath(config, debug);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get Firestore base path URL (without path)
|
|
153
|
+
* @param projectId Project ID
|
|
154
|
+
* @param databaseId Database ID (defaults to default)
|
|
155
|
+
* @param config Firestore configuration (for emulator settings)
|
|
156
|
+
* @returns Firestore base path URL (without path)
|
|
157
|
+
*/
|
|
158
|
+
function getFirestoreBasePath(projectId, databaseId, config) {
|
|
159
|
+
// Use emulator URL for emulator mode
|
|
160
|
+
if (config?.useEmulator) {
|
|
161
|
+
const host = config.emulatorHost || "127.0.0.1";
|
|
162
|
+
const port = config.emulatorPort || 8080;
|
|
163
|
+
return `http://${host}:${port}/v1/projects/${projectId}/databases/${databaseId || "(default)"}/documents`;
|
|
164
|
+
}
|
|
165
|
+
// Use normal production environment URL
|
|
166
|
+
return `https://firestore.googleapis.com/v1/projects/${projectId}/databases/${databaseId || "(default)"}/documents`;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Extract document ID from document path
|
|
170
|
+
* @param path Document path
|
|
171
|
+
* @returns Document ID
|
|
172
|
+
*/
|
|
173
|
+
function getDocumentId(path) {
|
|
174
|
+
const parts = path.split("/");
|
|
175
|
+
return parts[parts.length - 1];
|
|
176
|
+
}
|