Skip to content

Commit

Permalink
adds copy package.json option
Browse files Browse the repository at this point in the history
  • Loading branch information
3axap4eHko committed Sep 17, 2023
1 parent 0e2404c commit 8ecb847
Show file tree
Hide file tree
Showing 12 changed files with 611 additions and 497 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x]
node-version: [18.x, 20.x]
steps:
- name: Checkout code
uses: actions/checkout@v3
Expand All @@ -31,10 +31,12 @@ jobs:
- name: Run build process
run: |
yarn build
yarn build:example
- name: Run testing
run: |
yarn test
yarn test:example
env:
COVERAGE: 1

Expand Down
2 changes: 1 addition & 1 deletion .swcrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"module": {
"type": "nodenext",
"strict": true
"resolveFully": true
},
"jsc": {
"target": "esnext",
Expand Down
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ Use option `-p` to adjust `package.json` with following changes
}
```

Use option `-i` to ignore specific patterns
```bash
npx inop src build -i __tests__ -i __mocks__
```

As for module declarations and typechecking use the following command, since swc does not support them yet
```bash
tsc --declaration --emitDeclarationOnly
Expand All @@ -43,11 +48,11 @@ Here is the recommended `tsconfig.json`
{
"compilerOptions": {
...
"target": "esnext",
"module": "ESNext",
"target": "ESNext",
"module": "NodeNext",
"declaration": true,
"esModuleInterop": true,
"moduleResolution": "nodenext",
"moduleResolution": "NodeNext",
...
},
...
Expand Down
18 changes: 18 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "example",
"description": "",
"version": "1.0.0",
"type": "module",
"main": "build/index.cjs",
"scripts": {
"build": "../bin/inop.js src build -p -c -i __tests__",
"test": "node ./build/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@swc/core": "^1.3.63",
"fast-glob": "^3.2.12"
}
}
12 changes: 12 additions & 0 deletions example/src/A.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { strict as assert } from 'assert';
import { transform } from '@swc/core';
import glob from 'fast-glob';

export class A {
transform = transform;

constructor(public value: number){
assert.equal(typeof value, 'number');
glob('');
}
}
7 changes: 7 additions & 0 deletions example/src/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import '../index';

describe('Example test', () => {
it('should work', () => {
expect(true).toBe(true);
});
});
17 changes: 17 additions & 0 deletions example/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { randomInt } from 'crypto';
export { createServer } from 'http';
import { A } from './A';

export * from './A';

export const a = new A(randomInt(10));

export type Type = unknown;

export class C {}

const b = {};

export { b };

export default new A(1);
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
"inop": "bin/inop.js"
},
"scripts": {
"build": "rm -rf build && swc ./src -d build && rm -rf build/__tests__ && tsc --declaration --emitDeclarationOnly",
"test": "jest"
"build": "rm -rf build && swc --ignore __tests__ ./src -d build && tsc --declaration --emitDeclarationOnly",
"test": "jest",
"build:example": "(cd example && npm run build)",
"test:example": "(cd example && npm run test)"
},
"engines": {
"node": ">=16"
Expand Down Expand Up @@ -41,7 +43,7 @@
],
"dependencies": {
"@swc/core": "^1.3.63",
"commander": "^10.0.1",
"commander": "^11.0.0",
"fast-glob": "^3.2.12"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ commander
.option('-s, --swcrc <swcrc>', 'swcrc path', '.swcrc')
.option('-i, --ignore [ignore...]', 'ignore patterns')
.option('-p, --package', 'adjust package.json according to main property')
.option('-c, --copy', 'copy package.json to build directory with optimized dependencies')
.option('--commonjs-ext [commonjs-ext]', 'file extension of CommonJS files', '.cjs')
.option('--esm-ext [esm-ext]', 'file extension of ESM files', '.js')
.option('--skip-commonjs', 'do not generate CommonJS files')
Expand Down
63 changes: 47 additions & 16 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,24 @@ export const setNodeExtension = (node: swc.StringLiteral, extension: string) =>
};

export class ModuleVisitor extends Visitor {
public readonly modules = new Set<string>();

constructor(public extension: string) {
super();
}

visitModuleDeclaration(decl: swc.ModuleDeclaration) {
if ('source' in decl) {
if (decl.source?.type === 'StringLiteral' && isLocalFile.test(decl.source.value)) {
setNodeExtension(decl.source, this.extension);
if (decl.source?.type === 'StringLiteral') {
if (isLocalFile.test(decl.source.value)) {
setNodeExtension(decl.source, this.extension);
} else {
const moduleName = decl.source.value.split('/').slice(
0,
decl.source.value.startsWith('@') ? 2 : 1,
).join('/');
this.modules.add(moduleName);
}
}
}
if ('expression' in decl) {
Expand All @@ -46,16 +56,16 @@ export class ModuleVisitor extends Visitor {
}
return super.visitModuleDeclaration(decl);
}
visitTsType(decl: swc.TsType){
visitTsType(decl: swc.TsType) {
return decl;
}
}

export const patchCJS = (config: swc.Config, extension: string): Config => {
const visitor = new ModuleVisitor(extension);
export const patchCJS = (config: swc.Config, visitor: ModuleVisitor): Config => {
return {
...config,
module: {
strict: true,
...config?.module,
type: 'commonjs',
},
Expand All @@ -72,8 +82,7 @@ export const patchCJS = (config: swc.Config, extension: string): Config => {
},
};
};
export const patchMJS = (config: swc.Config, extension: string): Config => {
const visitor = new ModuleVisitor(extension);
export const patchMJS = (config: swc.Config, visitor: ModuleVisitor): Config => {
return {
...config,
module: {
Expand Down Expand Up @@ -123,15 +132,18 @@ interface TransformCommandOptions {
esmExt: string;
skipEsm: boolean;
package?: boolean;
copy?: boolean;
}

const defaultSwcrc = {
const defaultSwcrc: swc.Config = {
module: {
strict: true,
type: 'es6',
},
jsc: {
target: 'es2022',
parser: {},
parser: {
syntax: 'typescript',
},
},
};

Expand All @@ -158,9 +170,11 @@ export const patchPackageJSON = async ({ name, version, description, main }: Rec

export const transformCommand = async (source: string, build: string, options: TransformCommandOptions) => {
const swcrcFilepath = isLocalFile.test(options.swcrc) ? Path.resolve(options.swcrc) : options.swcrc;
const swcrcConfig = await fileNotExist(swcrcFilepath) ? defaultSwcrc : await readJSON(swcrcFilepath);
const swcrcCJS = patchCJS(swcrcConfig, options.commonjsExt);
const swcrcMJS = patchMJS(swcrcConfig, options.esmExt);
const swcrcConfig: swc.Config = await fileNotExist(swcrcFilepath) ? defaultSwcrc : await readJSON(swcrcFilepath);
const visitorCJS = new ModuleVisitor(options.commonjsExt);
const swcrcCJS = patchCJS(swcrcConfig, visitorCJS);
const visitorMJS = new ModuleVisitor(options.esmExt);
const swcrcMJS = patchMJS(swcrcConfig, visitorMJS);

const sourceDir = Path.resolve(source);
const buildDir = Path.resolve(build);
Expand All @@ -183,16 +197,33 @@ export const transformCommand = async (source: string, build: string, options: T
}
if (options.package) {
const packageJSONPath = Path.resolve('./package.json');
const packageJSONTargetPath = options.copy
? Path.resolve(buildDir, './package.json')
: packageJSONPath;

if (await fileNotExist(packageJSONPath)) {
throw new Error(`File package.json not found at ${packageJSONPath}`);
}

const { name, version, description, main, ...rest } = await readJSON(packageJSONPath);
const { name, version, description, main, dependencies, devDependencies, ...rest } = await readJSON(packageJSONPath);
if (await fileNotExist(main)) {
throw new Error(`File ${main} not found`);
throw new Error(`File ${main} of "main" section in package.json not found`);
}

if (options.copy) {
const deps = { ...devDependencies, ...dependencies };
rest.dependencies = {};
for (const moduleName of visitorMJS.modules) {
if (deps[moduleName]) {
rest.dependencies[moduleName] = deps[moduleName];
}
}
} else {
rest.dependencies = dependencies;
rest.devDependencies = devDependencies;
}

const patchedPackageJSON = await patchPackageJSON({ name, version, description, main }, buildDir, sourceDir, sourceFiles, options);
await writeJSON(packageJSONPath, { ...patchedPackageJSON, ...rest });
await writeJSON(packageJSONTargetPath, { ...patchedPackageJSON, ...rest });
}
};
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "nodenext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"rootDir": "src",
"outDir": "build"
Expand Down
Loading

0 comments on commit 8ecb847

Please sign in to comment.