diff --git a/.github/workflows/node-test.yml b/.github/workflows/node-test.yml index fc55932ae09..2376ce2bf3c 100644 --- a/.github/workflows/node-test.yml +++ b/.github/workflows/node-test.yml @@ -117,7 +117,7 @@ jobs: run: npm run test:e2e working-directory: firebase-vscode - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: failure() with: name: screenshots diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb2d..6669dc6f1f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +- Updated `cross-env` and `cross-spawn` dependencies to avoid vulnerable versions. (#7979) +- Fixed an issue with the Data Connect emulator where `dataDir` and `--export` were relative to the current directory insead of `firebase.json`. diff --git a/firebase-vscode/CHANGELOG.md b/firebase-vscode/CHANGELOG.md index 1fdd30c52e4..2844d0693d9 100644 --- a/firebase-vscode/CHANGELOG.md +++ b/firebase-vscode/CHANGELOG.md @@ -1,5 +1,7 @@ ## NEXT +- [Feature] Added `debug` setting to run commands with `--debug` + ## 0.12.0 - Updated internal firebase-tools dependency to 13.29.1 diff --git a/firebase-vscode/package.json b/firebase-vscode/package.json index 6de4ca57c69..8321c6862d4 100644 --- a/firebase-vscode/package.json +++ b/firebase-vscode/package.json @@ -77,6 +77,11 @@ "default": true, "markdownDescription": "%ext.config.idx.viewMetricNotice%", "scope": "application" + }, + "firebase.debug": { + "type": "boolean", + "default": false, + "markdownDescription": "%ext.config.debug%" } } }, diff --git a/firebase-vscode/package.nls.json b/firebase-vscode/package.nls.json index 2fd89eb524d..6064872232b 100644 --- a/firebase-vscode/package.nls.json +++ b/firebase-vscode/package.nls.json @@ -4,6 +4,7 @@ "ext.config.firebasePath": "Path to the `Firebase` module, e.g. `./node_modules/firebase`", "ext.config.hosting.useFrameworks": "Enable web frameworks", "ext.config.npmPath": "Path to NPM executable in local environment", + "ext.config.debug": "When true, add the --debug flag to any commands run by the extension", "ext.config.title": "Prettier", "ext.config.idx.viewMetricNotice": "Show data collection notice on next startup (IDX Only)" } diff --git a/firebase-vscode/src/data-connect/terminal.ts b/firebase-vscode/src/data-connect/terminal.ts index d09c8ce73b0..f61cb56aac7 100644 --- a/firebase-vscode/src/data-connect/terminal.ts +++ b/firebase-vscode/src/data-connect/terminal.ts @@ -17,6 +17,7 @@ export function setTerminalEnvVars(envVar: string, value: string) { } export function runCommand(command: string) { + const settings = getSettings(); const terminalOptions: TerminalOptions = { name: "Data Connect Terminal", env: environmentVariables, @@ -30,6 +31,9 @@ export function runCommand(command: string) { if (currentProjectId.value) { command = `${command} --project ${currentProjectId.value}`; } + if (settings.debug) { + command = `${command} --debug`; + } terminal.sendText(command); } @@ -38,6 +42,7 @@ export function runTerminalTask( command: string, presentationOptions: vscode.TaskPresentationOptions = { focus: true }, ): Promise { + const settings = getSettings(); const type = "firebase-" + Date.now(); return new Promise(async (resolve, reject) => { vscode.tasks.onDidEndTaskProcess(async (e) => { @@ -60,7 +65,7 @@ export function runTerminalTask( vscode.TaskScope.Workspace, taskName, "firebase", - new vscode.ShellExecution(command, executionOptions), + new vscode.ShellExecution(`${command}${settings.debug ? " --debug" : ""}`, executionOptions), ); task.presentationOptions = presentationOptions; await vscode.tasks.executeTask(task); diff --git a/firebase-vscode/src/utils/settings.ts b/firebase-vscode/src/utils/settings.ts index a1ba94a1568..680fbdfe6b4 100644 --- a/firebase-vscode/src/utils/settings.ts +++ b/firebase-vscode/src/utils/settings.ts @@ -7,6 +7,7 @@ export interface Settings { readonly npmPath: string; readonly useFrameworks: boolean; readonly shouldShowIdxMetricNotice: boolean; + readonly debug: boolean; } // TODO: Temporary fallback for bashing, this should probably point to the global firebase binary on the system @@ -37,6 +38,7 @@ export function getSettings(): Settings { "idx.viewMetricNotice", true, ), + debug: config.get("debug", false), }; } diff --git a/firebase-vscode/webpack.common.js b/firebase-vscode/webpack.common.js index aa3ffbbbe41..60212c2d6e8 100644 --- a/firebase-vscode/webpack.common.js +++ b/firebase-vscode/webpack.common.js @@ -191,19 +191,20 @@ const extensionConfig = { from: "../schema", to: "./schema", }, + // TODO(hlshen): Sanity check if these should be fixed or removed. AFIACT, they exist for functions and hosting deploys, which are not relevant anymore. // Copy uncompiled JS files called at runtime by // firebase-tools/src/parseTriggers.ts - { - from: "*.js", - to: "./", - context: "../src/deploy/functions/runtimes/node", - }, - // Copy cross-env-shell.js used to run predeploy scripts - // to ensure they work in Windows - { - from: "../node_modules/cross-env/dist", - to: "./cross-env/dist", - }, + // { + // from: "*.js", + // to: "./", + // context: "../src/deploy/functions/runtimes/node", + // }, + // // Copy cross-env-shell.js used to run predeploy scripts + // // to ensure they work in Windows + // { + // from: "../node_modules/cross-env/dist", + // to: "./cross-env/dist", + // }, ], }), ], diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 81d46dac925..49061466cd1 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -13,7 +13,8 @@ "@google-cloud/cloud-sql-connector": "^1.3.3", "@google-cloud/pubsub": "^4.5.0", "abort-controller": "^3.0.0", - "ajv": "^6.12.6", + "ajv": "^8.17.1", + "ajv-formats": "3.0.1", "archiver": "^7.0.0", "async-lock": "1.4.1", "body-parser": "^1.19.0", @@ -24,8 +25,8 @@ "commander": "^5.1.0", "configstore": "^5.0.1", "cors": "^2.8.5", - "cross-env": "^5.1.3", - "cross-spawn": "^7.0.3", + "cross-env": "^7.0.3", + "cross-spawn": "^7.0.5", "csv-parse": "^5.0.4", "deep-equal-in-any-order": "^2.0.6", "exegesis": "^4.2.0", @@ -166,7 +167,7 @@ "swagger2openapi": "^7.0.8", "ts-node": "^10.4.0", "typescript": "^4.5.4", - "typescript-json-schema": "^0.50.1", + "typescript-json-schema": "^0.65.1", "vite": "^4.2.1" }, "engines": { @@ -277,11 +278,22 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@angular-devkit/core/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/@angular-devkit/core/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, "node_modules/@angular-devkit/core/node_modules/rxjs": { "version": "6.6.7", @@ -1387,6 +1399,23 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@eslint/eslintrc/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1431,6 +1460,13 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/@eslint/eslintrc/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -5088,14 +5124,15 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -5103,9 +5140,9 @@ } }, "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dependencies": { "ajv": "^8.0.0" }, @@ -5118,26 +5155,6 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -7634,42 +7651,20 @@ "dev": true }, "node_modules/cross-env": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz", - "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "dependencies": { - "cross-spawn": "^6.0.5", - "is-windows": "^1.0.0" + "cross-spawn": "^7.0.1" }, "bin": { - "cross-env": "dist/bin/cross-env.js", - "cross-env-shell": "dist/bin/cross-env-shell.js" + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" }, "engines": { - "node": ">=4.0" - } - }, - "node_modules/cross-env/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/cross-env/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" } }, "node_modules/cross-fetch": { @@ -7682,9 +7677,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -8571,6 +8566,23 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -8722,6 +8734,13 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint/node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -9031,26 +9050,22 @@ "npm": ">5.0.0" } }, - "node_modules/exegesis/node_modules/ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "node_modules/exegesis/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "ajv": "^8.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/exegesis/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/express": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", @@ -9295,9 +9310,11 @@ } }, "node_modules/fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -9316,6 +9333,12 @@ "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "license": "BSD-3-Clause" + }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -12010,6 +12033,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -12466,18 +12490,10 @@ } }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "dependencies": { - "jsonify": "~0.0.0" - } + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -12520,15 +12536,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/jsonpath": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", @@ -14646,9 +14653,10 @@ } }, "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "license": "MIT", "optional": true }, "node_modules/nanoid": { @@ -14769,11 +14777,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, "node_modules/nise": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", @@ -16096,6 +16099,12 @@ "node": ">= 0.8" } }, + "node_modules/path-equal": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", + "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==", + "dev": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -16114,14 +16123,6 @@ "node": ">=0.10.0" } }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "engines": { - "node": ">=4" - } - }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -16903,6 +16904,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, "engines": { "node": ">=6" } @@ -17805,6 +17807,15 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -17997,25 +18008,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/shiki": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", @@ -19649,36 +19641,36 @@ } }, "node_modules/typescript-json-schema": { - "version": "0.50.1", - "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.50.1.tgz", - "integrity": "sha512-GCof/SDoiTDl0qzPonNEV4CHyCsZEIIf+mZtlrjoD8vURCcEzEfa2deRuxYid8Znp/e27eDR7Cjg8jgGrimBCA==", + "version": "0.65.1", + "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.65.1.tgz", + "integrity": "sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.7", - "@types/node": "^14.14.33", - "glob": "^7.1.6", - "json-stable-stringify": "^1.0.1", - "ts-node": "^9.1.1", - "typescript": "~4.2.3", - "yargs": "^16.2.0" + "@types/json-schema": "^7.0.9", + "@types/node": "^18.11.9", + "glob": "^7.1.7", + "path-equal": "^1.2.5", + "safe-stable-stringify": "^2.2.0", + "ts-node": "^10.9.1", + "typescript": "~5.5.0", + "yargs": "^17.1.1" }, "bin": { "typescript-json-schema": "bin/typescript-json-schema" } }, - "node_modules/typescript-json-schema/node_modules/@types/node": { - "version": "14.18.63", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", - "dev": true - }, - "node_modules/typescript-json-schema/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/typescript-json-schema/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, "engines": { - "node": ">=0.3.1" + "node": ">=12" } }, "node_modules/typescript-json-schema/node_modules/glob": { @@ -19702,43 +19694,53 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typescript-json-schema/node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "node_modules/typescript-json-schema/node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, - "dependencies": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "typescript": ">=2.7" + "node": ">=14.17" } }, - "node_modules/typescript-json-schema/node_modules/typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "node_modules/typescript-json-schema/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "engines": { + "node": ">=10" + } + }, + "node_modules/typescript-json-schema/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=4.2.0" + "node": ">=12" + } + }, + "node_modules/typescript-json-schema/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" } }, "node_modules/uc.micro": { @@ -20196,6 +20198,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -20531,17 +20534,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -21108,11 +21100,14 @@ "uri-js": "^4.2.2" } }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } }, "rxjs": { "version": "6.6.7", @@ -21848,6 +21843,18 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -21875,6 +21882,12 @@ "argparse": "^2.0.1" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -24903,40 +24916,22 @@ } }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" } }, "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "requires": { "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - } } }, "ansi-align": { @@ -26707,31 +26702,11 @@ "dev": true }, "cross-env": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz", - "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "requires": { - "cross-spawn": "^6.0.5", - "is-windows": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - } + "cross-spawn": "^7.0.1" } }, "cross-fetch": { @@ -26744,9 +26719,9 @@ } }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -27307,6 +27282,18 @@ "text-table": "^0.2.0" }, "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -27405,6 +27392,12 @@ "argparse": "^2.0.1" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -27738,21 +27731,13 @@ "semver": "^7.0.0" }, "dependencies": { - "ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "ajv": "^8.0.0" } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" } } }, @@ -27948,9 +27933,10 @@ } }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -27969,6 +27955,11 @@ "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", "dev": true }, + "fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==" + }, "fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -29966,7 +29957,8 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true }, "is-wsl": { "version": "1.1.0", @@ -30326,18 +30318,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -30372,12 +30355,6 @@ "universalify": "^2.0.0" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsonpath": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", @@ -31921,9 +31898,9 @@ } }, "nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", + "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", "optional": true }, "nanoid": { @@ -32004,11 +31981,6 @@ } } }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, "nise": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", @@ -32998,6 +32970,12 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "path-equal": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", + "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==", + "dev": true + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -33010,11 +32988,6 @@ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "devOptional": true }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -33594,7 +33567,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "punycode.js": { "version": "2.3.1", @@ -34249,6 +34223,12 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "dev": true + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -34406,19 +34386,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, "shiki": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", @@ -35691,31 +35658,31 @@ "dev": true }, "typescript-json-schema": { - "version": "0.50.1", - "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.50.1.tgz", - "integrity": "sha512-GCof/SDoiTDl0qzPonNEV4CHyCsZEIIf+mZtlrjoD8vURCcEzEfa2deRuxYid8Znp/e27eDR7Cjg8jgGrimBCA==", + "version": "0.65.1", + "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.65.1.tgz", + "integrity": "sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", - "@types/node": "^14.14.33", - "glob": "^7.1.6", - "json-stable-stringify": "^1.0.1", - "ts-node": "^9.1.1", - "typescript": "~4.2.3", - "yargs": "^16.2.0" + "@types/json-schema": "^7.0.9", + "@types/node": "^18.11.9", + "glob": "^7.1.7", + "path-equal": "^1.2.5", + "safe-stable-stringify": "^2.2.0", + "ts-node": "^10.9.1", + "typescript": "~5.5.0", + "yargs": "^17.1.1" }, "dependencies": { - "@types/node": { - "version": "14.18.63", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", - "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } }, "glob": { "version": "7.2.3", @@ -35731,24 +35698,37 @@ "path-is-absolute": "^1.0.0" } }, - "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" } }, - "typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true } } @@ -36072,6 +36052,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -36321,14 +36302,6 @@ "webidl-conversions": "^3.0.0" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", diff --git a/package.json b/package.json index b25f40497f9..88361aa32bf 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,8 @@ "@google-cloud/cloud-sql-connector": "^1.3.3", "@google-cloud/pubsub": "^4.5.0", "abort-controller": "^3.0.0", - "ajv": "^6.12.6", + "ajv": "^8.17.1", + "ajv-formats": "3.0.1", "archiver": "^7.0.0", "async-lock": "1.4.1", "body-parser": "^1.19.0", @@ -114,8 +115,8 @@ "commander": "^5.1.0", "configstore": "^5.0.1", "cors": "^2.8.5", - "cross-env": "^5.1.3", - "cross-spawn": "^7.0.3", + "cross-env": "^7.0.3", + "cross-spawn": "^7.0.5", "csv-parse": "^5.0.4", "deep-equal-in-any-order": "^2.0.6", "exegesis": "^4.2.0", @@ -253,7 +254,7 @@ "swagger2openapi": "^7.0.8", "ts-node": "^10.4.0", "typescript": "^4.5.4", - "typescript-json-schema": "^0.50.1", + "typescript-json-schema": "^0.65.1", "vite": "^4.2.1" } } diff --git a/schema/firebase-config.json b/schema/firebase-config.json index d9db62c2b52..da29a61bd6d 100644 --- a/schema/firebase-config.json +++ b/schema/firebase-config.json @@ -2,10 +2,127 @@ "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "definitions": { + "DataConnectSingle": { + "additionalProperties": false, + "properties": { + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "predeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "source": { + "type": "string" + } + }, + "required": [ + "source" + ], + "type": "object" + }, + "DatabaseSingle": { + "additionalProperties": false, + "properties": { + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "predeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "rules": { + "type": "string" + } + }, + "required": [ + "rules" + ], + "type": "object" + }, "ExtensionsConfig": { "additionalProperties": false, "type": "object" }, + "FirestoreSingle": { + "additionalProperties": false, + "properties": { + "database": { + "type": "string" + }, + "indexes": { + "type": "string" + }, + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "predeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "rules": { + "type": "string" + } + }, + "type": "object" + }, "FrameworksBackendOptions": { "additionalProperties": false, "properties": { @@ -23,9 +140,7 @@ "cpu": { "anyOf": [ { - "enum": [ - "gcf_gen1" - ], + "const": "gcf_gen1", "type": "string" }, { @@ -48,10 +163,8 @@ "type": "string" }, "invoker": { + "const": "public", "description": "Invoker to set access control on https functions.", - "enum": [ - "public" - ], "type": "string" }, "labels": { @@ -122,1317 +235,1207 @@ }, "type": "object" }, - "Record": { + "FunctionConfig": { "additionalProperties": false, + "properties": { + "codebase": { + "type": "string" + }, + "ignore": { + "items": { + "type": "string" + }, + "type": "array" + }, + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "predeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "runtime": { + "enum": [ + "nodejs10", + "nodejs12", + "nodejs14", + "nodejs16", + "nodejs18", + "nodejs20", + "nodejs22", + "python310", + "python311", + "python312" + ], + "type": "string" + }, + "source": { + "type": "string" + } + }, "type": "object" - } - }, - "properties": { - "$schema": { - "format": "uri", - "type": "string" }, - "database": { + "HostingHeaders": { "anyOf": [ { "additionalProperties": false, "properties": { - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] + "glob": { + "type": "string" }, - "predeploy": { - "anyOf": [ - { - "items": { + "headers": { + "items": { + "additionalProperties": false, + "properties": { + "key": { "type": "string" }, - "type": "array" + "value": { + "type": "string" + } }, - { - "type": "string" - } - ] - }, - "rules": { - "type": "string" + "required": [ + "key", + "value" + ], + "type": "object" + }, + "type": "array" } }, "required": [ - "rules" + "glob", + "headers" ], "type": "object" }, { - "items": { - "anyOf": [ - { + "additionalProperties": false, + "properties": { + "headers": { + "items": { "additionalProperties": false, "properties": { - "instance": { - "type": "string" - }, - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "rules": { + "key": { "type": "string" }, - "target": { + "value": { "type": "string" } }, "required": [ - "instance", - "rules" + "key", + "value" ], "type": "object" }, - { + "type": "array" + }, + "source": { + "type": "string" + } + }, + "required": [ + "headers", + "source" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "headers": { + "items": { "additionalProperties": false, "properties": { - "instance": { + "key": { "type": "string" }, - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "rules": { - "type": "string" - }, - "target": { + "value": { "type": "string" } }, "required": [ - "rules", - "target" + "key", + "value" ], "type": "object" - } - ] + }, + "type": "array" + }, + "regex": { + "type": "string" + } }, - "type": "array" + "required": [ + "headers", + "regex" + ], + "type": "object" } ] }, - "dataconnect": { + "HostingRedirects": { "anyOf": [ { "additionalProperties": false, "properties": { - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] + "destination": { + "type": "string" }, - "source": { + "glob": { "type": "string" + }, + "type": { + "type": "number" } }, "required": [ - "source" + "destination", + "glob" ], "type": "object" }, { - "items": { - "additionalProperties": false, - "properties": { - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "source": { - "type": "string" - } - }, - "required": [ - "source" - ], - "type": "object" - }, - "type": "array" - } - ] - }, - "emulators": { - "additionalProperties": false, - "properties": { - "apphosting": { "additionalProperties": false, "properties": { - "host": { - "type": "string" - }, - "port": { - "type": "number" - }, - "rootDirectory": { + "destination": { "type": "string" }, - "startCommand": { + "source": { "type": "string" }, - "startCommandOverride": { - "type": "string" + "type": { + "type": "number" } }, + "required": [ + "destination", + "source" + ], "type": "object" }, - "auth": { + { "additionalProperties": false, "properties": { - "host": { + "destination": { "type": "string" }, - "port": { + "regex": { + "type": "string" + }, + "type": { "type": "number" } }, + "required": [ + "destination", + "regex" + ], "type": "object" - }, - "database": { + } + ] + }, + "HostingRewrites": { + "anyOf": [ + { "additionalProperties": false, "properties": { - "host": { + "destination": { "type": "string" }, - "port": { - "type": "number" + "glob": { + "type": "string" } }, + "required": [ + "destination", + "glob" + ], "type": "object" }, - "dataconnect": { + { "additionalProperties": false, "properties": { - "dataDir": { + "function": { "type": "string" }, - "host": { + "glob": { "type": "string" }, - "port": { - "type": "number" - }, - "postgresHost": { + "region": { "type": "string" - }, - "postgresPort": { - "type": "number" } }, + "required": [ + "function", + "glob" + ], "type": "object" }, - "eventarc": { + { "additionalProperties": false, "properties": { - "host": { - "type": "string" + "function": { + "additionalProperties": false, + "properties": { + "functionId": { + "type": "string" + }, + "pinTag": { + "type": "boolean" + }, + "region": { + "type": "string" + } + }, + "required": [ + "functionId" + ], + "type": "object" }, - "port": { - "type": "number" + "glob": { + "type": "string" } }, + "required": [ + "function", + "glob" + ], "type": "object" }, - "extensions": { - "properties": { - }, - "type": "object" - }, - "firestore": { + { "additionalProperties": false, "properties": { - "host": { + "glob": { "type": "string" }, - "port": { - "type": "number" - }, - "websocketPort": { - "type": "number" + "run": { + "additionalProperties": false, + "properties": { + "pinTag": { + "type": "boolean" + }, + "region": { + "type": "string" + }, + "serviceId": { + "type": "string" + } + }, + "required": [ + "serviceId" + ], + "type": "object" } }, + "required": [ + "glob", + "run" + ], "type": "object" }, - "functions": { + { "additionalProperties": false, "properties": { - "host": { - "type": "string" + "dynamicLinks": { + "type": "boolean" }, - "port": { - "type": "number" + "glob": { + "type": "string" } }, + "required": [ + "dynamicLinks", + "glob" + ], "type": "object" }, - "hosting": { + { "additionalProperties": false, "properties": { - "host": { + "destination": { "type": "string" }, - "port": { - "type": "number" + "source": { + "type": "string" } }, + "required": [ + "destination", + "source" + ], "type": "object" }, - "hub": { + { "additionalProperties": false, "properties": { - "host": { + "function": { "type": "string" }, - "port": { - "type": "number" - } - }, - "type": "object" - }, - "logging": { - "additionalProperties": false, - "properties": { - "host": { + "region": { "type": "string" }, - "port": { - "type": "number" + "source": { + "type": "string" } }, + "required": [ + "function", + "source" + ], "type": "object" }, - "pubsub": { + { "additionalProperties": false, "properties": { - "host": { - "type": "string" + "function": { + "additionalProperties": false, + "properties": { + "functionId": { + "type": "string" + }, + "pinTag": { + "type": "boolean" + }, + "region": { + "type": "string" + } + }, + "required": [ + "functionId" + ], + "type": "object" }, - "port": { - "type": "number" + "source": { + "type": "string" } }, + "required": [ + "function", + "source" + ], "type": "object" }, - "singleProjectMode": { - "type": "boolean" - }, - "storage": { + { "additionalProperties": false, "properties": { - "host": { - "type": "string" - }, - "port": { - "type": "number" + "run": { + "additionalProperties": false, + "properties": { + "pinTag": { + "type": "boolean" + }, + "region": { + "type": "string" + }, + "serviceId": { + "type": "string" + } + }, + "required": [ + "serviceId" + ], + "type": "object" + }, + "source": { + "type": "string" } }, + "required": [ + "run", + "source" + ], "type": "object" }, - "tasks": { + { "additionalProperties": false, "properties": { - "host": { - "type": "string" + "dynamicLinks": { + "type": "boolean" }, - "port": { - "type": "number" + "source": { + "type": "string" } }, + "required": [ + "dynamicLinks", + "source" + ], "type": "object" }, - "ui": { + { "additionalProperties": false, "properties": { - "enabled": { - "type": "boolean" - }, - "host": { + "destination": { "type": "string" }, - "port": { - "type": [ - "string", - "number" - ] + "regex": { + "type": "string" } }, + "required": [ + "destination", + "regex" + ], "type": "object" - } - }, - "type": "object" - }, - "extensions": { - "$ref": "#/definitions/ExtensionsConfig" - }, - "firestore": { - "anyOf": [ + }, { "additionalProperties": false, "properties": { - "database": { + "function": { "type": "string" }, - "indexes": { + "regex": { "type": "string" }, - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { + "region": { + "type": "string" + } + }, + "required": [ + "function", + "regex" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "function": { + "additionalProperties": false, + "properties": { + "functionId": { "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" }, - { + "pinTag": { + "type": "boolean" + }, + "region": { "type": "string" } - ] + }, + "required": [ + "functionId" + ], + "type": "object" }, - "rules": { + "regex": { "type": "string" } }, + "required": [ + "function", + "regex" + ], "type": "object" }, - { - "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "database": { - "type": "string" - }, - "indexes": { - "type": "string" - }, - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "rules": { - "type": "string" - }, - "target": { - "type": "string" - } - }, - "required": [ - "target" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "database": { - "type": "string" - }, - "indexes": { - "type": "string" - }, - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "rules": { - "type": "string" - }, - "target": { - "type": "string" - } - }, - "required": [ - "database" - ], - "type": "object" - } - ] - }, - "type": "array" - } - ] - }, - "functions": { - "anyOf": [ { "additionalProperties": false, "properties": { - "codebase": { + "regex": { "type": "string" }, - "ignore": { - "items": { - "type": "string" - }, - "type": "array" - }, - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" + "run": { + "additionalProperties": false, + "properties": { + "pinTag": { + "type": "boolean" }, - { + "region": { "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" }, - { + "serviceId": { "type": "string" } - ] - }, - "runtime": { - "enum": [ - "nodejs10", - "nodejs12", - "nodejs14", - "nodejs16", - "nodejs18", - "nodejs20", - "nodejs22", - "nodejs6", - "nodejs8", - "python310", - "python311", - "python312" + }, + "required": [ + "serviceId" ], - "type": "string" + "type": "object" + } + }, + "required": [ + "regex", + "run" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "dynamicLinks": { + "type": "boolean" }, - "source": { + "regex": { + "type": "string" + } + }, + "required": [ + "dynamicLinks", + "regex" + ], + "type": "object" + } + ] + }, + "HostingSingle": { + "additionalProperties": false, + "properties": { + "appAssociation": { + "enum": [ + "AUTO", + "NONE" + ], + "type": "string" + }, + "cleanUrls": { + "type": "boolean" + }, + "frameworksBackend": { + "$ref": "#/definitions/FrameworksBackendOptions" + }, + "headers": { + "items": { + "$ref": "#/definitions/HostingHeaders" + }, + "type": "array" + }, + "i18n": { + "additionalProperties": false, + "properties": { + "root": { "type": "string" } }, + "required": [ + "root" + ], "type": "object" }, - { + "ignore": { "items": { - "additionalProperties": false, - "properties": { - "codebase": { + "type": "string" + }, + "type": "array" + }, + "postdeploy": { + "anyOf": [ + { + "items": { "type": "string" }, - "ignore": { - "items": { - "type": "string" - }, - "type": "array" - }, - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "runtime": { - "enum": [ - "nodejs10", - "nodejs12", - "nodejs14", - "nodejs16", - "nodejs18", - "nodejs20", - "nodejs22", - "nodejs6", - "nodejs8", - "python310", - "python311", - "python312" - ], + "type": "array" + }, + { + "type": "string" + } + ] + }, + "predeploy": { + "anyOf": [ + { + "items": { "type": "string" }, - "source": { - "type": "string" - } + "type": "array" }, - "type": "object" + { + "type": "string" + } + ] + }, + "public": { + "type": "string" + }, + "redirects": { + "items": { + "$ref": "#/definitions/HostingRedirects" + }, + "type": "array" + }, + "rewrites": { + "items": { + "$ref": "#/definitions/HostingRewrites" }, "type": "array" + }, + "site": { + "type": "string" + }, + "source": { + "type": "string" + }, + "target": { + "type": "string" + }, + "trailingSlash": { + "type": "boolean" } - ] + }, + "type": "object" }, - "hosting": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "appAssociation": { - "enum": [ - "AUTO", - "NONE" - ], - "type": "string" + "Record": { + "additionalProperties": false, + "type": "object" + }, + "RemoteConfigConfig": { + "additionalProperties": false, + "properties": { + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" }, - "cleanUrls": { - "type": "boolean" + { + "type": "string" + } + ] + }, + "predeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" }, - "frameworksBackend": { - "$ref": "#/definitions/FrameworksBackendOptions" + { + "type": "string" + } + ] + }, + "template": { + "type": "string" + } + }, + "required": [ + "template" + ], + "type": "object" + }, + "StorageSingle": { + "additionalProperties": false, + "properties": { + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" }, - "headers": { + { + "type": "string" + } + ] + }, + "predeploy": { + "anyOf": [ + { "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "glob": { - "type": "string" + "type": "string" + }, + "type": "array" + }, + { + "type": "string" + } + ] + }, + "rules": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "rules" + ], + "type": "object" + } + }, + "properties": { + "$schema": { + "format": "uri", + "type": "string" + }, + "database": { + "anyOf": [ + { + "$ref": "#/definitions/DatabaseSingle" + }, + { + "items": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "instance": { + "type": "string" + }, + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" }, - "headers": { + { + "type": "string" + } + ] + }, + "predeploy": { + "anyOf": [ + { "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" + "type": "string" }, "type": "array" + }, + { + "type": "string" } - }, - "required": [ - "glob", - "headers" - ], - "type": "object" + ] }, - { - "additionalProperties": false, - "properties": { - "headers": { + "rules": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "instance", + "rules" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "instance": { + "type": "string" + }, + "postdeploy": { + "anyOf": [ + { "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" + "type": "string" }, "type": "array" }, - "source": { + { "type": "string" } - }, - "required": [ - "headers", - "source" - ], - "type": "object" + ] }, - { - "additionalProperties": false, - "properties": { - "headers": { + "predeploy": { + "anyOf": [ + { "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" + "type": "string" }, "type": "array" }, - "regex": { + { "type": "string" } - }, - "required": [ - "headers", - "regex" - ], - "type": "object" + ] + }, + "rules": { + "type": "string" + }, + "target": { + "type": "string" } - ] - }, - "type": "array" - }, - "i18n": { - "additionalProperties": false, - "properties": { - "root": { - "type": "string" - } - }, - "required": [ - "root" - ], - "type": "object" + }, + "required": [ + "rules", + "target" + ], + "type": "object" + } + ] + }, + "type": "array" + } + ] + }, + "dataconnect": { + "anyOf": [ + { + "$ref": "#/definitions/DataConnectSingle" + }, + { + "items": { + "$ref": "#/definitions/DataConnectSingle" + }, + "type": "array" + } + ] + }, + "emulators": { + "additionalProperties": false, + "properties": { + "apphosting": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" }, - "ignore": { - "items": { - "type": "string" - }, - "type": "array" + "port": { + "type": "number" }, - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] + "rootDirectory": { + "type": "string" }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] + "startCommand": { + "type": "string" }, - "public": { + "startCommandOverride": { + "type": "string" + } + }, + "type": "object" + }, + "auth": { + "additionalProperties": false, + "properties": { + "host": { "type": "string" }, - "redirects": { - "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "glob": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "source": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "regex": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "regex" - ], - "type": "object" - } - ] - }, - "type": "array" + "port": { + "type": "number" + } + }, + "type": "object" + }, + "database": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" }, - "rewrites": { - "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "destination", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "glob": { - "type": "string" - }, - "region": { - "type": "string" - } - }, - "required": [ - "function", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } - }, - "required": [ - "functionId" - ], - "type": "object" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "function", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "glob": { - "type": "string" - }, - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } - }, - "required": [ - "serviceId" - ], - "type": "object" - } - }, - "required": [ - "glob", - "run" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "dynamicLinks", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "destination", - "source" - ], - "type": "object" + "port": { + "type": "number" + } + }, + "type": "object" + }, + "dataconnect": { + "additionalProperties": false, + "properties": { + "dataDir": { + "type": "string" + }, + "host": { + "type": "string" + }, + "port": { + "type": "number" + }, + "postgresHost": { + "type": "string" + }, + "postgresPort": { + "type": "number" + } + }, + "type": "object" + }, + "eventarc": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, + "extensions": { + "properties": {}, + "type": "object" + }, + "firestore": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + }, + "websocketPort": { + "type": "number" + } + }, + "type": "object" + }, + "functions": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, + "hosting": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, + "hub": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, + "logging": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, + "pubsub": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, + "singleProjectMode": { + "type": "boolean" + }, + "storage": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, + "tasks": { + "additionalProperties": false, + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "number" + } + }, + "type": "object" + }, + "ui": { + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "host": { + "type": "string" + }, + "port": { + "type": [ + "string", + "number" + ] + } + }, + "type": "object" + } + }, + "type": "object" + }, + "extensions": { + "$ref": "#/definitions/ExtensionsConfig" + }, + "firestore": { + "anyOf": [ + { + "$ref": "#/definitions/FirestoreSingle" + }, + { + "items": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "database": { + "type": "string" }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "region": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "function", - "source" - ], - "type": "object" + "indexes": { + "type": "string" }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" }, - "required": [ - "functionId" - ], - "type": "object" + "type": "array" }, - "source": { + { "type": "string" } - }, - "required": [ - "function", - "source" - ], - "type": "object" + ] }, - { - "additionalProperties": false, - "properties": { - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } + "predeploy": { + "anyOf": [ + { + "items": { + "type": "string" }, - "required": [ - "serviceId" - ], - "type": "object" + "type": "array" }, - "source": { + { "type": "string" } - }, - "required": [ - "run", - "source" - ], - "type": "object" + ] }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" - }, - "source": { - "type": "string" - } - }, - "required": [ - "dynamicLinks", - "source" - ], - "type": "object" + "rules": { + "type": "string" }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "destination", - "regex" - ], - "type": "object" + "target": { + "type": "string" + } + }, + "required": [ + "target" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "database": { + "type": "string" }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "regex": { - "type": "string" - }, - "region": { - "type": "string" - } - }, - "required": [ - "function", - "regex" - ], - "type": "object" + "indexes": { + "type": "string" }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } + "postdeploy": { + "anyOf": [ + { + "items": { + "type": "string" }, - "required": [ - "functionId" - ], - "type": "object" + "type": "array" }, - "regex": { + { "type": "string" } - }, - "required": [ - "function", - "regex" - ], - "type": "object" + ] }, - { - "additionalProperties": false, - "properties": { - "regex": { - "type": "string" - }, - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } + "predeploy": { + "anyOf": [ + { + "items": { + "type": "string" }, - "required": [ - "serviceId" - ], - "type": "object" - } - }, - "required": [ - "regex", - "run" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" + "type": "array" }, - "regex": { + { "type": "string" } - }, - "required": [ - "dynamicLinks", - "regex" - ], - "type": "object" + ] + }, + "rules": { + "type": "string" + }, + "target": { + "type": "string" } - ] - }, - "type": "array" - }, - "site": { - "type": "string" - }, - "source": { - "type": "string" - }, - "target": { - "type": "string" - }, - "trailingSlash": { - "type": "boolean" - } + }, + "required": [ + "database" + ], + "type": "object" + } + ] }, - "type": "object" + "type": "array" + } + ] + }, + "functions": { + "anyOf": [ + { + "$ref": "#/definitions/FunctionConfig" + }, + { + "items": { + "$ref": "#/definitions/FunctionConfig" + }, + "type": "array" + } + ] + }, + "hosting": { + "anyOf": [ + { + "$ref": "#/definitions/HostingSingle" }, { "items": { @@ -1455,104 +1458,7 @@ }, "headers": { "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "glob": { - "type": "string" - }, - "headers": { - "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "glob", - "headers" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "headers": { - "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" - }, - "type": "array" - }, - "source": { - "type": "string" - } - }, - "required": [ - "headers", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "headers": { - "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" - }, - "type": "array" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "headers", - "regex" - ], - "type": "object" - } - ] + "$ref": "#/definitions/HostingHeaders" }, "type": "array" }, @@ -1605,411 +1511,13 @@ }, "redirects": { "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "glob": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "source": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "regex": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "regex" - ], - "type": "object" - } - ] + "$ref": "#/definitions/HostingRedirects" }, "type": "array" }, "rewrites": { "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "destination", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "glob": { - "type": "string" - }, - "region": { - "type": "string" - } - }, - "required": [ - "function", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } - }, - "required": [ - "functionId" - ], - "type": "object" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "function", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "glob": { - "type": "string" - }, - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } - }, - "required": [ - "serviceId" - ], - "type": "object" - } - }, - "required": [ - "glob", - "run" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "dynamicLinks", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "destination", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "region": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "function", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } - }, - "required": [ - "functionId" - ], - "type": "object" - }, - "source": { - "type": "string" - } - }, - "required": [ - "function", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } - }, - "required": [ - "serviceId" - ], - "type": "object" - }, - "source": { - "type": "string" - } - }, - "required": [ - "run", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" - }, - "source": { - "type": "string" - } - }, - "required": [ - "dynamicLinks", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "destination", - "regex" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "regex": { - "type": "string" - }, - "region": { - "type": "string" - } - }, - "required": [ - "function", - "regex" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } - }, - "required": [ - "functionId" - ], - "type": "object" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "function", - "regex" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "regex": { - "type": "string" - }, - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } - }, - "required": [ - "serviceId" - ], - "type": "object" - } - }, - "required": [ - "regex", - "run" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "dynamicLinks", - "regex" - ], - "type": "object" - } - ] + "$ref": "#/definitions/HostingRewrites" }, "type": "array" }, @@ -2049,104 +1557,7 @@ }, "headers": { "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "glob": { - "type": "string" - }, - "headers": { - "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" - }, - "type": "array" - } - }, - "required": [ - "glob", - "headers" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "headers": { - "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" - }, - "type": "array" - }, - "source": { - "type": "string" - } - }, - "required": [ - "headers", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "headers": { - "items": { - "additionalProperties": false, - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": [ - "key", - "value" - ], - "type": "object" - }, - "type": "array" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "headers", - "regex" - ], - "type": "object" - } - ] + "$ref": "#/definitions/HostingHeaders" }, "type": "array" }, @@ -2199,411 +1610,13 @@ }, "redirects": { "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "glob": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "source": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "regex": { - "type": "string" - }, - "type": { - "type": "number" - } - }, - "required": [ - "destination", - "regex" - ], - "type": "object" - } - ] + "$ref": "#/definitions/HostingRedirects" }, "type": "array" }, "rewrites": { "items": { - "anyOf": [ - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "destination", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "glob": { - "type": "string" - }, - "region": { - "type": "string" - } - }, - "required": [ - "function", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } - }, - "required": [ - "functionId" - ], - "type": "object" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "function", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "glob": { - "type": "string" - }, - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } - }, - "required": [ - "serviceId" - ], - "type": "object" - } - }, - "required": [ - "glob", - "run" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" - }, - "glob": { - "type": "string" - } - }, - "required": [ - "dynamicLinks", - "glob" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "destination", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "region": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "function", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } - }, - "required": [ - "functionId" - ], - "type": "object" - }, - "source": { - "type": "string" - } - }, - "required": [ - "function", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } - }, - "required": [ - "serviceId" - ], - "type": "object" - }, - "source": { - "type": "string" - } - }, - "required": [ - "run", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" - }, - "source": { - "type": "string" - } - }, - "required": [ - "dynamicLinks", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "destination": { - "type": "string" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "destination", - "regex" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "type": "string" - }, - "regex": { - "type": "string" - }, - "region": { - "type": "string" - } - }, - "required": [ - "function", - "regex" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "function": { - "additionalProperties": false, - "properties": { - "functionId": { - "type": "string" - }, - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - } - }, - "required": [ - "functionId" - ], - "type": "object" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "function", - "regex" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "regex": { - "type": "string" - }, - "run": { - "additionalProperties": false, - "properties": { - "pinTag": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "serviceId": { - "type": "string" - } - }, - "required": [ - "serviceId" - ], - "type": "object" - } - }, - "required": [ - "regex", - "run" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "dynamicLinks": { - "type": "boolean" - }, - "regex": { - "type": "string" - } - }, - "required": [ - "dynamicLinks", - "regex" - ], - "type": "object" - } - ] + "$ref": "#/definitions/HostingRewrites" }, "type": "array" }, @@ -2632,85 +1645,12 @@ ] }, "remoteconfig": { - "additionalProperties": false, - "properties": { - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "template": { - "type": "string" - } - }, - "required": [ - "template" - ], - "type": "object" + "$ref": "#/definitions/RemoteConfigConfig" }, "storage": { "anyOf": [ { - "additionalProperties": false, - "properties": { - "postdeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "predeploy": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "string" - } - ] - }, - "rules": { - "type": "string" - }, - "target": { - "type": "string" - } - }, - "required": [ - "rules" - ], - "type": "object" + "$ref": "#/definitions/StorageSingle" }, { "items": { diff --git a/src/apphosting/utils.spec.ts b/src/apphosting/utils.spec.ts index 22bd274a50f..f44a07aa57f 100644 --- a/src/apphosting/utils.spec.ts +++ b/src/apphosting/utils.spec.ts @@ -23,6 +23,9 @@ describe("utils", () => { beforeEach(() => { prompt = sinon.stub(promptImport); }); + afterEach(() => { + sinon.verifyAndRestore(); + }); it("should prompt with the correct options", async () => { const apphostingFileNameToPathMap = new Map([ ["apphosting.yaml", "/parent/cwd/apphosting.yaml"], diff --git a/src/dataconnect/build.spec.ts b/src/dataconnect/build.spec.ts new file mode 100644 index 00000000000..94144c4bddf --- /dev/null +++ b/src/dataconnect/build.spec.ts @@ -0,0 +1,142 @@ +import { expect } from "chai"; +import * as sinon from "sinon"; +import * as prompt from "../prompt"; +import { handleBuildErrors } from "./build"; +import { GraphqlError } from "./types"; + +describe("handleBuildErrors", () => { + let promptOnceStub: sinon.SinonStub; + beforeEach(() => { + promptOnceStub = sinon + .stub(prompt, "promptOnce") + .throws("unexpected call to prompt.promptOnce"); + }); + afterEach(() => { + sinon.verifyAndRestore(); + }); + const cases: { + desc: string; + graphqlErr: GraphqlError[]; + nonInteractive: boolean; + force: boolean; + dryRun: boolean; + promptAnswer?: string; + expectErr: boolean; + }[] = [ + { + desc: "Only build error", + graphqlErr: [{ message: "build error" }], + nonInteractive: false, + force: true, + dryRun: false, + expectErr: true, + }, + { + desc: "Build error with evolution error", + graphqlErr: [ + { message: "build error" }, + { message: "evolution error", extensions: { warningLevel: "INTERACTIVE_ACK" } }, + ], + nonInteractive: false, + force: true, + dryRun: false, + expectErr: true, + }, + { + desc: "Interactive ack evolution error, prompt and accept", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "INTERACTIVE_ACK" } }], + nonInteractive: false, + force: false, + dryRun: false, + promptAnswer: "proceed", + expectErr: false, + }, + { + desc: "Interactive ack evolution error, prompt and reject", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "INTERACTIVE_ACK" } }], + nonInteractive: false, + force: false, + dryRun: false, + promptAnswer: "abort", + expectErr: true, + }, + { + desc: "Interactive ack evolution error, nonInteractive=true", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "INTERACTIVE_ACK" } }], + nonInteractive: true, + force: false, + dryRun: false, + expectErr: false, + }, + { + desc: "Interactive ack evolution error, force=true", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "INTERACTIVE_ACK" } }], + nonInteractive: false, + force: true, + dryRun: false, + expectErr: false, + }, + { + desc: "Interactive ack evolution error, dryRun=true", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "INTERACTIVE_ACK" } }], + nonInteractive: false, + force: false, + dryRun: true, + expectErr: false, + }, + { + desc: "Required ack evolution error, prompt and accept", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "REQUIRE_ACK" } }], + nonInteractive: false, + force: false, + dryRun: false, + promptAnswer: "proceed", + expectErr: false, + }, + { + desc: "Required ack evolution error, prompt and reject", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "REQUIRE_ACK" } }], + nonInteractive: false, + force: false, + dryRun: false, + promptAnswer: "abort", + expectErr: true, + }, + { + desc: "Required ack evolution error, nonInteractive=true, force=false", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "REQUIRE_ACK" } }], + nonInteractive: true, + force: false, + dryRun: false, + expectErr: true, + }, + { + desc: "Required ack evolution error, nonInteractive=true, force=true", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "REQUIRE_ACK" } }], + nonInteractive: true, + force: true, + dryRun: false, + expectErr: false, + }, + { + desc: "Required ack evolution error, nonInteractive=false, force=true", + graphqlErr: [{ message: "evolution error", extensions: { warningLevel: "REQUIRE_ACK" } }], + nonInteractive: false, + force: true, + dryRun: false, + expectErr: false, + }, + ]; + for (const c of cases) { + it(c.desc, async () => { + try { + if (c.promptAnswer) { + promptOnceStub.resolves(c.promptAnswer); + } + await handleBuildErrors(c.graphqlErr, c.nonInteractive, c.force, c.dryRun); + } catch (err) { + expect(c.expectErr).to.be.true; + } + }); + } +}); diff --git a/src/dataconnect/build.ts b/src/dataconnect/build.ts index 7f8b1f1aa0e..fb7b3055f9c 100644 --- a/src/dataconnect/build.ts +++ b/src/dataconnect/build.ts @@ -1,15 +1,90 @@ import { DataConnectEmulator } from "../emulator/dataconnectEmulator"; import { Options } from "../options"; import { FirebaseError } from "../error"; -import { prettify } from "./graphqlError"; -import { DeploymentMetadata } from "./types"; +import * as experiments from "../experiments"; +import { promptOnce } from "../prompt"; +import * as utils from "../utils"; +import { prettify, prettifyWithWorkaround } from "./graphqlError"; +import { DeploymentMetadata, GraphqlError } from "./types"; -export async function build(options: Options, configDir: string): Promise { - const buildResult = await DataConnectEmulator.build({ configDir }); +export async function build( + options: Options, + configDir: string, + dryRun?: boolean, +): Promise { + const args: { configDir: string; projectId?: string } = { configDir }; + if (experiments.isEnabled("fdcconnectorevolution") && options.projectId) { + const flags = process.env["DATA_CONNECT_PREVIEW"]; + if (flags) { + process.env["DATA_CONNECT_PREVIEW"] = flags + ",conn_evolution"; + } else { + process.env["DATA_CONNECT_PREVIEW"] = "conn_evolution"; + } + args.projectId = options.projectId; + } + const buildResult = await DataConnectEmulator.build(args); if (buildResult?.errors?.length) { + await handleBuildErrors(buildResult.errors, options.nonInteractive, options.force, dryRun); + } + return buildResult?.metadata ?? {}; +} + +export async function handleBuildErrors( + errors: GraphqlError[], + nonInteractive: boolean, + force: boolean, + dryRun?: boolean, +) { + if (errors.filter((w) => !w.extensions?.warningLevel).length) { + // Throw immediately if there are any build errors in the GraphQL schema or connectors. throw new FirebaseError( - `There are errors in your schema and connector files:\n${buildResult.errors.map(prettify).join("\n")}`, + `There are errors in your schema and connector files:\n${errors.map(prettify).join("\n")}`, ); } - return buildResult?.metadata ?? {}; + const interactiveAcks = errors.filter((w) => w.extensions?.warningLevel === "INTERACTIVE_ACK"); + const requiredAcks = errors.filter((w) => w.extensions?.warningLevel === "REQUIRE_ACK"); + const choices = [ + { name: "Acknowledge all changes and proceed", value: "proceed" }, + { name: "Reject changes and abort", value: "abort" }, + ]; + if (requiredAcks.length) { + utils.logLabeledWarning( + "dataconnect", + `There are changes in your schema or connectors that may break your existing applications. These changes require explicit acknowledgement to proceed. You may either reject the changes and update your sources with the suggested workaround(s), if any, or acknowledge these changes and proceed with the deployment:\n` + + prettifyWithWorkaround(requiredAcks), + ); + if (nonInteractive && !force) { + throw new FirebaseError( + "Explicit acknowledgement required for breaking schema or connector changes. Rerun this command with --force to deploy these changes.", + ); + } else if (!nonInteractive && !force && !dryRun) { + const result = await promptOnce({ + message: "Would you like to proceed with these breaking changes?", + type: "list", + choices, + default: "abort", + }); + if (result === "abort") { + throw new FirebaseError(`Deployment aborted.`); + } + } + } + if (interactiveAcks.length) { + utils.logLabeledWarning( + "dataconnect", + `There are changes in your schema or connectors that may cause unexpected behavior in your existing applications:\n` + + interactiveAcks.map(prettify).join("\n"), + ); + if (!nonInteractive && !force && !dryRun) { + const result = await promptOnce({ + message: "Would you like to proceed with these changes?", + type: "list", + choices, + default: "proceed", + }); + if (result === "abort") { + throw new FirebaseError(`Deployment aborted.`); + } + } + } } diff --git a/src/dataconnect/graphqlError.ts b/src/dataconnect/graphqlError.ts index ca1069fcb80..6d3ae683fe9 100644 --- a/src/dataconnect/graphqlError.ts +++ b/src/dataconnect/graphqlError.ts @@ -1,4 +1,5 @@ import { GraphqlError } from "./types"; +const Table = require("cli-table"); export function prettify(err: GraphqlError): string { const message = err.message; @@ -11,3 +12,25 @@ export function prettify(err: GraphqlError): string { } return header.length ? `${header}: ${message}` : message; } + +export function prettifyWithWorkaround(errs: GraphqlError[]): string { + const table = new Table({ + head: ["Issue", "Workaround", "Reason"], + style: { head: ["yellow"] }, + }); + for (const e of errs) { + if (!e.extensions?.workarounds?.length) { + table.push([prettify(e), "", ""]); + } else { + const workarounds = e.extensions.workarounds; + for (let i = 0; i < workarounds.length; i++) { + if (i === 0) { + table.push([prettify(e), workarounds[i].Description, workarounds[i].Reason]); + } else { + table.push(["", workarounds[i].Description, workarounds[i].Reason]); + } + } + } + } + return table.toString(); +} diff --git a/src/dataconnect/types.ts b/src/dataconnect/types.ts index 2f160209203..ddd9c6e9e3b 100644 --- a/src/dataconnect/types.ts +++ b/src/dataconnect/types.ts @@ -71,6 +71,15 @@ export interface Diff { destructive: boolean; } +export type WarningLevel = "INTERACTIVE_ACK" | "REQUIRE_ACK"; + +export interface Workaround { + // TODO: Make these lower-case after fixing the emulator, to match the style convention. + Description: string; + Reason: string; + ReplaceWith: string; +} + export interface GraphqlError { message: string; locations?: { @@ -79,6 +88,8 @@ export interface GraphqlError { }[]; extensions?: { file?: string; + warningLevel?: WarningLevel; + workarounds?: Workaround[]; [key: string]: any; }; } diff --git a/src/deploy/dataconnect/prepare.ts b/src/deploy/dataconnect/prepare.ts index 42e357b2e99..2f8785cdd4e 100644 --- a/src/deploy/dataconnect/prepare.ts +++ b/src/deploy/dataconnect/prepare.ts @@ -39,7 +39,7 @@ export default async function (context: any, options: DeployOptions): Promise load(projectId, options.config, c.source)), ); for (const si of serviceInfos) { - si.deploymentMetadata = await build(options, si.sourceDirectory); + si.deploymentMetadata = await build(options, si.sourceDirectory, options.dryRun); } const unmatchedFilters = filters?.filter((f) => { // filter out all filters that match no service diff --git a/src/emulator/apphosting/serve.ts b/src/emulator/apphosting/serve.ts index 51db30fa0c8..3e31a0dcdf3 100644 --- a/src/emulator/apphosting/serve.ts +++ b/src/emulator/apphosting/serve.ts @@ -12,6 +12,8 @@ import { logger } from "./developmentServer"; import { Emulators } from "../types"; import { getLocalAppHostingConfiguration } from "./config"; import { resolveProjectPath } from "../../projectPath"; +import { EmulatorRegistry } from "../registry"; +import { setEnvVarsForEmulators } from "../env"; interface StartOptions { port?: number; @@ -55,6 +57,7 @@ async function serve( } const environmentVariablesToInject = { + ...getEmulatorEnvs(), ...environmentVariablesAsRecord, PORT: port.toString(), }; @@ -81,3 +84,11 @@ function availablePort(host: string, port: number): Promise { family: isIPv4(host) ? "IPv4" : "IPv6", }); } + +function getEmulatorEnvs(): Record { + const envs: Record = {}; + const emulatorInfos = EmulatorRegistry.listRunningWithInfo(); + setEnvVarsForEmulators(envs, emulatorInfos); + + return envs; +} diff --git a/src/emulator/dataconnectEmulator.ts b/src/emulator/dataconnectEmulator.ts index 9041d66342a..1905aa2ab0c 100644 --- a/src/emulator/dataconnectEmulator.ts +++ b/src/emulator/dataconnectEmulator.ts @@ -51,6 +51,7 @@ export interface DataConnectGenerateArgs { export interface DataConnectBuildArgs { configDir: string; + projectId?: string; } // TODO: More concrete typing for events. Can we use string unions? @@ -113,9 +114,12 @@ export class DataConnectEmulator implements EmulatorInstance { `FIREBASE_DATACONNECT_POSTGRESQL_STRING is set to ${clc.bold(connStr)} - using that instead of starting a new database`, ); } else if (pgHost && pgPort) { - const dataDirectory = this.args.config.get("emulators.dataconnect.dataDir"); + let dataDirectory = this.args.config.get("emulators.dataconnect.dataDir"); + if (dataDirectory) { + dataDirectory = this.args.config.path(dataDirectory); + } const postgresDumpPath = this.args.importPath - ? path.join(this.args.importPath, "postgres.tar.gz") + ? path.join(this.args.config.path(this.args.importPath), "postgres.tar.gz") : undefined; this.postgresServer = new PostgresServer({ dataDirectory, @@ -204,7 +208,9 @@ export class DataConnectEmulator implements EmulatorInstance { async exportData(exportPath: string): Promise { if (this.postgresServer) { - await this.postgresServer.exportData(path.join(exportPath, "postgres.tar.gz")); + await this.postgresServer.exportData( + path.join(this.args.config.path(exportPath), "postgres.tar.gz"), + ); } else { throw new FirebaseError( "The Data Connect emulator is currently connected to a separate Postgres instance. Export is not supported.", @@ -249,6 +255,9 @@ export class DataConnectEmulator implements EmulatorInstance { static async build(args: DataConnectBuildArgs): Promise { const commandInfo = await downloadIfNecessary(Emulators.DATACONNECT); const cmd = ["--logtostderr", "-v=2", "build", `--config_dir=${args.configDir}`]; + if (args.projectId) { + cmd.push(`--project_id=${args.projectId}`); + } const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" }); if (isIncomaptibleArchError(res.error)) { diff --git a/src/experiments.ts b/src/experiments.ts index 334b75176ab..d44edf894cc 100644 --- a/src/experiments.ts +++ b/src/experiments.ts @@ -137,6 +137,13 @@ export const ALL_EXPERIMENTS = experiments({ default: true, public: false, }, + + fdcconnectorevolution: { + shortDescription: "Enable Data Connect connector evolution warnings.", + fullDescription: "Enable Data Connect connector evolution warnings.", + default: false, + public: false, + }, }); export type ExperimentName = keyof typeof ALL_EXPERIMENTS; diff --git a/src/firebaseConfigValidate.spec.ts b/src/firebaseConfigValidate.spec.ts index a1191d7eeed..327011a577b 100644 --- a/src/firebaseConfigValidate.spec.ts +++ b/src/firebaseConfigValidate.spec.ts @@ -42,7 +42,7 @@ describe("firebaseConfigValidate", () => { const firstError = validator.errors![0]; expect(firstError.keyword).to.eq("additionalProperties"); - expect(firstError.dataPath).to.eq(""); + expect(firstError.instancePath).to.eq(""); expect(firstError.params).to.deep.equal({ additionalProperty: "bananas" }); }); @@ -63,18 +63,18 @@ describe("firebaseConfigValidate", () => { // Missing required param expect(firstError.keyword).to.eq("required"); - expect(firstError.dataPath).to.eq(".storage"); + expect(firstError.instancePath).to.eq("/storage"); expect(firstError.params).to.deep.equal({ missingProperty: "rules" }); // Because it doesn't match the object type, we also get an "is not an array" // error since JSON Schema can't tell which type it is closest to. expect(secondError.keyword).to.eq("type"); - expect(secondError.dataPath).to.eq(".storage"); + expect(secondError.instancePath).to.eq("/storage"); expect(secondError.params).to.deep.equal({ type: "array" }); // Finally we get an error saying that 'storage' is not any of the known types expect(thirdError.keyword).to.eq("anyOf"); - expect(thirdError.dataPath).to.eq(".storage"); + expect(thirdError.instancePath).to.eq("/storage"); expect(thirdError.params).to.deep.equal({}); }); @@ -97,18 +97,18 @@ describe("firebaseConfigValidate", () => { // Wrong type expect(firstError.keyword).to.eq("type"); - expect(firstError.dataPath).to.eq(".storage.rules"); + expect(firstError.instancePath).to.eq("/storage/rules"); expect(firstError.params).to.deep.equal({ type: "string" }); // Because it doesn't match the object type, we also get an "is not an array" // error since JSON Schema can't tell which type it is closest to. expect(secondError.keyword).to.eq("type"); - expect(secondError.dataPath).to.eq(".storage"); + expect(secondError.instancePath).to.eq("/storage"); expect(secondError.params).to.deep.equal({ type: "array" }); // Finally we get an error saying that 'storage' is not any of the known types expect(thirdError.keyword).to.eq("anyOf"); - expect(thirdError.dataPath).to.eq(".storage"); + expect(thirdError.instancePath).to.eq("/storage"); expect(thirdError.params).to.deep.equal({}); }); }); diff --git a/src/firebaseConfigValidate.ts b/src/firebaseConfigValidate.ts index 4a6a7413413..1ed2b1932cb 100644 --- a/src/firebaseConfigValidate.ts +++ b/src/firebaseConfigValidate.ts @@ -1,12 +1,13 @@ -// Note: we are using ajv version 6.x because it's compatible with TypeScript -// 3.x, if we upgrade the TS version in this project we can upgrade ajv as well. +// Note: Upgraded ajv from 6 to 8 as we upgraded from Typescript 3 import { ValidateFunction, ErrorObject } from "ajv"; import * as fs from "fs"; import * as path from "path"; +import { Ajv } from "ajv"; +import addFormats from "ajv-formats"; -const Ajv = require("ajv"); - -const ajv = new Ajv(); +// We need to allow union types becuase typescript-json-schema generates them sometimes. +const ajv = new Ajv({ allowUnionTypes: true }); +addFormats(ajv); let _VALIDATOR: ValidateFunction | undefined = undefined; /** @@ -30,14 +31,14 @@ export function getValidator(): ValidateFunction { export function getErrorMessage(e: ErrorObject) { if (e.keyword === "additionalProperties") { - return `Object "${e.dataPath}" in "firebase.json" has unknown property: ${JSON.stringify( + return `Object "${e.instancePath}" in "firebase.json" has unknown property: ${JSON.stringify( e.params, )}`; } else if (e.keyword === "required") { return `Object "${ - e.dataPath + e.instancePath }" in "firebase.json" is missing required property: ${JSON.stringify(e.params)}`; } else { - return `Field "${e.dataPath}" in "firebase.json" is possibly invalid: ${e.message}`; + return `Field "${e.instancePath}" in "firebase.json" is possibly invalid: ${e.message}`; } }