Skip to content

Commit 542b4f5

Browse files
Nikola HristovNikola Hristov
authored andcommitted
1 parent 641afb8 commit 542b4f5

File tree

21 files changed

+256
-123
lines changed

21 files changed

+256
-123
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 0.2.3
2+
13
## 0.2.2
24

35
### Change

README.md

Lines changed: 152 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,36 @@ capabilities of the `TypeScript` compiler.
77
## Feature 📦
88

99
- Fast compilation using `ESBuild`
10-
- `TypeScript` support with type-checking
11-
- Watch mode for development
12-
- Customizable `ESBuild` configuration
10+
- `TypeScript` support with type-checking (`tsc` & `tsc-alias`)
11+
- Watch mode for development (`--Watch`)
12+
- Customizable `ESBuild` configuration via object or function (`--ESBuild`)
1313
- Supports both `CommonJS` and `ES` modules
14+
- Glob pattern support for input files
15+
- Exclusion patterns for input files
1416

1517
## Installation 🚀
1618

1719
Install the package as a development dependency:
1820

1921
```sh
22+
# Using npm
2023
npm install -D -E @playform/build
24+
25+
# Or using yarn
26+
# yarn add -D -E @playform/build
27+
28+
# Or using pnpm
29+
# pnpm add -D -E @playform/build
2130
```
2231

2332
## Usage 🛠️
2433

2534
### Command Line
2635

27-
Run the build tool from the command line:
36+
Run the build tool from the command line, providing file patterns:
2837

2938
```sh
30-
npx @playform/build 'Source/**/*.ts'
39+
npx @playform/build 'Source/**/*.ts' 'OtherSource/**/*.mts'
3140
```
3241

3342
### CLI Options
@@ -36,13 +45,13 @@ npx @playform/build 'Source/**/*.ts'
3645
Usage: Build [options] <File...>
3746
3847
Arguments:
39-
File File patterns to build 📝
48+
File One or more glob patterns matching files to build 📝
4049
4150
Options:
4251
-V, --version Output the version number
43-
-ES, --ESBuild <File> Custom `ESBuild` configuration file 📜
44-
-TS, --TypeScript <File> Custom `TypeScript` configuration file (default: "tsconfig.json") 📜
45-
-W, --Watch Watch mode: rebuild on file changes 👁️
52+
-E, --ESBuild <File> Path to a custom ESBuild configuration file (exports an object or a function) 📜
53+
-T, --TypeScript <File> Path to a custom TypeScript configuration file (default: "tsconfig.json") 📜
54+
-W, --Watch Enable watch mode: rebuild on file changes 👁️
4655
-h, --help Display help information
4756
```
4857

@@ -62,59 +71,171 @@ Add `Build` to your `package.json` scripts:
6271

6372
## Configuration ⚙️
6473

65-
### ESBuild Configuration 📜
74+
### ESBuild Configuration (`--ESBuild`) 📜
75+
76+
You can provide a custom configuration file to modify the default ESBuild
77+
options used by `@playform/build`. This file (e.g., `ESBuild.js` or
78+
`esbuild.config.ts`) should use `export default` with **either** a configuration
79+
object **or** a function.
6680

67-
Create a custom `ESBuild` configuration file (e.g., `ESBuild.ts`):
81+
**1. Exporting an Object:**
82+
83+
Provide an object with ESBuild options. These will be merged with the base
84+
configuration.
6885

6986
```javascript
70-
export default {
87+
// ESBuild.js
88+
/** @type {import('esbuild').BuildOptions} */
89+
const config = {
7190
minify: true,
72-
sourcemap: true,
91+
sourcemap: "external",
92+
platform: "node",
7393
// Add other esbuild options here
7494
};
95+
96+
export default config;
97+
```
98+
99+
**2. Exporting a Function:**
100+
101+
Provide a function that receives the _current_ ESBuild configuration object
102+
(`BuildOptions` from `esbuild`) as its argument. You can modify this object
103+
directly **or** return a new (partial) object containing options to be merged.
104+
This allows for dynamic configuration, such as filtering entry points.
105+
106+
```javascript
107+
// ESBuild.js
108+
/**
109+
* @param {import('esbuild').BuildOptions} Current The configuration object before this function runs.
110+
* @returns {import('esbuild').BuildOptions | void} Return changes to merge, or modify Current directly.
111+
*/
112+
export default (Current) => {
113+
console.log("Applying custom ESBuild function...");
114+
115+
// Example: Filter out test files from entry points
116+
if (Array.isArray(Current.entryPoints)) {
117+
Current.entryPoints = Current.entryPoints.filter(
118+
(entry) => !/\.(test|spec)\.[mc]?[jt]s$/.test(entry),
119+
);
120+
121+
console.log("Filtered entry points:", Current.entryPoints);
122+
}
123+
124+
// Example: Modify the config directly
125+
Current.define = {
126+
...(Current.define ?? {}), // Preserve existing defines
127+
"process.env.BUILD_TIME": `"${new Date().toISOString()}"`,
128+
};
129+
130+
// Example: Return additional options to merge
131+
return {
132+
banner: {
133+
js: "// Generated by @playform/build",
134+
},
135+
logLevel: "info",
136+
};
137+
138+
// If you only modify 'Current' directly, you can simply have no return:
139+
// return;
140+
141+
// or return undefined;
142+
};
75143
```
76144
77-
Use the custom configuration:
145+
**Usage:**
146+
147+
Specify the path to your configuration file using the `--ESBuild` option:
78148
79149
```sh
80150
npx @playform/build 'Source/**/*.ts' --ESBuild ESBuild.ts
81151
```
82152
83-
See an example of a configuration file in
84-
[`ESBuild.ts`](Source/Variable/ESBuild.ts)
153+
See the base configuration used internally in
154+
[`Source/Variable/ESBuild.ts`](Source/Variable/ESBuild.ts) (link might need
155+
adjustment based on your actual path).
85156
86-
### TypeScript Configuration📜
157+
### TypeScript Configuration (`--TypeScript`) 📜
87158
88-
Create a `tsconfig.json` file in your project root:
159+
By default, `Build` looks for `tsconfig.json` in the current working directory.
160+
You can specify a different path using the `--TypeScript` option. This
161+
`tsconfig.json` is used by `ESBuild` for path resolution and by the `tsc` and
162+
`tsc-alias` commands run after the build for type checking and path alias
163+
replacement.
164+
165+
A typical `tsconfig.json` might look like this:
89166
90167
```json
168+
// tsconfig.json
91169
{
92170
"compilerOptions": {
93-
"outDir": "Target",
94-
"rootDir": "Source",
95-
"strict": true
171+
// --- Essential for tsc/tsc-alias ---
172+
"outDir": "Target", // Must match esbuild's outdir/outfile directory
173+
"rootDir": "Source", // Or your source root
174+
"baseUrl": ".", // Often needed for path aliases
175+
"paths": {
176+
// Example alias - must match esbuild alias config if used
177+
"@/*": ["Source/*"]
178+
},
179+
// --- Type Checking Options ---
180+
"strict": true,
181+
"skipLibCheck": true,
182+
"forceConsistentCasingInFileNames": true,
183+
// --- Module Settings (match esbuild target/format) ---
184+
"target": "ES2020",
185+
"module": "ESNext", // or CommonJS
186+
"moduleResolution": "node", // or node16/nodenext
187+
// --- Interoperability ---
188+
"esModuleInterop": true,
189+
"allowSyntheticDefaultImports": true,
190+
// --- Other ---
191+
"resolveJsonModule": true,
192+
"isolatedModules": true, // Good practice with transpilers like esbuild
193+
"noEmit": true // Important: Set noEmit to true as esbuild handles file emission
96194
},
97-
"extends": "@playform/build/tsconfig",
98-
"include": ["Source"]
195+
// Use @playform/build's base config for sensible defaults (optional)
196+
// "extends": "@playform/build/tsconfig",
197+
"include": ["Source/**/*"], // Files to be type-checked
198+
"exclude": ["node_modules", "Target"] // Exclude output and dependencies
99199
}
100200
```
101201
102-
### JSConfig Configuration 📜 (optional)
202+
**Important:** Ensure `compilerOptions.outDir` in your `tsconfig.json` aligns
203+
with the output directory configured for `ESBuild` (either via the default
204+
`Source/Variable/ESBuild.ts` or your custom `--ESBuild` config). Also, set
205+
`"noEmit": true` as `esbuild` handles the file generation; `tsc` is only used
206+
for type checking here.
103207
104-
For `JavaScript` projects using `JSDoc` comments, create a `jsconfig.json`:
208+
### JSConfig Configuration (Optional) 📜
209+
210+
If you are working with JavaScript and JSDoc for type checking, you can use a
211+
`jsconfig.json` file instead of `tsconfig.json`. The principles are similar.
105212
106213
```json
214+
// jsconfig.json
107215
{
108216
"compilerOptions": {
109217
"outDir": "Target",
110218
"rootDir": "Source",
111-
"checkJs": true
219+
"checkJs": true, // Enable type checking for JS files
220+
"target": "ES2020",
221+
"module": "ESNext", // or CommonJS
222+
"moduleResolution": "node", // or node16/nodenext
223+
"baseUrl": ".",
224+
"paths": {
225+
"@/*": ["Source/*"]
226+
},
227+
"noEmit": true // Still important
112228
},
113-
"extends": "@playform/build/jsconfig",
114-
"include": ["Source"]
229+
"extends": "@playform/build/jsconfig", // If you provide a base jsconfig
230+
"include": ["Source/**/*"],
231+
"exclude": ["node_modules", "Target"]
115232
}
116233
```
117234
235+
Remember to pass the path to this file if it's not named `tsconfig.json` (even
236+
if it's a JS project, the default flag might still look for `tsconfig.json`
237+
unless you explicitly pass `--TypeScript jsconfig.json`).
238+
118239
## Contributing 🤝
119240
120241
Contributions are welcome! Please see [`CONTRIBUTING.md`](CONTRIBUTING.md) for
@@ -124,6 +245,6 @@ guidelines and feel free to submit a Pull Request.
124245
125246
See [`CHANGELOG.md`](CHANGELOG.md) for a history of changes to this component.
126247
127-
[ESBuild]: HTTPS://NPMJS.Org/esbuild
128-
[TypeDoc]: HTTPS://NPMJS.Org/typedoc
129-
[Build]: HTTPS://NPMJS.Org/@playform/build
248+
[ESBuild]: HTTPS://esbuild.github.io/
249+
[TypeScript]: HTTPS://www.typescriptlang.org/
250+
[Build]: HTTPS://www.npmjs.com/package/@playform/build

Source/Function/Build.ts

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import type { BuildOptions } from "esbuild";
2+
13
import type Interface from "../Interface/Build.js";
4+
import type Set from "../Interface/Build/Set.js";
25

36
/**
47
* @module Build
@@ -24,44 +27,85 @@ export default (async (...[File, Option]) => {
2427
});
2528

2629
if (Option?.ESBuild) {
27-
Merge(
28-
Configuration,
29-
await (await import("@Function/File.js")).default(Option.ESBuild),
30-
);
30+
const Export = await (
31+
await import("@Function/File.js")
32+
).default(Option.ESBuild);
33+
34+
let Change: Partial<BuildOptions> | undefined;
35+
36+
if (typeof Export === "function") {
37+
const Result = await (Export as Set)(Configuration);
38+
39+
if (Result && typeof Result === "object") {
40+
Change = Result;
41+
}
42+
} else if (
43+
Export &&
44+
typeof Export === "object" &&
45+
!Array.isArray(Export)
46+
) {
47+
Change = Export as Partial<BuildOptions>;
48+
}
49+
50+
if (Change) {
51+
Merge(Configuration, Change);
52+
}
53+
54+
if (
55+
!Configuration.entryPoints ||
56+
!Array.isArray(Configuration.entryPoints)
57+
) {
58+
Configuration.entryPoints = [...Pipe];
59+
}
3160
}
3261

3362
Merge(Configuration, {
3463
tsconfig: Option?.TypeScript ?? "tsconfig.json",
3564
});
3665

37-
if (!Configuration.plugins && !Array.isArray(Configuration.plugins)) {
66+
if (!Configuration.plugins) {
67+
Configuration.plugins = [];
68+
} else if (!Array.isArray(Configuration.plugins)) {
3869
Configuration.plugins = [];
3970
}
4071

41-
Configuration.plugins?.push({
72+
Configuration.plugins.push({
4273
name: "TypeScript",
4374
setup({ onEnd }) {
4475
onEnd(async () => {
45-
await Exec(`tsc -p ${Configuration.tsconfig}`);
46-
await Exec(`tsc-alias -f -p ${Configuration.tsconfig}`);
76+
if (
77+
!Configuration.tsconfig ||
78+
typeof Configuration.tsconfig !== "string"
79+
) {
80+
return;
81+
}
82+
83+
try {
84+
await Exec(`tsc -p ${Configuration.tsconfig}`);
85+
86+
await Exec(`tsc-alias -f -p ${Configuration.tsconfig}`);
87+
} catch (_Error) {
88+
console.error(_Error);
89+
}
4790
});
4891
},
4992
});
5093

5194
if (Option?.Watch) {
5295
await (await (await import("esbuild")).context(Configuration)).watch();
5396
} else {
54-
console.log(
55-
await (
56-
await import("esbuild")
57-
).analyzeMetafile(
58-
(await (await import("esbuild")).build(Configuration))
59-
?.metafile ?? "",
60-
{
97+
const Result = await (await import("esbuild")).build(Configuration);
98+
99+
if (Result.metafile) {
100+
console.log(
101+
await (
102+
await import("esbuild")
103+
).analyzeMetafile(Result.metafile, {
61104
verbose: true,
62-
},
63-
),
64-
);
105+
color: false,
106+
}),
107+
);
108+
}
65109
}
66110
}) satisfies Interface as Interface;
67111

Source/Function/Merge.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* @module Merge
33
*
44
*/
5-
export default <T extends object>(Target: T, Source: T) =>
6-
Into(Target, Source) as unknown as T;
7-
8-
export const { default: Into } = await import("./Merge/Into.js");
5+
export default (await import("deepmerge-ts")).deepmergeIntoCustom({
6+
mergeArrays: false,
7+
});

0 commit comments

Comments
 (0)