From afa4ae7ab3b19c98a44c73254f79675bfe82633d Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 1 Jun 2022 11:32:03 -0700 Subject: [PATCH 1/4] Create path checker script --- .github/workflows/check-pkg-paths.yml | 27 ++++++ packages/auth/package.json | 2 +- packages/firestore/package.json | 6 +- packages/installations-compat/package.json | 2 +- scripts/ci-test/check-paths.ts | 97 ++++++++++++++++++++++ 5 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/check-pkg-paths.yml create mode 100644 scripts/ci-test/check-paths.ts diff --git a/.github/workflows/check-pkg-paths.yml b/.github/workflows/check-pkg-paths.yml new file mode 100644 index 00000000000..c7ffa36525d --- /dev/null +++ b/.github/workflows/check-pkg-paths.yml @@ -0,0 +1,27 @@ +name: Test Package Paths + +on: pull_request + +jobs: + test: + name: Test Package Paths + runs-on: ubuntu-latest + + steps: + - name: Checkout Repo + uses: actions/checkout@master + with: + # This makes Actions fetch all Git history so run-changed script can diff properly. + fetch-depth: 0 + - name: Set up Node (14) + uses: actions/setup-node@v2 + with: + node-version: 14.x + - name: Yarn install + run: yarn + - name: Yarn build + run: yarn build + - name: Swap in public typings + run: yarn release:prepare + - name: Check paths + run: xvfb-run yarn test:changed core \ No newline at end of file diff --git a/packages/auth/package.json b/packages/auth/package.json index a8769088bef..fe76ca4b21a 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -7,7 +7,7 @@ "react-native": "dist/rn/index.js", "browser": "dist/esm2017/index.js", "module": "dist/esm2017/index.js", - "cordova": "dist/cordova/index.esm5.js", + "cordova": "dist/cordova/index.js", "webworker": "dist/index.webworker.esm5.js", "esm5": "dist/esm5/index.js", "exports": { diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 0ed48a7a648..5fee9c6f176 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -59,9 +59,9 @@ "require": "./dist/lite/index.node.cjs.js", "import": "./dist/lite/index.node.mjs" }, - "react-native": "./dist/lite/index.rn.esm2017.js", - "esm5": "./dist/lite/index.browser.esm5.js", - "default": "./dist/lite/index.browser.esm2017.js" + "react-native": "./dist/index.rn.js", + "esm5": "./dist/index.esm5.js", + "default": "./dist/index.esm2017.js" }, "./package.json": "./package.json" }, diff --git a/packages/installations-compat/package.json b/packages/installations-compat/package.json index c3ecd743c1b..a5d7228c188 100644 --- a/packages/installations-compat/package.json +++ b/packages/installations-compat/package.json @@ -14,7 +14,7 @@ }, "./package.json": "./package.json" }, - "typings": "dist/installations-compat.d.ts", + "typings": "dist/src/index.d.ts", "license": "Apache-2.0", "files": [ "dist" diff --git a/scripts/ci-test/check-paths.ts b/scripts/ci-test/check-paths.ts new file mode 100644 index 00000000000..855ce81c254 --- /dev/null +++ b/scripts/ci-test/check-paths.ts @@ -0,0 +1,97 @@ +import glob from 'glob'; +import { existsSync } from 'fs'; +import { resolve } from 'path'; +import { projectRoot as root } from '../utils'; + +const TOP_LEVEL_FIELDS = [ + 'main', + 'browser', + 'module', + 'typings', + 'react-native', + 'cordova', + 'esm5', + 'webworker', + 'main-esm' +]; + +interface Result { + packageName: string; + found: boolean; + filePath: string; + fieldPath: string; +} +const results: Result[] = []; + +function getPaths(): Promise { + return new Promise((resolve, reject) => { + glob('packages/*', (err, paths) => { + if (err) reject(err); + resolve(paths); + }); + }) +} + +function checkExports(pkgName: string, pkgRoot: string, path: string = '', exports: Record) { + for (const key in exports) { + if (typeof exports[key] === 'string') { + const filePath = resolve(pkgRoot, exports[key]); + const result = { + packageName: pkgName, + found: false, + filePath, + fieldPath: `exports${path}[${key}]` + }; + if (existsSync(filePath)) { + result.found = true; + } + results.push(result); + } else { + checkExports(pkgName, pkgRoot, path ? `${path}[${key}]` : `[${key}]`, exports[key]); + } + } +} + +async function main() { + const paths = await getPaths(); + for (const path of paths) { + const pkgRoot = `${root}/${path}`; + if (existsSync(`${pkgRoot}/package.json`)) { + const pkg = require(`${pkgRoot}/package.json`); + for (const field of TOP_LEVEL_FIELDS) { + if (pkg[field]) { + const filePath = resolve(pkgRoot, pkg[field]); + const result = { + packageName: pkg.name, + found: false, + filePath, + fieldPath: field + }; + if (existsSync(filePath)) { + result.found = true; + } + results.push(result); + } + } + if (pkg.exports) { + checkExports(pkg.name, pkgRoot, '', pkg.exports); + } + } + } + + let missingPaths: boolean = false; + + for (const result of results) { + if (!result.found) { + missingPaths = true; + console.log(`${result.packageName}: Field "${result.fieldPath}" ` + + `points to ${result.filePath} which is not found.`); + } + } + + if (missingPaths) { + process.exit(1); + } +} + +main(); \ No newline at end of file From 838cafd3b3b01f485cddbe84d73ca492e18b1795 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 1 Jun 2022 11:32:36 -0700 Subject: [PATCH 2/4] call script --- .github/workflows/check-pkg-paths.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-pkg-paths.yml b/.github/workflows/check-pkg-paths.yml index c7ffa36525d..d8a41fee0f1 100644 --- a/.github/workflows/check-pkg-paths.yml +++ b/.github/workflows/check-pkg-paths.yml @@ -24,4 +24,4 @@ jobs: - name: Swap in public typings run: yarn release:prepare - name: Check paths - run: xvfb-run yarn test:changed core \ No newline at end of file + run: yarn ts-node scripts/ci-test/check-paths.ts \ No newline at end of file From 795f731fb38f2aba7cb22a9652a46ba9c863aa51 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 1 Jun 2022 11:33:46 -0700 Subject: [PATCH 3/4] format and changeset --- .changeset/old-lamps-nail.md | 7 ++++++ scripts/ci-test/check-paths.ts | 41 +++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 .changeset/old-lamps-nail.md diff --git a/.changeset/old-lamps-nail.md b/.changeset/old-lamps-nail.md new file mode 100644 index 00000000000..ae0c99e7882 --- /dev/null +++ b/.changeset/old-lamps-nail.md @@ -0,0 +1,7 @@ +--- +'@firebase/auth': patch +'@firebase/firestore': patch +'@firebase/installations-compat': patch +--- + +Fix incorrect paths in package.json diff --git a/scripts/ci-test/check-paths.ts b/scripts/ci-test/check-paths.ts index 855ce81c254..703ab8b258e 100644 --- a/scripts/ci-test/check-paths.ts +++ b/scripts/ci-test/check-paths.ts @@ -1,3 +1,20 @@ +/** + * @license + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import glob from 'glob'; import { existsSync } from 'fs'; import { resolve } from 'path'; @@ -29,10 +46,15 @@ function getPaths(): Promise { if (err) reject(err); resolve(paths); }); - }) + }); } -function checkExports(pkgName: string, pkgRoot: string, path: string = '', exports: Record) { +function checkExports( + pkgName: string, + pkgRoot: string, + path: string = '', + exports: Record +) { for (const key in exports) { if (typeof exports[key] === 'string') { const filePath = resolve(pkgRoot, exports[key]); @@ -47,7 +69,12 @@ function checkExports(pkgName: string, pkgRoot: string, path: string = '', expor } results.push(result); } else { - checkExports(pkgName, pkgRoot, path ? `${path}[${key}]` : `[${key}]`, exports[key]); + checkExports( + pkgName, + pkgRoot, + path ? `${path}[${key}]` : `[${key}]`, + exports[key] + ); } } } @@ -84,8 +111,10 @@ async function main() { for (const result of results) { if (!result.found) { missingPaths = true; - console.log(`${result.packageName}: Field "${result.fieldPath}" ` + - `points to ${result.filePath} which is not found.`); + console.log( + `${result.packageName}: Field "${result.fieldPath}" ` + + `points to ${result.filePath} which is not found.` + ); } } @@ -94,4 +123,4 @@ async function main() { } } -main(); \ No newline at end of file +main(); From 6cbb47e41de3e232388c1ae79710d597b3faec48 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Wed, 1 Jun 2022 11:39:52 -0700 Subject: [PATCH 4/4] Add comments --- scripts/ci-test/check-paths.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/ci-test/check-paths.ts b/scripts/ci-test/check-paths.ts index 703ab8b258e..d943e89ae90 100644 --- a/scripts/ci-test/check-paths.ts +++ b/scripts/ci-test/check-paths.ts @@ -20,6 +20,10 @@ import { existsSync } from 'fs'; import { resolve } from 'path'; import { projectRoot as root } from '../utils'; +/** + * Top level fields in package.json that may point to entry point and + * typings files. + */ const TOP_LEVEL_FIELDS = [ 'main', 'browser', @@ -40,6 +44,10 @@ interface Result { } const results: Result[] = []; +/** + * Get paths to packages. Only check the ones we actually + * publish (packages/*). + */ function getPaths(): Promise { return new Promise((resolve, reject) => { glob('packages/*', (err, paths) => { @@ -49,6 +57,9 @@ function getPaths(): Promise { }); } +/** + * Recursively check `exports` field in package.json. + */ function checkExports( pkgName: string, pkgRoot: string, @@ -81,10 +92,15 @@ function checkExports( async function main() { const paths = await getPaths(); + for (const path of paths) { const pkgRoot = `${root}/${path}`; if (existsSync(`${pkgRoot}/package.json`)) { const pkg = require(`${pkgRoot}/package.json`); + + /** + * Check top level fields. + */ for (const field of TOP_LEVEL_FIELDS) { if (pkg[field]) { const filePath = resolve(pkgRoot, pkg[field]); @@ -100,6 +116,9 @@ async function main() { results.push(result); } } + /** + * Check all levels of exports field. + */ if (pkg.exports) { checkExports(pkg.name, pkgRoot, '', pkg.exports); } @@ -118,6 +137,9 @@ async function main() { } } + /** + * Fail CI if any missing paths found. + */ if (missingPaths) { process.exit(1); }