firebase-tools 13.28.0 → 13.29.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/lib/dataconnect/fileUtils.js +3 -0
- package/lib/deploy/functions/backend.js +1 -3
- package/lib/deploy/functions/build.js +3 -1
- package/lib/deploy/functions/release/planner.js +4 -4
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +4 -0
- package/lib/deploy/functions/runtimes/supported/types.js +1 -1
- package/lib/emulator/controller.js +14 -0
- package/lib/emulator/dataconnect/pgliteServer.js +34 -7
- package/lib/emulator/dataconnectEmulator.js +10 -1
- package/lib/emulator/downloadableEmulators.js +9 -10
- package/lib/error.js +3 -1
- package/lib/functions/events/v2.js +7 -3
- package/lib/gcp/cloudfunctionsv2.js +6 -0
- package/lib/init/features/dataconnect/index.js +4 -0
- package/lib/management/projects.js +23 -1
- package/package.json +1 -1
- package/templates/init/functions/javascript/package.lint.json +1 -1
- package/templates/init/functions/javascript/package.nolint.json +1 -1
- package/templates/init/functions/typescript/package.lint.json +1 -1
- package/templates/init/functions/typescript/package.nolint.json +1 -1
- package/templates/init/functions/typescript/tsconfig.json +3 -1
|
@@ -53,6 +53,9 @@ function validateConnectorYaml(unvalidated) {
|
|
|
53
53
|
return unvalidated;
|
|
54
54
|
}
|
|
55
55
|
async function readGQLFiles(sourceDir) {
|
|
56
|
+
if (!fs.existsSync(sourceDir)) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
56
59
|
const files = await fs.readdir(sourceDir);
|
|
57
60
|
return files
|
|
58
61
|
.filter((f) => f.endsWith(".gql") || f.endsWith(".graphql"))
|
|
@@ -25,9 +25,7 @@ function endpointTriggerType(endpoint) {
|
|
|
25
25
|
else if (isBlockingTriggered(endpoint)) {
|
|
26
26
|
return endpoint.blockingTrigger.eventType;
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
throw new Error("Unexpected trigger type for endpoint " + JSON.stringify(endpoint));
|
|
30
|
-
}
|
|
28
|
+
(0, functional_1.assertExhaustive)(endpoint);
|
|
31
29
|
}
|
|
32
30
|
exports.endpointTriggerType = endpointTriggerType;
|
|
33
31
|
exports.AllVpcEgressSettings = ["PRIVATE_RANGES_ONLY", "ALL_TRAFFIC"];
|
|
@@ -259,7 +259,9 @@ function discoverTrigger(endpoint, region, r) {
|
|
|
259
259
|
return { httpsTrigger };
|
|
260
260
|
}
|
|
261
261
|
else if (isCallableTriggered(endpoint)) {
|
|
262
|
-
|
|
262
|
+
const trigger = { callableTrigger: {} };
|
|
263
|
+
proto.copyIfPresent(trigger.callableTrigger, endpoint.callableTrigger, "genkitAction");
|
|
264
|
+
return trigger;
|
|
263
265
|
}
|
|
264
266
|
else if (isBlockingTriggered(endpoint)) {
|
|
265
267
|
return { blockingTrigger: endpoint.blockingTrigger };
|
|
@@ -7,7 +7,6 @@ const error_1 = require("../../../error");
|
|
|
7
7
|
const utils = require("../../../utils");
|
|
8
8
|
const backend = require("../backend");
|
|
9
9
|
const v2events = require("../../../functions/events/v2");
|
|
10
|
-
const v2_1 = require("../../../functions/events/v2");
|
|
11
10
|
function calculateChangesets(want, have, keyFn, deleteAll) {
|
|
12
11
|
const toCreate = utils.groupBy(Object.keys(want)
|
|
13
12
|
.filter((id) => !have[id])
|
|
@@ -167,9 +166,9 @@ function upgradedScheduleFromV1ToV2(want, have) {
|
|
|
167
166
|
exports.upgradedScheduleFromV1ToV2 = upgradedScheduleFromV1ToV2;
|
|
168
167
|
function checkForUnsafeUpdate(want, have) {
|
|
169
168
|
return (backend.isEventTriggered(want) &&
|
|
170
|
-
v2_1.FIRESTORE_EVENT_WITH_AUTH_CONTEXT_REGEX.test(want.eventTrigger.eventType) &&
|
|
171
169
|
backend.isEventTriggered(have) &&
|
|
172
|
-
|
|
170
|
+
want.eventTrigger.eventType ===
|
|
171
|
+
v2events.CONVERTABLE_EVENTS[have.eventTrigger.eventType]);
|
|
173
172
|
}
|
|
174
173
|
exports.checkForUnsafeUpdate = checkForUnsafeUpdate;
|
|
175
174
|
function checkForIllegalUpdate(want, have) {
|
|
@@ -196,7 +195,8 @@ function checkForIllegalUpdate(want, have) {
|
|
|
196
195
|
};
|
|
197
196
|
const wantType = triggerType(want);
|
|
198
197
|
const haveType = triggerType(have);
|
|
199
|
-
|
|
198
|
+
const upgradingHttpsFunction = backend.isHttpsTriggered(have) && backend.isCallableTriggered(want);
|
|
199
|
+
if (wantType !== haveType && !upgradingHttpsFunction) {
|
|
200
200
|
throw new error_1.FirebaseError(`[${(0, functionsDeployHelper_1.getFunctionLabel)(want)}] Changing from ${haveType} function to ${wantType} function is not allowed. Please delete your function and create a new one instead.`);
|
|
201
201
|
}
|
|
202
202
|
if (want.platform === "gcfv1" && have.platform === "gcfv2") {
|
|
@@ -134,6 +134,9 @@ function assertBuildEndpoint(ep, id) {
|
|
|
134
134
|
});
|
|
135
135
|
}
|
|
136
136
|
else if (build.isCallableTriggered(ep)) {
|
|
137
|
+
(0, parsing_1.assertKeyTypes)(prefix + ".callableTrigger", ep.callableTrigger, {
|
|
138
|
+
genkitAction: "string?",
|
|
139
|
+
});
|
|
137
140
|
}
|
|
138
141
|
else if (build.isScheduleTriggered(ep)) {
|
|
139
142
|
(0, parsing_1.assertKeyTypes)(prefix + ".scheduleTrigger", ep.scheduleTrigger, {
|
|
@@ -216,6 +219,7 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
|
|
|
216
219
|
}
|
|
217
220
|
else if (build.isCallableTriggered(ep)) {
|
|
218
221
|
triggered = { callableTrigger: {} };
|
|
222
|
+
(0, proto_1.copyIfPresent)(triggered.callableTrigger, ep.callableTrigger, "genkitAction");
|
|
219
223
|
}
|
|
220
224
|
else if (build.isScheduleTriggered(ep)) {
|
|
221
225
|
const st = {
|
|
@@ -577,6 +577,20 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
577
577
|
utils.assertIsString(options.import);
|
|
578
578
|
const importDirAbsPath = path.resolve(options.import);
|
|
579
579
|
const exportMetadataFilePath = path.resolve(importDirAbsPath, exportMetadata.dataconnect.path);
|
|
580
|
+
const dataDirectory = options.config.get("emulators.dataconnect.dataDir");
|
|
581
|
+
if (exportMetadataFilePath && dataDirectory) {
|
|
582
|
+
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATACONNECT).logLabeled("WARN", "dataconnect", "'firebase.json#emulators.dataconnect.dataDir' is set and `--import` flag was passed. " +
|
|
583
|
+
"This will overwrite any data saved from previous runs.");
|
|
584
|
+
if (!options.nonInteractive &&
|
|
585
|
+
!(await (0, prompt_1.promptOnce)({
|
|
586
|
+
type: "confirm",
|
|
587
|
+
message: `Do you wish to continue and overwrite data in ${dataDirectory}?`,
|
|
588
|
+
default: false,
|
|
589
|
+
}))) {
|
|
590
|
+
await cleanShutdown();
|
|
591
|
+
return { deprecationNotices: [] };
|
|
592
|
+
}
|
|
593
|
+
}
|
|
580
594
|
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATACONNECT).logLabeled("BULLET", "dataconnect", `Importing data from ${exportMetadataFilePath}`);
|
|
581
595
|
args.importPath = exportMetadataFilePath;
|
|
582
596
|
void (0, track_1.trackEmulator)("emulator_import", {
|
|
@@ -27,6 +27,7 @@ const fs = require("fs");
|
|
|
27
27
|
const index_1 = require("./pg-gateway/index");
|
|
28
28
|
const node_1 = require("./pg-gateway/platforms/node");
|
|
29
29
|
const logger_1 = require("../../logger");
|
|
30
|
+
const error_1 = require("../../error");
|
|
30
31
|
exports.TRUNCATE_TABLES_SQL = `
|
|
31
32
|
DO $do$
|
|
32
33
|
BEGIN
|
|
@@ -62,6 +63,7 @@ class PostgresServer {
|
|
|
62
63
|
server.emit("error", err);
|
|
63
64
|
});
|
|
64
65
|
});
|
|
66
|
+
this.server = server;
|
|
65
67
|
const listeningPromise = new Promise((resolve) => {
|
|
66
68
|
server.listen(port, host, () => {
|
|
67
69
|
resolve();
|
|
@@ -77,7 +79,7 @@ class PostgresServer {
|
|
|
77
79
|
const pgliteArgs = {
|
|
78
80
|
username: this.username,
|
|
79
81
|
database: this.database,
|
|
80
|
-
debug:
|
|
82
|
+
debug: this.debug,
|
|
81
83
|
extensions: {
|
|
82
84
|
vector,
|
|
83
85
|
uuidOssp,
|
|
@@ -90,7 +92,7 @@ class PostgresServer {
|
|
|
90
92
|
const file = new File([rf], this.importPath);
|
|
91
93
|
pgliteArgs.loadDataDir = file;
|
|
92
94
|
}
|
|
93
|
-
this.db = await
|
|
95
|
+
this.db = await this.forceCreateDB(pgliteArgs);
|
|
94
96
|
await this.db.waitReady;
|
|
95
97
|
}
|
|
96
98
|
return this.db;
|
|
@@ -105,12 +107,37 @@ class PostgresServer {
|
|
|
105
107
|
const arrayBuff = await dump.arrayBuffer();
|
|
106
108
|
fs.writeFileSync(exportPath, new Uint8Array(arrayBuff));
|
|
107
109
|
}
|
|
108
|
-
|
|
110
|
+
async forceCreateDB(pgliteArgs) {
|
|
111
|
+
try {
|
|
112
|
+
const db = await pglite_1.PGlite.create(pgliteArgs);
|
|
113
|
+
return db;
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
if (pgliteArgs.dataDir && (0, error_1.hasMessage)(err) && /Database already exists/.test(err.message)) {
|
|
117
|
+
fs.rmSync(pgliteArgs.dataDir, { force: true, recursive: true });
|
|
118
|
+
const db = await pglite_1.PGlite.create(pgliteArgs);
|
|
119
|
+
return db;
|
|
120
|
+
}
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async stop() {
|
|
125
|
+
if (this.db) {
|
|
126
|
+
await this.db.close();
|
|
127
|
+
}
|
|
128
|
+
if (this.server) {
|
|
129
|
+
this.server.close();
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
constructor(args) {
|
|
109
134
|
this.db = undefined;
|
|
110
|
-
this.
|
|
111
|
-
this.
|
|
112
|
-
this.
|
|
113
|
-
this.
|
|
135
|
+
this.server = undefined;
|
|
136
|
+
this.username = args.username;
|
|
137
|
+
this.database = args.database;
|
|
138
|
+
this.dataDirectory = args.dataDirectory;
|
|
139
|
+
this.importPath = args.importPath;
|
|
140
|
+
this.debug = args.debug ? 5 : 0;
|
|
114
141
|
}
|
|
115
142
|
}
|
|
116
143
|
exports.PostgresServer = PostgresServer;
|
|
@@ -69,7 +69,13 @@ class DataConnectEmulator {
|
|
|
69
69
|
const postgresDumpPath = this.args.importPath
|
|
70
70
|
? path.join(this.args.importPath, "postgres.tar.gz")
|
|
71
71
|
: undefined;
|
|
72
|
-
this.postgresServer = new pgliteServer_1.PostgresServer(
|
|
72
|
+
this.postgresServer = new pgliteServer_1.PostgresServer({
|
|
73
|
+
database: dbId,
|
|
74
|
+
username: "fdc",
|
|
75
|
+
dataDirectory,
|
|
76
|
+
importPath: postgresDumpPath,
|
|
77
|
+
debug: this.args.debug,
|
|
78
|
+
});
|
|
73
79
|
const server = await this.postgresServer.createPGServer(pgHost, pgPort);
|
|
74
80
|
const connectableHost = (0, utils_1.connectableHostname)(pgHost);
|
|
75
81
|
connStr = `postgres://${connectableHost}:${pgPort}/${dbId}?sslmode=disable`;
|
|
@@ -101,6 +107,9 @@ class DataConnectEmulator {
|
|
|
101
107
|
this.logger.logLabeled("INFO", "dataconnect", "Skipping cleanup of Data Connect emulator, as it was not started by this process.");
|
|
102
108
|
return;
|
|
103
109
|
}
|
|
110
|
+
if (this.postgresServer) {
|
|
111
|
+
await this.postgresServer.stop();
|
|
112
|
+
}
|
|
104
113
|
return (0, downloadableEmulators_1.stop)(types_1.Emulators.DATACONNECT);
|
|
105
114
|
}
|
|
106
115
|
getInfo() {
|
|
@@ -48,20 +48,20 @@ const EMULATOR_UPDATE_DETAILS = {
|
|
|
48
48
|
},
|
|
49
49
|
dataconnect: process.platform === "darwin"
|
|
50
50
|
? {
|
|
51
|
-
version: "1.7.
|
|
52
|
-
expectedSize:
|
|
53
|
-
expectedChecksum: "
|
|
51
|
+
version: "1.7.5",
|
|
52
|
+
expectedSize: 25281280,
|
|
53
|
+
expectedChecksum: "85d0de96b5c08b553fd8506a2bc381bb",
|
|
54
54
|
}
|
|
55
55
|
: process.platform === "win32"
|
|
56
56
|
? {
|
|
57
|
-
version: "1.7.
|
|
58
|
-
expectedSize:
|
|
59
|
-
expectedChecksum: "
|
|
57
|
+
version: "1.7.5",
|
|
58
|
+
expectedSize: 25711616,
|
|
59
|
+
expectedChecksum: "c99d67fa8e74d41760b96122b055b8e2",
|
|
60
60
|
}
|
|
61
61
|
: {
|
|
62
|
-
version: "1.7.
|
|
62
|
+
version: "1.7.5",
|
|
63
63
|
expectedSize: 25190552,
|
|
64
|
-
expectedChecksum: "
|
|
64
|
+
expectedChecksum: "61d966b781e6f2887f8b38ec271b54e2",
|
|
65
65
|
},
|
|
66
66
|
};
|
|
67
67
|
exports.DownloadDetails = {
|
|
@@ -475,8 +475,7 @@ async function start(targetName, args, extraEnv = {}) {
|
|
|
475
475
|
exports.start = start;
|
|
476
476
|
function isIncomaptibleArchError(err) {
|
|
477
477
|
var _a;
|
|
478
|
-
|
|
479
|
-
return (hasMessage(err) &&
|
|
478
|
+
return ((0, error_1.hasMessage)(err) &&
|
|
480
479
|
/Unknown system error/.test((_a = err.message) !== null && _a !== void 0 ? _a : "") &&
|
|
481
480
|
process.platform === "darwin");
|
|
482
481
|
}
|
package/lib/error.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isBillingError = exports.getError = exports.getErrStatus = exports.isObject = exports.getErrStack = exports.getErrMsg = exports.FirebaseError = void 0;
|
|
3
|
+
exports.hasMessage = exports.isBillingError = exports.getError = exports.getErrStatus = exports.isObject = exports.getErrStack = exports.getErrMsg = exports.FirebaseError = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
const DEFAULT_CHILDREN = [];
|
|
6
6
|
const DEFAULT_EXIT = 1;
|
|
@@ -65,3 +65,5 @@ function isBillingError(e) {
|
|
|
65
65
|
}));
|
|
66
66
|
}
|
|
67
67
|
exports.isBillingError = isBillingError;
|
|
68
|
+
const hasMessage = (e) => !!(e === null || e === void 0 ? void 0 : e.message);
|
|
69
|
+
exports.hasMessage = hasMessage;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.CONVERTABLE_EVENTS = exports.FIREALERTS_EVENT = exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
|
|
4
4
|
exports.PUBSUB_PUBLISH_EVENT = "google.cloud.pubsub.topic.v1.messagePublished";
|
|
5
5
|
exports.STORAGE_EVENTS = [
|
|
6
6
|
"google.cloud.storage.object.v1.finalized",
|
|
@@ -28,5 +28,9 @@ exports.FIRESTORE_EVENTS = [
|
|
|
28
28
|
"google.cloud.firestore.document.v1.deleted.withAuthContext",
|
|
29
29
|
];
|
|
30
30
|
exports.FIREALERTS_EVENT = "google.firebase.firebasealerts.alerts.v1.published";
|
|
31
|
-
exports.
|
|
32
|
-
|
|
31
|
+
exports.CONVERTABLE_EVENTS = {
|
|
32
|
+
"google.cloud.firestore.document.v1.created": "google.cloud.firestore.document.v1.created.withAuthContext",
|
|
33
|
+
"google.cloud.firestore.document.v1.updated": "google.cloud.firestore.document.v1.updated.withAuthContext",
|
|
34
|
+
"google.cloud.firestore.document.v1.deleted": "google.cloud.firestore.document.v1.deleted.withAuthContext",
|
|
35
|
+
"google.cloud.firestore.document.v1.written": "google.cloud.firestore.document.v1.written.withAuthContext",
|
|
36
|
+
};
|
|
@@ -259,6 +259,9 @@ function functionFromEndpoint(endpoint) {
|
|
|
259
259
|
}
|
|
260
260
|
else if (backend.isCallableTriggered(endpoint)) {
|
|
261
261
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-callable": "true" });
|
|
262
|
+
if (endpoint.callableTrigger.genkitAction) {
|
|
263
|
+
gcfFunction.labels["genkit-action"] = endpoint.callableTrigger.genkitAction;
|
|
264
|
+
}
|
|
262
265
|
}
|
|
263
266
|
else if (backend.isBlockingTriggered(endpoint)) {
|
|
264
267
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.BLOCKING_LABEL]: constants_1.BLOCKING_EVENT_TO_LABEL_KEY[endpoint.blockingTrigger.eventType] });
|
|
@@ -294,6 +297,9 @@ function endpointFromFunction(gcfFunction) {
|
|
|
294
297
|
trigger = {
|
|
295
298
|
callableTrigger: {},
|
|
296
299
|
};
|
|
300
|
+
if (gcfFunction.labels["genkit-action"]) {
|
|
301
|
+
trigger.callableTrigger.genkitAction = gcfFunction.labels["genkit-action"];
|
|
302
|
+
}
|
|
297
303
|
}
|
|
298
304
|
else if ((_d = gcfFunction.labels) === null || _d === void 0 ? void 0 : _d[constants_1.BLOCKING_LABEL]) {
|
|
299
305
|
trigger = {
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.actuate = exports.doSetup = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const clc = require("colorette");
|
|
6
|
+
const fs = require("fs-extra");
|
|
6
7
|
const prompt_1 = require("../../../prompt");
|
|
7
8
|
const provisionCloudSql_1 = require("../../../dataconnect/provisionCloudSql");
|
|
8
9
|
const freeTrial_1 = require("../../../dataconnect/freeTrial");
|
|
@@ -137,6 +138,9 @@ async function writeFiles(config, info) {
|
|
|
137
138
|
await config.askWriteProjectFile((0, path_1.join)(dir, "schema", f.path), f.content);
|
|
138
139
|
}
|
|
139
140
|
}
|
|
141
|
+
else {
|
|
142
|
+
fs.ensureFileSync((0, path_1.join)(dir, "schema", "schema.gql"));
|
|
143
|
+
}
|
|
140
144
|
for (const c of info.connectors) {
|
|
141
145
|
await writeConnectorFiles(config, c);
|
|
142
146
|
}
|
|
@@ -26,12 +26,34 @@ exports.PROJECTS_CREATE_QUESTIONS = [
|
|
|
26
26
|
default: "",
|
|
27
27
|
message: "Please specify a unique project id " +
|
|
28
28
|
`(${clc.yellow("warning")}: cannot be modified afterward) [6-30 characters]:\n`,
|
|
29
|
+
validate: (projectId) => {
|
|
30
|
+
if (projectId.length < 6) {
|
|
31
|
+
return "Project ID must be at least 6 characters long";
|
|
32
|
+
}
|
|
33
|
+
else if (projectId.length > 30) {
|
|
34
|
+
return "Project ID cannot be longer than 30 characters";
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
},
|
|
29
40
|
},
|
|
30
41
|
{
|
|
31
42
|
type: "input",
|
|
32
43
|
name: "displayName",
|
|
33
|
-
default:
|
|
44
|
+
default: (answers) => answers.projectId,
|
|
34
45
|
message: "What would you like to call your project? (defaults to your project ID)",
|
|
46
|
+
validate: (displayName) => {
|
|
47
|
+
if (displayName.length < 4) {
|
|
48
|
+
return "Project name must be at least 4 characters long";
|
|
49
|
+
}
|
|
50
|
+
else if (displayName.length > 30) {
|
|
51
|
+
return "Project name cannot be longer than 30 characters";
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
35
57
|
},
|
|
36
58
|
];
|
|
37
59
|
const firebaseAPIClient = new apiv2_1.Client({
|
package/package.json
CHANGED