@stoker-platform/cli 0.5.101 → 0.5.102

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.
@@ -8,6 +8,7 @@ GCP_FOLDER=""
8
8
 
9
9
  FB_GOOGLE_ANALYTICS_ACCOUNT_ID=""
10
10
 
11
+ FB_FIRESTORE_EDITION="enterprise"
11
12
  FB_FIRESTORE_REGION="australia-southeast2"
12
13
  FB_FIRESTORE_ENABLE_PITR=true
13
14
  FB_FIRESTORE_BACKUP_RECURRENCE="daily"
@@ -4,6 +4,7 @@ import { fileURLToPath } from "url"
4
4
  import { dirname, join } from "path"
5
5
  import { readFile, writeFile, readdir } from "fs/promises"
6
6
  import { existsSync, cpSync, rmSync } from "fs"
7
+ import { getFirestoreDatabaseId } from "@stoker-platform/utils"
7
8
  import dotenv from "dotenv"
8
9
 
9
10
  const envDir = join(process.cwd(), ".env")
@@ -101,6 +102,7 @@ try {
101
102
  "SMTP_CONNECTION_URI=",
102
103
  "firebaseextensions.v1beta.function/location=",
103
104
  "DATABASE_REGION=",
105
+ "DATABASE=",
104
106
  ]
105
107
  const filteredLines = extensionEnvFileLines.filter(
106
108
  (line) => !linesToRemove.some((removeStr) => line.startsWith(removeStr)),
@@ -113,6 +115,7 @@ try {
113
115
  filteredLines.push(`DEFAULT_REPLY_TO=${mailSender.split("=")[1].replace(/^"|"$/g, "")}`)
114
116
  filteredLines.push(`SMTP_CONNECTION_URI=${mailSmtpConnectionUri.split("=")[1].replace(/^"|"$/g, "")}`)
115
117
  filteredLines.push(`DATABASE_REGION=${databaseRegion.split("=")[1].replace(/^"|"$/g, "")}`)
118
+ filteredLines.push(`DATABASE=${getFirestoreDatabaseId(process.env.FB_FIRESTORE_EDITION, process.env.GCP_PROJECT)}`)
116
119
  await writeFile(join(__dirname, "..", "extensions", "firestore-send-email.env"), filteredLines.join("\n"))
117
120
 
118
121
  // Create functions .env file with filtered environment variables
@@ -122,7 +125,7 @@ try {
122
125
  const projectSpecificEnvFile = join(envDir, `.env.${process.env.GCP_PROJECT}`)
123
126
 
124
127
  let envContent = ""
125
- const envPattern = /^(FB_FUNCTIONS_|FB_AI_REGION|STOKER_|ADMIN_)/
128
+ const envPattern = /^(FB_FIRESTORE_EDITION|FB_FUNCTIONS_|FB_AI_REGION|STOKER_|ADMIN_)/
126
129
 
127
130
  if (existsSync(projectEnvFile)) {
128
131
  const projectEnvContent = await readFile(projectEnvFile, "utf8")
@@ -39,6 +39,7 @@ import {defineSecret} from "firebase-functions/params";
39
39
  import {readFileSync} from "fs";
40
40
  import {
41
41
  getPathCollections,
42
+ getFirestoreTriggerDatabase,
42
43
  roleHasOperationAccess,
43
44
  } from "@stoker-platform/utils";
44
45
  import {
@@ -67,6 +68,12 @@ const consumeAppCheckToken =
67
68
  process.env.FB_FUNCTIONS_CONSUME_APP_CHECK_TOKEN === "true";
68
69
  const v1Region = process.env.FB_FUNCTIONS_V1_REGION ||
69
70
  process.env.FB_FUNCTIONS_REGION;
71
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
72
+ const webAppConfig = JSON.parse(process.env.STOKER_FB_WEB_APP_CONFIG!);
73
+ const projectId = webAppConfig.projectId;
74
+ const firestoreDatabase =
75
+ getFirestoreTriggerDatabase(process.env.FB_FIRESTORE_EDITION, projectId);
76
+
70
77
 
71
78
  const ai = genkit({
72
79
  plugins: [vertexAI({
@@ -83,6 +90,7 @@ export const stoker: any = {};
83
90
 
84
91
  stoker["notifications"] = onDocumentCreated({
85
92
  document: "tenants/{tenantId}/Inbox/{messageId}",
93
+ database: firestoreDatabase,
86
94
  }, (event) => {
87
95
  return messageNotifications(
88
96
  event,
@@ -182,6 +190,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
182
190
  stoker[`validatefields${collectionNameLower}`] =
183
191
  onDocumentWritten({
184
192
  document,
193
+ database: firestoreDatabase,
185
194
  retry: true,
186
195
  }, (event) => {
187
196
  return validateFields(
@@ -197,6 +206,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
197
206
  stoker[`verifywritelog${collectionNameLower}`] =
198
207
  onDocumentWritten({
199
208
  document,
209
+ database: firestoreDatabase,
200
210
  retry: true,
201
211
  }, (event) => {
202
212
  return verifyWriteLog(event, collectionSchema);
@@ -216,6 +226,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
216
226
  stoker[`fulltextsearch${collectionNameLower}`] =
217
227
  onDocumentWritten({
218
228
  document,
229
+ database: firestoreDatabase,
219
230
  retry: true,
220
231
  secrets: [algoliaAdminKey],
221
232
  }, (event) => {
@@ -234,6 +245,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
234
245
  stoker[`autoincrement${collectionNameLower}`] =
235
246
  onDocumentWritten({
236
247
  document,
248
+ database: firestoreDatabase,
237
249
  retry: true,
238
250
  }, (event) => {
239
251
  return autoIncrement(event, collectionSchema, schema);
@@ -243,6 +255,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
243
255
  stoker[`validatedenormalized${collectionNameLower}`] =
244
256
  onDocumentWritten({
245
257
  document,
258
+ database: firestoreDatabase,
246
259
  retry: true,
247
260
  }, (event) => {
248
261
  return validateDenormalized(event, collectionSchema, schema);
@@ -258,6 +271,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
258
271
  stoker[`includefields${collectionNameLower}`] =
259
272
  onDocumentUpdated({
260
273
  document,
274
+ database: firestoreDatabase,
261
275
  retry: true,
262
276
  }, (event) => {
263
277
  return updateIncludeFields(event, collectionSchema, schema);
@@ -273,6 +287,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
273
287
  }`] =
274
288
  onDocumentWritten({
275
289
  document,
290
+ database: firestoreDatabase,
276
291
  retry: true,
277
292
  }, (event) => {
278
293
  return validateRelations(
@@ -295,6 +310,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
295
310
  }`] =
296
311
  onDocumentDeleted({
297
312
  document,
313
+ database: firestoreDatabase,
298
314
  retry: true,
299
315
  }, (event) => {
300
316
  return removeRelations(
@@ -312,6 +328,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
312
328
  stoker[`uniquedelete${collectionNameLower}`] =
313
329
  onDocumentWritten({
314
330
  document,
331
+ database: firestoreDatabase,
315
332
  retry: true,
316
333
  }, (event) => {
317
334
  return uniqueDelete(
@@ -324,6 +341,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
324
341
  stoker[`deletefiles${collectionNameLower}`] =
325
342
  onDocumentDeleted({
326
343
  document,
344
+ database: firestoreDatabase,
327
345
  retry: true,
328
346
  }, (event) => {
329
347
  return deleteFiles(
@@ -336,6 +354,7 @@ Object.values(schema.collections).forEach((collectionSchema) => {
336
354
  stoker[`embedding${collectionNameLower}`] =
337
355
  onDocumentWritten({
338
356
  document,
357
+ database: firestoreDatabase,
339
358
  retry: true,
340
359
  }, (event) => {
341
360
  return writeEmbedding(
@@ -401,6 +420,7 @@ if (process.env.STOKER_SMS_ENABLED === "true") {
401
420
  const twilioPhoneNumber = defineSecret("TWILIO_PHONE_NUMBER");
402
421
  stoker["sendmessage"] = onDocumentCreated({
403
422
  document: "system_messages/{messageId}",
423
+ database: firestoreDatabase,
404
424
  retry: true,
405
425
  secrets: [twilioAccountSid, twilioAuthToken, twilioPhoneNumber],
406
426
  }, (event) => {
@@ -1,4 +1,5 @@
1
1
  import { runChildProcess, initializeFirebase } from "@stoker-platform/node-client";
2
+ import { getFirestoreDatabaseId } from "@stoker-platform/utils";
2
3
  import spawn from "cross-spawn";
3
4
  import { generateSchema } from "../schema/generateSchema.js";
4
5
  import { lintSchema } from "../../lint/lintSchema.js";
@@ -23,6 +24,7 @@ export const deployTTLs = async () => {
23
24
  ttl,
24
25
  `--collection-group=${collectionName}`,
25
26
  "--enable-ttl",
27
+ `--database=${getFirestoreDatabaseId(process.env.FB_FIRESTORE_EDITION, projectId)}`,
26
28
  `--project=${projectId}`,
27
29
  "--quiet",
28
30
  "--async",
@@ -41,6 +43,7 @@ export const deployTTLs = async () => {
41
43
  ttl,
42
44
  `--collection-group=${collectionName}`,
43
45
  "--disable-ttl",
46
+ `--database=${getFirestoreDatabaseId(process.env.FB_FIRESTORE_EDITION, projectId)}`,
44
47
  `--project=${projectId}`,
45
48
  "--quiet",
46
49
  "--async",
@@ -61,6 +64,7 @@ export const deployTTLs = async () => {
61
64
  "ttls",
62
65
  "list",
63
66
  `--collection-group=${collection}`,
67
+ `--database=${getFirestoreDatabaseId(process.env.FB_FIRESTORE_EDITION, projectId)}`,
64
68
  `--project=${projectId}`,
65
69
  ]);
66
70
  let stdout = "";
@@ -1,9 +1,10 @@
1
1
  import { fetchCurrentSchema, initializeFirebase } from "@stoker-platform/node-client";
2
- import { getFirestore, FieldValue } from "firebase-admin/firestore";
2
+ import { FieldValue } from "firebase-admin/firestore";
3
+ import { getCLIFirestore } from "../../utils/getCLIFirestore.js";
3
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
5
  export const liveUpdate = async (options) => {
5
6
  await initializeFirebase();
6
- const db = getFirestore();
7
+ const db = getCLIFirestore();
7
8
  const batch = db.batch();
8
9
  const currentSchema = await fetchCurrentSchema();
9
10
  const deployId = db.collection("system_deployment").doc("latest_deploy").collection("deploy_history").doc().id;
@@ -1,8 +1,8 @@
1
1
  import { initializeFirebase } from "@stoker-platform/node-client";
2
- import { getFirestore } from "firebase-admin/firestore";
2
+ import { getCLIFirestore } from "../../utils/getCLIFirestore.js";
3
3
  export const activateMaintenanceMode = async () => {
4
4
  await initializeFirebase();
5
- const db = getFirestore();
5
+ const db = getCLIFirestore();
6
6
  await db.collection("system_deployment").doc("maintenance_mode").set({ active: true });
7
7
  console.info("MAINTENANCE MODE ENGAGED");
8
8
  process.exit();
@@ -1,8 +1,8 @@
1
1
  import { initializeFirebase } from "@stoker-platform/node-client";
2
- import { getFirestore } from "firebase-admin/firestore";
2
+ import { getCLIFirestore } from "../../utils/getCLIFirestore.js";
3
3
  export const disableMaintenanceMode = async () => {
4
4
  await initializeFirebase();
5
- const db = getFirestore();
5
+ const db = getCLIFirestore();
6
6
  await db.collection("system_deployment").doc("maintenance_mode").set({ active: false });
7
7
  console.info("MAINTENANCE MODE DISENGAGED");
8
8
  process.exit();
@@ -1,9 +1,9 @@
1
1
  import { initializeFirebase } from "@stoker-platform/node-client";
2
- import { getFirestore } from "firebase-admin/firestore";
2
+ import { getCLIFirestore } from "../../utils/getCLIFirestore.js";
3
3
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
4
  export const setDeploymentStatus = async (status) => {
5
5
  await initializeFirebase();
6
- const db = getFirestore();
6
+ const db = getCLIFirestore();
7
7
  if (!["idle", "in_progress"].includes(status)) {
8
8
  throw new Error("Invalid deployment status");
9
9
  }
@@ -11,11 +11,12 @@ export const generateFirestoreIndexes = async () => {
11
11
  const __dirname = dirname(__filename);
12
12
  const schema = await generateSchema();
13
13
  await lintSchema(true);
14
+ const edition = process.env.FB_FIRESTORE_EDITION || "enterprise";
14
15
  const indexesResponse = await fetch(process.env.URL_FIRESTORE_INDEXES, {
15
16
  headers: {
16
17
  "Content-Type": "application/json",
17
18
  },
18
- body: JSON.stringify({ schema }),
19
+ body: JSON.stringify({ schema, edition }),
19
20
  method: "POST",
20
21
  });
21
22
  const { indexes, message, error } = await indexesResponse.json();
@@ -1,6 +1,7 @@
1
- import { getFirestore, FieldValue } from "firebase-admin/firestore";
1
+ import { FieldValue } from "firebase-admin/firestore";
2
2
  import { appendFileSync } from "fs";
3
3
  import { join } from "path";
4
+ import { getCLIFirestore } from "../../../utils/getCLIFirestore.js";
4
5
  export const deleteField = async (currentSchema, lastSchema) => {
5
6
  const deletedFields = [];
6
7
  const currentSchemaKeys = Object.keys(currentSchema.collections);
@@ -19,7 +20,7 @@ export const deleteField = async (currentSchema, lastSchema) => {
19
20
  });
20
21
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21
22
  const filePath = join(process.cwd(), ".migration", process.env.GCP_PROJECT, `v${currentSchema.version.toString()}`);
22
- const db = await getFirestore();
23
+ const db = getCLIFirestore();
23
24
  const bulkWriter = db.bulkWriter();
24
25
  for (const field of deletedFields) {
25
26
  const [collection, fieldName] = field.split(".");
@@ -1,14 +1,14 @@
1
1
  import { fetchCurrentSchema, initializeStoker } from "@stoker-platform/node-client";
2
2
  import { getDependencyIndexFields, getLowercaseFields, getRoleGroups, getSingleFieldRelations, isDependencyField, isRelationField, } from "@stoker-platform/utils";
3
3
  import { join } from "node:path";
4
+ import { getCLIFirestore } from "../utils/getCLIFirestore.js";
4
5
  import isEqual from "lodash/isEqual.js";
5
6
  import isEmpty from "lodash/isEmpty.js";
6
- import { getFirestore } from "firebase-admin/firestore";
7
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
8
  export const auditDenormalized = async (options) => {
9
9
  await initializeStoker(options.mode || "production", options.tenant, join(process.cwd(), "lib", "main.js"), join(process.cwd(), "lib", "collections"));
10
10
  const schema = await fetchCurrentSchema();
11
- const db = getFirestore();
11
+ const db = getCLIFirestore();
12
12
  for (const [collectionName, collectionSchema] of Object.entries(schema.collections)) {
13
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
14
  const collectionData = {};
@@ -1,12 +1,11 @@
1
1
  import { fetchCurrentSchema, initializeStoker } from "@stoker-platform/node-client";
2
- import { getFirestore } from "firebase-admin/firestore";
3
2
  import { join } from "node:path";
3
+ import { getCLIFirestore } from "../utils/getCLIFirestore.js";
4
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
5
  export const auditPermissions = async (options) => {
6
6
  await initializeStoker(options.mode || "production", options.tenant, join(process.cwd(), "lib", "main.js"), join(process.cwd(), "lib", "collections"));
7
7
  const schema = await fetchCurrentSchema();
8
- const db = getFirestore();
9
- const dbMain = getFirestore();
8
+ const db = getCLIFirestore();
10
9
  const mismatches = [];
11
10
  const permissions = await db.collection("tenants").doc(options.tenant).collection("system_user_permissions").get();
12
11
  for (const authCollection of Object.values(schema.collections)) {
@@ -79,7 +78,7 @@ export const auditPermissions = async (options) => {
79
78
  }
80
79
  console.log(mismatches.join("\n\n"));
81
80
  if (options.email && mismatches.length > 0) {
82
- await dbMain.collection("system_mail").add({
81
+ await db.collection("system_mail").add({
83
82
  to: options.email,
84
83
  message: {
85
84
  subject: `Stoker Permissions Audit`,
@@ -1,13 +1,13 @@
1
1
  import { fetchCurrentSchema, getFirestorePathRef, initializeStoker } from "@stoker-platform/node-client";
2
- import { getFirestore } from "firebase-admin/firestore";
3
2
  import { join } from "node:path";
3
+ import { getCLIFirestore } from "../utils/getCLIFirestore.js";
4
4
  import isEqual from "lodash/isEqual.js";
5
5
  import { getField, getLowercaseFields, getSingleFieldRelations } from "@stoker-platform/utils";
6
6
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
7
  export const auditRelations = async (options) => {
8
8
  await initializeStoker(options.mode || "production", options.tenant, join(process.cwd(), "lib", "main.js"), join(process.cwd(), "lib", "collections"));
9
9
  const schema = await fetchCurrentSchema();
10
- const db = getFirestore();
10
+ const db = getCLIFirestore();
11
11
  const tenantPrefix = `tenants/${options.tenant}`;
12
12
  const recordByDocumentPath = new Map();
13
13
  const collectionDocsByName = new Map();
@@ -1,13 +1,14 @@
1
1
  import { fetchCurrentSchema, getCollectionRefs, initializeStoker } from "@stoker-platform/node-client";
2
2
  import { tryPromise, getRange } from "@stoker-platform/utils";
3
- import { Filter, getFirestore } from "firebase-admin/firestore";
3
+ import { Filter } from "firebase-admin/firestore";
4
4
  import { join } from "path";
5
+ import { getCLIFirestore } from "../utils/getCLIFirestore.js";
5
6
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
7
  export const explainPreloadQueries = async (options) => {
7
8
  const { getGlobalConfigModule } = await initializeStoker("production", options.tenant, join(process.cwd(), "lib", "main.js"), join(process.cwd(), "lib", "collections"));
8
9
  const globalConfig = getGlobalConfigModule();
9
10
  const schema = await fetchCurrentSchema();
10
- const db = getFirestore();
11
+ const db = getCLIFirestore();
11
12
  const permissionsSnapshot = await db
12
13
  .collection("tenants")
13
14
  .doc(options.tenant)
@@ -1,9 +1,9 @@
1
1
  import { initializeFirebase } from "@stoker-platform/node-client";
2
- import { getFirestore } from "firebase-admin/firestore";
2
+ import { getCLIFirestore } from "../utils/getCLIFirestore.js";
3
3
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
4
  export const getUserPermissions = async (options) => {
5
5
  await initializeFirebase();
6
- const db = getFirestore();
6
+ const db = getCLIFirestore();
7
7
  const usersRef = await db
8
8
  .collection("tenants")
9
9
  .doc(options.tenant)
@@ -1,9 +1,9 @@
1
1
  import { initializeFirebase } from "@stoker-platform/node-client";
2
- import { getFirestore } from "firebase-admin/firestore";
2
+ import { getCLIFirestore } from "../utils/getCLIFirestore.js";
3
3
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
4
  export const getUserRecord = async (options) => {
5
5
  await initializeFirebase();
6
- const db = getFirestore();
6
+ const db = getCLIFirestore();
7
7
  const usersRef = await db
8
8
  .collection("tenants")
9
9
  .doc(options.tenant)
@@ -2,7 +2,7 @@ import { runChildProcess } from "@stoker-platform/node-client";
2
2
  import { writeFile, unlink, readFile } from "fs/promises";
3
3
  import { join } from "path";
4
4
  import dotenv from "dotenv";
5
- import { retryOperation } from "@stoker-platform/utils";
5
+ import { retryOperation, getFirestoreDatabaseId } from "@stoker-platform/utils";
6
6
  import { SecretManagerServiceClient } from "@google-cloud/secret-manager";
7
7
  import { addTenant } from "./addTenant.js";
8
8
  import { existsSync } from "fs";
@@ -277,20 +277,26 @@ export const addProject = async (options) => {
277
277
  }
278
278
  if (getProgress() < 10) {
279
279
  await new Promise((resolve) => setTimeout(resolve, 10000));
280
+ const args = [
281
+ "firestore",
282
+ "databases",
283
+ "create",
284
+ `--location=${process.env.FB_FIRESTORE_REGION}`,
285
+ "--type=firestore-native",
286
+ process.env.FB_FIRESTORE_EDITION ? `--edition=${process.env.FB_FIRESTORE_EDITION}` : "--edition=enterprise",
287
+ "--delete-protection",
288
+ options.pitr && process.env.FB_FIRESTORE_ENABLE_PITR !== "false" ? "--enable-pitr" : "--no-enable-pitr",
289
+ `--project=${projectId}`,
290
+ "--quiet",
291
+ ];
292
+ if ((process.env.FB_FIRESTORE_EDITION || "enterprise") === "enterprise") {
293
+ args.push(`--database=${projectId}`);
294
+ args.push("--enable-firestore-data-access");
295
+ args.push("--enable-realtime-updates");
296
+ args.push("--concurrency-mode=pessimistic");
297
+ }
280
298
  await retryOperation(async () => {
281
- await runChildProcess("gcloud", [
282
- "firestore",
283
- "databases",
284
- "create",
285
- `--location=${process.env.FB_FIRESTORE_REGION}`,
286
- "--type=firestore-native",
287
- "--delete-protection",
288
- options.pitr && process.env.FB_FIRESTORE_ENABLE_PITR !== "false"
289
- ? "--enable-pitr"
290
- : "--no-enable-pitr",
291
- `--project=${projectId}`,
292
- "--quiet",
293
- ]).catch(() => {
299
+ await runChildProcess("gcloud", args).catch(() => {
294
300
  throw new Error("Error creating Firestore database.");
295
301
  });
296
302
  }, [], undefined, 5000);
@@ -313,7 +319,7 @@ export const addProject = async (options) => {
313
319
  : process.env.FB_FIRESTORE_BACKUP_RETENTION
314
320
  ? `--retention=${process.env.FB_FIRESTORE_BACKUP_RETENTION}`
315
321
  : "--retention=7d",
316
- "--database=(default)",
322
+ `--database=${getFirestoreDatabaseId(process.env.FB_FIRESTORE_EDITION, projectId)}`,
317
323
  `--project=${projectId}`,
318
324
  "--quiet",
319
325
  ];
@@ -432,6 +438,18 @@ export const addProject = async (options) => {
432
438
  await runChildProcess("attrib", ["-H", firebasercPath]);
433
439
  }
434
440
  await runChildProcess("firebase", ["target:apply", "storage", "default", projectId, "--project", projectId]);
441
+ if ((process.env.FB_FIRESTORE_EDITION || "enterprise") === "enterprise") {
442
+ const firebaseJsonPath = join(process.cwd(), "firebase.json");
443
+ const firebaseJson = JSON.parse(await readFile(firebaseJsonPath, "utf8"));
444
+ firebaseJson.firestore = [
445
+ {
446
+ database: projectId,
447
+ rules: "firebase-rules/firestore.rules",
448
+ indexes: "firebase-rules/firestore.indexes.json",
449
+ },
450
+ ];
451
+ await writeFile(firebaseJsonPath, JSON.stringify(firebaseJson, null, 4), "utf8");
452
+ }
435
453
  await updateProjectData(17);
436
454
  }
437
455
  if (getProgress() < 18) {
@@ -750,23 +768,31 @@ export const addProject = async (options) => {
750
768
  if (getProgress() < 33) {
751
769
  const externalSecrets = JSON.parse(process.env.EXTERNAL_SECRETS || "{}");
752
770
  for (const [secretName, secretValue] of Object.entries(externalSecrets)) {
753
- const [externalSecret] = await secretManager.createSecret({
754
- parent: `projects/${projectId}`,
755
- secret: {
756
- name: secretName,
757
- replication: {
758
- automatic: {},
771
+ try {
772
+ const [externalSecret] = await secretManager.createSecret({
773
+ parent: `projects/${projectId}`,
774
+ secret: {
775
+ name: secretName,
776
+ replication: {
777
+ automatic: {},
778
+ },
759
779
  },
760
- },
761
- secretId: secretName,
762
- });
763
- const [secretVersion] = await secretManager.addSecretVersion({
764
- parent: externalSecret.name,
765
- payload: {
766
- data: Buffer.from(secretValue, "utf8"),
767
- },
768
- });
769
- console.log(secretVersion);
780
+ secretId: secretName,
781
+ });
782
+ const [secretVersion] = await secretManager.addSecretVersion({
783
+ parent: externalSecret.name,
784
+ payload: {
785
+ data: Buffer.from(secretValue, "utf8"),
786
+ },
787
+ });
788
+ console.log(secretVersion);
789
+ }
790
+ catch (error) {
791
+ if (error?.code === 6) {
792
+ continue;
793
+ }
794
+ throw error;
795
+ }
770
796
  }
771
797
  await updateProjectData(33);
772
798
  }
@@ -951,6 +977,7 @@ STOKER_FB_ENABLE_APP_CHECK=${process.env.FB_ENABLE_APP_CHECK}
951
977
  STOKER_FB_APP_CHECK_KEY="${recaptchaKeyId}"
952
978
  STOKER_ALGOLIA_ID="${process.env.ALGOLIA_ID || ""}"
953
979
  STOKER_FB_FUNCTIONS_REGION="${process.env.FB_FUNCTIONS_REGION}"
980
+ STOKER_FB_FIRESTORE_EDITION="${process.env.FB_FIRESTORE_EDITION || "enterprise"}"
954
981
  FB_DATABASE="${projectId}-default-rtdb"
955
982
  FB_FIRESTORE_EXPORT_BUCKET="${projectId}-export"`;
956
983
  if (process.env.SENTRY_DSN && !options.development) {
@@ -1,12 +1,12 @@
1
1
  import { input } from "@inquirer/prompts";
2
2
  import { fetchCurrentSchema, initializeFirebase, initializeStoker } from "@stoker-platform/node-client";
3
- import { getFirestore } from "firebase-admin/firestore";
4
3
  import { join } from "path";
5
4
  import { retryOperation, isRelationField } from "@stoker-platform/utils";
6
5
  import { addRecordPrompt } from "./addRecordPrompt.js";
6
+ import { getCLIFirestore } from "../utils/getCLIFirestore.js";
7
7
  export const addTenant = async () => {
8
8
  await initializeFirebase();
9
- const db = getFirestore();
9
+ const db = getCLIFirestore();
10
10
  const doc = await db.collection("tenants").add({});
11
11
  const tenantId = doc.id;
12
12
  await initializeStoker("production", tenantId, join(process.cwd(), "lib", "main.js"), join(process.cwd(), "lib", "collections"));
@@ -1,14 +1,14 @@
1
1
  import { fetchCurrentSchema, initializeFirebase } from "@stoker-platform/node-client";
2
2
  import { getAuth } from "firebase-admin/auth";
3
- import { getFirestore } from "firebase-admin/firestore";
4
- import { getStorage } from "firebase-admin/storage";
5
3
  import { getApp } from "firebase-admin/app";
4
+ import { getStorage } from "firebase-admin/storage";
5
+ import { getCLIFirestore } from "../utils/getCLIFirestore.js";
6
6
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
7
  export const deleteTenant = async (options) => {
8
8
  await initializeFirebase();
9
9
  const app = getApp();
10
10
  const auth = getAuth();
11
- const db = getFirestore();
11
+ const db = getCLIFirestore();
12
12
  const storage = getStorage();
13
13
  const schema = await fetchCurrentSchema();
14
14
  const users = await db.collection("tenants").doc(options.tenant).collection("system_user_permissions").get();
@@ -0,0 +1,8 @@
1
+ import { getApp } from "firebase-admin/app";
2
+ import { getFirestore } from "firebase-admin/firestore";
3
+ import { getFirestoreDatabaseId } from "@stoker-platform/utils";
4
+ export const getCLIFirestore = (app) => {
5
+ return getFirestore(app || getApp(),
6
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
7
+ getFirestoreDatabaseId(process.env.FB_FIRESTORE_EDITION, process.env.GCP_PROJECT));
8
+ };
@@ -1 +1 @@
1
- {"root":["../src/main.ts","../src/data/exporttobigquery.ts","../src/data/seeddata.ts","../src/deploy/deployproject.ts","../src/deploy/cloud-functions/getfunctionsdata.ts","../src/deploy/firestore-export/exportfirestoredata.ts","../src/deploy/firestore-ttl/deployttls.ts","../src/deploy/live-update/liveupdate.ts","../src/deploy/maintenance/activatemaintenancemode.ts","../src/deploy/maintenance/disablemaintenancemode.ts","../src/deploy/maintenance/setdeploymentstatus.ts","../src/deploy/rules-indexes/generatefirestoreindexes.ts","../src/deploy/rules-indexes/generatefirestorerules.ts","../src/deploy/rules-indexes/generatestoragerules.ts","../src/deploy/schema/applyschema.ts","../src/deploy/schema/generateschema.ts","../src/deploy/schema/persistschema.ts","../src/deploy/schema/updateliveschema.ts","../src/lint/lintschema.ts","../src/lint/securityreport.ts","../src/migration/migrateall.ts","../src/migration/firestore/migratefirestore.ts","../src/migration/firestore/operations/deletefield.ts","../src/ops/auditdenormalized.ts","../src/ops/auditpermissions.ts","../src/ops/auditrelations.ts","../src/ops/explainpreloadqueries.ts","../src/ops/getuser.ts","../src/ops/getuserpermissions.ts","../src/ops/getuserrecord.ts","../src/ops/listprojects.ts","../src/ops/setusercollection.ts","../src/ops/setuserdocument.ts","../src/ops/setuserrole.ts","../src/project/addproject.ts","../src/project/addrecord.ts","../src/project/addrecordprompt.ts","../src/project/addtenant.ts","../src/project/buildwebapp.ts","../src/project/customdomain.ts","../src/project/deleteproject.ts","../src/project/deleterecord.ts","../src/project/deletetenant.ts","../src/project/getone.ts","../src/project/getsome.ts","../src/project/initproject.ts","../src/project/prepareemulatordata.ts","../src/project/setproject.ts","../src/project/startemulators.ts","../src/project/updaterecord.ts","../src/types/generatetypes.ts"],"version":"6.0.3"}
1
+ {"root":["../src/main.ts","../src/data/exporttobigquery.ts","../src/data/seeddata.ts","../src/deploy/deployproject.ts","../src/deploy/cloud-functions/getfunctionsdata.ts","../src/deploy/firestore-export/exportfirestoredata.ts","../src/deploy/firestore-ttl/deployttls.ts","../src/deploy/live-update/liveupdate.ts","../src/deploy/maintenance/activatemaintenancemode.ts","../src/deploy/maintenance/disablemaintenancemode.ts","../src/deploy/maintenance/setdeploymentstatus.ts","../src/deploy/rules-indexes/generatefirestoreindexes.ts","../src/deploy/rules-indexes/generatefirestorerules.ts","../src/deploy/rules-indexes/generatestoragerules.ts","../src/deploy/schema/applyschema.ts","../src/deploy/schema/generateschema.ts","../src/deploy/schema/persistschema.ts","../src/deploy/schema/updateliveschema.ts","../src/lint/lintschema.ts","../src/lint/securityreport.ts","../src/migration/migrateall.ts","../src/migration/firestore/migratefirestore.ts","../src/migration/firestore/operations/deletefield.ts","../src/ops/auditdenormalized.ts","../src/ops/auditpermissions.ts","../src/ops/auditrelations.ts","../src/ops/explainpreloadqueries.ts","../src/ops/getuser.ts","../src/ops/getuserpermissions.ts","../src/ops/getuserrecord.ts","../src/ops/listprojects.ts","../src/ops/setusercollection.ts","../src/ops/setuserdocument.ts","../src/ops/setuserrole.ts","../src/project/addproject.ts","../src/project/addrecord.ts","../src/project/addrecordprompt.ts","../src/project/addtenant.ts","../src/project/buildwebapp.ts","../src/project/customdomain.ts","../src/project/deleteproject.ts","../src/project/deleterecord.ts","../src/project/deletetenant.ts","../src/project/getone.ts","../src/project/getsome.ts","../src/project/initproject.ts","../src/project/prepareemulatordata.ts","../src/project/setproject.ts","../src/project/startemulators.ts","../src/project/updaterecord.ts","../src/types/generatetypes.ts","../src/utils/getclifirestore.ts"],"version":"6.0.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/cli",
3
- "version": "0.5.101",
3
+ "version": "0.5.102",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "main": "./lib/src/main.js",
@@ -24,9 +24,9 @@
24
24
  "@google-cloud/secret-manager": "^6.1.2",
25
25
  "@google-cloud/storage": "^7.19.0",
26
26
  "@inquirer/prompts": "^8.5.2",
27
- "@stoker-platform/node-client": "0.5.67",
28
- "@stoker-platform/types": "0.5.46",
29
- "@stoker-platform/utils": "0.5.58",
27
+ "@stoker-platform/node-client": "0.5.68",
28
+ "@stoker-platform/types": "0.5.47",
29
+ "@stoker-platform/utils": "0.5.59",
30
30
  "algoliasearch": "^5.53.0",
31
31
  "commander": "^15.0.0",
32
32
  "cross-spawn": "^7.0.6",