Skip to content

Commit

Permalink
feat: add support for custom typings file extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
favna committed Dec 1, 2023
1 parent 096c04d commit 06f37d1
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 28 deletions.
6 changes: 6 additions & 0 deletions assets/rollup-type-bundler.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
"type": "string",
"default": "build"
},
"typingsFileExtension": {
"description": "The file extension for your typings files. Useful if you want to set `.cts` or `.mts`. If you forego adding a prefixing dot (`.`), it will be added for you.",
"pattern": "^\\.?[a-z]+$",
"type": "string",
"default": ".ts"
},
"external": {
"description": "Modules that should be considered as external. See https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency",
"type": "array",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"prepack": "yarn build"
},
"dependencies": {
"@sapphire/node-utilities": "^1.0.0",
"@sapphire/utilities": "^3.13.0",
"colorette": "^2.0.20",
"commander": "^11.1.0",
Expand Down
6 changes: 6 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const command = new Command()
.version(packageJson.version)
.option('-d, --dist <dist>', 'The dist directory to target')
.option('-b, --build-script [buildScript]', 'The build script to call after cleaning your dist directory')
.option(
'-t, --typings-file-extension [typingsFileExtension]',
'The file extension for your typings files. Useful if you want to set `.cts` or `.mts`. If you forego adding a prefixing dot (`.`), it will be added for you.'
)
.option('-v, --verbose', 'Print verbose information')
.option(
'-e, --external [external...]',
Expand All @@ -38,6 +42,8 @@ logVerboseInfo(
[
'Resolved options: ',
`${indent}dist: ${JSON.stringify(options.dist)}`,
`${indent}buildScript: ${JSON.stringify(options.buildScript)}`,
`${indent}typingsFileExtension: ${JSON.stringify(options.typingsFileExtension)}`,
`${indent}verbose: ${JSON.stringify(options.verbose)}`,
`${indent}external: ${JSON.stringify(options.external)}`,
''
Expand Down
3 changes: 2 additions & 1 deletion src/commands/bundle-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { fileExistsAsync } from '#lib/promisified';
import { getTypingsInputFileName } from '#lib/utils';
import type { Options } from 'commander';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
Expand All @@ -13,7 +14,7 @@ const sleep = promisify(setTimeout);
* @param options The options that tell this function where to clean up
*/
export async function bundleTypes(options: Options): Promise<void> {
const typingsFile = join(fileURLToPath(options.dist), 'index.d.ts');
const typingsFile = join(fileURLToPath(options.dist), getTypingsInputFileName(options));

// Sleep repeated 1 second until the `index.d.ts` file exists
do {
Expand Down
35 changes: 9 additions & 26 deletions src/commands/clean-extraneous-types.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,21 @@
import { logVerboseError } from '#lib/logVerbose';
import { findFilesRecursivelyRegex } from '@sapphire/node-utilities';
import type { Options } from 'commander';
import { opendir, rm } from 'node:fs/promises';
import { basename, join, sep } from 'node:path';
import { fileURLToPath, URL } from 'node:url';
import { rm } from 'node:fs/promises';
import { basename, sep } from 'node:path';
import { getTypingsInputFileName } from '#lib/utils';
import { fileURLToPath } from 'node:url';

/**
* Scans a given {@link path} applying the {@link cb} filter
* @param path The path to scan
* @param cb The callback to apply to filter files in the {@link path}
*/
async function* scan(path: URL | string, cb: (path: string) => boolean): AsyncGenerator<string> {
const dir = await opendir(typeof path === 'string' ? path : fileURLToPath(path));

for await (const item of dir) {
const file = join(dir.path, item.name);
if (item.isFile()) {
if (cb(file)) yield file;
} else if (item.isDirectory()) {
yield* scan(file, cb);
}
}
}

/**
* Cleans up the extraneous types from the `dist` folder after bundling all the types into the root `index.d.ts`
* Cleans up the extraneous types from the `dist` folder after bundling all the types into the root `index.d.[cm]?ts`
* @param options The options that tell this function where to clean up
*/
export async function cleanExtraneousTypes(options: Options): Promise<void> {
try {
const regexp = /(?:\.d\.ts(?:\.map)?|\.tsbuildinfo)$/;
const cb = (path: string) => regexp.test(path);
const regexp = /(?:\.d\.[cm]?ts(?:\.map)?|\.tsbuildinfo)$/;

for await (const path of scan(options.dist, cb)) {
if (!path.endsWith(`${basename(fileURLToPath(options.dist))}${sep}index.d.ts`)) {
for await (const path of findFilesRecursivelyRegex(options.dist, regexp)) {
if (!path.endsWith(`${basename(fileURLToPath(options.dist))}${sep}${getTypingsInputFileName(options)}`)) {
await rm(path);
}
}
Expand Down
18 changes: 17 additions & 1 deletion src/lib/interfaces.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,26 @@ export default undefined;

declare module 'commander' {
export interface Options {
/**
* The dist folder where the TypeScript types are located
*/
dist: URL;
/**
* The package.json script that builds your code
*/
buildScript?: string;
config?: string;
/**
* The file extension for your typings files. Useful if you want to set `.cts` or `.mts`. If you forego adding a prefixing dot (`.`), it will be added for you.
* @default .ts
*/
typingsFileExtension?: string;
/**
* Whether or not to show verbose output
*/
verbose?: boolean;
/**
* External packages to pass to rollup as external
*/
external?: string[];
}
}
10 changes: 10 additions & 0 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { isNullishOrEmpty } from '@sapphire/utilities';
import { cyan, green, red } from 'colorette';
import type { Options } from 'commander';
import { load } from 'js-yaml';
import type { PathLike } from 'node:fs';
import { readFile } from 'node:fs/promises';
Expand Down Expand Up @@ -31,3 +33,11 @@ export async function doActionAndLog<T>(preActionLog: string, action: Promise<T>
process.exit(1);
}
}

export function getTypingsInputFileName(options: Options) {
return isNullishOrEmpty(options.typingsFileExtension)
? 'index.d.ts'
: options.typingsFileExtension.startsWith('.')
? `index.d${options.typingsFileExtension}`
: `index.d.${options.typingsFileExtension}`;
}
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ __metadata:
"@commitlint/config-conventional": "npm:^18.4.3"
"@favware/cliff-jumper": "npm:^2.2.3"
"@sapphire/eslint-config": "npm:^5.0.2"
"@sapphire/node-utilities": "npm:^1.0.0"
"@sapphire/prettier-config": "npm:^2.0.0"
"@sapphire/ts-config": "npm:^5.0.0"
"@sapphire/utilities": "npm:^3.13.0"
Expand Down Expand Up @@ -529,6 +530,13 @@ __metadata:
languageName: node
linkType: hard

"@sapphire/node-utilities@npm:^1.0.0":
version: 1.0.0
resolution: "@sapphire/node-utilities@npm:1.0.0"
checksum: eb919c92e8b230dbfb57a38d631788c28c00512c587b2c37cbb4d2c0968ea35c48439a065a10ab4bce929c04e8b1523dfa12a1f655ae5988866428118c11ac20
languageName: node
linkType: hard

"@sapphire/prettier-config@npm:^2.0.0":
version: 2.0.0
resolution: "@sapphire/prettier-config@npm:2.0.0"
Expand Down

0 comments on commit 06f37d1

Please sign in to comment.