feat(bundling): add esbuild plugin (#12053)
This commit is contained in:
parent
38e4a8e7d0
commit
ed7db7c114
254
docs/generated/packages/esbuild.json
Normal file
254
docs/generated/packages/esbuild.json
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
{
|
||||||
|
"githubRoot": "https://github.com/nrwl/nx/blob/master",
|
||||||
|
"name": "esbuild",
|
||||||
|
"packageName": "@nrwl/esbuild",
|
||||||
|
"description": "The Nx Plugin for EsBuild contains executors and generators that support building applications using EsBuild",
|
||||||
|
"root": "/packages/esbuild",
|
||||||
|
"source": "/packages/esbuild/src",
|
||||||
|
"documentation": [],
|
||||||
|
"generators": [
|
||||||
|
{
|
||||||
|
"name": "init",
|
||||||
|
"factory": "./src/generators/init/init#esbuildInitGenerator",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"$id": "NxWebpackInit",
|
||||||
|
"cli": "nx",
|
||||||
|
"title": "Init Webpack Plugin",
|
||||||
|
"description": "Init Webpack Plugin.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"compiler": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["babel", "swc", "tsc"],
|
||||||
|
"description": "The compiler to initialize for.",
|
||||||
|
"default": "babel"
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"description": "Skip formatting files.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [],
|
||||||
|
"presets": []
|
||||||
|
},
|
||||||
|
"description": "Initialize the `@nrwl/esbuild` plugin.",
|
||||||
|
"aliases": ["ng-add"],
|
||||||
|
"hidden": true,
|
||||||
|
"implementation": "/packages/esbuild/src/generators/init/init#esbuildInitGenerator.ts",
|
||||||
|
"path": "/packages/esbuild/src/generators/init/schema.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "esbuild-project",
|
||||||
|
"factory": "./src/generators/esbuild-project/esbuild-project#esbuildProjectGenerator",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"$id": "NxEsBuildProject",
|
||||||
|
"cli": "nx",
|
||||||
|
"title": "Add EsBuild Configuration to a project",
|
||||||
|
"description": "Add EsBuild Configuration to a project.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the project.",
|
||||||
|
"$default": { "$source": "argv", "index": 0 },
|
||||||
|
"x-dropdown": "project",
|
||||||
|
"x-prompt": "What is the name of the project to set up a esbuild for?"
|
||||||
|
},
|
||||||
|
"main": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path relative to the workspace root for the main entry file. Defaults to '<projectRoot>/src/main.ts'.",
|
||||||
|
"alias": "entryFile"
|
||||||
|
},
|
||||||
|
"tsConfig": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path relative to the workspace root for the tsconfig file to build with. Defaults to '<projectRoot>/tsconfig.app.json'."
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"description": "Skip formatting files.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"skipPackageJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Do not add dependencies to `package.json`."
|
||||||
|
},
|
||||||
|
"importPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The library name used to import it, like `@myorg/my-awesome-lib`."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [],
|
||||||
|
"presets": []
|
||||||
|
},
|
||||||
|
"description": "Add esbuild configuration to a project.",
|
||||||
|
"hidden": true,
|
||||||
|
"implementation": "/packages/esbuild/src/generators/esbuild-project/esbuild-project#esbuildProjectGenerator.ts",
|
||||||
|
"aliases": [],
|
||||||
|
"path": "/packages/esbuild/src/generators/esbuild-project/schema.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"executors": [
|
||||||
|
{
|
||||||
|
"name": "esbuild",
|
||||||
|
"implementation": "/packages/esbuild/src/executors/esbuild/esbuild.impl.ts",
|
||||||
|
"schema": {
|
||||||
|
"title": "Web Library EsBuild Target (Experimental)",
|
||||||
|
"description": "Packages a library for different web usages (`UMD`, `ESM`, `CJS`).",
|
||||||
|
"cli": "nx",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"main": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The path to the entry file, relative to project.",
|
||||||
|
"alias": "entryFile",
|
||||||
|
"x-completion-type": "file",
|
||||||
|
"x-completion-glob": "**/*@(.js|.ts)"
|
||||||
|
},
|
||||||
|
"outputPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The output path of the generated files.",
|
||||||
|
"x-completion-type": "directory"
|
||||||
|
},
|
||||||
|
"outputFileName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the main output file. Defaults same basename as 'main' file."
|
||||||
|
},
|
||||||
|
"tsConfig": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The path to tsconfig file.",
|
||||||
|
"x-completion-type": "file",
|
||||||
|
"x-completion-glob": "tsconfig.*.json"
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The path to package.json file."
|
||||||
|
},
|
||||||
|
"format": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Set the output format(s).",
|
||||||
|
"alias": "f",
|
||||||
|
"items": { "type": "string", "enum": ["esm", "cjs"] },
|
||||||
|
"default": ["esm"]
|
||||||
|
},
|
||||||
|
"watch": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Enable re-building when files change.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"assets": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "List of static assets.",
|
||||||
|
"default": [],
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"glob": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The pattern to match."
|
||||||
|
},
|
||||||
|
"input": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The input directory path in which to apply `glob`. Defaults to the project root."
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Relative path within the output folder."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["glob", "input", "output"]
|
||||||
|
},
|
||||||
|
{ "type": "string" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"clean": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Remove previous output before build.",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"external": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Mark one or more module as external. Can use * wildcards, such as '*.png'.",
|
||||||
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"metafile": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Generate a meta.json file in the output folder that includes metadata about the build. This file can be analyzed by other tools.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"minify": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Minifies outputs.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"platform": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Platform target for outputs.",
|
||||||
|
"enum": ["browser", "node", "neutral"],
|
||||||
|
"default": "node"
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The environment target for outputs.",
|
||||||
|
"default": "esnext"
|
||||||
|
},
|
||||||
|
"skipTypeCheck": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Skip type-checking via TypeScript. Skipping type-checking speeds up the build but type errors are not caught.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"updateBuildableProjectDepsInPackageJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Update buildable project dependencies in `package.json`.",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"buildableProjectDepsInPackageJsonType": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.",
|
||||||
|
"enum": ["dependencies", "peerDependencies"],
|
||||||
|
"default": "peerDependencies"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["tsConfig", "main", "outputPath"],
|
||||||
|
"definitions": {
|
||||||
|
"assetPattern": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"glob": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The pattern to match."
|
||||||
|
},
|
||||||
|
"input": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The input directory path in which to apply `glob`. Defaults to the project root."
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Relative path within the output folder."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["glob", "input", "output"]
|
||||||
|
},
|
||||||
|
{ "type": "string" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presets": []
|
||||||
|
},
|
||||||
|
"description": "Bundle a package using EsBuild.",
|
||||||
|
"aliases": [],
|
||||||
|
"hidden": false,
|
||||||
|
"path": "/packages/esbuild/src/executors/esbuild/schema.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -126,6 +126,11 @@
|
|||||||
"default": "tsc",
|
"default": "tsc",
|
||||||
"description": "The compiler used by the build and test targets"
|
"description": "The compiler used by the build and test targets"
|
||||||
},
|
},
|
||||||
|
"bundler": {
|
||||||
|
"description": "The bundler to use.",
|
||||||
|
"enum": ["none", "esbuild", "rollup", "webpack"],
|
||||||
|
"default": "none"
|
||||||
|
},
|
||||||
"skipTypeCheck": {
|
"skipTypeCheck": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether to skip TypeScript type checking for SWC compiler.",
|
"description": "Whether to skip TypeScript type checking for SWC compiler.",
|
||||||
|
|||||||
@ -109,6 +109,16 @@
|
|||||||
"path": "generated/packages/devkit.json",
|
"path": "generated/packages/devkit.json",
|
||||||
"schemas": { "executors": [], "generators": [] }
|
"schemas": { "executors": [], "generators": [] }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "esbuild",
|
||||||
|
"packageName": "esbuild",
|
||||||
|
"description": "The Nx Plugin for EsBuild contains executors and generators that support building applications using EsBuild",
|
||||||
|
"path": "generated/packages/esbuild.json",
|
||||||
|
"schemas": {
|
||||||
|
"executors": ["esbuild"],
|
||||||
|
"generators": ["init", "esbuild-project"]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "eslint-plugin-nx",
|
"name": "eslint-plugin-nx",
|
||||||
"packageName": "eslint-plugin-nx",
|
"packageName": "eslint-plugin-nx",
|
||||||
|
|||||||
11
e2e/esbuild/jest.config.ts
Normal file
11
e2e/esbuild/jest.config.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
export default {
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': 'ts-jest',
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||||
|
maxWorkers: 1,
|
||||||
|
globals: { 'ts-jest': { tsconfig: '<rootDir>/tsconfig.spec.json' } },
|
||||||
|
displayName: 'e2e-esbuild',
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
};
|
||||||
34
e2e/esbuild/project.json
Normal file
34
e2e/esbuild/project.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "e2e/esbuild",
|
||||||
|
"projectType": "application",
|
||||||
|
"targets": {
|
||||||
|
"e2e": {
|
||||||
|
"executor": "nx:run-commands",
|
||||||
|
"options": {
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "yarn e2e-start-local-registry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "yarn e2e-build-package-publish"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "nx run-e2e-tests e2e-esbuild"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parallel": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"run-e2e-tests": {
|
||||||
|
"executor": "@nrwl/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "e2e/esbuild/jest.config.ts",
|
||||||
|
"passWithNoTests": true,
|
||||||
|
"runInBand": true
|
||||||
|
},
|
||||||
|
"outputs": ["coverage/e2e/esbuild"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"implicitDependencies": ["esbuild"]
|
||||||
|
}
|
||||||
63
e2e/esbuild/src/esbuild.test.ts
Normal file
63
e2e/esbuild/src/esbuild.test.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import {
|
||||||
|
checkFilesExist,
|
||||||
|
checkFilesDoNotExist,
|
||||||
|
cleanupProject,
|
||||||
|
newProject,
|
||||||
|
readFile,
|
||||||
|
runCLI,
|
||||||
|
runCommand,
|
||||||
|
uniq,
|
||||||
|
updateFile,
|
||||||
|
updateJson,
|
||||||
|
updateProjectConfig,
|
||||||
|
} from '@nrwl/e2e/utils';
|
||||||
|
|
||||||
|
describe('EsBuild Plugin', () => {
|
||||||
|
beforeEach(() => newProject());
|
||||||
|
afterEach(() => cleanupProject());
|
||||||
|
|
||||||
|
it('should setup and build projects using build', async () => {
|
||||||
|
const myPkg = uniq('my-pkg');
|
||||||
|
runCLI(`generate @nrwl/js:lib ${myPkg} --bundler=esbuild`);
|
||||||
|
updateFile(`libs/${myPkg}/src/index.ts`, `console.log('Hello');\n`);
|
||||||
|
updateProjectConfig(myPkg, (json) => {
|
||||||
|
json.targets.build.options.assets = [`libs/${myPkg}/assets/*`];
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
updateFile(`libs/${myPkg}/assets/a.md`, 'file a');
|
||||||
|
updateFile(`libs/${myPkg}/assets/b.md`, 'file b');
|
||||||
|
|
||||||
|
runCLI(`build ${myPkg}`);
|
||||||
|
|
||||||
|
expect(runCommand(`node dist/libs/${myPkg}/main.js`)).toMatch(/Hello/);
|
||||||
|
|
||||||
|
checkFilesExist(`dist/libs/${myPkg}/package.json`);
|
||||||
|
expect(readFile(`dist/libs/${myPkg}/assets/a.md`)).toMatch(/file a/);
|
||||||
|
expect(readFile(`dist/libs/${myPkg}/assets/b.md`)).toMatch(/file b/);
|
||||||
|
|
||||||
|
/* CJS format is not used by default, but passing --format=esm,cjs generates with it.
|
||||||
|
*/
|
||||||
|
checkFilesDoNotExist(`dist/libs/${myPkg}/main.cjs`);
|
||||||
|
runCLI(`build ${myPkg} --format=esm,cjs`);
|
||||||
|
checkFilesExist(`dist/libs/${myPkg}/main.cjs`);
|
||||||
|
|
||||||
|
/* Metafile is not generated by default, but passing --metafile generates it.
|
||||||
|
*/
|
||||||
|
checkFilesDoNotExist(`dist/libs/${myPkg}/meta.json`);
|
||||||
|
runCLI(`build ${myPkg} --metafile`);
|
||||||
|
checkFilesExist(`dist/libs/${myPkg}/meta.json`);
|
||||||
|
|
||||||
|
/* Type errors are turned on by default
|
||||||
|
*/
|
||||||
|
updateFile(
|
||||||
|
`libs/${myPkg}/src/index.ts`,
|
||||||
|
`
|
||||||
|
const x: number = 'a'; // type error
|
||||||
|
console.log('Bye');
|
||||||
|
`
|
||||||
|
);
|
||||||
|
expect(() => runCLI(`build ${myPkg}`)).toThrow();
|
||||||
|
expect(() => runCLI(`build ${myPkg} --skipTypeCheck`)).not.toThrow();
|
||||||
|
expect(runCommand(`node dist/libs/${myPkg}/main.js`)).toMatch(/Bye/);
|
||||||
|
}, 300_000);
|
||||||
|
});
|
||||||
13
e2e/esbuild/tsconfig.json
Normal file
13
e2e/esbuild/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["node", "jest"]
|
||||||
|
},
|
||||||
|
"include": [],
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
20
e2e/esbuild/tsconfig.spec.json
Normal file
20
e2e/esbuild/tsconfig.spec.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.test.ts",
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.spec.tsx",
|
||||||
|
"**/*.test.tsx",
|
||||||
|
"**/*.spec.js",
|
||||||
|
"**/*.test.js",
|
||||||
|
"**/*.spec.jsx",
|
||||||
|
"**/*.test.jsx",
|
||||||
|
"**/*.d.ts",
|
||||||
|
"jest.config.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -100,8 +100,8 @@ describe('Workspace Tests', () => {
|
|||||||
checkFilesExist(`dist/libs/${buildableLib}/README.md`);
|
checkFilesExist(`dist/libs/${buildableLib}/README.md`);
|
||||||
|
|
||||||
const json = readJson(`dist/libs/${buildableLib}/package.json`);
|
const json = readJson(`dist/libs/${buildableLib}/package.json`);
|
||||||
expect(json.main).toEqual('./src/index.js');
|
expect(json.main).toEqual('./src/index.cjs');
|
||||||
expect(json.typings).toEqual('./src/index.d.ts');
|
expect(json.types).toEqual('./src/index.d.ts');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -308,6 +308,7 @@ export function newProject({
|
|||||||
`@nrwl/angular`,
|
`@nrwl/angular`,
|
||||||
`@nrwl/eslint-plugin-nx`,
|
`@nrwl/eslint-plugin-nx`,
|
||||||
`@nrwl/express`,
|
`@nrwl/express`,
|
||||||
|
`@nrwl/esbuild`,
|
||||||
`@nrwl/jest`,
|
`@nrwl/jest`,
|
||||||
`@nrwl/js`,
|
`@nrwl/js`,
|
||||||
`@nrwl/linter`,
|
`@nrwl/linter`,
|
||||||
|
|||||||
@ -153,6 +153,11 @@ describe('nx-dev: Packages Section', () => {
|
|||||||
{ title: '@nrwl/detox:build', path: '/packages/detox/executors/build' },
|
{ title: '@nrwl/detox:build', path: '/packages/detox/executors/build' },
|
||||||
{ title: '@nrwl/detox:test', path: '/packages/detox/executors/test' },
|
{ title: '@nrwl/detox:test', path: '/packages/detox/executors/test' },
|
||||||
{ title: '@nrwl/devkit', path: '/packages/devkit' },
|
{ title: '@nrwl/devkit', path: '/packages/devkit' },
|
||||||
|
{ title: '@nrwl/esbuild', path: '/packages/esbuild' },
|
||||||
|
{
|
||||||
|
title: '@nrwl/esbuild:esbuild',
|
||||||
|
path: '/packages/esbuild/executors/esbuild',
|
||||||
|
},
|
||||||
{ title: '@nrwl/eslint-plugin-nx', path: '/packages/eslint-plugin-nx' },
|
{ title: '@nrwl/eslint-plugin-nx', path: '/packages/eslint-plugin-nx' },
|
||||||
{ title: '@nrwl/express', path: '/packages/express' },
|
{ title: '@nrwl/express', path: '/packages/express' },
|
||||||
{ title: '@nrwl/express:init', path: '/packages/express/generators/init' },
|
{ title: '@nrwl/express:init', path: '/packages/express/generators/init' },
|
||||||
|
|||||||
4
nx-dev/nx-dev/public/images/icons/esbuild.svg
Normal file
4
nx-dev/nx-dev/public/images/icons/esbuild.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="100" cy="100" r="100" fill="#000"/>
|
||||||
|
<path d="M47.5 52.5L95 100l-47.5 47.5m60-95L155 100l-47.5 47.5" fill="none" stroke="#FFF" stroke-width="24"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 235 B |
@ -4,6 +4,7 @@ export const iconsMap: Record<string, string> = {
|
|||||||
cypress: '/images/icons/cypress.svg',
|
cypress: '/images/icons/cypress.svg',
|
||||||
detox: '/images/icons/react.svg',
|
detox: '/images/icons/react.svg',
|
||||||
devkit: '/images/icons/nx.svg',
|
devkit: '/images/icons/nx.svg',
|
||||||
|
esbuild: '/images/icons/esbuild.svg',
|
||||||
'eslint-plugin-nx': '/images/icons/eslint.svg',
|
'eslint-plugin-nx': '/images/icons/eslint.svg',
|
||||||
expo: '/images/icons/expo.svg',
|
expo: '/images/icons/expo.svg',
|
||||||
express: '/images/icons/express.svg',
|
express: '/images/icons/express.svg',
|
||||||
|
|||||||
25
packages/esbuild/.eslintrc.json
Normal file
25
packages/esbuild/.eslintrc.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"extends": ["../../.eslintrc.json"],
|
||||||
|
"ignorePatterns": ["!**/*"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["./package.json", "./generators.json", "./executors.json"],
|
||||||
|
"parser": "jsonc-eslint-parser",
|
||||||
|
"rules": {
|
||||||
|
"@nrwl/nx/nx-plugin-checks": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
13
packages/esbuild/README.md
Normal file
13
packages/esbuild/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<p style="text-align: center;"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx.png" width="600" alt="Nx - Smart, Fast and Extensible Build System"></p>
|
||||||
|
|
||||||
|
{{links}}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
# Nx: Smart, Fast and Extensible Build System
|
||||||
|
|
||||||
|
Nx is a next generation build system with first class monorepo support and powerful integrations.
|
||||||
|
|
||||||
|
This package is a [EsBuild plugin for Nx](https://nx.dev/packages/esbuild).
|
||||||
|
|
||||||
|
{{content}}
|
||||||
16
packages/esbuild/executors.json
Normal file
16
packages/esbuild/executors.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"builders": {
|
||||||
|
"esbuild": {
|
||||||
|
"implementation": "./src/executors/esbuild/compat",
|
||||||
|
"schema": "./src/executors/esbuild/schema.json",
|
||||||
|
"description": "Bundle a package using EsBuild."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"executors": {
|
||||||
|
"esbuild": {
|
||||||
|
"implementation": "./src/executors/esbuild/esbuild.impl",
|
||||||
|
"schema": "./src/executors/esbuild/schema.json",
|
||||||
|
"description": "Bundle a package using EsBuild."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
packages/esbuild/generators.json
Normal file
33
packages/esbuild/generators.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "Nx esbuild",
|
||||||
|
"version": "0.1",
|
||||||
|
"schematics": {
|
||||||
|
"init": {
|
||||||
|
"factory": "./src/generators/init/init#esbuildInitSchematic",
|
||||||
|
"schema": "./src/generators/init/schema.json",
|
||||||
|
"description": "Initialize the `@nrwl/esbuild` plugin.",
|
||||||
|
"hidden": true
|
||||||
|
},
|
||||||
|
"esbuild-project": {
|
||||||
|
"factory": "./src/generators/esbuild-project/esbuild-project#esbuildProjectSchematic",
|
||||||
|
"schema": "./src/generators/esbuild-project/schema.json",
|
||||||
|
"description": "Add esbuild configuration to a project.",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"generators": {
|
||||||
|
"init": {
|
||||||
|
"factory": "./src/generators/init/init#esbuildInitGenerator",
|
||||||
|
"schema": "./src/generators/init/schema.json",
|
||||||
|
"description": "Initialize the `@nrwl/esbuild` plugin.",
|
||||||
|
"aliases": ["ng-add"],
|
||||||
|
"hidden": true
|
||||||
|
},
|
||||||
|
"esbuild-project": {
|
||||||
|
"factory": "./src/generators/esbuild-project/esbuild-project#esbuildProjectGenerator",
|
||||||
|
"schema": "./src/generators/esbuild-project/schema.json",
|
||||||
|
"description": "Add esbuild configuration to a project.",
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
packages/esbuild/index.ts
Normal file
2
packages/esbuild/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './src/executors/esbuild/schema';
|
||||||
|
export * from './src/executors/esbuild/esbuild.impl';
|
||||||
11
packages/esbuild/jest.config.ts
Normal file
11
packages/esbuild/jest.config.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
export default {
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': 'ts-jest',
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
|
||||||
|
globals: { 'ts-jest': { tsconfig: '<rootDir>/tsconfig.spec.json' } },
|
||||||
|
displayName: 'esbuild',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
};
|
||||||
39
packages/esbuild/package.json
Normal file
39
packages/esbuild/package.json
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "@nrwl/esbuild",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "The Nx Plugin for EsBuild contains executors and generators that support building applications using EsBuild",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/nrwl/nx.git",
|
||||||
|
"directory": "packages/esbuild"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"Monorepo",
|
||||||
|
"EsBuild",
|
||||||
|
"Web",
|
||||||
|
"CLI"
|
||||||
|
],
|
||||||
|
"main": "./index.js",
|
||||||
|
"typings": "./index.d.ts",
|
||||||
|
"author": "Victor Savkin",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/nrwl/nx/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://nx.dev",
|
||||||
|
"schematics": "./generators.json",
|
||||||
|
"builders": "./executors.json",
|
||||||
|
"ng-update": {
|
||||||
|
"requirements": {},
|
||||||
|
"migrations": "./migrations.json"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nrwl/devkit": "file:../devkit",
|
||||||
|
"@nrwl/js": "file:../js",
|
||||||
|
"@nrwl/workspace": "file:../workspace",
|
||||||
|
"dotenv": "~10.0.0",
|
||||||
|
"esbuild": "^0.15.7",
|
||||||
|
"fs-extra": "^10.1.0",
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
87
packages/esbuild/project.json
Normal file
87
packages/esbuild/project.json
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "packages/esbuild",
|
||||||
|
"projectType": "library",
|
||||||
|
"targets": {
|
||||||
|
"test": {
|
||||||
|
"executor": "@nrwl/jest:jest",
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "packages/esbuild/jest.config.ts",
|
||||||
|
"passWithNoTests": true
|
||||||
|
},
|
||||||
|
"outputs": ["coverage/packages/esbuild"]
|
||||||
|
},
|
||||||
|
"build-base": {
|
||||||
|
"executor": "@nrwl/js:tsc",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "build/packages/esbuild",
|
||||||
|
"tsConfig": "packages/esbuild/tsconfig.lib.json",
|
||||||
|
"main": "packages/esbuild/index.ts",
|
||||||
|
"updateBuildableProjectDepsInPackageJson": false,
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"input": "packages/esbuild",
|
||||||
|
"glob": "**/files/**",
|
||||||
|
"output": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": "packages/esbuild",
|
||||||
|
"glob": "**/files/**/.gitkeep",
|
||||||
|
"output": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": "packages/esbuild",
|
||||||
|
"glob": "**/*.json",
|
||||||
|
"ignore": ["**/tsconfig*.json", "project.json", ".eslintrc.json"],
|
||||||
|
"output": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": "packages/esbuild",
|
||||||
|
"glob": "**/*.js",
|
||||||
|
"ignore": ["**/jest.config.js"],
|
||||||
|
"output": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": "packages/esbuild",
|
||||||
|
"glob": "**/*.d.ts",
|
||||||
|
"output": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": "",
|
||||||
|
"glob": "LICENSE",
|
||||||
|
"output": "/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"outputs": ["{options.outputPath}"]
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"executor": "nx:run-commands",
|
||||||
|
"outputs": ["build/packages/esbuild"],
|
||||||
|
"options": {
|
||||||
|
"command": "node ./scripts/copy-readme.js esbuild"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nrwl/linter:eslint",
|
||||||
|
"options": {
|
||||||
|
"lintFilePatterns": [
|
||||||
|
"packages/esbuild/**/*.ts",
|
||||||
|
"packages/esbuild/**/*.spec.ts",
|
||||||
|
"packages/esbuild/**/*_spec.ts",
|
||||||
|
"packages/esbuild/**/*.spec.tsx",
|
||||||
|
"packages/esbuild/**/*.spec.js",
|
||||||
|
"packages/esbuild/**/*.spec.jsx",
|
||||||
|
"packages/esbuild/**/*.d.ts",
|
||||||
|
"packages/esbuild/**/executors/**/schema.json",
|
||||||
|
"packages/esbuild/**/generators/**/schema.json",
|
||||||
|
"packages/esbuild/generators.json",
|
||||||
|
"packages/esbuild/executors.json",
|
||||||
|
"packages/esbuild/package.json",
|
||||||
|
"packages/esbuild/migrations.json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"outputs": ["{options.outputFile}"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
packages/esbuild/src/executors/esbuild/compat.ts
Normal file
5
packages/esbuild/src/executors/esbuild/compat.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { convertNxExecutor } from '@nrwl/devkit';
|
||||||
|
|
||||||
|
import esbuildExecutor from './esbuild.impl';
|
||||||
|
|
||||||
|
export default convertNxExecutor(esbuildExecutor);
|
||||||
192
packages/esbuild/src/executors/esbuild/esbuild.impl.ts
Normal file
192
packages/esbuild/src/executors/esbuild/esbuild.impl.ts
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
import 'dotenv/config';
|
||||||
|
import type { ExecutorContext } from '@nrwl/devkit';
|
||||||
|
import { cacheDir, joinPathFragments, logger } from '@nrwl/devkit';
|
||||||
|
import { parse } from 'path';
|
||||||
|
import {
|
||||||
|
copyAssets,
|
||||||
|
copyPackageJson,
|
||||||
|
printDiagnostics,
|
||||||
|
runTypeCheck,
|
||||||
|
TypeCheckOptions,
|
||||||
|
} from '@nrwl/js';
|
||||||
|
import * as esbuild from 'esbuild';
|
||||||
|
import { normalizeOptions } from './lib/normalize';
|
||||||
|
|
||||||
|
import { EsBuildExecutorOptions } from './schema';
|
||||||
|
import { removeSync, writeJsonSync } from 'fs-extra';
|
||||||
|
import { getClientEnvironment } from '../../utils/environment-variables';
|
||||||
|
import { createAsyncIterable } from '@nrwl/js/src/utils/create-async-iterable/create-async-iteratable';
|
||||||
|
|
||||||
|
export async function* esbuildExecutor(
|
||||||
|
_options: EsBuildExecutorOptions,
|
||||||
|
context: ExecutorContext
|
||||||
|
) {
|
||||||
|
const options = normalizeOptions(_options);
|
||||||
|
if (options.clean) removeSync(options.outputPath);
|
||||||
|
|
||||||
|
const assetsResult = await copyAssets(options, context);
|
||||||
|
|
||||||
|
const packageJsonResult = await copyPackageJson(
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
skipTypings: options.skipTypeCheck,
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
const esbuildOptions: esbuild.BuildOptions = {
|
||||||
|
entryPoints: [options.main],
|
||||||
|
bundle: true,
|
||||||
|
define: getClientEnvironment(),
|
||||||
|
external: options.external,
|
||||||
|
minify: options.minify,
|
||||||
|
platform: options.platform,
|
||||||
|
target: options.target,
|
||||||
|
metafile: options.metafile,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.watch) {
|
||||||
|
return yield* createAsyncIterable<{ success: boolean; outfile: string }>(
|
||||||
|
async ({ next, done }) => {
|
||||||
|
const results = await Promise.all(
|
||||||
|
options.format.map((format, idx) => {
|
||||||
|
const outfile = getOutfile(format, options, context);
|
||||||
|
return esbuild.build({
|
||||||
|
...esbuildOptions,
|
||||||
|
metafile: true, // Always include metafile so we can see what files have changed.
|
||||||
|
watch:
|
||||||
|
// Only emit info on one of the watch processes.
|
||||||
|
idx === 0
|
||||||
|
? {
|
||||||
|
onRebuild: (
|
||||||
|
error: esbuild.BuildFailure,
|
||||||
|
result: esbuild.BuildResult
|
||||||
|
) => {
|
||||||
|
if (error) {
|
||||||
|
logger.info(`[watch] build failed`);
|
||||||
|
} else if (result?.metafile) {
|
||||||
|
logger.info(
|
||||||
|
`[watch] build succeeded (change: "${
|
||||||
|
Object.keys(result.metafile?.inputs)[0]
|
||||||
|
}")`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
logger.info(`[watch] build succeeded`);
|
||||||
|
}
|
||||||
|
next({ success: !!error, outfile });
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: true,
|
||||||
|
format,
|
||||||
|
outfile,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.info(`[watch] build finished, watching for changes...`);
|
||||||
|
|
||||||
|
const processOnExit = () => {
|
||||||
|
assetsResult?.stop();
|
||||||
|
packageJsonResult?.stop();
|
||||||
|
results.forEach((r) => r?.stop());
|
||||||
|
done();
|
||||||
|
process.off('SIGINT', processOnExit);
|
||||||
|
process.off('SIGTERM', processOnExit);
|
||||||
|
process.off('exit', processOnExit);
|
||||||
|
};
|
||||||
|
|
||||||
|
process.on('SIGINT', processOnExit);
|
||||||
|
process.on('SIGTERM', processOnExit);
|
||||||
|
process.on('exit', processOnExit);
|
||||||
|
|
||||||
|
next({
|
||||||
|
success: results.every((r) => r.errors?.length === 0),
|
||||||
|
outfile: getOutfile(options.format[0], options, context),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const buildResults = await Promise.all(
|
||||||
|
options.format.map((format) =>
|
||||||
|
esbuild.build({
|
||||||
|
...esbuildOptions,
|
||||||
|
format,
|
||||||
|
outfile: getOutfile(format, options, context),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const buildSuccess = buildResults.every((r) => r.errors?.length === 0);
|
||||||
|
|
||||||
|
if (options.skipTypeCheck) {
|
||||||
|
return { success: buildSuccess };
|
||||||
|
}
|
||||||
|
|
||||||
|
const { errors, warnings } = await runTypeCheck(
|
||||||
|
getTypeCheckOptions(options, context)
|
||||||
|
);
|
||||||
|
const hasErrors = errors.length > 0;
|
||||||
|
const hasWarnings = warnings.length > 0;
|
||||||
|
|
||||||
|
if (hasErrors || hasWarnings) {
|
||||||
|
await printDiagnostics(errors, warnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.metafile) {
|
||||||
|
buildResults.forEach((r, idx) => {
|
||||||
|
const filename =
|
||||||
|
options.format.length === 1
|
||||||
|
? 'meta.json'
|
||||||
|
: `meta.${options.format[idx]}.json`;
|
||||||
|
writeJsonSync(
|
||||||
|
joinPathFragments(options.outputPath, filename),
|
||||||
|
r.metafile
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: buildSuccess && !hasErrors };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTypeCheckOptions(
|
||||||
|
options: EsBuildExecutorOptions,
|
||||||
|
context: ExecutorContext
|
||||||
|
) {
|
||||||
|
const root = context.root;
|
||||||
|
const projectRoot = context.workspace.projects[context.projectName].root;
|
||||||
|
const { watch, tsConfig, outputPath } = options;
|
||||||
|
|
||||||
|
const typeCheckOptions: TypeCheckOptions = {
|
||||||
|
mode: 'emitDeclarationOnly',
|
||||||
|
tsConfigPath: tsConfig,
|
||||||
|
outDir: outputPath,
|
||||||
|
workspaceRoot: root,
|
||||||
|
rootDir: projectRoot,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (watch) {
|
||||||
|
typeCheckOptions.incremental = true;
|
||||||
|
typeCheckOptions.cacheDir = cacheDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeCheckOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOutfile(
|
||||||
|
format: 'cjs' | 'esm',
|
||||||
|
options: EsBuildExecutorOptions,
|
||||||
|
context: ExecutorContext
|
||||||
|
) {
|
||||||
|
const candidate = joinPathFragments(
|
||||||
|
context.target.options.outputPath,
|
||||||
|
options.outputFileName
|
||||||
|
);
|
||||||
|
if (format === 'esm') {
|
||||||
|
return candidate;
|
||||||
|
} else {
|
||||||
|
const { dir, name } = parse(candidate);
|
||||||
|
return `${dir}/${name}.cjs`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default esbuildExecutor;
|
||||||
9
packages/esbuild/src/executors/esbuild/lib/normalize.ts
Normal file
9
packages/esbuild/src/executors/esbuild/lib/normalize.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { EsBuildExecutorOptions } from '../schema';
|
||||||
|
export function normalizeOptions(
|
||||||
|
options: EsBuildExecutorOptions
|
||||||
|
): EsBuildExecutorOptions {
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
outputFileName: options.outputFileName ?? 'main.js',
|
||||||
|
};
|
||||||
|
}
|
||||||
22
packages/esbuild/src/executors/esbuild/schema.d.ts
vendored
Normal file
22
packages/esbuild/src/executors/esbuild/schema.d.ts
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { AssetGlob } from '@nrwl/workspace/src/utilities/assets';
|
||||||
|
|
||||||
|
type Compiler = 'babel' | 'swc';
|
||||||
|
export interface EsBuildExecutorOptions {
|
||||||
|
outputPath: string;
|
||||||
|
tsConfig: string;
|
||||||
|
project: string;
|
||||||
|
main: string;
|
||||||
|
outputFileName?: string;
|
||||||
|
assets: AssetGlob[];
|
||||||
|
watch?: boolean;
|
||||||
|
clean?: boolean;
|
||||||
|
external?: string[];
|
||||||
|
format?: Array<'esm' | 'cjs'>;
|
||||||
|
metafile?: boolean;
|
||||||
|
minify?: boolean;
|
||||||
|
platform?: 'node' | 'browser' | 'neutral';
|
||||||
|
target?: string;
|
||||||
|
skipTypeCheck?: boolean;
|
||||||
|
updateBuildableProjectDepsInPackageJson?: boolean;
|
||||||
|
buildableProjectDepsInPackageJsonType?: 'dependencies' | 'peerDependencies';
|
||||||
|
}
|
||||||
144
packages/esbuild/src/executors/esbuild/schema.json
Normal file
144
packages/esbuild/src/executors/esbuild/schema.json
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
{
|
||||||
|
"title": "Web Library EsBuild Target (Experimental)",
|
||||||
|
"description": "Packages a library for different web usages (`UMD`, `ESM`, `CJS`).",
|
||||||
|
"cli": "nx",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"main": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The path to the entry file, relative to project.",
|
||||||
|
"alias": "entryFile",
|
||||||
|
"x-completion-type": "file",
|
||||||
|
"x-completion-glob": "**/*@(.js|.ts)"
|
||||||
|
},
|
||||||
|
"outputPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The output path of the generated files.",
|
||||||
|
"x-completion-type": "directory"
|
||||||
|
},
|
||||||
|
"outputFileName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the main output file. Defaults same basename as 'main' file."
|
||||||
|
},
|
||||||
|
"tsConfig": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The path to tsconfig file.",
|
||||||
|
"x-completion-type": "file",
|
||||||
|
"x-completion-glob": "tsconfig.*.json"
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The path to package.json file."
|
||||||
|
},
|
||||||
|
"format": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "List of module formats to output. Defaults to matching format from tsconfig (e.g. CJS for CommonJS, and ESM otherwise).",
|
||||||
|
"alias": "f",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["esm", "umd", "cjs"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"watch": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Enable re-building when files change.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"assets": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "List of static assets.",
|
||||||
|
"default": [],
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/assetPattern"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"clean": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Remove previous output before build.",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"external": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Mark one or more module as external. Can use * wildcards, such as '*.png'.",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"format": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Set the output format(s).",
|
||||||
|
"alias": "f",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["esm", "cjs"]
|
||||||
|
},
|
||||||
|
"default": ["esm"]
|
||||||
|
},
|
||||||
|
"metafile": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Generate a meta.json file in the output folder that includes metadata about the build. This file can be analyzed by other tools.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"minify": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Minifies outputs.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"platform": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Platform target for outputs.",
|
||||||
|
"enum": ["browser", "node", "neutral"],
|
||||||
|
"default": "node"
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The environment target for outputs.",
|
||||||
|
"default": "esnext"
|
||||||
|
},
|
||||||
|
"skipTypeCheck": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Skip type-checking via TypeScript. Skipping type-checking speeds up the build but type errors are not caught.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"updateBuildableProjectDepsInPackageJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Update buildable project dependencies in `package.json`.",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"buildableProjectDepsInPackageJsonType": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.",
|
||||||
|
"enum": ["dependencies", "peerDependencies"],
|
||||||
|
"default": "peerDependencies"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["tsConfig", "main", "outputPath"],
|
||||||
|
"definitions": {
|
||||||
|
"assetPattern": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"glob": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The pattern to match."
|
||||||
|
},
|
||||||
|
"input": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The input directory path in which to apply `glob`. Defaults to the project root."
|
||||||
|
},
|
||||||
|
"output": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Relative path within the output folder."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["glob", "input", "output"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
import type { Tree } from '@nrwl/devkit';
|
||||||
|
import {
|
||||||
|
convertNxGenerator,
|
||||||
|
formatFiles,
|
||||||
|
getImportPath,
|
||||||
|
getWorkspaceLayout,
|
||||||
|
joinPathFragments,
|
||||||
|
readProjectConfiguration,
|
||||||
|
updateProjectConfiguration,
|
||||||
|
writeJson,
|
||||||
|
} from '@nrwl/devkit';
|
||||||
|
|
||||||
|
import { esbuildInitGenerator } from '../init/init';
|
||||||
|
import { EsBuildExecutorOptions } from '../../executors/esbuild/schema';
|
||||||
|
import { EsBuildProjectSchema } from './schema';
|
||||||
|
|
||||||
|
export async function esbuildProjectGenerator(
|
||||||
|
tree: Tree,
|
||||||
|
options: EsBuildProjectSchema
|
||||||
|
) {
|
||||||
|
const task = await esbuildInitGenerator(tree, options);
|
||||||
|
checkForTargetConflicts(tree, options);
|
||||||
|
addBuildTarget(tree, options);
|
||||||
|
await formatFiles(tree);
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkForTargetConflicts(tree: Tree, options: EsBuildProjectSchema) {
|
||||||
|
const project = readProjectConfiguration(tree, options.project);
|
||||||
|
if (project.targets.build) {
|
||||||
|
throw new Error(`Project "${project.name}" already has a build target.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.devServer && project.targets.serve) {
|
||||||
|
throw new Error(`Project "${project.name}" already has a serve target.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addBuildTarget(tree: Tree, options: EsBuildProjectSchema) {
|
||||||
|
const project = readProjectConfiguration(tree, options.project);
|
||||||
|
const packageJsonPath = joinPathFragments(project.root, 'package.json');
|
||||||
|
|
||||||
|
if (!tree.exists(packageJsonPath)) {
|
||||||
|
const { npmScope } = getWorkspaceLayout(tree);
|
||||||
|
const importPath =
|
||||||
|
options.importPath || getImportPath(npmScope, options.project);
|
||||||
|
writeJson(tree, packageJsonPath, {
|
||||||
|
name: importPath,
|
||||||
|
version: '0.0.1',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const tsConfig =
|
||||||
|
options.tsConfig ?? joinPathFragments(project.root, 'tsconfig.lib.json');
|
||||||
|
|
||||||
|
const buildOptions: EsBuildExecutorOptions = {
|
||||||
|
main: options.main ?? joinPathFragments(project.root, 'src/main.ts'),
|
||||||
|
outputPath: joinPathFragments('dist', project.root),
|
||||||
|
outputFileName: 'main.js',
|
||||||
|
tsConfig,
|
||||||
|
project: `${project.root}/package.json`,
|
||||||
|
assets: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tree.exists(joinPathFragments(project.root, 'README.md'))) {
|
||||||
|
buildOptions.assets = [
|
||||||
|
{
|
||||||
|
glob: `${project.root}/README.md`,
|
||||||
|
input: '.',
|
||||||
|
output: '.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProjectConfiguration(tree, options.project, {
|
||||||
|
...project,
|
||||||
|
targets: {
|
||||||
|
...project.targets,
|
||||||
|
build: {
|
||||||
|
executor: '@nrwl/esbuild:esbuild',
|
||||||
|
outputs: ['{options.outputPath}'],
|
||||||
|
defaultConfiguration: 'production',
|
||||||
|
options: buildOptions,
|
||||||
|
configurations: {
|
||||||
|
production: {
|
||||||
|
optimization: true,
|
||||||
|
sourceMap: false,
|
||||||
|
namedChunks: false,
|
||||||
|
extractLicenses: true,
|
||||||
|
vendorChunk: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default esbuildProjectGenerator;
|
||||||
|
|
||||||
|
export const esbuildProjectSchematic = convertNxGenerator(
|
||||||
|
esbuildProjectGenerator
|
||||||
|
);
|
||||||
10
packages/esbuild/src/generators/esbuild-project/schema.d.ts
vendored
Normal file
10
packages/esbuild/src/generators/esbuild-project/schema.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export interface EsBuildProjectSchema {
|
||||||
|
project: string;
|
||||||
|
main?: string;
|
||||||
|
tsConfig?: string;
|
||||||
|
devServer?: boolean;
|
||||||
|
skipFormat?: boolean;
|
||||||
|
skipPackageJson?: boolean;
|
||||||
|
importPath?: string;
|
||||||
|
esbuildConfig?: string;
|
||||||
|
}
|
||||||
44
packages/esbuild/src/generators/esbuild-project/schema.json
Normal file
44
packages/esbuild/src/generators/esbuild-project/schema.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"$id": "NxEsBuildProject",
|
||||||
|
"cli": "nx",
|
||||||
|
"title": "Add EsBuild Configuration to a project",
|
||||||
|
"description": "Add EsBuild Configuration to a project.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the project.",
|
||||||
|
"$default": {
|
||||||
|
"$source": "argv",
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
"x-dropdown": "project",
|
||||||
|
"x-prompt": "What is the name of the project to set up a esbuild for?"
|
||||||
|
},
|
||||||
|
"main": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path relative to the workspace root for the main entry file. Defaults to '<projectRoot>/src/main.ts'.",
|
||||||
|
"alias": "entryFile"
|
||||||
|
},
|
||||||
|
"tsConfig": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path relative to the workspace root for the tsconfig file to build with. Defaults to '<projectRoot>/tsconfig.app.json'."
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"description": "Skip formatting files.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"skipPackageJson": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Do not add dependencies to `package.json`."
|
||||||
|
},
|
||||||
|
"importPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The library name used to import it, like `@myorg/my-awesome-lib`."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": []
|
||||||
|
}
|
||||||
16
packages/esbuild/src/generators/init/init.spec.ts
Normal file
16
packages/esbuild/src/generators/init/init.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Tree } from '@nrwl/devkit';
|
||||||
|
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||||
|
|
||||||
|
import { esbuildInitGenerator } from './init';
|
||||||
|
|
||||||
|
describe('esbuildInitGenerator', () => {
|
||||||
|
let tree: Tree;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tree = createTreeWithEmptyWorkspace();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run successfully', async () => {
|
||||||
|
await expect(esbuildInitGenerator(tree, {})).resolves.not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
15
packages/esbuild/src/generators/init/init.ts
Normal file
15
packages/esbuild/src/generators/init/init.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { convertNxGenerator, formatFiles, Tree } from '@nrwl/devkit';
|
||||||
|
import { Schema } from './schema';
|
||||||
|
|
||||||
|
export async function esbuildInitGenerator(tree: Tree, schema: Schema) {
|
||||||
|
/*
|
||||||
|
* Empty for now, might need to add setup files later.
|
||||||
|
*/
|
||||||
|
if (!schema.skipFormat) {
|
||||||
|
await formatFiles(tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default esbuildInitGenerator;
|
||||||
|
|
||||||
|
export const esbuildInitSchematic = convertNxGenerator(esbuildInitGenerator);
|
||||||
4
packages/esbuild/src/generators/init/schema.d.ts
vendored
Normal file
4
packages/esbuild/src/generators/init/schema.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface Schema {
|
||||||
|
compiler?: 'babel' | 'swc' | 'tsc';
|
||||||
|
skipFormat?: boolean;
|
||||||
|
}
|
||||||
22
packages/esbuild/src/generators/init/schema.json
Normal file
22
packages/esbuild/src/generators/init/schema.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"$id": "NxWebpackInit",
|
||||||
|
"cli": "nx",
|
||||||
|
"title": "Init Webpack Plugin",
|
||||||
|
"description": "Init Webpack Plugin.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"compiler": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["babel", "swc", "tsc"],
|
||||||
|
"description": "The compiler to initialize for.",
|
||||||
|
"default": "babel"
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"description": "Skip formatting files.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": []
|
||||||
|
}
|
||||||
10
packages/esbuild/src/utils/environment-variables.ts
Normal file
10
packages/esbuild/src/utils/environment-variables.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export function getClientEnvironment(): Record<string, string> {
|
||||||
|
const NX_APP = /^NX_/i;
|
||||||
|
|
||||||
|
return Object.keys(process.env)
|
||||||
|
.filter((key) => NX_APP.test(key) || key === 'NODE_ENV')
|
||||||
|
.reduce((env, key) => {
|
||||||
|
env[`process.env.${key}`] = JSON.stringify(process.env[key]);
|
||||||
|
return env;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
14
packages/esbuild/src/utils/fs.ts
Normal file
14
packages/esbuild/src/utils/fs.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import { removeSync } from 'fs-extra';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an output directory, but error out if it's the root of the project.
|
||||||
|
*/
|
||||||
|
export function deleteOutputDir(root: string, outputPath: string) {
|
||||||
|
const resolvedOutputPath = path.resolve(root, outputPath);
|
||||||
|
if (resolvedOutputPath === root) {
|
||||||
|
throw new Error('Output path MUST not be project root directory!');
|
||||||
|
}
|
||||||
|
|
||||||
|
removeSync(resolvedOutputPath);
|
||||||
|
}
|
||||||
5
packages/esbuild/src/utils/versions.ts
Normal file
5
packages/esbuild/src/utils/versions.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export const nxVersion = require('../../package.json').version;
|
||||||
|
|
||||||
|
export const swcLoaderVersion = '0.1.15';
|
||||||
|
export const swcHelpersVersion = '~0.3.3';
|
||||||
|
export const tsLibVersion = '^2.3.0';
|
||||||
16
packages/esbuild/tsconfig.json
Normal file
16
packages/esbuild/tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs"
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
10
packages/esbuild/tsconfig.lib.json
Normal file
10
packages/esbuild/tsconfig.lib.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"declaration": true,
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"include": ["**/*.ts"],
|
||||||
|
"exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"]
|
||||||
|
}
|
||||||
9
packages/esbuild/tsconfig.spec.json
Normal file
9
packages/esbuild/tsconfig.spec.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
},
|
||||||
|
"include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
|
||||||
|
}
|
||||||
@ -1,9 +1,8 @@
|
|||||||
import { ExecutorContext, ProjectGraphProjectNode } from '@nrwl/devkit';
|
import { ExecutorContext } from '@nrwl/devkit';
|
||||||
import {
|
import {
|
||||||
assetGlobsToFiles,
|
assetGlobsToFiles,
|
||||||
FileInputOutput,
|
FileInputOutput,
|
||||||
} from '@nrwl/workspace/src/utilities/assets';
|
} from '@nrwl/workspace/src/utilities/assets';
|
||||||
import { DependentBuildableProjectNode } from '@nrwl/workspace/src/utilities/buildable-libs-utils';
|
|
||||||
import { join, relative, resolve } from 'path';
|
import { join, relative, resolve } from 'path';
|
||||||
|
|
||||||
import { checkDependencies } from '../../utils/check-dependencies';
|
import { checkDependencies } from '../../utils/check-dependencies';
|
||||||
@ -11,15 +10,14 @@ import {
|
|||||||
getHelperDependency,
|
getHelperDependency,
|
||||||
HelperDependency,
|
HelperDependency,
|
||||||
} from '../../utils/compiler-helper-dependency';
|
} from '../../utils/compiler-helper-dependency';
|
||||||
import { CopyAssetsHandler } from '../../utils/copy-assets-handler';
|
|
||||||
import {
|
import {
|
||||||
NormalizedSwcExecutorOptions,
|
NormalizedSwcExecutorOptions,
|
||||||
SwcExecutorOptions,
|
SwcExecutorOptions,
|
||||||
} from '../../utils/schema';
|
} from '../../utils/schema';
|
||||||
import { compileSwc, compileSwcWatch } from '../../utils/swc/compile-swc';
|
import { compileSwc, compileSwcWatch } from '../../utils/swc/compile-swc';
|
||||||
import { getSwcrcPath } from '../../utils/swc/get-swcrc-path';
|
import { getSwcrcPath } from '../../utils/swc/get-swcrc-path';
|
||||||
import { updatePackageJson } from '../../utils/update-package-json';
|
import { copyAssets } from '../../utils/assets';
|
||||||
import { watchForSingleFileChanges } from '../../utils/watch-for-single-file-changes';
|
import { copyPackageJson } from '../../utils/package-json';
|
||||||
|
|
||||||
export function normalizeOptions(
|
export function normalizeOptions(
|
||||||
options: SwcExecutorOptions,
|
options: SwcExecutorOptions,
|
||||||
@ -75,32 +73,13 @@ export function normalizeOptions(
|
|||||||
} as NormalizedSwcExecutorOptions;
|
} as NormalizedSwcExecutorOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
function processAssetsAndPackageJsonOnce(
|
|
||||||
assetHandler: CopyAssetsHandler,
|
|
||||||
options: NormalizedSwcExecutorOptions,
|
|
||||||
context: ExecutorContext,
|
|
||||||
target: ProjectGraphProjectNode<any>,
|
|
||||||
dependencies: DependentBuildableProjectNode[]
|
|
||||||
) {
|
|
||||||
return async () => {
|
|
||||||
await assetHandler.processAllAssetsOnce();
|
|
||||||
updatePackageJson(
|
|
||||||
options,
|
|
||||||
context,
|
|
||||||
target,
|
|
||||||
dependencies,
|
|
||||||
!options.skipTypeCheck
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function* swcExecutor(
|
export async function* swcExecutor(
|
||||||
_options: SwcExecutorOptions,
|
_options: SwcExecutorOptions,
|
||||||
context: ExecutorContext
|
context: ExecutorContext
|
||||||
) {
|
) {
|
||||||
const { sourceRoot, root } = context.workspace.projects[context.projectName];
|
const { sourceRoot, root } = context.workspace.projects[context.projectName];
|
||||||
const options = normalizeOptions(_options, context.root, sourceRoot, root);
|
const options = normalizeOptions(_options, context.root, sourceRoot, root);
|
||||||
const { tmpTsConfig, projectRoot, target, dependencies } = checkDependencies(
|
const { tmpTsConfig, dependencies } = checkDependencies(
|
||||||
context,
|
context,
|
||||||
options.tsConfig
|
options.tsConfig
|
||||||
);
|
);
|
||||||
@ -120,58 +99,38 @@ export async function* swcExecutor(
|
|||||||
dependencies.push(swcHelperDependency);
|
dependencies.push(swcHelperDependency);
|
||||||
}
|
}
|
||||||
|
|
||||||
const assetHandler = new CopyAssetsHandler({
|
|
||||||
projectDir: projectRoot,
|
|
||||||
rootDir: context.root,
|
|
||||||
outputDir: options.outputPath,
|
|
||||||
assets: options.assets,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.watch) {
|
if (options.watch) {
|
||||||
const disposeWatchAssetChanges =
|
let disposeFn: () => void;
|
||||||
await assetHandler.watchAndProcessOnAssetChange();
|
process.on('SIGINT', () => disposeFn());
|
||||||
const disposePackageJsonChanges = await watchForSingleFileChanges(
|
process.on('SIGTERM', () => disposeFn());
|
||||||
join(context.root, projectRoot),
|
|
||||||
'package.json',
|
|
||||||
() =>
|
|
||||||
updatePackageJson(
|
|
||||||
options,
|
|
||||||
context,
|
|
||||||
target,
|
|
||||||
dependencies,
|
|
||||||
!options.skipTypeCheck
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const handleTermination = async () => {
|
|
||||||
await disposeWatchAssetChanges();
|
|
||||||
await disposePackageJsonChanges();
|
|
||||||
};
|
|
||||||
process.on('SIGINT', () => handleTermination());
|
|
||||||
process.on('SIGTERM', () => handleTermination());
|
|
||||||
|
|
||||||
return yield* compileSwcWatch(
|
return yield* compileSwcWatch(context, options, async () => {
|
||||||
context,
|
const assetResult = await copyAssets(options, context);
|
||||||
options,
|
const packageJsonResult = await copyPackageJson(
|
||||||
processAssetsAndPackageJsonOnce(
|
{
|
||||||
assetHandler,
|
...options,
|
||||||
options,
|
skipTypings: !options.skipTypeCheck,
|
||||||
context,
|
},
|
||||||
target,
|
context
|
||||||
dependencies
|
);
|
||||||
)
|
disposeFn = () => {
|
||||||
);
|
assetResult?.stop();
|
||||||
|
packageJsonResult?.stop();
|
||||||
|
};
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return yield compileSwc(
|
return yield compileSwc(context, options, async () => {
|
||||||
context,
|
await copyAssets(options, context);
|
||||||
options,
|
await copyPackageJson(
|
||||||
processAssetsAndPackageJsonOnce(
|
{
|
||||||
assetHandler,
|
...options,
|
||||||
options,
|
generateExportsField: true,
|
||||||
context,
|
skipTypings: !options.skipTypeCheck,
|
||||||
target,
|
extraDependencies: swcHelperDependency ? [swcHelperDependency] : [],
|
||||||
dependencies
|
},
|
||||||
)
|
context
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,11 +16,11 @@ import {
|
|||||||
getHelperDependency,
|
getHelperDependency,
|
||||||
HelperDependency,
|
HelperDependency,
|
||||||
} from '../../utils/compiler-helper-dependency';
|
} from '../../utils/compiler-helper-dependency';
|
||||||
import { CopyAssetsHandler } from '../../utils/copy-assets-handler';
|
import { CopyAssetsHandler } from '../../utils/assets/copy-assets-handler';
|
||||||
import { ExecutorOptions, NormalizedExecutorOptions } from '../../utils/schema';
|
import { ExecutorOptions, NormalizedExecutorOptions } from '../../utils/schema';
|
||||||
import { compileTypeScriptFiles } from '../../utils/typescript/compile-typescript-files';
|
import { compileTypeScriptFiles } from '../../utils/typescript/compile-typescript-files';
|
||||||
import { loadTsTransformers } from '../../utils/typescript/load-ts-transformers';
|
import { loadTsTransformers } from '../../utils/typescript/load-ts-transformers';
|
||||||
import { updatePackageJson } from '../../utils/update-package-json';
|
import { updatePackageJson } from '../../utils/package-json/update-package-json';
|
||||||
import { watchForSingleFileChanges } from '../../utils/watch-for-single-file-changes';
|
import { watchForSingleFileChanges } from '../../utils/watch-for-single-file-changes';
|
||||||
|
|
||||||
export function normalizeOptions(
|
export function normalizeOptions(
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
addDependenciesToPackageJson,
|
||||||
addProjectConfiguration,
|
addProjectConfiguration,
|
||||||
convertNxGenerator,
|
convertNxGenerator,
|
||||||
formatFiles,
|
formatFiles,
|
||||||
@ -9,10 +10,10 @@ import {
|
|||||||
names,
|
names,
|
||||||
offsetFromRoot,
|
offsetFromRoot,
|
||||||
ProjectConfiguration,
|
ProjectConfiguration,
|
||||||
|
readJson,
|
||||||
toJS,
|
toJS,
|
||||||
Tree,
|
Tree,
|
||||||
updateJson,
|
updateJson,
|
||||||
readJson,
|
|
||||||
writeJson,
|
writeJson,
|
||||||
} from '@nrwl/devkit';
|
} from '@nrwl/devkit';
|
||||||
import { getImportPath } from 'nx/src/utils/path';
|
import { getImportPath } from 'nx/src/utils/path';
|
||||||
@ -28,6 +29,7 @@ import { addMinimalPublishScript } from '../../utils/minimal-publish-script';
|
|||||||
import { LibraryGeneratorSchema } from '../../utils/schema';
|
import { LibraryGeneratorSchema } from '../../utils/schema';
|
||||||
import { addSwcConfig } from '../../utils/swc/add-swc-config';
|
import { addSwcConfig } from '../../utils/swc/add-swc-config';
|
||||||
import { addSwcDependencies } from '../../utils/swc/add-swc-dependencies';
|
import { addSwcDependencies } from '../../utils/swc/add-swc-dependencies';
|
||||||
|
import { nxVersion } from '../../utils/versions';
|
||||||
|
|
||||||
export async function libraryGenerator(
|
export async function libraryGenerator(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
@ -43,18 +45,19 @@ export async function projectGenerator(
|
|||||||
destinationDir: string,
|
destinationDir: string,
|
||||||
filesDir: string
|
filesDir: string
|
||||||
) {
|
) {
|
||||||
|
const tasks: GeneratorCallback[] = [];
|
||||||
const options = normalizeOptions(tree, schema, destinationDir);
|
const options = normalizeOptions(tree, schema, destinationDir);
|
||||||
|
|
||||||
createFiles(tree, options, `${filesDir}/lib`);
|
createFiles(tree, options, `${filesDir}/lib`);
|
||||||
|
|
||||||
addProject(tree, options, destinationDir);
|
addProject(tree, options, destinationDir);
|
||||||
|
|
||||||
|
// tasks.push(addProjectDependencies(tree, options));
|
||||||
|
|
||||||
if (!schema.skipTsConfig) {
|
if (!schema.skipTsConfig) {
|
||||||
updateRootTsConfig(tree, options);
|
updateRootTsConfig(tree, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tasks: GeneratorCallback[] = [];
|
|
||||||
|
|
||||||
if (options.linter !== 'none') {
|
if (options.linter !== 'none') {
|
||||||
const lintCallback = await addLint(tree, options);
|
const lintCallback = await addLint(tree, options);
|
||||||
tasks.push(lintCallback);
|
tasks.push(lintCallback);
|
||||||
@ -99,7 +102,7 @@ function addProject(
|
|||||||
if (options.buildable && options.config !== 'npm-scripts') {
|
if (options.buildable && options.config !== 'npm-scripts') {
|
||||||
const outputPath = `dist/${destinationDir}/${options.projectDirectory}`;
|
const outputPath = `dist/${destinationDir}/${options.projectDirectory}`;
|
||||||
projectConfiguration.targets.build = {
|
projectConfiguration.targets.build = {
|
||||||
executor: `@nrwl/js:${options.compiler}`,
|
executor: getBuildExecutor(options),
|
||||||
outputs: ['{options.outputPath}'],
|
outputs: ['{options.outputPath}'],
|
||||||
options: {
|
options: {
|
||||||
outputPath,
|
outputPath,
|
||||||
@ -408,5 +411,50 @@ function updateRootTsConfig(host: Tree, options: NormalizedSchema) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addProjectDependencies(
|
||||||
|
tree: Tree,
|
||||||
|
options: NormalizedSchema
|
||||||
|
): GeneratorCallback {
|
||||||
|
if (options.bundler == 'esbuild') {
|
||||||
|
return addDependenciesToPackageJson(
|
||||||
|
tree,
|
||||||
|
{},
|
||||||
|
{ '@nrwl/esbuild': nxVersion }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.bundler == 'rollup') {
|
||||||
|
return addDependenciesToPackageJson(
|
||||||
|
tree,
|
||||||
|
{},
|
||||||
|
{ '@nrwl/rollup': nxVersion }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.bundler == 'webpack') {
|
||||||
|
return addDependenciesToPackageJson(
|
||||||
|
tree,
|
||||||
|
{},
|
||||||
|
{ '@nrwl/webpack': nxVersion }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// noop
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBuildExecutor(options: NormalizedSchema) {
|
||||||
|
switch (options.bundler) {
|
||||||
|
case 'esbuild':
|
||||||
|
return `@nrwl/esbuild:esbuild`;
|
||||||
|
case 'rollup':
|
||||||
|
return `@nrwl/rollup:rollup`;
|
||||||
|
case 'webpack':
|
||||||
|
return `@nrwl/webpack:webpack`;
|
||||||
|
default:
|
||||||
|
return `@nrwl/js:${options.compiler}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default libraryGenerator;
|
export default libraryGenerator;
|
||||||
export const librarySchematic = convertNxGenerator(libraryGenerator);
|
export const librarySchematic = convertNxGenerator(libraryGenerator);
|
||||||
|
|||||||
@ -109,6 +109,11 @@
|
|||||||
"default": "tsc",
|
"default": "tsc",
|
||||||
"description": "The compiler used by the build and test targets"
|
"description": "The compiler used by the build and test targets"
|
||||||
},
|
},
|
||||||
|
"bundler": {
|
||||||
|
"description": "The bundler to use.",
|
||||||
|
"enum": ["none", "esbuild", "rollup", "webpack"],
|
||||||
|
"default": "none"
|
||||||
|
},
|
||||||
"skipTypeCheck": {
|
"skipTypeCheck": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether to skip TypeScript type checking for SWC compiler.",
|
"description": "Whether to skip TypeScript type checking for SWC compiler.",
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
export * from './utils/typescript/load-ts-transformers';
|
export * from './utils/typescript/load-ts-transformers';
|
||||||
export * from './utils/typescript/print-diagnostics';
|
export * from './utils/typescript/print-diagnostics';
|
||||||
export * from './utils/typescript/run-type-check';
|
export * from './utils/typescript/run-type-check';
|
||||||
|
export * from './utils/package-json';
|
||||||
|
export * from './utils/assets';
|
||||||
|
export * from './utils/package-json/update-package-json';
|
||||||
export { libraryGenerator } from './generators/library/library';
|
export { libraryGenerator } from './generators/library/library';
|
||||||
|
|||||||
47
packages/js/src/utils/assets/index.ts
Normal file
47
packages/js/src/utils/assets/index.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { AssetGlob } from '@nrwl/workspace/src/utilities/assets';
|
||||||
|
import { CopyAssetsHandler, FileEvent } from './copy-assets-handler';
|
||||||
|
import { ExecutorContext } from '@nrwl/devkit';
|
||||||
|
|
||||||
|
export interface CopyAssetsOptions {
|
||||||
|
outputPath: string;
|
||||||
|
assets: (string | AssetGlob)[];
|
||||||
|
watch?: boolean | WatchMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CopyAssetsResult {
|
||||||
|
success?: boolean;
|
||||||
|
// Only when "watch: true"
|
||||||
|
stop?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WatchMode {
|
||||||
|
onCopy?: (events: FileEvent[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function copyAssets(
|
||||||
|
options: CopyAssetsOptions,
|
||||||
|
context: ExecutorContext
|
||||||
|
): Promise<CopyAssetsResult> {
|
||||||
|
const assetHandler = new CopyAssetsHandler({
|
||||||
|
projectDir: context.workspace.projects[context.projectName].root,
|
||||||
|
rootDir: context.root,
|
||||||
|
outputDir: options.outputPath,
|
||||||
|
assets: options.assets,
|
||||||
|
callback:
|
||||||
|
typeof options?.watch === 'object' ? options.watch.onCopy : undefined,
|
||||||
|
});
|
||||||
|
if (options.watch) {
|
||||||
|
const dispose = await assetHandler.watchAndProcessOnAssetChange();
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
stop: dispose,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await assetHandler.processAllAssetsOnce();
|
||||||
|
} catch {
|
||||||
|
return { success: false };
|
||||||
|
}
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
52
packages/js/src/utils/package-json/index.ts
Normal file
52
packages/js/src/utils/package-json/index.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { join } from 'path';
|
||||||
|
import { ExecutorContext } from '@nrwl/devkit';
|
||||||
|
import { DependentBuildableProjectNode } from '@nrwl/workspace/src/utilities/buildable-libs-utils';
|
||||||
|
|
||||||
|
import { watchForSingleFileChanges } from '../watch-for-single-file-changes';
|
||||||
|
import type { UpdatePackageJsonOption } from './update-package-json';
|
||||||
|
import { updatePackageJson } from './update-package-json';
|
||||||
|
import { checkDependencies } from '../check-dependencies';
|
||||||
|
|
||||||
|
export interface CopyPackageJsonOptions
|
||||||
|
extends Omit<UpdatePackageJsonOption, 'projectRoot'> {
|
||||||
|
watch?: boolean;
|
||||||
|
extraDependencies?: DependentBuildableProjectNode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CopyPackageJsonResult {
|
||||||
|
success?: boolean;
|
||||||
|
// Only when "watch: true"
|
||||||
|
stop?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function copyPackageJson(
|
||||||
|
_options: CopyPackageJsonOptions,
|
||||||
|
context: ExecutorContext
|
||||||
|
): Promise<CopyPackageJsonResult> {
|
||||||
|
if (!context.target.options.tsConfig) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not find tsConfig option for "${context.targetName}" target of "${context.projectName}" project. Check that your project configuration is correct.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const { target, dependencies, projectRoot } = checkDependencies(
|
||||||
|
context,
|
||||||
|
context.target.options.tsConfig
|
||||||
|
);
|
||||||
|
const options = { ..._options, projectRoot };
|
||||||
|
if (options.extraDependencies?.length) {
|
||||||
|
dependencies.push(...options.extraDependencies);
|
||||||
|
}
|
||||||
|
if (options.watch) {
|
||||||
|
const dispose = await watchForSingleFileChanges(
|
||||||
|
join(context.root, projectRoot),
|
||||||
|
'package.json',
|
||||||
|
() => updatePackageJson(options, context, target, dependencies)
|
||||||
|
);
|
||||||
|
// Copy it once before changes
|
||||||
|
updatePackageJson(options, context, target, dependencies);
|
||||||
|
return { success: true, stop: dispose };
|
||||||
|
} else {
|
||||||
|
updatePackageJson(options, context, target, dependencies);
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
119
packages/js/src/utils/package-json/update-package-json.spec.ts
Normal file
119
packages/js/src/utils/package-json/update-package-json.spec.ts
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import { getUpdatedPackageJsonContent } from './update-package-json';
|
||||||
|
|
||||||
|
describe('getUpdatedPackageJsonContent', () => {
|
||||||
|
it('should update fields for commonjs only (default)', () => {
|
||||||
|
const json = getUpdatedPackageJsonContent(
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
version: '0.0.1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
main: 'proj/src/index.ts',
|
||||||
|
outputPath: 'dist/proj',
|
||||||
|
projectRoot: 'proj',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(json).toEqual({
|
||||||
|
name: 'test',
|
||||||
|
main: './src/index.cjs',
|
||||||
|
types: './src/index.d.ts',
|
||||||
|
version: '0.0.1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update fields for esm only', () => {
|
||||||
|
const json = getUpdatedPackageJsonContent(
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
version: '0.0.1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
main: 'proj/src/index.ts',
|
||||||
|
outputPath: 'dist/proj',
|
||||||
|
projectRoot: 'proj',
|
||||||
|
format: ['esm'],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(json).toEqual({
|
||||||
|
name: 'test',
|
||||||
|
type: 'module',
|
||||||
|
module: './src/index.js',
|
||||||
|
main: './src/index.js',
|
||||||
|
types: './src/index.d.ts',
|
||||||
|
version: '0.0.1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update fields for commonjs + esm', () => {
|
||||||
|
const json = getUpdatedPackageJsonContent(
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
version: '0.0.1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
main: 'proj/src/index.ts',
|
||||||
|
outputPath: 'dist/proj',
|
||||||
|
projectRoot: 'proj',
|
||||||
|
format: ['esm', 'cjs'],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(json).toEqual({
|
||||||
|
name: 'test',
|
||||||
|
main: './src/index.cjs',
|
||||||
|
module: './src/index.js',
|
||||||
|
types: './src/index.d.ts',
|
||||||
|
version: '0.0.1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support skipping types', () => {
|
||||||
|
const json = getUpdatedPackageJsonContent(
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
version: '0.0.1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
main: 'proj/src/index.ts',
|
||||||
|
outputPath: 'dist/proj',
|
||||||
|
projectRoot: 'proj',
|
||||||
|
skipTypings: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(json).toEqual({
|
||||||
|
name: 'test',
|
||||||
|
main: './src/index.cjs',
|
||||||
|
version: '0.0.1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support generated exports field', () => {
|
||||||
|
const json = getUpdatedPackageJsonContent(
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
version: '0.0.1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
main: 'proj/src/index.ts',
|
||||||
|
outputPath: 'dist/proj',
|
||||||
|
projectRoot: 'proj',
|
||||||
|
format: ['esm', 'cjs'],
|
||||||
|
generateExportsField: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(json).toEqual({
|
||||||
|
name: 'test',
|
||||||
|
module: './src/index.js',
|
||||||
|
main: './src/index.cjs',
|
||||||
|
types: './src/index.d.ts',
|
||||||
|
version: '0.0.1',
|
||||||
|
exports: {
|
||||||
|
'.': { require: './src/index.cjs', import: './src/index.js' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
124
packages/js/src/utils/package-json/update-package-json.ts
Normal file
124
packages/js/src/utils/package-json/update-package-json.ts
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import {
|
||||||
|
ExecutorContext,
|
||||||
|
normalizePath,
|
||||||
|
ProjectGraphProjectNode,
|
||||||
|
readJsonFile,
|
||||||
|
writeJsonFile,
|
||||||
|
} from '@nrwl/devkit';
|
||||||
|
import {
|
||||||
|
DependentBuildableProjectNode,
|
||||||
|
updateBuildableProjectPackageJsonDependencies,
|
||||||
|
} from '@nrwl/workspace/src/utilities/buildable-libs-utils';
|
||||||
|
import { basename, dirname, join, parse, relative } from 'path';
|
||||||
|
import { fileExists } from 'nx/src/utils/fileutils';
|
||||||
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
||||||
|
|
||||||
|
function getMainFileDirRelativeToProjectRoot(
|
||||||
|
main: string,
|
||||||
|
projectRoot: string
|
||||||
|
): string {
|
||||||
|
const mainFileDir = dirname(main);
|
||||||
|
const relativeDir = normalizePath(relative(projectRoot, mainFileDir));
|
||||||
|
return relativeDir === '' ? `./` : `./${relativeDir}/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdatePackageJsonOption {
|
||||||
|
projectRoot: string;
|
||||||
|
outputPath: string;
|
||||||
|
main: string;
|
||||||
|
format?: string[];
|
||||||
|
skipTypings?: boolean;
|
||||||
|
outputFileName?: string;
|
||||||
|
generateExportsField?: boolean;
|
||||||
|
updateBuildableProjectDepsInPackageJson?: boolean;
|
||||||
|
buildableProjectDepsInPackageJsonType?: 'dependencies' | 'peerDependencies';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updatePackageJson(
|
||||||
|
options: UpdatePackageJsonOption,
|
||||||
|
context: ExecutorContext,
|
||||||
|
target: ProjectGraphProjectNode,
|
||||||
|
dependencies: DependentBuildableProjectNode[]
|
||||||
|
): void {
|
||||||
|
const pathToPackageJson = join(
|
||||||
|
context.root,
|
||||||
|
options.projectRoot,
|
||||||
|
'package.json'
|
||||||
|
);
|
||||||
|
|
||||||
|
const packageJson = fileExists(pathToPackageJson)
|
||||||
|
? readJsonFile(pathToPackageJson)
|
||||||
|
: { name: context.projectName };
|
||||||
|
|
||||||
|
writeJsonFile(
|
||||||
|
`${options.outputPath}/package.json`,
|
||||||
|
getUpdatedPackageJsonContent(packageJson, options)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
dependencies.length > 0 &&
|
||||||
|
options.updateBuildableProjectDepsInPackageJson
|
||||||
|
) {
|
||||||
|
updateBuildableProjectPackageJsonDependencies(
|
||||||
|
context.root,
|
||||||
|
context.projectName,
|
||||||
|
context.targetName,
|
||||||
|
context.configurationName,
|
||||||
|
target,
|
||||||
|
dependencies,
|
||||||
|
options.buildableProjectDepsInPackageJsonType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUpdatedPackageJsonContent(
|
||||||
|
packageJson: PackageJson,
|
||||||
|
options: UpdatePackageJsonOption
|
||||||
|
) {
|
||||||
|
// Default is CJS unless esm is explicitly passed.
|
||||||
|
const hasCjsFormat = !options.format || options.format?.includes('cjs');
|
||||||
|
const hasEsmFormat = options.format?.includes('esm');
|
||||||
|
|
||||||
|
const mainFile = basename(options.main).replace(/\.[tj]s$/, '');
|
||||||
|
const relativeMainFileDir = getMainFileDirRelativeToProjectRoot(
|
||||||
|
options.main,
|
||||||
|
options.projectRoot
|
||||||
|
);
|
||||||
|
const typingsFile = `${relativeMainFileDir}${mainFile}.d.ts`;
|
||||||
|
const exports = {
|
||||||
|
'.': {},
|
||||||
|
...packageJson.exports,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mainJsFile =
|
||||||
|
options.outputFileName ?? `${relativeMainFileDir}${mainFile}.js`;
|
||||||
|
|
||||||
|
if (hasEsmFormat) {
|
||||||
|
// Unofficial field for backwards compat.
|
||||||
|
packageJson.module ??= mainJsFile;
|
||||||
|
|
||||||
|
if (!hasCjsFormat) {
|
||||||
|
packageJson.type = 'module';
|
||||||
|
packageJson.main ??= mainJsFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports['.']['import'] = mainJsFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCjsFormat) {
|
||||||
|
const { dir, name } = parse(mainJsFile);
|
||||||
|
const cjsMain = `${dir}/${name}.cjs`;
|
||||||
|
packageJson.main ??= cjsMain;
|
||||||
|
exports['.']['require'] = cjsMain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.generateExportsField) {
|
||||||
|
packageJson.exports = exports;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.skipTypings) {
|
||||||
|
packageJson.types = packageJson.types ?? typingsFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return packageJson;
|
||||||
|
}
|
||||||
4
packages/js/src/utils/schema.d.ts
vendored
4
packages/js/src/utils/schema.d.ts
vendored
@ -7,6 +7,7 @@ import type {
|
|||||||
import { TransformerEntry } from './typescript/types';
|
import { TransformerEntry } from './typescript/types';
|
||||||
|
|
||||||
export type Compiler = 'tsc' | 'swc';
|
export type Compiler = 'tsc' | 'swc';
|
||||||
|
export type Bundler = 'none' | 'rollup' | 'esbuild' | 'webpack';
|
||||||
|
|
||||||
export interface LibraryGeneratorSchema {
|
export interface LibraryGeneratorSchema {
|
||||||
name: string;
|
name: string;
|
||||||
@ -28,6 +29,7 @@ export interface LibraryGeneratorSchema {
|
|||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
config?: 'workspace' | 'project' | 'npm-scripts';
|
config?: 'workspace' | 'project' | 'npm-scripts';
|
||||||
compiler?: Compiler;
|
compiler?: Compiler;
|
||||||
|
bundler?: Bundler;
|
||||||
skipTypeCheck?: boolean;
|
skipTypeCheck?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ export interface ExecutorOptions {
|
|||||||
export interface NormalizedExecutorOptions extends ExecutorOptions {
|
export interface NormalizedExecutorOptions extends ExecutorOptions {
|
||||||
root?: string;
|
root?: string;
|
||||||
sourceRoot?: string;
|
sourceRoot?: string;
|
||||||
projectRoot?: string;
|
projectRoot: string;
|
||||||
mainOutputPath: string;
|
mainOutputPath: string;
|
||||||
files: Array<FileInputOutput>;
|
files: Array<FileInputOutput>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
import {
|
|
||||||
ExecutorContext,
|
|
||||||
normalizePath,
|
|
||||||
ProjectGraphProjectNode,
|
|
||||||
readJsonFile,
|
|
||||||
writeJsonFile,
|
|
||||||
} from '@nrwl/devkit';
|
|
||||||
import {
|
|
||||||
DependentBuildableProjectNode,
|
|
||||||
updateBuildableProjectPackageJsonDependencies,
|
|
||||||
} from '@nrwl/workspace/src/utilities/buildable-libs-utils';
|
|
||||||
import { basename, dirname, join, relative } from 'path';
|
|
||||||
import { NormalizedExecutorOptions } from './schema';
|
|
||||||
import { fileExists } from 'nx/src/utils/fileutils';
|
|
||||||
|
|
||||||
function getMainFileDirRelativeToProjectRoot(
|
|
||||||
main: string,
|
|
||||||
projectRoot: string
|
|
||||||
): string {
|
|
||||||
const mainFileDir = dirname(main);
|
|
||||||
const relativeDir = normalizePath(relative(projectRoot, mainFileDir));
|
|
||||||
return relativeDir === '' ? `./` : `./${relativeDir}/`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updatePackageJson(
|
|
||||||
options: NormalizedExecutorOptions,
|
|
||||||
context: ExecutorContext,
|
|
||||||
target: ProjectGraphProjectNode<any>,
|
|
||||||
dependencies: DependentBuildableProjectNode[],
|
|
||||||
withTypings = true
|
|
||||||
): void {
|
|
||||||
const pathToPackageJson = join(
|
|
||||||
context.root,
|
|
||||||
options.projectRoot,
|
|
||||||
'package.json'
|
|
||||||
);
|
|
||||||
|
|
||||||
const packageJson = fileExists(pathToPackageJson)
|
|
||||||
? readJsonFile(pathToPackageJson)
|
|
||||||
: { name: context.projectName };
|
|
||||||
|
|
||||||
const mainFile = basename(options.main).replace(/\.[tj]s$/, '');
|
|
||||||
const relativeMainFileDir = getMainFileDirRelativeToProjectRoot(
|
|
||||||
options.main,
|
|
||||||
options.projectRoot
|
|
||||||
);
|
|
||||||
const mainJsFile = `${relativeMainFileDir}${mainFile}.js`;
|
|
||||||
const typingsFile = `${relativeMainFileDir}${mainFile}.d.ts`;
|
|
||||||
|
|
||||||
packageJson.main = packageJson.main ?? mainJsFile;
|
|
||||||
|
|
||||||
if (withTypings) {
|
|
||||||
packageJson.typings = packageJson.typings ?? typingsFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeJsonFile(`${options.outputPath}/package.json`, packageJson);
|
|
||||||
|
|
||||||
if (
|
|
||||||
dependencies.length > 0 &&
|
|
||||||
options.updateBuildableProjectDepsInPackageJson
|
|
||||||
) {
|
|
||||||
updateBuildableProjectPackageJsonDependencies(
|
|
||||||
context.root,
|
|
||||||
context.projectName,
|
|
||||||
context.targetName,
|
|
||||||
context.configurationName,
|
|
||||||
target,
|
|
||||||
dependencies,
|
|
||||||
options.buildableProjectDepsInPackageJsonType
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -40,6 +40,7 @@
|
|||||||
"autoprefixer": "^10.4.9",
|
"autoprefixer": "^10.4.9",
|
||||||
"babel-plugin-transform-async-to-promises": "^0.8.15",
|
"babel-plugin-transform-async-to-promises": "^0.8.15",
|
||||||
"chalk": "4.1.0",
|
"chalk": "4.1.0",
|
||||||
|
"dotenv": "~10.0.0",
|
||||||
"fs-extra": "^10.1.0",
|
"fs-extra": "^10.1.0",
|
||||||
"postcss": "^8.4.14",
|
"postcss": "^8.4.14",
|
||||||
"rollup": "^2.56.2",
|
"rollup": "^2.56.2",
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'dotenv/config';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import * as rollup from 'rollup';
|
import * as rollup from 'rollup';
|
||||||
import * as peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
import * as peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
||||||
|
|||||||
@ -40,6 +40,7 @@
|
|||||||
"chokidar": "^3.5.1",
|
"chokidar": "^3.5.1",
|
||||||
"copy-webpack-plugin": "^10.2.4",
|
"copy-webpack-plugin": "^10.2.4",
|
||||||
"css-minimizer-webpack-plugin": "^3.4.1",
|
"css-minimizer-webpack-plugin": "^3.4.1",
|
||||||
|
"dotenv": "~10.0.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"fork-ts-checker-webpack-plugin": "7.2.13",
|
"fork-ts-checker-webpack-plugin": "7.2.13",
|
||||||
"fs-extra": "^10.1.0",
|
"fs-extra": "^10.1.0",
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'dotenv/config';
|
||||||
import { ExecutorContext, logger } from '@nrwl/devkit';
|
import { ExecutorContext, logger } from '@nrwl/devkit';
|
||||||
import { eachValueFrom } from '@nrwl/devkit/src/utils/rxjs-for-await';
|
import { eachValueFrom } from '@nrwl/devkit/src/utils/rxjs-for-await';
|
||||||
import type { Configuration, Stats } from 'webpack';
|
import type { Configuration, Stats } from 'webpack';
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export type FileInputOutput = {
|
|||||||
};
|
};
|
||||||
export type AssetGlob = FileInputOutput & {
|
export type AssetGlob = FileInputOutput & {
|
||||||
glob: string;
|
glob: string;
|
||||||
ignore: string[];
|
ignore?: string[];
|
||||||
dot?: boolean;
|
dot?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
"e2e-angular-extensions": "e2e/angular-extensions",
|
"e2e-angular-extensions": "e2e/angular-extensions",
|
||||||
"e2e-cypress": "e2e/cypress",
|
"e2e-cypress": "e2e/cypress",
|
||||||
"e2e-detox": "e2e/detox",
|
"e2e-detox": "e2e/detox",
|
||||||
|
"e2e-esbuild": "e2e/esbuild",
|
||||||
"e2e-expo": "e2e/expo",
|
"e2e-expo": "e2e/expo",
|
||||||
"e2e-graph-client": "graph/client-e2e",
|
"e2e-graph-client": "graph/client-e2e",
|
||||||
"e2e-jest": "e2e/jest",
|
"e2e-jest": "e2e/jest",
|
||||||
@ -37,6 +38,7 @@
|
|||||||
"e2e-web": "e2e/web",
|
"e2e-web": "e2e/web",
|
||||||
"e2e-webpack": "e2e/webpack",
|
"e2e-webpack": "e2e/webpack",
|
||||||
"e2e-workspace-create": "e2e/workspace-create",
|
"e2e-workspace-create": "e2e/workspace-create",
|
||||||
|
"esbuild": "packages/esbuild",
|
||||||
"eslint-plugin-nx": "packages/eslint-plugin-nx",
|
"eslint-plugin-nx": "packages/eslint-plugin-nx",
|
||||||
"eslint-rules": "tools/eslint-rules",
|
"eslint-rules": "tools/eslint-rules",
|
||||||
"expo": "packages/expo",
|
"expo": "packages/expo",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user