Skip to content

Commit

Permalink
new: Support .cts and .mts files. (#130)
Browse files Browse the repository at this point in the history
* Start on cts support.

* Test file exts.

* Increase timeout.

* Add mts.

* Update TS.

* Fix scaffold.
  • Loading branch information
milesj authored May 28, 2022
1 parent a3fd4c4 commit f0a9041
Show file tree
Hide file tree
Showing 16 changed files with 307 additions and 17 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"conventional-changelog-beemo": "^3.0.1",
"lerna": "^4.0.0",
"ts-node": "^10.7.0",
"typescript": "^4.7.0-beta"
"typescript": "^4.7.2"
},
"funding": {
"type": "ko-fi",
Expand Down
2 changes: 1 addition & 1 deletion packages/packemon/src/Package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ export class Package {

// Type declarations
if (artifact instanceof TypesArtifact) {
files.add('dts/**/*.d.ts');
files.add(`dts/**/*.${artifact.getDeclExt()}`);
}
});

Expand Down
37 changes: 34 additions & 3 deletions packages/packemon/src/TypesArtifact.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import path from 'path';
import { VirtualPath } from '@boost/common';
import { createDebugger, Debugger } from '@boost/debug';
import { Artifact } from './Artifact';
Expand All @@ -24,7 +25,35 @@ export class TypesArtifact extends Artifact<TypesBuild> {
return '';
}

return `./${new VirtualPath('dts', removeSourcePath(output.inputFile))}.d.ts`;
return `./${new VirtualPath(
'dts',
removeSourcePath(output.inputFile),
)}.${this.getDeclExtFromInput(output.inputFile)}`;
}

getDeclExt(): string {
const baseInputExt = path.extname(this.builds[0].inputFile);
const isAllSameExt = this.builds.every((build) => build.inputFile.endsWith(baseInputExt));

if (!isAllSameExt) {
throw new Error(
'All inputs must share the same extension. Cannot determine a TypeScript declaration format.',
);
}

return this.getDeclExtFromInput(baseInputExt);
}

getDeclExtFromInput(inputFile: string): string {
if (inputFile.endsWith('.cts')) {
return 'd.cts';
}

if (inputFile.endsWith('.mts')) {
return 'd.mts';
}

return 'd.ts';
}

getLabel(): string {
Expand All @@ -45,8 +74,10 @@ export class TypesArtifact extends Artifact<TypesBuild> {
};
});
} else {
exportMap['./*'] = { types: './dts/*.d.ts' };
exportMap['.'] = { types: './dts/index.d.ts' };
const ext = this.getDeclExt();

exportMap['./*'] = { types: `./dts/*.${ext}` };
exportMap['.'] = { types: `./dts/index.${ext}` };
}

return exportMap;
Expand Down
6 changes: 5 additions & 1 deletion packages/packemon/src/commands/Scaffold.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,11 @@ export class ScaffoldCommand extends Command {
break;

default: {
args.unshift('add', '--dev', type === 'monorepo' ? '-W' : '');
const version = Number.parseFloat(
(await this.executeCommand('yarn', ['-v'], { preferLocal: false })).stdout,
);

args.unshift('add', '--dev', type === 'monorepo' && version < 2 ? '-W' : '');
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/packemon/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const ASSETS = [
'.ttf',
];

export const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.cjs', '.mjs'];
export const EXTENSIONS = ['.ts', '.tsx', '.cts', '.mts', '.js', '.jsx', '.cjs', '.mjs'];

export const EXCLUDE = [
'**/node_modules/**',
Expand Down
69 changes: 69 additions & 0 deletions packages/packemon/tests/TypesArtifact.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,47 @@ describe('TypesArtifact', () => {
expect(artifact.findEntryPoint('index')).toBe('./dts/index.d.ts');
expect(artifact.findEntryPoint('test')).toBe('./dts/sub/test.d.ts');
});

it('supports .d.cts', () => {
artifact.builds[0].inputFile = 'src/index.cts';

expect(artifact.findEntryPoint('index')).toBe('./dts/index.d.cts');
});

it('supports .d.mts', () => {
artifact.builds[0].inputFile = 'src/index.mts';

expect(artifact.findEntryPoint('index')).toBe('./dts/index.d.mts');
});
});

describe('getDeclExt()', () => {
it('defaults to .d.ts', () => {
expect(artifact.getDeclExt()).toBe('d.ts');
});

it('supports .d.cts', () => {
artifact.builds[0].inputFile = 'src/index.cts';
artifact.builds[1].inputFile = 'src/sub/test.cts';

expect(artifact.getDeclExt()).toBe('d.cts');
});

it('supports .d.mts', () => {
artifact.builds[0].inputFile = 'src/index.mts';
artifact.builds[1].inputFile = 'src/sub/test.mts';

expect(artifact.getDeclExt()).toBe('d.mts');
});

it('errors if multiple source formats', () => {
artifact.builds[0].inputFile = 'src/index.cts';
artifact.builds[1].inputFile = 'src/sub/test.mts';

expect(() => artifact.getDeclExt()).toThrow(
'All inputs must share the same extension. Cannot determine a TypeScript declaration format.',
);
});
});

describe('getPackageExports()', () => {
Expand All @@ -91,5 +132,33 @@ describe('TypesArtifact', () => {
},
});
});

it('supports .d.cts', () => {
artifact.builds[0].inputFile = 'src/index.cts';
artifact.builds[1].inputFile = 'src/sub/test.cts';

expect(artifact.getPackageExports()).toEqual({
'.': {
types: './dts/index.d.cts',
},
'./test': {
types: './dts/sub/test.d.cts',
},
});
});

it('supports .d.mts', () => {
artifact.builds[0].inputFile = 'src/index.mts';
artifact.builds[1].inputFile = 'src/sub/test.mts';

expect(artifact.getPackageExports()).toEqual({
'.': {
types: './dts/index.d.mts',
},
'./test': {
types: './dts/sub/test.d.mts',
},
});
});
});
});
76 changes: 76 additions & 0 deletions packages/packemon/tests/__snapshots__/outputs.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1503,3 +1503,79 @@ Array [
"assets/fonts-4e5dc96c.css",
]
`;

exports[`Special formats cts supports .cts -> .cjs / .d.cts 1`] = `
Array [
"cjs/index.cjs",
"// Bundled with Packemon: https://packemon.dev
// Platform: node, Support: stable, Format: cjs
'use strict';
function test() {
return 123;
}
module.exports = test;
",
]
`;

exports[`Special formats cts supports .cts -> .cjs / .d.cts 2`] = `
Array [
"package.json",
Object {
"main": "./cjs/index.cjs",
"name": "project-cts",
"packemon": Object {
"format": "cjs",
"inputs": Object {
"index": "src/index.cts",
},
},
"type": "commonjs",
"types": "./dts/index.d.cts",
},
]
`;

exports[`Special formats cts supports .cts -> .cjs / .d.cts 3`] = `
"export default function test(): number;
//# sourceMappingURL=index.d.cts.map"
`;

exports[`Special formats mts supports .mts -> .mjs / .d.mts 1`] = `
Array [
"mjs/index.mjs",
"// Bundled with Packemon: https://packemon.dev
// Platform: node, Support: stable, Format: mjs
function test() {
return 'abc';
}
export { test as default };
",
]
`;

exports[`Special formats mts supports .mts -> .mjs / .d.mts 2`] = `
Array [
"package.json",
Object {
"main": "./mjs/index.mjs",
"name": "project-mts",
"packemon": Object {
"format": "mjs",
"inputs": Object {
"index": "src/index.mts",
},
},
"type": "module",
"types": "./dts/index.d.mts",
},
]
`;

exports[`Special formats mts supports .mts -> .mjs / .d.mts 3`] = `
"export default function test(): string;
//# sourceMappingURL=index.d.mts.map"
`;
3 changes: 3 additions & 0 deletions packages/packemon/tests/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ export function createSnapshotSpies(root: PortablePath, captureJson: boolean = f
filePath.endsWith('.js') ||
filePath.endsWith('.cjs') ||
filePath.endsWith('.mjs') ||
filePath.endsWith('.d.ts') ||
filePath.endsWith('.d.cts') ||
filePath.endsWith('.d.mts') ||
(captureJson && filePath.endsWith('.json'))
) {
snapshots.push([filePath, content]);
Expand Down
67 changes: 66 additions & 1 deletion packages/packemon/tests/outputs.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable jest/no-conditional-in-test */

import fs from 'fs';
import { Path } from '@boost/common';
import { getFixturePath } from '@boost/test-utils';
import { CodeArtifact } from '../src';
import { CodeArtifact, TypesArtifact } from '../src';
import { createProjectPackage, createSnapshotSpies } from './helpers';

['babel', 'swc'].forEach((transformer) => {
Expand Down Expand Up @@ -189,3 +190,67 @@ import { createProjectPackage, createSnapshotSpies } from './helpers';
});
});
});

describe('Special formats', () => {
jest.setTimeout(30_000);

describe('cts', () => {
const root = new Path(getFixturePath('project-cts'));
const snapshots = createSnapshotSpies(root, true);

it('supports .cts -> .cjs / .d.cts', async () => {
const pkg = createProjectPackage(root);

const index = new CodeArtifact(pkg, [{ format: 'cjs' }]);
index.bundle = true;
index.platform = 'node';
index.support = 'stable';
index.inputs = { index: 'src/index.cts' };

pkg.addArtifact(index);

const types = new TypesArtifact(pkg, [{ inputFile: 'src/index.cts', outputName: 'index' }]);

pkg.addArtifact(types);

await pkg.build({}, {});

snapshots(pkg).forEach((ss) => {
expect(ss).toMatchSnapshot();
});

// Declaration snapshots are not captured above because it runs in a child process
expect(fs.readFileSync(root.append('dts/index.d.cts').path(), 'utf8')).toMatchSnapshot();
});
});

describe('mts', () => {
const root = new Path(getFixturePath('project-mts'));
const snapshots = createSnapshotSpies(root, true);

it('supports .mts -> .mjs / .d.mts', async () => {
const pkg = createProjectPackage(root);

const index = new CodeArtifact(pkg, [{ format: 'mjs' }]);
index.bundle = true;
index.platform = 'node';
index.support = 'stable';
index.inputs = { index: 'src/index.mts' };

pkg.addArtifact(index);

const types = new TypesArtifact(pkg, [{ inputFile: 'src/index.mts', outputName: 'index' }]);

pkg.addArtifact(types);

await pkg.build({}, {});

snapshots(pkg).forEach((ss) => {
expect(ss).toMatchSnapshot();
});

// Declaration snapshots are not captured above because it runs in a child process
expect(fs.readFileSync(root.append('dts/index.d.mts').path(), 'utf8')).toMatchSnapshot();
});
});
});
12 changes: 12 additions & 0 deletions tests/__fixtures__/project-cts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "project-cts",
"packemon": {
"format": "cjs",
"inputs": {
"index": "src/index.cts"
}
},
"types": "./dts/index.d.cts",
"main": "./cjs/index.cjs",
"type": "commonjs"
}
3 changes: 3 additions & 0 deletions tests/__fixtures__/project-cts/src/index.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function test() {
return 123;
}
6 changes: 6 additions & 0 deletions tests/__fixtures__/project-cts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"outDir": "dts"
},
"include": ["src/**/*"]
}
12 changes: 12 additions & 0 deletions tests/__fixtures__/project-mts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "project-mts",
"packemon": {
"format": "mjs",
"inputs": {
"index": "src/index.mts"
}
},
"types": "./dts/index.d.mts",
"main": "./mjs/index.mjs",
"type": "module"
}
3 changes: 3 additions & 0 deletions tests/__fixtures__/project-mts/src/index.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function test() {
return 'abc';
}
6 changes: 6 additions & 0 deletions tests/__fixtures__/project-mts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"outDir": "dts"
},
"include": ["src/**/*"]
}
Loading

0 comments on commit f0a9041

Please sign in to comment.