Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Expose esm hooks factory to public API #1439

Merged
merged 11 commits into from Oct 10, 2021
19 changes: 13 additions & 6 deletions esm.mjs
Expand Up @@ -3,9 +3,16 @@ import { createRequire } from 'module';
const require = createRequire(fileURLToPath(import.meta.url));

/** @type {import('./dist/esm')} */
const esm = require('./dist/esm');
export const {
resolve,
getFormat,
transformSource,
} = esm.registerAndCreateEsmHooks();
const { createEsmHooks } = require('./dist/esm');

/** @type {import('./dist/index')} */
const { register } = require('./dist/index');

// Automatically performs registration just like `-r ts-node/register`
const tsNodeInstance = register({
experimentalEsmLoader: true,
});

export const { resolve, getFormat, transformSource } = createEsmHooks(
tsNodeInstance
);
20 changes: 14 additions & 6 deletions esm/transpile-only.mjs
Expand Up @@ -3,9 +3,17 @@ import { createRequire } from 'module';
const require = createRequire(fileURLToPath(import.meta.url));

/** @type {import('../dist/esm')} */
const esm = require('../dist/esm');
export const {
resolve,
getFormat,
transformSource,
} = esm.registerAndCreateEsmHooks({ transpileOnly: true });
const { createEsmHooks } = require('../dist/esm');

/** @type {import('../dist/index')} */
const { register } = require('../dist/index');

// Automatically performs registration just like `-r ts-node/register`
const tsNodeInstance = register({
transpileOnly: true,
experimentalEsmLoader: true,
});

export const { resolve, getFormat, transformSource } = createEsmHooks(
tsNodeInstance
);
24 changes: 9 additions & 15 deletions src/esm.ts
@@ -1,4 +1,4 @@
import { register, getExtensions, RegisterOptions } from './index';
import { getExtensions, Service } from './index';
import {
parse as parseUrl,
format as formatUrl,
Expand All @@ -15,17 +15,11 @@ const {

// Note: On Windows, URLs look like this: file:///D:/dev/@TypeStrong/ts-node-examples/foo.ts

export function registerAndCreateEsmHooks(opts?: RegisterOptions) {
nonara marked this conversation as resolved.
Show resolved Hide resolved
// Automatically performs registration just like `-r ts-node/register`
const tsNodeInstance = register({
...opts,
experimentalEsmLoader: true,
});

export function createEsmHooks(tsNodeService: Service) {
// Custom implementation that considers additional file extensions and automatically adds file extensions
const nodeResolveImplementation = createResolve({
...getExtensions(tsNodeInstance.config),
preferTsExts: tsNodeInstance.options.preferTsExts,
...getExtensions(tsNodeService.config),
preferTsExts: tsNodeService.options.preferTsExts,
});

return { resolve, getFormat, transformSource };
Expand Down Expand Up @@ -98,17 +92,17 @@ export function registerAndCreateEsmHooks(opts?: RegisterOptions) {
// If file has .ts, .tsx, or .jsx extension, then ask node how it would treat this file if it were .js
const ext = extname(nativePath);
let nodeSays: { format: Format };
if (ext !== '.js' && !tsNodeInstance.ignored(nativePath)) {
if (ext !== '.js' && !tsNodeService.ignored(nativePath)) {
nodeSays = await defer(formatUrl(pathToFileURL(nativePath + '.js')));
} else {
nodeSays = await defer();
}
// For files compiled by ts-node that node believes are either CJS or ESM, check if we should override that classification
if (
!tsNodeInstance.ignored(nativePath) &&
!tsNodeService.ignored(nativePath) &&
(nodeSays.format === 'commonjs' || nodeSays.format === 'module')
) {
const { moduleType } = tsNodeInstance.moduleTypeClassifier.classifyModule(
const { moduleType } = tsNodeService.moduleTypeClassifier.classifyModule(
normalizeSlashes(nativePath)
);
if (moduleType === 'cjs') {
Expand Down Expand Up @@ -139,11 +133,11 @@ export function registerAndCreateEsmHooks(opts?: RegisterOptions) {
}
const nativePath = fileURLToPath(url);

if (tsNodeInstance.ignored(nativePath)) {
if (tsNodeService.ignored(nativePath)) {
return defer();
}

const emittedJs = tsNodeInstance.compile(sourceAsString, nativePath);
const emittedJs = tsNodeService.compile(sourceAsString, nativePath);

return { source: emittedJs };
}
Expand Down
5 changes: 5 additions & 0 deletions src/index.ts
Expand Up @@ -1430,3 +1430,8 @@ function getTokenAtPosition(
return current;
}
}

import type { createEsmHooks as createEsmHooksFn } from './esm';
export const createEsmHooks: typeof createEsmHooksFn = (
tsNodeService: Service
) => require('./esm').createEsmHooks(tsNodeService);