Skip to content

Commit b8cad94

Browse files
committed
Initial commit
0 parents  commit b8cad94

File tree

14 files changed

+352
-0
lines changed

14 files changed

+352
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
dist

.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Place your settings in this file to overwrite default and user settings.
2+
{
3+
"eslint.enable": false
4+
}

.vscode/tasks.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
// See https://go.microsoft.com/fwlink/?LinkId=733558
3+
// for the documentation about the tasks.json format
4+
"version": "0.1.0",
5+
"command": "tsc",
6+
"isShellCommand": true,
7+
"args": ["-w", "-p", "./src"],
8+
"showOutput": "silent",
9+
"isWatching": true,
10+
"problemMatcher": "$tsc-watch"
11+
}

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Introduction
2+
3+
Tired of waiting for ES6 `imports` implementation in Node.JS?
4+
Tired of using transpilers with difficult defug and sourcemapping?
5+
6+
This plugin transforms your ES6 imports to commonjs counterparts.
7+
No sourcemapping is needed.
8+
9+
# How to use
10+
11+
Simply import the registration script as a first line in your server:
12+
13+
```js
14+
require('import-to-commonjs/dist/register');
15+
```
16+
17+
# Known issues
18+
19+
Currently none, but I'm pretty sure I missed some import cases. PRs welcome.
20+

package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "import-to-commonjs",
3+
"version": "0.0.2",
4+
"description": "Transforms import statements to commonjs",
5+
"main": "dist/index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [
10+
"NodeJs",
11+
"ES6",
12+
"CommonJS",
13+
"Javascript"
14+
],
15+
"author": "Tomi Trescak",
16+
"license": "MIT",
17+
"devDependencies": {
18+
"assert": "^1.4.1"
19+
}
20+
}

src/index.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
const importReg = /^import\s*((\* as )?\s*([\w_]+)\s*)?,?\s*(\{\s*([\w_,\s]*)\s\})?\s*(from\s+)?(['"][\._\-\w\/]+['"])/gm;
2+
const exportRef = /^export\s*(default)?\s*(const|let|var|class|function|interface)?\s*([\w_]*)/mg;
3+
4+
export default function transform(source: string) {
5+
importReg.lastIndex = 0;
6+
7+
// handle exports
8+
const moduleExports: string[] = [];
9+
let defaultExport: string = null;
10+
11+
exportRef.lastIndex = 0;
12+
let match: RegExpExecArray = null;
13+
while ((match = exportRef.exec(source)) != null) {
14+
if (match[1]) {
15+
if (defaultExport) {
16+
console.error('Multiple default exports!');
17+
throw new Error('Multiple default exports');
18+
} else {
19+
defaultExport = match[3];
20+
}
21+
} else {
22+
moduleExports.push(match[3]);
23+
}
24+
}
25+
26+
// remove export statements
27+
source = source.replace(/^export\s+(default)?\s*(function\s*\(|\{|\()?\s*/gm, (full: string, defaultKw: string, type: string) => {
28+
// console.log(type);
29+
if (type) {
30+
if (type.match(/function\s/)) {
31+
defaultExport = 'defaultFunction';
32+
return 'function defaultFunction(';
33+
} else if (type.match(/\{/)) {
34+
defaultExport = 'defaultObject';
35+
return 'const defaultObject = {';
36+
} else if (type.match(/\(/)) {
37+
defaultExport = 'defaultFunction';
38+
return 'const defaultFunction = (';
39+
}
40+
}
41+
return '';
42+
});
43+
44+
// construct exports
45+
let allExports = '';
46+
if (moduleExports.length) {
47+
// append export statement at the end of the file
48+
moduleExports.forEach((e) => { allExports += `\nexports.${e} = ${e};` });
49+
}
50+
if (defaultExport) {
51+
allExports += `\nexports.default = ${defaultExport};`;
52+
}
53+
54+
source += allExports;
55+
56+
// handle imports
57+
return source.replace(importReg,
58+
(wholeMatch: string,
59+
defaultImport: string,
60+
defaultAs: string,
61+
defaultAsVar: string,
62+
specificImportWrapper: string,
63+
specificImports: string,
64+
fromKeyword: string,
65+
source: string) => {
66+
67+
if (!fromKeyword) {
68+
return `require(${source})`;
69+
}
70+
else if (defaultImport && specificImports) {
71+
return handleDefaultImports(defaultAs, defaultAsVar, defaultImport, source) +
72+
'\n' +
73+
handleSpecificImports(specificImports, source);
74+
}
75+
else if (defaultImport) {
76+
return handleDefaultImports(defaultAs, defaultAsVar, defaultImport, source);
77+
} else if (specificImports) {
78+
return handleSpecificImports(specificImports, source);
79+
}
80+
return wholeMatch;
81+
});
82+
}
83+
84+
function handleSpecificImports(specificImports: string, source: string) {
85+
specificImports = specificImports.replace(/ as /g, ': ');
86+
return `const { ${specificImports} } = require(${source})`;
87+
}
88+
89+
function handleDefaultImports(defaultAs: string, defaultAsVar: string, defaultImport: string, source: string) {
90+
if (defaultAs) {
91+
return `const ${defaultAsVar.trim()} = require(${source})`;
92+
} else {
93+
return `const ${defaultImport.trim()} = require(${source}).default`;
94+
}
95+
}

src/register.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import transform from './index';
2+
3+
var fs = require('fs');
4+
5+
var prev = require.extensions['.js'];
6+
7+
require.extensions['.js'] = function(module: any, filename: string) {
8+
if (filename.indexOf('node_modules') === -1) {
9+
var source = fs.readFileSync(filename, 'utf8');
10+
module._compile(transform(source), filename);
11+
} else if (prev) {
12+
prev(module, filename);
13+
} else {
14+
var source = fs.readFileSync(filename, 'utf8');
15+
module._compile(source, filename);
16+
}
17+
};

src/tests/transform_spec.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import * as assert from 'assert';
2+
import transform from '../index';
3+
4+
describe('transform', () => {
5+
it('transforms named imports', () => {
6+
const imp = "import 'Bar'";
7+
assert.equal(transform(imp), "require('Bar')");
8+
9+
const imp1 = "import * as Foo from 'Bar'";
10+
assert.equal(transform(imp1), "const Foo = require('Bar')");
11+
});
12+
13+
it('transforms default imports', () => {
14+
const imp = "import Foo from 'Bar'";
15+
assert.equal(transform(imp), "const Foo = require('Bar').default");
16+
17+
const imp1 = "import * as Foo from 'Bar'";
18+
assert.equal(transform(imp1), "const Foo = require('Bar')");
19+
});
20+
21+
it('transforms named arguments', () => {
22+
const imp = "import { Foo, Foo1 } from 'Bar'";
23+
assert.equal(transform(imp), "const { Foo, Foo1 } = require('Bar')");
24+
25+
const imp1 = "import { Foo as Boo, Foo1 } from 'Bar'";
26+
assert.equal(transform(imp1), "const { Foo: Boo, Foo1 } = require('Bar')");
27+
});
28+
29+
it('transforms default and named arguments', () => {
30+
const imp = "import Foo, { Foo1 } from 'Bar'";
31+
assert.equal(transform(imp), "const Foo = require('Bar').default\nconst { Foo1 } = require('Bar')");
32+
33+
const imp1 = "import * as Foo { Foo1 } from 'Bar'";
34+
assert.equal(transform(imp1), "const Foo = require('Bar')\nconst { Foo1 } = require('Bar')");
35+
});
36+
37+
it('transforms exports', () => {
38+
let imp = "export function m()";
39+
assert.equal(transform(imp), "function m()\nexports.m = m;");
40+
});
41+
42+
it('transforms multiple exports', () => {
43+
let imp = `export function m()\nexport const n()`;
44+
assert.equal(transform(imp), "function m()\nconst n()\nexports.m = m;\nexports.n = n;");
45+
});
46+
47+
it('transforms default exports', () => {
48+
let imp = `export default function m()\nexport const n()`;
49+
assert.equal(transform(imp), "function m()\nconst n()\nexports.n = n;\nexports.default = m;");
50+
});
51+
52+
it('transforms unnamed default exports', () => {
53+
let imp = `export default function ()`;
54+
assert.equal(transform(imp), "function defaultFunction()\nexports.default = defaultFunction;");
55+
56+
imp = `export default {`;
57+
assert.equal(transform(imp), "const defaultObject = {\nexports.default = defaultObject;");
58+
59+
imp = `export default () =>`;
60+
assert.equal(transform(imp), "const defaultFunction = () =>\nexports.default = defaultFunction;");
61+
});
62+
63+
it('transforms default export variables', () => {
64+
let imp = `export default m`;
65+
assert.equal(transform(imp), "m\nexports.default = m;");
66+
});
67+
});

src/tsconfig.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"compileOnSave": true,
3+
"compilerOptions": {
4+
"target": "es5",
5+
"module": "commonjs",
6+
"declaration": false,
7+
"noImplicitAny": true,
8+
"removeComments": true,
9+
"noLib": false,
10+
"preserveConstEnums": true,
11+
"outDir": "../dist",
12+
"suppressImplicitAnyIndexErrors": true,
13+
"experimentalDecorators": true,
14+
"sourceMap": false,
15+
"allowSyntheticDefaultImports": true,
16+
"moduleResolution": "classic",
17+
"allowJs": true,
18+
"strictNullChecks": false
19+
},
20+
"filesGlob": [
21+
"**/*.ts"
22+
],
23+
"exclude": [
24+
"node_modules"
25+
]
26+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Generated by typings
2+
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/assert/assert.d.ts
3+
declare function assert(value:any, message?:string):void;
4+
declare namespace assert {
5+
export class AssertionError implements Error {
6+
name:string;
7+
message:string;
8+
actual:any;
9+
expected:any;
10+
operator:string;
11+
generatedMessage:boolean;
12+
13+
constructor(options?:{message?: string; actual?: any; expected?: any; operator?: string; stackStartFunction?: Function});
14+
}
15+
16+
export function fail(actual?:any, expected?:any, message?:string, operator?:string):void;
17+
18+
export function ok(value:any, message?:string):void;
19+
20+
export function equal(actual:any, expected:any, message?:string):void;
21+
22+
export function notEqual(actual:any, expected:any, message?:string):void;
23+
24+
export function deepEqual(actual:any, expected:any, message?:string):void;
25+
26+
export function notDeepEqual(acutal:any, expected:any, message?:string):void;
27+
28+
export function strictEqual(actual:any, expected:any, message?:string):void;
29+
30+
export function notStrictEqual(actual:any, expected:any, message?:string):void;
31+
32+
export var throws:{
33+
(block:Function, message?:string): void;
34+
(block:Function, error:Function, message?:string): void;
35+
(block:Function, error:RegExp, message?:string): void;
36+
(block:Function, error:(err:any) => boolean, message?:string): void;
37+
};
38+
39+
export var doesNotThrow:{
40+
(block:Function, message?:string): void;
41+
(block:Function, error:Function, message?:string): void;
42+
(block:Function, error:RegExp, message?:string): void;
43+
(block:Function, error:(err:any) => boolean, message?:string): void;
44+
};
45+
46+
export function ifError(value:any):void;
47+
}
48+
49+
// duplicate to node.d.ts
50+
// declare module "assert" {
51+
// export = assert;
52+
// }
53+
54+
// move to power-assert.d.ts. do not use this definition file.
55+
declare module "assert" {
56+
export = assert;
57+
}

0 commit comments

Comments
 (0)