@cocreate/firestore 1.0.0 → 1.1.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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [1.1.0](https://github.com/CoCreate-app/CoCreate-firestore/compare/v1.0.0...v1.1.0) (2026-07-18)
2
+
3
+
4
+ ### Features
5
+
6
+ * Enhance Firestore client connection handling and normalize storage URL usage ([a97f76b](https://github.com/CoCreate-app/CoCreate-firestore/commit/a97f76b0dde45697e24875af2436e3b53c3b5b8f))
7
+
1
8
  # 1.0.0 (2026-07-18)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/firestore",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A simple firestore component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "firestore",
package/src/index.js CHANGED
@@ -12,26 +12,43 @@ const organizations = {};
12
12
  /**
13
13
  * Dynamically resolves or caches a long-lived Firestore database client connection.
14
14
  * Caches the connection promise to prevent duplicate authentication handshakes.
15
- * Normalizes custom credential protocols directly out of standard CoCreate storageUrls.
15
+ * Normalizes custom credential protocols directly out of standard CoCreate storageUrls or urls.
16
16
  */
17
17
  async function dbClient(data) {
18
- if (data.storageUrl) {
18
+ const storageUrl = data.storageUrl || data.url;
19
+ const storageName = data.storageName || data.provider || "firestore";
20
+
21
+ if (storageUrl) {
19
22
  if (!organizations[data.organization_id]) {
20
23
  organizations[data.organization_id] = {};
21
24
  }
22
25
  try {
23
- if (!organizations[data.organization_id][data.storageUrl]) {
26
+ if (!organizations[data.organization_id][storageUrl]) {
24
27
  const connectionPromise = (async () => {
25
28
  let config = {};
26
29
 
27
- // Option A: The Credentials Path URL (e.g. firestore:///path/to/credentials.json)
28
- if (data.storageUrl.startsWith("firestore:///")) {
29
- const filePath = data.storageUrl.replace("firestore://", "");
30
+ // Option A: The Structured Credentials Object (Highly recommended)
31
+ if (typeof storageUrl === "object" && storageUrl !== null) {
32
+ const projectId = storageUrl.projectId || storageUrl.project_id;
33
+ const clientEmail = storageUrl.clientEmail || storageUrl.client_email;
34
+ const privateKey = storageUrl.privateKey || storageUrl.private_key;
35
+
36
+ config = {
37
+ projectId,
38
+ credentials: {
39
+ client_email: clientEmail,
40
+ private_key: privateKey ? privateKey.replace(/\\n/g, "\n") : undefined
41
+ }
42
+ };
43
+ }
44
+ // Option B: The Credentials Path URL (e.g. firestore:///path/to/credentials.json)
45
+ else if (typeof storageUrl === "string" && storageUrl.startsWith("firestore:///")) {
46
+ const filePath = storageUrl.replace("firestore://", "");
30
47
  config = { keyFilename: filePath };
31
48
  }
32
- // Option B: Query Params Encoded URI (e.g. firestore://project-id?client_email=...&private_key=...)
33
- else if (data.storageUrl.startsWith("firestore://")) {
34
- const urlParsed = new URL(data.storageUrl);
49
+ // Option C: Query Params Encoded URI (e.g. firestore://project-id?client_email=...&private_key=...)
50
+ else if (typeof storageUrl === "string" && storageUrl.startsWith("firestore://")) {
51
+ const urlParsed = new URL(storageUrl);
35
52
  const projectId = urlParsed.host || urlParsed.hostname;
36
53
  const clientEmail = urlParsed.searchParams.get("client_email");
37
54
  const privateKey = urlParsed.searchParams.get("private_key");
@@ -57,21 +74,21 @@ async function dbClient(data) {
57
74
  return client;
58
75
  })();
59
76
 
60
- organizations[data.organization_id][data.storageUrl] = connectionPromise;
77
+ organizations[data.organization_id][storageUrl] = connectionPromise;
61
78
  }
62
79
 
63
80
  // Await connection resolution safely
64
- return await organizations[data.organization_id][data.storageUrl];
81
+ return await organizations[data.organization_id][storageUrl];
65
82
  } catch (error) {
66
83
  console.error(
67
- `${data.organization_id}: storageUrl ${data.storageUrl} failed to connect to Firestore`
84
+ `${data.organization_id}: Firestore failed to connect`
68
85
  );
69
86
  errorHandler(data, error);
70
87
  return { status: false };
71
88
  }
72
89
  }
73
90
 
74
- errorHandler(data, "missing StorageUrl");
91
+ errorHandler(data, "missing Firestore Connection URL/Credentials");
75
92
  return;
76
93
  }
77
94
 
@@ -121,6 +138,7 @@ function send(data) {
121
138
  * "database" operations mapped to Firestore Databases.
122
139
  */
123
140
  function database(method, data) {
141
+ const storageName = data.storageName || data.provider || "firestore";
124
142
  return new Promise(
125
143
  async (resolve, reject) => {
126
144
  let type = "database";
@@ -147,13 +165,13 @@ function database(method, data) {
147
165
  if (isFilter) {
148
166
  databaseArray.push({
149
167
  database: dbObj,
150
- storage: data.storageName
168
+ storage: storageName
151
169
  });
152
170
  }
153
171
  } else {
154
172
  databaseArray.push({
155
173
  database: dbObj,
156
- storage: data.storageName
174
+ storage: storageName
157
175
  });
158
176
  }
159
177
  resolve(createData(data, databaseArray, type));
@@ -187,6 +205,7 @@ function database(method, data) {
187
205
  * "array" operations mapped to Firestore Collections.
188
206
  */
189
207
  function array(method, data) {
208
+ const storageName = data.storageName || data.provider || "firestore";
190
209
  return new Promise(
191
210
  async (resolve, reject) => {
192
211
  let type = "array";
@@ -220,14 +239,14 @@ function array(method, data) {
220
239
  arrayArray.push({
221
240
  name: col.id,
222
241
  database,
223
- storage: data.storageName
242
+ storage: storageName
224
243
  });
225
244
  }
226
245
  } else {
227
246
  arrayArray.push({
228
247
  name: col.id,
229
248
  database,
230
- storage: data.storageName
249
+ storage: storageName
231
250
  });
232
251
  }
233
252
  }
@@ -260,7 +279,7 @@ function array(method, data) {
260
279
  arrayArray.push({
261
280
  name: array,
262
281
  database,
263
- storage: data.storageName
282
+ storage: storageName
264
283
  });
265
284
 
266
285
  arraysLength -= 1;
@@ -295,7 +314,7 @@ function array(method, data) {
295
314
  name: newName,
296
315
  oldName: oldName,
297
316
  database,
298
- storage: data.storageName
317
+ storage: storageName
299
318
  });
300
319
 
301
320
  arraysLength -= 1;
@@ -319,7 +338,7 @@ function array(method, data) {
319
338
  arrayArray.push({
320
339
  name: array,
321
340
  database,
322
- storage: data.storageName
341
+ storage: storageName
323
342
  });
324
343
 
325
344
  arraysLength -= 1;
@@ -349,6 +368,7 @@ function array(method, data) {
349
368
  * "object" operations mapped to Firestore Documents.
350
369
  */
351
370
  function object(method, data) {
371
+ const storageName = data.storageName || data.provider || "firestore";
352
372
  return new Promise(
353
373
  async (resolve, reject) => {
354
374
  try {
@@ -371,7 +391,7 @@ function object(method, data) {
371
391
 
372
392
  for (let array of arrays) {
373
393
  const reference = {
374
- $storage: data.storageName,
394
+ $storage: storageName,
375
395
  $database: database,
376
396
  $array: array
377
397
  };
@@ -396,7 +416,7 @@ function object(method, data) {
396
416
  if (!Array.isArray($database)) $database = [data[type][i].$database];
397
417
  if (!Array.isArray($array)) $array = [data[type][i].$array];
398
418
 
399
- if (!$storage.includes(data.storageName)) $storage.push(data.storageName);
419
+ if (!$storage.includes(storageName)) $storage.push(storageName);
400
420
  if (!$database.includes(database)) $database.push(database);
401
421
  if (!$array.includes(array)) $array.push(array);
402
422
 
@@ -456,7 +476,6 @@ function object(method, data) {
456
476
  queryRef = queryRef.limit(data.$filter.limit);
457
477
  }
458
478
  if (data.$filter && typeof data.$filter.index === "number") {
459
- // Standard offset queries are supported but startAt is normally preferred in production
460
479
  queryRef = queryRef.offset(data.$filter.index);
461
480
  }
462
481