Skip to content

Commit 274c44f

Browse files
fix(schematics): restore ng deploy under the CommonJS schematics bundle
`ng deploy` threw at module load in 21.0.0-rc.0, before any user code ran: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string or an instance of URL. Received undefined at fileURLToPath (node:internal/url) The schematics are bundled by esbuild with `format: "cjs"`, and esbuild rewrites `import.meta` to an empty object in CommonJS output. The shipped bundle therefore read `undefined.url`, so both `deploy/actions.js` and `deploy/builder.js` failed to load. Every other shipped entry point (ng add, both ng update migrations, the setup schematic) was unaffected. The shim was introduced when `versions.json` moved from a compile-time import to a runtime read. That move fixed a real bug of its own: because esbuild bundles before the build copies and rewrites `versions.json`, the compile-time import inlined the unreplaced `0.0.0` placeholders, and 20.0.1 generates a Cloud Functions manifest pinning `0.0.0` that cannot install. So the runtime read has to stay. `typeof` on an undeclared identifier is the one form that does not throw under ESM, so a single expression works under both loaders. The alternatives were built and run, not assumed: - plain `__dirname` breaks `npm run test:node-esm`, which genuinely loads the compiled specs as ESM - `require('../versions.json')` reintroduces the `0.0.0` bug above - an esbuild define/banner works today but fails with "require is not defined in ES module scope" the moment `format: "esm"` is enabled, which tools/build.ts already has staged in a comment Verified against the built package: all seven shipped entry points now load via both `require()` and `await import()`, the builder exposes the Architect builder symbols, and the runtime `versions.json` read resolves correctly. `ng lint` also drops its only warning, which sat on the replaced line. This is v21-only. v20 has no `import.meta` shim and must not take this change.
1 parent b551b5f commit 274c44f

1 file changed

Lines changed: 7 additions & 3 deletions

File tree

src/schematics/deploy/actions.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ import * as winston from 'winston';
1313
import { BuildTarget, CloudRunOptions, DeployBuilderSchema, FSHost, FirebaseTools } from '../interfaces';
1414
import { DEFAULT_FUNCTION_NAME, defaultFunction, defaultPackage, dockerfile, functionGen2 } from './functions-templates.js';
1515

16-
// @ts-ignore
17-
const __dirname = dirname(fileURLToPath(import.meta.url));
16+
// The CommonJS branch must come first: esbuild rewrites `import.meta` to an empty object in the
17+
// CommonJS bundle this file ships as, so the ESM branch reads `undefined` there. `typeof` on an
18+
// undeclared identifier is the only form that does not throw under ESM.
19+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
20+
// @ts-ignore `import.meta` is rejected by the --module es2015 pass of `npm run build:jasmine`.
21+
const moduleDirectory = typeof __dirname === 'string' ? __dirname : dirname(fileURLToPath(import.meta.url));
1822

1923
const { copySync, removeSync, readJsonSync } = fsExtra;
2024

@@ -128,7 +132,7 @@ const findPackageVersion = (packageManager: string, name: string) => {
128132
const getPackageJson = (context: BuilderContext, workspaceRoot: string, options: DeployBuilderOptions, main?: string) => {
129133
const dependencies: Record<string, string> = {};
130134
const devDependencies: Record<string, string> = {};
131-
const { firebaseFunctionsDependencies } = readJsonSync(join(__dirname, '..', 'versions.json'));
135+
const { firebaseFunctionsDependencies } = readJsonSync(join(moduleDirectory, '..', 'versions.json'));
132136
if (options.ssr !== 'cloud-run') {
133137
Object.keys(firebaseFunctionsDependencies).forEach(name => {
134138
const { version, dev } = firebaseFunctionsDependencies[name];

0 commit comments

Comments
 (0)