firebase-tools 13.17.0 → 13.19.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 +10 -9
- package/lib/commands/dataconnect-services-list.js +4 -3
- package/lib/commands/dataconnect-sql-grant.js +37 -0
- package/lib/commands/dataconnect-sql-migrate.js +2 -1
- package/lib/commands/deploy.js +2 -0
- package/lib/commands/ext-info.js +3 -1
- package/lib/commands/ext-sdk-install.js +88 -0
- package/lib/commands/ext.js +1 -0
- package/lib/commands/index.js +3 -0
- package/lib/dataconnect/client.js +1 -1
- package/lib/dataconnect/dataplaneClient.js +1 -1
- package/lib/dataconnect/ensureApis.js +6 -1
- package/lib/dataconnect/load.js +3 -1
- package/lib/dataconnect/provisionCloudSql.js +34 -21
- package/lib/dataconnect/schemaMigration.js +126 -73
- package/lib/deploy/dataconnect/deploy.js +16 -13
- package/lib/deploy/dataconnect/prepare.js +36 -0
- package/lib/deploy/dataconnect/release.js +9 -2
- package/lib/deploy/extensions/deploymentSummary.js +3 -2
- package/lib/deploy/extensions/planner.js +32 -3
- package/lib/deploy/extensions/prepare.js +36 -64
- package/lib/deploy/extensions/release.js +11 -10
- package/lib/deploy/extensions/tasks.js +32 -21
- package/lib/deploy/firestore/prepare.js +10 -0
- package/lib/deploy/firestore/release.js +3 -6
- package/lib/deploy/functions/checkIam.js +7 -2
- package/lib/deploy/functions/ensure.js +10 -2
- package/lib/deploy/functions/prepare.js +10 -2
- package/lib/deploy/functions/runtimes/node/index.js +1 -1
- package/lib/deploy/index.js +9 -5
- package/lib/emulator/downloadableEmulators.js +9 -9
- package/lib/extensions/extensionsApi.js +3 -2
- package/lib/extensions/extensionsHelper.js +3 -3
- package/lib/extensions/localHelper.js +31 -0
- package/lib/extensions/runtimes/common.js +186 -38
- package/lib/extensions/runtimes/node.js +399 -0
- package/lib/extensions/types.js +10 -14
- package/lib/extensions/warnings.js +5 -2
- package/lib/firestore/checkDatabaseType.js +10 -3
- package/lib/frameworks/angular/index.js +15 -3
- package/lib/frameworks/next/utils.js +1 -1
- package/lib/gcp/cloudsql/permissions.js +6 -1
- package/lib/gcp/secretManager.js +12 -5
- package/lib/init/features/dataconnect/index.js +66 -53
- package/lib/init/features/firestore/index.js +20 -1
- package/lib/init/features/firestore/indexes.js +4 -4
- package/package.json +1 -1
- package/schema/connector-yaml.json +43 -17
- package/templates/init/dataconnect/connector.yaml +0 -1
- package/templates/init/dataconnect/dataconnect-fdccompatiblemode.yaml +12 -0
- package/templates/init/dataconnect/dataconnect.yaml +1 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.migrateSchema = exports.diffSchema = void 0;
|
|
3
|
+
exports.grantRoleToUserInSchema = exports.migrateSchema = exports.diffSchema = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const sql_formatter_1 = require("sql-formatter");
|
|
6
6
|
const types_1 = require("./types");
|
|
7
7
|
const client_1 = require("./client");
|
|
8
8
|
const connect_1 = require("../gcp/cloudsql/connect");
|
|
9
9
|
const permissions_1 = require("../gcp/cloudsql/permissions");
|
|
10
|
+
const cloudSqlAdminClient = require("../gcp/cloudsql/cloudsqladmin");
|
|
11
|
+
const projectUtils_1 = require("../projectUtils");
|
|
10
12
|
const prompt_1 = require("../prompt");
|
|
11
13
|
const logger_1 = require("../logger");
|
|
12
14
|
const error_1 = require("../error");
|
|
@@ -17,15 +19,9 @@ async function diffSchema(schema, schemaValidation) {
|
|
|
17
19
|
const { serviceName, instanceName, databaseId } = getIdentifiers(schema);
|
|
18
20
|
await ensureServiceIsConnectedToCloudSql(serviceName, instanceName, databaseId, false);
|
|
19
21
|
let diffs = [];
|
|
20
|
-
let validationMode = "
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
validationMode = "COMPATIBLE";
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
validationMode = schemaValidation;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
22
|
+
let validationMode = experiments.isEnabled("fdccompatiblemode")
|
|
23
|
+
? schemaValidation !== null && schemaValidation !== void 0 ? schemaValidation : "COMPATIBLE"
|
|
24
|
+
: "STRICT";
|
|
29
25
|
setSchemaValidationMode(schema, validationMode);
|
|
30
26
|
try {
|
|
31
27
|
if (!schemaValidation && experiments.isEnabled("fdccompatiblemode")) {
|
|
@@ -56,33 +52,31 @@ async function diffSchema(schema, schemaValidation) {
|
|
|
56
52
|
diffs = incompatible.diffs;
|
|
57
53
|
}
|
|
58
54
|
}
|
|
59
|
-
if (experiments.isEnabled("fdccompatiblemode")) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
if (experiments.isEnabled("fdccompatiblemode") && !schemaValidation) {
|
|
56
|
+
validationMode = "STRICT";
|
|
57
|
+
setSchemaValidationMode(schema, validationMode);
|
|
58
|
+
try {
|
|
59
|
+
(0, utils_1.logLabeledBullet)("dataconnect", `generating schema changes, including optional changes...`);
|
|
60
|
+
await (0, client_1.upsertSchema)(schema, true);
|
|
61
|
+
(0, utils_1.logLabeledSuccess)("dataconnect", `no additional optional changes`);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if ((err === null || err === void 0 ? void 0 : err.status) !== 400) {
|
|
65
|
+
throw err;
|
|
67
66
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (incompatible) {
|
|
74
|
-
if (!diffsEqual(diffs, incompatible.diffs)) {
|
|
75
|
-
if (diffs.length === 0) {
|
|
76
|
-
displaySchemaChanges(incompatible, "STRICT_AFTER_COMPATIBLE", instanceName, databaseId);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
displaySchemaChanges(incompatible, validationMode, instanceName, databaseId);
|
|
80
|
-
}
|
|
81
|
-
diffs = incompatible.diffs;
|
|
67
|
+
const incompatible = errors.getIncompatibleSchemaError(err);
|
|
68
|
+
if (incompatible) {
|
|
69
|
+
if (!diffsEqual(diffs, incompatible.diffs)) {
|
|
70
|
+
if (diffs.length === 0) {
|
|
71
|
+
displaySchemaChanges(incompatible, "STRICT_AFTER_COMPATIBLE", instanceName, databaseId);
|
|
82
72
|
}
|
|
83
73
|
else {
|
|
84
|
-
(
|
|
74
|
+
displaySchemaChanges(incompatible, validationMode, instanceName, databaseId);
|
|
85
75
|
}
|
|
76
|
+
diffs = incompatible.diffs;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
(0, utils_1.logLabeledSuccess)("dataconnect", `no additional optional changes`);
|
|
86
80
|
}
|
|
87
81
|
}
|
|
88
82
|
}
|
|
@@ -91,10 +85,13 @@ async function diffSchema(schema, schemaValidation) {
|
|
|
91
85
|
}
|
|
92
86
|
exports.diffSchema = diffSchema;
|
|
93
87
|
async function migrateSchema(args) {
|
|
94
|
-
const { options, schema, validateOnly } = args;
|
|
88
|
+
const { options, schema, validateOnly, schemaValidation } = args;
|
|
95
89
|
const { serviceName, instanceId, instanceName, databaseId } = getIdentifiers(schema);
|
|
96
90
|
await ensureServiceIsConnectedToCloudSql(serviceName, instanceName, databaseId, true);
|
|
97
|
-
|
|
91
|
+
let diffs = [];
|
|
92
|
+
let validationMode = experiments.isEnabled("fdccompatiblemode")
|
|
93
|
+
? schemaValidation !== null && schemaValidation !== void 0 ? schemaValidation : "COMPATIBLE"
|
|
94
|
+
: "STRICT";
|
|
98
95
|
setSchemaValidationMode(schema, validationMode);
|
|
99
96
|
try {
|
|
100
97
|
await (0, client_1.upsertSchema)(schema, validateOnly);
|
|
@@ -111,7 +108,6 @@ async function migrateSchema(args) {
|
|
|
111
108
|
}
|
|
112
109
|
const migrationMode = await promptForSchemaMigration(options, instanceName, databaseId, incompatible, validateOnly, validationMode);
|
|
113
110
|
const shouldDeleteInvalidConnectors = await promptForInvalidConnectorError(options, serviceName, invalidConnectors, validateOnly);
|
|
114
|
-
let diffs = [];
|
|
115
111
|
if (incompatible) {
|
|
116
112
|
diffs = await handleIncompatibleSchemaError({
|
|
117
113
|
options,
|
|
@@ -127,11 +123,54 @@ async function migrateSchema(args) {
|
|
|
127
123
|
if (!validateOnly) {
|
|
128
124
|
await (0, client_1.upsertSchema)(schema, validateOnly);
|
|
129
125
|
}
|
|
130
|
-
return diffs;
|
|
131
126
|
}
|
|
132
|
-
|
|
127
|
+
if (experiments.isEnabled("fdccompatiblemode") && !schemaValidation) {
|
|
128
|
+
validationMode = "STRICT";
|
|
129
|
+
setSchemaValidationMode(schema, validationMode);
|
|
130
|
+
try {
|
|
131
|
+
await (0, client_1.upsertSchema)(schema, validateOnly);
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
if (err.status !== 400) {
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
const incompatible = errors.getIncompatibleSchemaError(err);
|
|
138
|
+
const invalidConnectors = errors.getInvalidConnectors(err);
|
|
139
|
+
if (!incompatible && !invalidConnectors.length) {
|
|
140
|
+
throw err;
|
|
141
|
+
}
|
|
142
|
+
const migrationMode = await promptForSchemaMigration(options, instanceName, databaseId, incompatible, validateOnly, "STRICT_AFTER_COMPATIBLE");
|
|
143
|
+
if (incompatible) {
|
|
144
|
+
const maybeDiffs = await handleIncompatibleSchemaError({
|
|
145
|
+
options,
|
|
146
|
+
databaseId,
|
|
147
|
+
instanceId,
|
|
148
|
+
incompatibleSchemaError: incompatible,
|
|
149
|
+
choice: migrationMode,
|
|
150
|
+
});
|
|
151
|
+
diffs = diffs.concat(maybeDiffs);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return diffs;
|
|
133
156
|
}
|
|
134
157
|
exports.migrateSchema = migrateSchema;
|
|
158
|
+
async function grantRoleToUserInSchema(options, schema) {
|
|
159
|
+
const role = options.role;
|
|
160
|
+
const email = options.email;
|
|
161
|
+
const { instanceId, databaseId } = getIdentifiers(schema);
|
|
162
|
+
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
163
|
+
const { user, mode } = (0, connect_1.toDatabaseUser)(email);
|
|
164
|
+
const fdcSqlRole = permissions_1.fdcSqlRoleMap[role](databaseId);
|
|
165
|
+
const userIsCSQLAdmin = await (0, permissions_1.iamUserIsCSQLAdmin)(options);
|
|
166
|
+
if (!userIsCSQLAdmin) {
|
|
167
|
+
throw new error_1.FirebaseError(`Only users with 'roles/cloudsql.admin' can grant SQL roles. If you do not have this role, ask your database administrator to run this command or manually grant ${fdcSqlRole} to ${user}`);
|
|
168
|
+
}
|
|
169
|
+
await (0, connect_1.setupIAMUsers)(instanceId, databaseId, options);
|
|
170
|
+
await cloudSqlAdminClient.createUser(projectId, instanceId, mode, user);
|
|
171
|
+
await (0, connect_1.executeSqlCmdsAsSuperUser)(options, instanceId, databaseId, [`GRANT "${fdcSqlRole}" TO "${user}"`], false);
|
|
172
|
+
}
|
|
173
|
+
exports.grantRoleToUserInSchema = grantRoleToUserInSchema;
|
|
135
174
|
function diffsEqual(x, y) {
|
|
136
175
|
if (x.length !== y.length) {
|
|
137
176
|
return false;
|
|
@@ -146,17 +185,21 @@ function diffsEqual(x, y) {
|
|
|
146
185
|
return true;
|
|
147
186
|
}
|
|
148
187
|
function setSchemaValidationMode(schema, schemaValidation) {
|
|
149
|
-
if (experiments.isEnabled("fdccompatiblemode")
|
|
150
|
-
schema.
|
|
188
|
+
if (experiments.isEnabled("fdccompatiblemode")) {
|
|
189
|
+
const postgresDatasource = schema.datasources.find((d) => d.postgresql);
|
|
190
|
+
if (postgresDatasource === null || postgresDatasource === void 0 ? void 0 : postgresDatasource.postgresql) {
|
|
191
|
+
postgresDatasource.postgresql.schemaValidation = schemaValidation;
|
|
192
|
+
}
|
|
151
193
|
}
|
|
152
194
|
}
|
|
153
195
|
function getIdentifiers(schema) {
|
|
154
196
|
var _a, _b;
|
|
155
|
-
const
|
|
197
|
+
const postgresDatasource = schema.datasources.find((d) => d.postgresql);
|
|
198
|
+
const databaseId = (_a = postgresDatasource === null || postgresDatasource === void 0 ? void 0 : postgresDatasource.postgresql) === null || _a === void 0 ? void 0 : _a.database;
|
|
156
199
|
if (!databaseId) {
|
|
157
|
-
throw new error_1.FirebaseError("
|
|
200
|
+
throw new error_1.FirebaseError("Service does not have a postgres datasource, cannot migrate");
|
|
158
201
|
}
|
|
159
|
-
const instanceName = (_b =
|
|
202
|
+
const instanceName = (_b = postgresDatasource === null || postgresDatasource === void 0 ? void 0 : postgresDatasource.postgresql) === null || _b === void 0 ? void 0 : _b.cloudSql.instance;
|
|
160
203
|
if (!instanceName) {
|
|
161
204
|
throw new error_1.FirebaseError("tried to migrate schema but instance name was not provided in dataconnect.yaml");
|
|
162
205
|
}
|
|
@@ -218,28 +261,38 @@ async function handleIncompatibleSchemaError(args) {
|
|
|
218
261
|
}
|
|
219
262
|
return [];
|
|
220
263
|
}
|
|
221
|
-
async function promptForSchemaMigration(options, instanceName, databaseId, err, validateOnly,
|
|
264
|
+
async function promptForSchemaMigration(options, instanceName, databaseId, err, validateOnly, validationMode) {
|
|
222
265
|
if (!err) {
|
|
223
266
|
return "none";
|
|
224
267
|
}
|
|
225
|
-
|
|
268
|
+
if (validationMode === "STRICT_AFTER_COMPATIBLE" && (options.nonInteractive || options.force)) {
|
|
269
|
+
return "none";
|
|
270
|
+
}
|
|
271
|
+
displaySchemaChanges(err, validationMode, instanceName, databaseId);
|
|
226
272
|
if (!options.nonInteractive) {
|
|
227
273
|
if (validateOnly && options.force) {
|
|
228
274
|
return "all";
|
|
229
275
|
}
|
|
230
|
-
const
|
|
231
|
-
?
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
276
|
+
const message = validationMode === "STRICT_AFTER_COMPATIBLE"
|
|
277
|
+
? `Would you like to execute these optional changes against ${databaseId} in your CloudSQL instance ${instanceName}?`
|
|
278
|
+
: `Would you like to execute these changes against ${databaseId} in your CloudSQL instance ${instanceName}?`;
|
|
279
|
+
let executeChangePrompt = "Execute changes";
|
|
280
|
+
if (validationMode === "STRICT_AFTER_COMPATIBLE") {
|
|
281
|
+
executeChangePrompt = "Execute optional changes";
|
|
282
|
+
}
|
|
283
|
+
if (err.destructive) {
|
|
284
|
+
executeChangePrompt = executeChangePrompt + " (including destructive changes)";
|
|
285
|
+
}
|
|
286
|
+
const choices = [
|
|
287
|
+
{ name: executeChangePrompt, value: "all" },
|
|
288
|
+
{ name: "Abort changes", value: "none" },
|
|
289
|
+
];
|
|
290
|
+
const defaultValue = validationMode === "STRICT_AFTER_COMPATIBLE" ? "none" : "all";
|
|
239
291
|
return await (0, prompt_1.promptOnce)({
|
|
240
|
-
message:
|
|
292
|
+
message: message,
|
|
241
293
|
type: "list",
|
|
242
294
|
choices,
|
|
295
|
+
default: defaultValue,
|
|
243
296
|
});
|
|
244
297
|
}
|
|
245
298
|
if (!validateOnly) {
|
|
@@ -261,10 +314,7 @@ async function promptForInvalidConnectorError(options, serviceName, invalidConne
|
|
|
261
314
|
}
|
|
262
315
|
displayInvalidConnectors(invalidConnectors);
|
|
263
316
|
if (validateOnly) {
|
|
264
|
-
|
|
265
|
-
return false;
|
|
266
|
-
}
|
|
267
|
-
throw new error_1.FirebaseError(`Command aborted. If you'd like to migrate it anyway, you may override with --force.`);
|
|
317
|
+
return false;
|
|
268
318
|
}
|
|
269
319
|
if (options.force) {
|
|
270
320
|
return true;
|
|
@@ -297,17 +347,20 @@ async function ensureServiceIsConnectedToCloudSql(serviceName, instanceId, datab
|
|
|
297
347
|
source: {
|
|
298
348
|
files: [],
|
|
299
349
|
},
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
350
|
+
datasources: [
|
|
351
|
+
{
|
|
352
|
+
postgresql: {
|
|
353
|
+
database: databaseId,
|
|
354
|
+
cloudSql: {
|
|
355
|
+
instance: instanceId,
|
|
356
|
+
},
|
|
305
357
|
},
|
|
306
358
|
},
|
|
307
|
-
|
|
359
|
+
],
|
|
308
360
|
};
|
|
309
361
|
}
|
|
310
|
-
const
|
|
362
|
+
const postgresDatasource = currentSchema.datasources.find((d) => d.postgresql);
|
|
363
|
+
const postgresql = postgresDatasource === null || postgresDatasource === void 0 ? void 0 : postgresDatasource.postgresql;
|
|
311
364
|
if ((postgresql === null || postgresql === void 0 ? void 0 : postgresql.cloudSql.instance) !== instanceId) {
|
|
312
365
|
(0, utils_1.logLabeledWarning)("dataconnect", `Switching connected Cloud SQL instance\nFrom ${postgresql === null || postgresql === void 0 ? void 0 : postgresql.cloudSql.instance}\nTo ${instanceId}`);
|
|
313
366
|
}
|
|
@@ -328,22 +381,22 @@ async function ensureServiceIsConnectedToCloudSql(serviceName, instanceId, datab
|
|
|
328
381
|
logger_1.logger.debug(err);
|
|
329
382
|
}
|
|
330
383
|
}
|
|
331
|
-
function displaySchemaChanges(error,
|
|
384
|
+
function displaySchemaChanges(error, validationMode, instanceName, databaseId) {
|
|
332
385
|
switch (error.violationType) {
|
|
333
386
|
case "INCOMPATIBLE_SCHEMA":
|
|
334
387
|
{
|
|
335
388
|
let message;
|
|
336
|
-
if (
|
|
389
|
+
if (validationMode === "COMPATIBLE") {
|
|
337
390
|
message =
|
|
338
|
-
"Your
|
|
391
|
+
"Your PostgreSQL database " +
|
|
339
392
|
databaseId +
|
|
340
393
|
" in your CloudSQL instance " +
|
|
341
394
|
instanceName +
|
|
342
|
-
". " +
|
|
395
|
+
" must be migrated in order to be compatible with your application schema. " +
|
|
343
396
|
"The following SQL statements will migrate your database schema to be compatible with your new Data Connect schema.\n" +
|
|
344
397
|
error.diffs.map(toString).join("\n");
|
|
345
398
|
}
|
|
346
|
-
else if (
|
|
399
|
+
else if (validationMode === "STRICT_AFTER_COMPATIBLE") {
|
|
347
400
|
message =
|
|
348
401
|
"Your new application schema is compatible with the schema of your PostgreSQL database " +
|
|
349
402
|
databaseId +
|
|
@@ -355,11 +408,11 @@ function displaySchemaChanges(error, schemaValidation, instanceName, databaseId)
|
|
|
355
408
|
}
|
|
356
409
|
else {
|
|
357
410
|
message =
|
|
358
|
-
"Your
|
|
411
|
+
"Your PostgreSQL database " +
|
|
359
412
|
databaseId +
|
|
360
413
|
" in your CloudSQL instance " +
|
|
361
414
|
instanceName +
|
|
362
|
-
". " +
|
|
415
|
+
" must be migrated in order to match your application schema. " +
|
|
363
416
|
"The following SQL statements will migrate your database schema to match your new Data Connect schema.\n" +
|
|
364
417
|
error.diffs.map(toString).join("\n");
|
|
365
418
|
}
|
|
@@ -44,20 +44,23 @@ async function default_1(context, options) {
|
|
|
44
44
|
})
|
|
45
45
|
.map(async (s) => {
|
|
46
46
|
var _a, _b;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const postgresDatasource = s.schema.datasources.find((d) => d.postgresql);
|
|
48
|
+
if (postgresDatasource) {
|
|
49
|
+
const instanceId = (_a = postgresDatasource.postgresql) === null || _a === void 0 ? void 0 : _a.cloudSql.instance.split("/").pop();
|
|
50
|
+
const databaseId = (_b = postgresDatasource.postgresql) === null || _b === void 0 ? void 0 : _b.database;
|
|
51
|
+
if (!instanceId || !databaseId) {
|
|
52
|
+
return Promise.resolve();
|
|
53
|
+
}
|
|
54
|
+
const enableGoogleMlIntegration = (0, types_1.requiresVector)(s.deploymentMetadata);
|
|
55
|
+
return (0, provisionCloudSql_1.provisionCloudSql)({
|
|
56
|
+
projectId,
|
|
57
|
+
locationId: (0, names_1.parseServiceName)(s.serviceName).location,
|
|
58
|
+
instanceId,
|
|
59
|
+
databaseId,
|
|
60
|
+
enableGoogleMlIntegration,
|
|
61
|
+
waitForCreation: true,
|
|
62
|
+
});
|
|
51
63
|
}
|
|
52
|
-
const enableGoogleMlIntegration = (0, types_1.requiresVector)(s.deploymentMetadata);
|
|
53
|
-
return (0, provisionCloudSql_1.provisionCloudSql)({
|
|
54
|
-
projectId,
|
|
55
|
-
locationId: (0, names_1.parseServiceName)(s.serviceName).location,
|
|
56
|
-
instanceId,
|
|
57
|
-
databaseId,
|
|
58
|
-
enableGoogleMlIntegration,
|
|
59
|
-
waitForCreation: true,
|
|
60
|
-
});
|
|
61
64
|
}));
|
|
62
65
|
return;
|
|
63
66
|
}
|
|
@@ -11,8 +11,13 @@ const build_1 = require("../../dataconnect/build");
|
|
|
11
11
|
const ensureApis_1 = require("../../dataconnect/ensureApis");
|
|
12
12
|
const requireTosAcceptance_1 = require("../../requireTosAcceptance");
|
|
13
13
|
const firedata_1 = require("../../gcp/firedata");
|
|
14
|
+
const provisionCloudSql_1 = require("../../dataconnect/provisionCloudSql");
|
|
15
|
+
const names_1 = require("../../dataconnect/names");
|
|
14
16
|
const error_1 = require("../../error");
|
|
17
|
+
const types_1 = require("../../dataconnect/types");
|
|
18
|
+
const schemaMigration_1 = require("../../dataconnect/schemaMigration");
|
|
15
19
|
async function default_1(context, options) {
|
|
20
|
+
var _a;
|
|
16
21
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
17
22
|
await (0, ensureApis_1.ensureApis)(projectId);
|
|
18
23
|
await (0, requireTosAcceptance_1.requireTosAcceptance)(firedata_1.DATA_CONNECT_TOS_ID)(options);
|
|
@@ -41,6 +46,37 @@ async function default_1(context, options) {
|
|
|
41
46
|
filters,
|
|
42
47
|
};
|
|
43
48
|
utils.logLabeledBullet("dataconnect", `Successfully prepared schema and connectors`);
|
|
49
|
+
if (options.dryRun) {
|
|
50
|
+
for (const si of serviceInfos) {
|
|
51
|
+
await (0, schemaMigration_1.diffSchema)(si.schema, (_a = si.dataConnectYaml.schema.datasource.postgresql) === null || _a === void 0 ? void 0 : _a.schemaValidation);
|
|
52
|
+
}
|
|
53
|
+
utils.logLabeledBullet("dataconnect", "Checking for CloudSQL resources...");
|
|
54
|
+
await Promise.all(serviceInfos
|
|
55
|
+
.filter((si) => {
|
|
56
|
+
return !filters || (filters === null || filters === void 0 ? void 0 : filters.some((f) => si.dataConnectYaml.serviceId === f.serviceId));
|
|
57
|
+
})
|
|
58
|
+
.map(async (s) => {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
const postgresDatasource = s.schema.datasources.find((d) => d.postgresql);
|
|
61
|
+
if (postgresDatasource) {
|
|
62
|
+
const instanceId = (_a = postgresDatasource.postgresql) === null || _a === void 0 ? void 0 : _a.cloudSql.instance.split("/").pop();
|
|
63
|
+
const databaseId = (_b = postgresDatasource.postgresql) === null || _b === void 0 ? void 0 : _b.database;
|
|
64
|
+
if (!instanceId || !databaseId) {
|
|
65
|
+
return Promise.resolve();
|
|
66
|
+
}
|
|
67
|
+
const enableGoogleMlIntegration = (0, types_1.requiresVector)(s.deploymentMetadata);
|
|
68
|
+
return (0, provisionCloudSql_1.provisionCloudSql)({
|
|
69
|
+
projectId,
|
|
70
|
+
locationId: (0, names_1.parseServiceName)(s.serviceName).location,
|
|
71
|
+
instanceId,
|
|
72
|
+
databaseId,
|
|
73
|
+
enableGoogleMlIntegration,
|
|
74
|
+
waitForCreation: true,
|
|
75
|
+
dryRun: options.dryRun,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
44
80
|
logger_1.logger.debug(JSON.stringify(context.dataconnect, null, 2));
|
|
45
81
|
return;
|
|
46
82
|
}
|
|
@@ -14,14 +14,21 @@ async function default_1(context, options) {
|
|
|
14
14
|
return f.serviceId === si.dataConnectYaml.serviceId && (f.schemaOnly || f.fullService);
|
|
15
15
|
}));
|
|
16
16
|
})
|
|
17
|
-
.map((s) =>
|
|
17
|
+
.map((s) => {
|
|
18
|
+
var _a;
|
|
19
|
+
return ({
|
|
20
|
+
schema: s.schema,
|
|
21
|
+
validationMode: (_a = s.dataConnectYaml.schema.datasource.postgresql) === null || _a === void 0 ? void 0 : _a.schemaValidation,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
18
24
|
if (wantSchemas.length) {
|
|
19
25
|
utils.logLabeledBullet("dataconnect", "Releasing Data Connect schemas...");
|
|
20
26
|
for (const s of wantSchemas) {
|
|
21
27
|
await (0, schemaMigration_1.migrateSchema)({
|
|
22
28
|
options,
|
|
23
|
-
schema: s,
|
|
29
|
+
schema: s.schema,
|
|
24
30
|
validateOnly: false,
|
|
31
|
+
schemaValidation: s.validationMode,
|
|
25
32
|
});
|
|
26
33
|
}
|
|
27
34
|
utils.logLabeledBullet("dataconnect", "Schemas released.");
|
|
@@ -47,10 +47,11 @@ function configuresSummary(toConfigure) {
|
|
|
47
47
|
: "";
|
|
48
48
|
}
|
|
49
49
|
exports.configuresSummary = configuresSummary;
|
|
50
|
-
function deletesSummary(toDelete) {
|
|
50
|
+
function deletesSummary(toDelete, isDynamic) {
|
|
51
51
|
const instancesToDelete = toDelete.map((s) => `\t${(0, exports.humanReadable)(s)}`).join("\n");
|
|
52
|
+
const definedLocation = isDynamic ? "your local source code" : "'firebase.json'";
|
|
52
53
|
return toDelete.length
|
|
53
|
-
? `The following extension instances are not
|
|
54
|
+
? `The following extension instances are found in your project but do not exist in ${definedLocation}:\n${instancesToDelete}\n`
|
|
54
55
|
: "";
|
|
55
56
|
}
|
|
56
57
|
exports.deletesSummary = deletesSummary;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveVersion = exports.want = exports.wantDynamic = exports.have = exports.getExtensionSpec = exports.getExtension = exports.getExtensionVersion = void 0;
|
|
3
|
+
exports.resolveVersion = exports.want = exports.wantDynamic = exports.have = exports.haveDynamic = exports.getExtensionSpec = exports.getExtension = exports.getExtensionVersion = void 0;
|
|
4
4
|
const semver = require("semver");
|
|
5
5
|
const extensionsApi = require("../../extensions/extensionsApi");
|
|
6
6
|
const refs = require("../../extensions/refs");
|
|
@@ -49,9 +49,33 @@ async function getExtensionSpec(i) {
|
|
|
49
49
|
return i.extensionSpec;
|
|
50
50
|
}
|
|
51
51
|
exports.getExtensionSpec = getExtensionSpec;
|
|
52
|
+
async function haveDynamic(projectId) {
|
|
53
|
+
return (await extensionsApi.listInstances(projectId))
|
|
54
|
+
.filter((i) => { var _a; return ((_a = i.labels) === null || _a === void 0 ? void 0 : _a.createdBy) === "SDK"; })
|
|
55
|
+
.map((i) => {
|
|
56
|
+
var _a;
|
|
57
|
+
const dep = {
|
|
58
|
+
instanceId: i.name.split("/").pop(),
|
|
59
|
+
params: i.config.params,
|
|
60
|
+
systemParams: (_a = i.config.systemParams) !== null && _a !== void 0 ? _a : {},
|
|
61
|
+
allowedEventTypes: i.config.allowedEventTypes,
|
|
62
|
+
eventarcChannel: i.config.eventarcChannel,
|
|
63
|
+
etag: i.etag,
|
|
64
|
+
labels: i.labels,
|
|
65
|
+
};
|
|
66
|
+
if (i.config.extensionRef) {
|
|
67
|
+
const ref = refs.parse(i.config.extensionRef);
|
|
68
|
+
dep.ref = ref;
|
|
69
|
+
dep.ref.version = i.config.extensionVersion;
|
|
70
|
+
}
|
|
71
|
+
return dep;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
exports.haveDynamic = haveDynamic;
|
|
52
75
|
async function have(projectId) {
|
|
53
|
-
|
|
54
|
-
|
|
76
|
+
return (await extensionsApi.listInstances(projectId))
|
|
77
|
+
.filter((i) => { var _a; return !(((_a = i.labels) === null || _a === void 0 ? void 0 : _a.createdBy) === "SDK"); })
|
|
78
|
+
.map((i) => {
|
|
55
79
|
var _a;
|
|
56
80
|
const dep = {
|
|
57
81
|
instanceId: i.name.split("/").pop(),
|
|
@@ -61,6 +85,9 @@ async function have(projectId) {
|
|
|
61
85
|
eventarcChannel: i.config.eventarcChannel,
|
|
62
86
|
etag: i.etag,
|
|
63
87
|
};
|
|
88
|
+
if (i.labels) {
|
|
89
|
+
dep.labels = i.labels;
|
|
90
|
+
}
|
|
64
91
|
if (i.config.extensionRef) {
|
|
65
92
|
const ref = refs.parse(i.config.extensionRef);
|
|
66
93
|
dep.ref = ref;
|
|
@@ -97,6 +124,7 @@ async function wantDynamic(args) {
|
|
|
97
124
|
systemParams,
|
|
98
125
|
allowedEventTypes,
|
|
99
126
|
eventarcChannel,
|
|
127
|
+
labels: ext.labels,
|
|
100
128
|
});
|
|
101
129
|
}
|
|
102
130
|
else if (ext.ref) {
|
|
@@ -107,6 +135,7 @@ async function wantDynamic(args) {
|
|
|
107
135
|
systemParams,
|
|
108
136
|
allowedEventTypes,
|
|
109
137
|
eventarcChannel,
|
|
138
|
+
labels: ext.labels,
|
|
110
139
|
});
|
|
111
140
|
}
|
|
112
141
|
}
|