Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ describe('DataView', () => {
label: 'Status',
filterable: true,
filterType: 'select',
filterOptions: [{ label: 'Active', value: 'string' }]
filterOptions: [{ label: 'Active', value: 'active' }]
},
{
accessorKey: 'email',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('FilterChip data-slot contract', () => {
<FilterChip
label='Field'
columnType={columnType}
options={[{ label: 'A', value: 'string' }]}
options={[{ label: 'A', value: 'a' }]}
/>
);
expect(
Expand Down
1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
"rollup-plugin-preserve-directives": "^0.4.0",
"rollup-plugin-tsconfig-paths": "^1.5.2",
"semver": "^7.6.0",
"tsc-alias": "1.9.10",
"typescript": "~5.4.3",
"vitest": "^3.2.4"
},
Expand Down
42 changes: 42 additions & 0 deletions packages/react/rollup.config.mjs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's replace the custom plugin with tsc-alias. It reads the ~/ alias from tsconfig, so we do not need to maintain a regex of our own.

  1. Add tsc-alias to devDependencies.
  2. Add packages/react/tsconfig.alias.json:
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "paths": {
      "~/*": ["./*"]
    }
  }
}

tsc-alias needs this config. With tsconfig.json, it also rewrites react imports to node_modules/@types/react, because of the react entry in paths.

  1. Run it from closeBundle, and add it after typescript() in createPlugins:
import { replaceTscAliasPaths } from 'tsc-alias';

const resolveDeclarationAliases = () => ({
  name: 'apsara-declaration-aliases',
  closeBundle: () =>
    replaceTscAliasPaths({ configFile: 'tsconfig.alias.json', outDir: 'dist' })
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 0add681. Thanks for the suggestion. I switched to tsc-alias and kept a small check that fails the build if a ~/ import is left.

Custom plugin tsc-alias
Alias rules Own regex, does not read tsconfig Reads tsconfig.alias.json
Code to maintain About 40 lines of path logic About 5 lines
Unresolved alias Fails the build Leaves the import as is, build passes
Dependencies None Adds tsc-alias and a second tsconfig
When it runs In the bundle, before files are written On dist after write, once per config (about 0.4s each)
Output '../types/filters' '../types/filters.js'

I went with tsc-alias because it takes the alias rules from tsconfig, so we no longer maintain our own regex. The one thing the old plugin had that tsc-alias does not is the failed build on a leftover alias. So closeBundle now reads every .d.ts in dist after tsc-alias runs and fails the build if it finds one. I tested this with a fake import('~/does-not-exist'), and the build failed with the file and line.

I also type-checked a small app against the built package with bundler and node16 module resolution. Both pass, and the .js paths resolve to their .d.ts files.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
Expand All @@ -7,6 +9,7 @@ import nodeExternals from 'rollup-plugin-node-externals';
import postcss from 'rollup-plugin-postcss';
import preserveDirectives from 'rollup-plugin-preserve-directives';
import tsconfigPaths from 'rollup-plugin-tsconfig-paths';
import { replaceTscAliasPaths } from 'tsc-alias';

/** Matches `@import url("https://fonts.googleapis.com/…");` in any quoting. */
const FONT_IMPORT =
Expand Down Expand Up @@ -42,6 +45,44 @@ const emitFontFreeCss = ({ from, to }) => {
};
};

/** Matches a quoted `~/` module specifier. */
const ALIAS_SPECIFIER = /(['"])~\/[^'"]+\1/g;

/**
* Rewrites `~/` specifiers in emitted declarations to relative paths, because
* TypeScript keeps `paths` aliases as written and apps cannot resolve them.
* `tsconfig.alias.json` leaves out the `react` entry of `tsconfig.json`, which
* tsc-alias would otherwise rewrite to `node_modules/@types/react`. Fails the
* build if a specifier is left. Must be ordered after `typescript()`.
*/
const resolveDeclarationAliases = () => ({
name: 'apsara-declaration-aliases',
async closeBundle() {
await replaceTscAliasPaths({
configFile: 'tsconfig.alias.json',
outDir: 'dist'
});
const leaks = [];
const declarations = readdirSync('dist', { recursive: true }).filter(
fileName => fileName.endsWith('.d.ts')
);
for (const fileName of declarations) {
readFileSync(join('dist', fileName), 'utf8')
.split('\n')
.forEach((line, index) => {
for (const [specifier] of line.matchAll(ALIAS_SPECIFIER)) {
leaks.push(`dist/${fileName}:${index + 1} ${specifier}`);
}
});
}
if (leaks.length > 0) {
this.error(
`Declarations still import through the ~/ alias:\n${leaks.join('\n')}`
);
}
}
});

const createPlugins = ({ rootDir, declarationDir }) => [
// Externalize all dependencies and peer dependencies
// This must be placed before nodeResolve() to work correctly
Expand Down Expand Up @@ -79,6 +120,7 @@ const createPlugins = ({ rootDir, declarationDir }) => [
rootDir: rootDir,
declarationDir: declarationDir
}),
resolveDeclarationAliases(),
preserveDirectives() //preserve `use client` directive
];

Expand Down
8 changes: 8 additions & 0 deletions packages/react/tsconfig.alias.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"paths": {
"~/*": ["./*"]
}
}
}
Loading
Loading