From fa9438bf161a4960145d7a9e28c8ea76382162b9 Mon Sep 17 00:00:00 2001 From: imccyu Date: Mon, 22 Jun 2026 09:03:28 +0800 Subject: [PATCH] docs: update rewriteRelativeImportExtensions to current rfc --- .../rfc/implemented/process/2026-06-17-ts-build-config.md | 5 +++-- scripts/verify-node-next-types.ts | 8 ++++---- tsconfig.json | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/rfc/implemented/process/2026-06-17-ts-build-config.md b/docs/rfc/implemented/process/2026-06-17-ts-build-config.md index fdcc85aa38..a45962c70e 100644 --- a/docs/rfc/implemented/process/2026-06-17-ts-build-config.md +++ b/docs/rfc/implemented/process/2026-06-17-ts-build-config.md @@ -17,7 +17,7 @@ Validation found several concrete technical issues and possible routes: - `tsdown` uses `oxc` to transform TypeScript, which is not the same behavior as `tsc`. - Bundled `.d.ts` emitted by `tsdown` conflicts with Cordis' internal relative module augmentation shape. - - The tsc output is affected by `allowImportingTsExtensions`, so we need to ensure that generated `.js` files do not import `.ts` files and generated `.d.ts` files do not contain extensionless relative imports. Therefore, in-package relative imports use explicit `.ts` specifiers in TypeScript source and `rewriteRelativeImportExtensions` rewrites those specifiers to `.js` in emitted JS. + - The tsc output is affected by `allowImportingTsExtensions`, so we need to ensure that generated `.js` files do not import `.ts` files and generated `.d.ts` files keep explicit relative specifiers that NodeNext/Node16 accepts. Therefore, in-package relative imports use explicit `.ts` specifiers in TypeScript source and `rewriteRelativeImportExtensions` rewrites those specifiers to `.js` in emitted JS. - Bundled `.js` emitted by `tsdown` is not the same behavior as per-file `.js` emitted by `tsc -b`, such as decorator transform behavior. - `vendor/*/src`, examples, tests, and scripts cannot all be plain-included in one root strict program. - Directly typechecking `vendor/*/src` under the root strict config triggers many type errors outside this project's ownership. @@ -39,6 +39,7 @@ In-package relative imports use explicit `.ts` specifiers. `pnpm run typecheck` runs build mode over the root `tsconfig.json`. - The root `tsconfig.json` is the single development/typecheck project. It typechecks examples, tests, and scripts with `noEmit`, and validates package/vendor source through references. - Referenced package/vendor projects keep the same emit behavior as build, so typecheck can refresh their `lib/types` outputs instead of using a separate no-emit graph. Project-specific strictness changes live in the owning `packages/*/*/tsconfig.json` or `vendor/*/tsconfig.json`. +- The root no-emit project disables `rewriteRelativeImportExtensions`; it emits nothing and includes tests that import helpers across project-reference boundaries. Package/vendor emit projects keep the rewrite enabled. The command orchestration shape is: @@ -66,7 +67,7 @@ Build responsibilities are clearer: - `lib/types/*.d.ts` uses explicit `.ts` relative specifiers, which TypeScript's NodeNext/Node16 resolver maps to sibling `.d.ts` files. - `lib/types/*.js` is only a bundler input and must not be used as a runtime entry or public import target. - `lib/index.*` is the publish runtime output and is generated by the bundler, currently `tsdown`. -- `pnpm run verify-node-next-types` scans built declarations for extensionless relative specifiers, then typechecks a temporary external ESM consumer with `moduleResolution: "NodeNext"` against the built `types`/`exports` surface, so declaration specifier regressions fail before publish. +- `pnpm run verify-node-next-types` scans built declarations for relative specifiers without file extensions, then typechecks a temporary external ESM consumer with `moduleResolution: "NodeNext"` against the built `types`/`exports` surface, so declaration specifier regressions fail before publish. - The `typecheck` command uses `tsconfig.json`. Examples, tests, and scripts are checked by the root no-emit project, while packages and vendor modules keep the same emit behavior as `build`. Package and vendor source stays behind project-reference boundaries. The Cordis vendor copy now has one more type-structure divergence from upstream. During upstream sync, that divergence must be reapplied or explicitly retired. diff --git a/scripts/verify-node-next-types.ts b/scripts/verify-node-next-types.ts index 0f2e392666..7883a855c3 100644 --- a/scripts/verify-node-next-types.ts +++ b/scripts/verify-node-next-types.ts @@ -47,7 +47,7 @@ function workspacePackages(): WorkspacePackage[] { const declarationSpecifierPattern = /(?:from\s*|import\s*\(\s*|import\s+|declare\s+module\s*)["'](\.{0,2}(?:\/[^"']*)?)["']/g const hasExtension = /\.[^/.]+$/ -function extensionlessRelativeSpecifiers(): string[] { +function relativeSpecifiersMissingExtensions(): string[] { const errors: string[] = [] const files = [ ...globSync('vendor/*/lib/types/**/*.d.ts', { cwd: root }), @@ -88,9 +88,9 @@ function linkPackage(pkg: WorkspacePackage, nodeModules: string): void { } const packages = workspacePackages() -const badSpecifiers = extensionlessRelativeSpecifiers() +const badSpecifiers = relativeSpecifiersMissingExtensions() if (badSpecifiers.length > 0) { - console.error('verify-node-next-types: declaration files still contain extensionless relative specifiers.') + console.error('verify-node-next-types: declaration files still contain relative specifiers without file extensions.') console.error(badSpecifiers.join('\n')) process.exit(1) } @@ -129,7 +129,7 @@ try { strict: true, // Third-party SDK declarations can have their own lib-check noise under a // symlinked temp install. The explicit scan above owns our regression: - // extensionless relative specifiers in built declarations. + // relative specifiers without file extensions in built declarations. skipLibCheck: true, preserveSymlinks: true, noEmit: true, diff --git a/tsconfig.json b/tsconfig.json index a4c1a8245c..bc5aee0bb9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "./tsconfig.base.json", "compilerOptions": { - "noEmit": true + "noEmit": true, + "rewriteRelativeImportExtensions": false }, "include": [ "examples/*/src/**/*.ts",