Skip to content

Commit

Permalink
fix(compiler): fix typedef file generated for dist-custom-elements (#…
Browse files Browse the repository at this point in the history
…3468)

This fixes the typedef file generated for the `index.js` file produced
by `dist-custom-elements`. Previously it was mistakenly assuming that
the path to a component's `d.ts` file could be generated on the basis of
the `tag` set on the component. This _is_ the case if the component's
filename is equal to it's tag, but there is no requirement that that be
the case.

This changes the way that the relative path from
`${outputDir}/components/index.d.ts` to the `.d.ts` file for a specific
component is generated.

Previously we were doing something like:

```ts
${outputDir}/types/components/${component.tagName}/${component.tagName}
```

This doesn't work if a component is saved in
`src/components/button/button.tsx` but has a tag like `custom-button`.
So to fix this we can instead:

- find the relative path from the source root to the component, giving
  us e.g. `components/button/button.tsx`
- join that relative path with the relative path from where `index.d.ts`
  is going to be saved (`${outputDir}/components/index.d.ts`) to the
  directory where types are written (e.g. `${outputDir}/types`)

This will give us an import in `index.d.ts` that looks like:

```ts
export { Button as CustomButton } from '../types/components/button/button.tsx';
```
  • Loading branch information
alicewriteswrongs committed Jul 13, 2022
1 parent b9fbe85 commit 854d498
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const generateCustomElementsTypesOutput = async (
// the path where we're going to write the typedef for the whole dist-custom-elements output
const customElementsDtsPath = join(outputTarget.dir!, 'index.d.ts');
// the directory where types for the individual components are written
const componentsTypeDirectoryPath = relative(outputTarget.dir!, join(typesDir, 'components'));
const componentsTypeDirectoryRelPath = relative(outputTarget.dir!, typesDir);

const components = buildCtx.components.filter((m) => !m.isCollectionDependency);

Expand All @@ -56,7 +56,14 @@ const generateCustomElementsTypesOutput = async (
const importName = component.componentClassName;
// typedefs for individual components can be found under paths like
// $TYPES_DIR/components/my-component/my-component.d.ts
const componentDTSPath = join(componentsTypeDirectoryPath, component.tagName, component.tagName);
//
// To construct this path we:
//
// - get the relative path to the component's source file from the source directory
// - join that relative path to the relative path from the `index.d.ts` file to the
// directory where typedefs are saved
const componentSourceRelPath = relative(config.srcDir, component.sourceFilePath).replace('.tsx', '');
const componentDTSPath = join(componentsTypeDirectoryRelPath, componentSourceRelPath);

return `export { ${importName} as ${exportName} } from '${componentDTSPath}';`;
}),
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/output-targets/dist-custom-elements/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export const addCustomElementInputs = (buildCtx: d.BuildCtx, bundleOpts: BundleO
exp.push(`export const ${exportName} = ${importAs};`);
exp.push(`export const defineCustomElement = cmpDefCustomEle;`);

// Here we push an export (with a rename for `defineCustomElement` for
// Here we push an export (with a rename for `defineCustomElement`) for
// this component onto our array which references the `coreKey` (prefixed
// with `\0`). We have to do this so that our import is referencing the
// correct virtual module, if we instead referenced, for instance,
Expand Down
16 changes: 12 additions & 4 deletions src/compiler/output-targets/test/custom-elements-types.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,16 @@ const setup = () => {

describe('Custom Elements Typedef generation', () => {
it('should generate an index.d.ts file corresponding to the index.js file', async () => {
const componentOne = stubComponentCompilerMeta();
// this component tests the 'happy path' of a component's filename coinciding with its
// tag name
const componentOne = stubComponentCompilerMeta({
tagName: 'my-component',
sourceFilePath: '/src/components/my-component/my-component.tsx',
});
// this component tests that we correctly resolve its path when the component tag does
// not match its filename
const componentTwo = stubComponentCompilerMeta({
sourceFilePath: '/src/components/the-other-component/my-real-best-component.tsx',
componentClassName: 'MyBestComponent',
tagName: 'my-best-component',
});
Expand All @@ -47,11 +55,11 @@ describe('Custom Elements Typedef generation', () => {

const expectedTypedefOutput = [
'/* TestApp custom elements */',
`export { StubCmp as StubCmp } from '${join(componentsTypeDirectoryPath, 'stub-cmp', 'stub-cmp')}';`,
`export { StubCmp as MyComponent } from '${join(componentsTypeDirectoryPath, 'my-component', 'my-component')}';`,
`export { MyBestComponent as MyBestComponent } from '${join(
componentsTypeDirectoryPath,
'my-best-component',
'my-best-component'
'the-other-component',
'my-real-best-component'
)}';`,
'',
'/**',
Expand Down

0 comments on commit 854d498

Please sign in to comment.