Compare commits
197 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 681f2b4c54 | |||
| fb6bd614d3 | |||
| 0eaca1f3d1 | |||
| aeaa957efa | |||
| e5fcbb9a09 | |||
| 4ebc37fa5a | |||
| 5bfe60927e | |||
| 9e6b91b891 | |||
| e40e8f6a77 | |||
| ebe7afce82 | |||
| 27aa318054 | |||
| 9a071ce82f | |||
| ad227ded73 | |||
| c66a941aaf | |||
| a3b58dda39 | |||
| 4b29107130 | |||
| 09adbc1965 | |||
| 7fb571d4f6 | |||
| 6b32dced5a | |||
| df39aa48d0 | |||
| a4863bc761 | |||
| b38ef6cf82 | |||
| 8b50cd3090 | |||
| c6ab493efc | |||
| 82ae8a0e4a | |||
| 787becc4d3 | |||
| 746ca8767a | |||
| 55c1a2953a | |||
| 8e9fcb8135 | |||
| 18573c777d | |||
| fa654b83e3 | |||
| aa3c83cd95 | |||
| 20ed41df42 | |||
| 7162476f7f | |||
| 1b012628eb | |||
| 4081086621 | |||
| b9cf09ccba | |||
| 8463fbc78a | |||
| 0164eb51a1 | |||
| a305dd89dd | |||
| fa6b053ee0 | |||
| adfba21c67 | |||
| 050e41cdf9 | |||
| f220a11caa | |||
| 0909fa306a | |||
| 88c0601c03 | |||
| 9645f27942 | |||
| b73aa4f21f | |||
| d9d6878a9f | |||
| 30506da84c | |||
| 52b4d8f944 | |||
| 57d2726f6b | |||
| 960fc5f213 | |||
| 6d68f35a9a | |||
| 0378b9feca | |||
| 5ecf4b7125 | |||
| 2aa6348cdd | |||
| 9f42670865 | |||
| 6cc9f41bd2 | |||
| 5d32ac85e0 | |||
| 4f2ac6922a | |||
| 31834e0b3e | |||
| c6c94866bb | |||
| 09a648b435 | |||
| 065e0baaf7 | |||
| 89d32617ce | |||
| 094702b917 | |||
| c2aec98da3 | |||
| 289421206c | |||
| 1f9870ffbb | |||
| 8f7f34d61e | |||
| 2e23919503 | |||
| f601cf8eb8 | |||
| 15af2e4e2d | |||
| 59c6e72187 | |||
| 5369e8d931 | |||
| 88444e835f | |||
| 4892c8f7ae | |||
| 687f01d1a3 | |||
| 071b3e222f | |||
| fa41dbf332 | |||
| c45a216379 | |||
| 00046837a7 | |||
| ed22b539f2 | |||
| 43c7021aea | |||
| b21009f815 | |||
| deba95dfa6 | |||
| 50e6fec9b0 | |||
| f7c2a67d81 | |||
| 91e3502965 | |||
| 0afddbefce | |||
| 94e879d9fe | |||
| 43e2a1d777 | |||
| 9a1f57b92d | |||
| 0064f63ddb | |||
| 6e90bdda36 | |||
| 82cce58d69 | |||
| a316cc6725 | |||
| 05738a5c94 | |||
| 651a06ff7b | |||
| 2f04474dab | |||
| d88af368a4 | |||
| e60816be4c | |||
| a9e383ba2d | |||
| a3e1cf9e3d | |||
| 8790886815 | |||
| 611bd0d542 | |||
| b182fa5c0a | |||
| 03d4996284 | |||
| 6b2d2c9cc3 | |||
| e9dc5ae444 | |||
| 24574bdb4d | |||
| 2fe98bec22 | |||
| 87b6a4efb2 | |||
| dc81d99ac3 | |||
| 5d0c9b0326 | |||
| f27c27bd31 | |||
| 67e42cc0bd | |||
| 4a71b92868 | |||
| c251bce006 | |||
| f83b872f31 | |||
| 4e93832683 | |||
| 4d37e880a3 | |||
| b7e6412b7a | |||
| 113717886c | |||
| 98b4d4bc5b | |||
| 83f496f0ca | |||
| 662b7d4e6c | |||
| ab43ea0a10 | |||
| 0561f655cb | |||
| b0b1be70ab | |||
| dda03bad45 | |||
| a0b9f8d8f3 | |||
| da823e51d5 | |||
| b68aa06941 | |||
| f5ee2c2c70 | |||
| 0c018e6448 | |||
| 565c66e4e6 | |||
| 72ad77446c | |||
| 59ce28395f | |||
| cddd7ffd25 | |||
| 48ef556e6b | |||
| 0645beb199 | |||
| 97f52d1016 | |||
| 8d725e2e11 | |||
| 42b83b888e | |||
| 832664b667 | |||
| 4925809030 | |||
| 622a080b3c | |||
| 18747dbc83 | |||
| 210a7a07f7 | |||
| 211d42c36b | |||
| cfbe4bbcb9 | |||
| 72350a49ec | |||
| d4a0d03301 | |||
| 75f506ba0e | |||
| 035207f4f9 | |||
| 6d2d48af9d | |||
| 9adbce12e1 | |||
| 318189c7b2 | |||
| 167483b909 | |||
| 67db62e7d5 | |||
| ddf76c31b9 | |||
| 6a0a53adda | |||
| eb1a70ea70 | |||
| c10ddd3c1e | |||
| 9c9f7ae1dc | |||
| 70245584d7 | |||
| f11d7c6cb0 | |||
| dc7980e619 | |||
| 686a428624 | |||
| 6772bb439c | |||
| 3acab250db | |||
| ec90a006ce | |||
| 30ba0c99fd | |||
| 17a7749f23 | |||
| 3926a66d1d | |||
| 6eb5755aed | |||
| 165113f132 | |||
| 7ee9935a9a | |||
| 5128d450bc | |||
| 8708b1442d | |||
| 0e39dfecba | |||
| b4e8accad6 | |||
| 1415d66ffb | |||
| 38e3eed003 | |||
| 466095ed26 | |||
| 3d8041fdde | |||
| f021525f9e | |||
| 63fa2e84d4 | |||
| af66bd8ff1 | |||
| 53f4e402f5 | |||
| 2f57c26b87 | |||
| 3e05c116f3 | |||
| d2dbe40b50 | |||
| 835fba3452 | |||
| d35cff7135 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -15,8 +15,7 @@ node_modules/
|
|||||||
|
|
||||||
# builds
|
# builds
|
||||||
dist/
|
dist/
|
||||||
dist_web/
|
dist_*/
|
||||||
dist_serve/
|
|
||||||
dist_ts_web/
|
|
||||||
|
|
||||||
# custom
|
# custom
|
||||||
|
.claude
|
||||||
121
.gitlab-ci.yml
121
.gitlab-ci.yml
@@ -1,121 +0,0 @@
|
|||||||
# gitzone ci_default
|
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: clone
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- .npmci_cache/
|
|
||||||
key: "$CI_BUILD_STAGE"
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- security
|
|
||||||
- test
|
|
||||||
- release
|
|
||||||
- metadata
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# security stage
|
|
||||||
# ====================
|
|
||||||
mirror:
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci git mirror
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
snyk:
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci command npm install -g snyk
|
|
||||||
- npmci command npm install --ignore-scripts
|
|
||||||
- npmci command snyk test
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# test stage
|
|
||||||
# ====================
|
|
||||||
|
|
||||||
testStable:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm test
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- priv
|
|
||||||
|
|
||||||
testBuild:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci node install lts
|
|
||||||
- npmci npm install
|
|
||||||
- npmci command npm run build
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
release:
|
|
||||||
stage: release
|
|
||||||
script:
|
|
||||||
- npmci node install lts
|
|
||||||
- npmci npm publish
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# metadata stage
|
|
||||||
# ====================
|
|
||||||
codequality:
|
|
||||||
stage: metadata
|
|
||||||
allow_failure: true
|
|
||||||
script:
|
|
||||||
- npmci command npm install -g tslint typescript
|
|
||||||
- npmci npm install
|
|
||||||
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- priv
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
stage: metadata
|
|
||||||
script:
|
|
||||||
- npmci trigger
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
pages:
|
|
||||||
image: hosttoday/ht-docker-dbase:npmci
|
|
||||||
services:
|
|
||||||
- docker:18-dind
|
|
||||||
stage: metadata
|
|
||||||
script:
|
|
||||||
- npmci command npm install -g @gitzone/tsdoc
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci npm install
|
|
||||||
- npmci command tsdoc
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
allow_failure: true
|
|
||||||
4
.snyk
4
.snyk
@@ -1,4 +0,0 @@
|
|||||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
|
||||||
version: v1.13.3
|
|
||||||
ignore: {}
|
|
||||||
patch: {}
|
|
||||||
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"command": "npm test",
|
||||||
|
"name": "Run npm test",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"json.schemas": [
|
||||||
|
{
|
||||||
|
"fileMatch": ["/npmextra.json"],
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"npmci": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for npmci"
|
||||||
|
},
|
||||||
|
"gitzone": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for gitzone",
|
||||||
|
"properties": {
|
||||||
|
"projectType": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["website", "element", "service", "npm", "wcc"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
75
README.md
75
README.md
@@ -1,75 +0,0 @@
|
|||||||
# @gitzone/tsbuild
|
|
||||||
TypeScript nightly to easily make use of latest features
|
|
||||||
|
|
||||||
## Availabililty and Links
|
|
||||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@gitzone/tsbuild)
|
|
||||||
* [gitlab.com (source)](https://gitlab.com/gitzone/tsbuild)
|
|
||||||
* [github.com (source mirror)](https://github.com/gitzone/tsbuild)
|
|
||||||
* [docs (typedoc)](https://gitzone.gitlab.io/tsbuild/)
|
|
||||||
|
|
||||||
## Status for master
|
|
||||||
[](https://gitlab.com/gitzone/tsbuild/commits/master)
|
|
||||||
[](https://gitlab.com/gitzone/tsbuild/commits/master)
|
|
||||||
[](https://www.npmjs.com/package/@gitzone/tsbuild)
|
|
||||||
[](https://snyk.io/test/npm/@gitzone/tsbuild)
|
|
||||||
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
|
||||||
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
|
||||||
[](https://prettier.io/)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Tsn uses the **next** tagged npm version of typescript
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import * as tsn from 'tsn';
|
|
||||||
|
|
||||||
let myGlobStringObject = {
|
|
||||||
'./myTsFolder/**/*.ts': './myDestinationFolder/',
|
|
||||||
'./someOtherTsFolder/**/*.ts': './myOtherDestinationFolder/'
|
|
||||||
};
|
|
||||||
|
|
||||||
let tsOptions = {
|
|
||||||
target: tsn.ScriptTarget.ES2015,
|
|
||||||
module: tsn.ModuleKind.CommonJS
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
note: since this only works in code, here are the target numbers
|
|
||||||
enum ScriptTarget {
|
|
||||||
ES3 = 0,
|
|
||||||
ES5 = 1,
|
|
||||||
ES2015 = 2,
|
|
||||||
ES2016 = 3,
|
|
||||||
ES2017 = 4,
|
|
||||||
ESNext = 5,
|
|
||||||
Latest = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
and here are the module kinds
|
|
||||||
enum ModuleKind {
|
|
||||||
None = 0,
|
|
||||||
CommonJS = 1,
|
|
||||||
AMD = 2,
|
|
||||||
UMD = 3,
|
|
||||||
System = 4,
|
|
||||||
ES2015 = 5,
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
let myCwd = process.cwd();
|
|
||||||
|
|
||||||
tsn.compileGlobStringObject(
|
|
||||||
myGlobStringObject, // the glob string object describing from where to compile what to where
|
|
||||||
tsOptions, // the options for TypeScript
|
|
||||||
myCwd // a custom cwd, optional, defaults to process.cwd()
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
[](https://push.rocks)
|
|
||||||
|
|
||||||
For further information read the linked docs at the top of this readme.
|
|
||||||
|
|
||||||
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
|
||||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
|
||||||
|
|
||||||
[](https://maintainedby.lossless.com)
|
|
||||||
438
changelog.md
Normal file
438
changelog.md
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-12-14 - 4.0.2 - fix(TsCompiler)
|
||||||
|
Clear output directories before compilation to ensure clean builds and avoid stale files
|
||||||
|
|
||||||
|
- TsCompiler.compileGlob now clears the destination directory (if it exists) before compiling each glob pattern.
|
||||||
|
- Clearing is logged unless --quiet or --json flags are set (e.g. "🧹 Clearing output directory: <dest>").
|
||||||
|
- Uses FsHelpers.removeDirectory to remove previous output, preventing stale or duplicate emitted files.
|
||||||
|
- Documentation (readme.md) updated to advertise automatic output directory management / clean builds.
|
||||||
|
- Removed stale compiled test artifacts from test/assets/output to avoid interference with tests.
|
||||||
|
|
||||||
|
## 2025-12-13 - 3.1.3 - fix(npmextra)
|
||||||
|
Align npmextra.json package name with package.json (@git.zone/tsbuild)
|
||||||
|
|
||||||
|
- Corrected npmPackagename in npmextra.json from "@gitzone/tsbuild" to "@git.zone/tsbuild" to match package.json and README
|
||||||
|
- Metadata-only change: no code or API behavior affected
|
||||||
|
|
||||||
|
## 2025-11-28 - 3.1.2 - fix(TsBuild)
|
||||||
|
Set default TypeScript target to ESNext
|
||||||
|
|
||||||
|
- Default compiler target changed from ScriptTarget.ES2024 to ScriptTarget.ESNext in ts/tsbuild.classes.tsbuild.ts
|
||||||
|
- Aligns the default compiler options with documentation and ensures use of the latest language features
|
||||||
|
|
||||||
|
## 2025-11-27 - 3.1.1 - fix(compiler)
|
||||||
|
Update default TypeScript target to ES2024
|
||||||
|
|
||||||
|
- Default compiler option 'target' changed from ScriptTarget.ESNext to ScriptTarget.ES2024 in ts/tsbuild.classes.tsbuild.ts
|
||||||
|
- Aligns emitted code to ES2024 language features by default
|
||||||
|
|
||||||
|
## 2025-11-17 - 3.1.0 - feat(tsbuild.classes)
|
||||||
|
Update default TypeScript lib to lib.esnext.d.ts
|
||||||
|
|
||||||
|
- Changed default compilerOptions.lib from ['lib.dom.d.ts', 'lib.es2022.d.ts'] to ['lib.dom.d.ts', 'lib.esnext.d.ts'] in compilerOptionsDefault.
|
||||||
|
- Allows newer ECMAScript/DOM features by default when compiling with tsbuild (affects emitted types and available globals).
|
||||||
|
- Behavioral default change only — no public API changes; callers can still override lib via tsconfig, programmatic options, or CLI.
|
||||||
|
|
||||||
|
## 2025-11-17 - 3.0.0 - BREAKING CHANGE(TsBuild)
|
||||||
|
Stop forcing emitDecoratorMetadata in protected compiler defaults
|
||||||
|
|
||||||
|
- Removed emitDecoratorMetadata from the set of protected/critical default compiler options.
|
||||||
|
- Projects that relied on tsbuild automatically enabling emitDecoratorMetadata (for DI frameworks like NestJS, TypeORM, Inversify) must now enable it explicitly in their tsconfig.json or via programmatic/CLI options.
|
||||||
|
- No other protected defaults were changed; outDir, noEmitOnError, declaration and inlineSourceMap remain enforced.
|
||||||
|
- Behavior is now more permissive: decorator metadata generation is controlled by user configuration rather than being forced by tsbuild.
|
||||||
|
|
||||||
|
## 2025-11-17 - 2.7.3 - fix(tsbuild.classes)
|
||||||
|
Remove duplicate emitDecoratorMetadata from default compiler options and centralize it in protected defaults
|
||||||
|
|
||||||
|
- Removed emitDecoratorMetadata from compilerOptionsDefault in ts/tsbuild.classes.tsbuild.ts to avoid duplicate configuration.
|
||||||
|
- emitDecoratorMetadata remains enforced via getCriticalDefaults(), ensuring decorator metadata support is protected from tsconfig.json overrides.
|
||||||
|
- Prevents inconsistencies during compiler option merging by centralizing the decorator-related setting.
|
||||||
|
|
||||||
|
## 2025-11-17 - 2.7.2 - fix(compilerOptions)
|
||||||
|
Remove experimentalDecorators and useDefineForClassFields from default TypeScript compiler options
|
||||||
|
|
||||||
|
- Removed experimentalDecorators from compilerOptionsDefault in ts/tsbuild.classes.tsbuild.ts
|
||||||
|
- Removed useDefineForClassFields from compilerOptionsDefault in ts/tsbuild.classes.tsbuild.ts
|
||||||
|
- Default compiler options now rely on TypeScript's upstream defaults for decorator and class field behavior
|
||||||
|
- If your project relies on these settings, re-enable them in your tsconfig.json or pass them via the programmatic API / CLI
|
||||||
|
|
||||||
|
## 2025-11-02 - 2.7.1 - fix(readme)
|
||||||
|
Update documentation: expand README with usage, CLI and API examples; add readme.hints.md project memory
|
||||||
|
|
||||||
|
- Add readme.hints.md: new project memory / quick reference with public API and CLI summaries
|
||||||
|
- Expand and restructure readme.md: more comprehensive Quick Start, CLI Commands, API Reference, configuration, examples and troubleshooting
|
||||||
|
- Clarify protected compiler options, default compiler options, path transformation behavior and error-handling patterns
|
||||||
|
- Docs-only change — no source code or behavioral changes
|
||||||
|
|
||||||
|
## 2025-11-02 - 2.7.0 - feat(tsbuild)
|
||||||
|
Add tsconfig.json support and safer compiler option merging; protect critical options; apply path and enum transforms; bump dependencies.
|
||||||
|
|
||||||
|
- Add robust tsconfig.json reading with graceful fallback when no tsconfig is present or it is invalid
|
||||||
|
- Merge compiler options in a clear priority order (defaults -> tsconfig -> protected defaults -> programmatic -> CLI flags)
|
||||||
|
- Introduce protected (critical) compiler options that cannot be overridden by tsconfig.json: outDir, noEmitOnError, declaration, emitDecoratorMetadata, inlineSourceMap
|
||||||
|
- Convert string values from tsconfig (target, module, moduleResolution) to TypeScript enum values where applicable; special-case NodeNext
|
||||||
|
- Transform tsconfig path mappings by replacing './ts_' with './dist_ts_' to keep runtime path resolution consistent with compiled output
|
||||||
|
- Expose getCriticalDefaults helper and adjust mergeCompilerOptions to apply protected defaults before programmatic and CLI overrides
|
||||||
|
- Update README with documentation for tsconfig support, merge order, protected compiler options, and example tsconfig
|
||||||
|
- Bump dependencies/devDependencies: @push.rocks/smartcli ^4.0.19, @push.rocks/smartlog ^3.1.10, typescript 5.9.3, @git.zone/tsrun ^1.6.2, @git.zone/tstest ^2.7.0
|
||||||
|
|
||||||
|
## 2025-08-29 - 2.6.8 - fix(tsbuild)
|
||||||
|
Avoid process.exit in library, add confirmskiplibcheck flag, improve CLI exit handling and JSON/quiet modes, update test script
|
||||||
|
|
||||||
|
- Changed package.json test script from "tsrun test/test.ts --verbose" to "tstest test/test.ts --verbose".
|
||||||
|
- Library no longer calls process.exit from compile and compileWithErrorTracking; errors are returned or thrown so callers can decide process termination.
|
||||||
|
- skipLibCheck behavior updated: delay/warning only happens when --confirmskiplibcheck is present; otherwise a short informational note is printed (suppressed in --quiet/--json).
|
||||||
|
- CLI now awaits compileGlobStringObject calls and inspects a final error summary attached to argv to decide process.exit(1) when errors occurred.
|
||||||
|
- compileGlobStringObject/exports now respect --quiet and --json modes, emit a JSON summary when --json is used, and attach the final error summary to argv so the CLI can determine exit behavior.
|
||||||
|
|
||||||
|
## 2025-08-18 - 2.6.7 - fix(tspublish)
|
||||||
|
Bump @git.zone/tspublish dependency to ^1.10.3
|
||||||
|
|
||||||
|
- Updated dependency @git.zone/tspublish from ^1.10.2 to ^1.10.3 in package.json
|
||||||
|
|
||||||
|
## 2025-08-18 - 2.6.6 - fix(dependencies)
|
||||||
|
Update dependency @git.zone/tspublish to ^1.10.2
|
||||||
|
|
||||||
|
- Bumped @git.zone/tspublish in package.json from ^1.10.1 to ^1.10.2
|
||||||
|
|
||||||
|
## 2025-08-18 - 2.6.5 - fix(dependencies)
|
||||||
|
Bump dependencies and add pnpm-workspace configuration
|
||||||
|
|
||||||
|
- Updated @git.zone/tspublish from ^1.9.1 to ^1.10.1
|
||||||
|
- Updated @push.rocks/smartfile from ^11.2.4 to ^11.2.7
|
||||||
|
- Updated @push.rocks/smartpath from ^5.0.18 to ^6.0.0
|
||||||
|
- Updated typescript from 5.8.3 to 5.9.2
|
||||||
|
- Updated devDependency @git.zone/tstest from ^1.10.1 to ^2.3.4
|
||||||
|
- Added pnpm-workspace.yaml with onlyBuiltDependencies list (esbuild, mongodb-memory-server, puppeteer)
|
||||||
|
|
||||||
|
## 2025-05-24 - 2.6.4 - fix(dependencies)
|
||||||
|
Add .npmrc and update dependency versions for smartfile and tstest
|
||||||
|
|
||||||
|
- Add .npmrc with registry configuration for npm
|
||||||
|
- Bump @push.rocks/smartfile version from ^11.2.3 to ^11.2.4
|
||||||
|
- Bump @git.zone/tstest version from ^1.9.0 to ^1.10.1
|
||||||
|
|
||||||
|
## 2025-05-21 - 2.6.3 - fix(tsbuild)
|
||||||
|
minor maintenance updates and documentation improvements
|
||||||
|
|
||||||
|
- Updated commit metadata to align with project version
|
||||||
|
- Refined CLI command parsing and diagnostics logging for better clarity
|
||||||
|
- Improved code readability in compiler options merging
|
||||||
|
|
||||||
|
## 2025-05-21 - 2.6.2 - fix(npm configuration)
|
||||||
|
Remove .npmrc file to default npm registry behavior
|
||||||
|
|
||||||
|
- Deleted .npmrc file that hard-coded the npm registry URL to https://registry.npmjs.org/
|
||||||
|
- This change leverages npm's default registry settings and reduces configuration clutter
|
||||||
|
|
||||||
|
## 2025-05-21 - 2.6.1 - fix(tsbuild.classes)
|
||||||
|
Improve error diagnostics handling by removing legacy helper and integrating more robust error summaries in the compilation process
|
||||||
|
|
||||||
|
- Removed the handleDiagnostics method and its legacy usage
|
||||||
|
- Replaced legacy calls with inline processDiagnostics checks for pre-emit and emit phases
|
||||||
|
- Combined error summaries for clearer reporting during emit checks and type validation
|
||||||
|
- Enhanced error output to guide users on resolving TypeScript errors before emission
|
||||||
|
|
||||||
|
## 2025-05-21 - 2.6.0 - feat(tsbuild)
|
||||||
|
Improve task logging and update dependencies
|
||||||
|
|
||||||
|
- Add .npmrc file with npm registry configuration
|
||||||
|
- Update test script to use '--verbose' flag
|
||||||
|
- Bump dependency versions for @push.rocks packages and TypeScript
|
||||||
|
- Enhance TsBuild logging by incorporating task info (e.g. task number, total tasks, output folder, and compile durations)
|
||||||
|
- Propagate task info in compileFileArrayWithErrorTracking for better task tracking
|
||||||
|
|
||||||
|
## 2025-05-21 - 2.5.2 - fix(tsbuild)
|
||||||
|
Improve diagnostic error handling and summary reporting for TypeScript compilation by refactoring diagnostic processing and adding pre-emit error checks.
|
||||||
|
|
||||||
|
- Introduce a dedicated processDiagnostics function that categorizes errors by file and computes error totals.
|
||||||
|
- Refactor displayErrorSummary to provide clearer, color-coded output of error details.
|
||||||
|
- Add pre-emit error checking in compileWithErrorTracking to prevent emission when errors exist.
|
||||||
|
- Consolidate error summary merging in compileFileArrayWithErrorTracking for improved reporting.
|
||||||
|
|
||||||
|
## 2025-05-15 - 2.5.1 - fix(commitinfo)
|
||||||
|
Update commit information and metadata to synchronize release data
|
||||||
|
|
||||||
|
- Regenerated the commitinfo file with current version details
|
||||||
|
- Maintained existing functionality with no functional code changes
|
||||||
|
|
||||||
|
## 2025-05-15 - 2.5.0 - feat(cli)
|
||||||
|
Enhance type checking in CLI by adding default file pattern handling
|
||||||
|
|
||||||
|
- When no TypeScript file or glob pattern is provided, the CLI now performs a default type checking sequence.
|
||||||
|
- First checks 'ts/**/*' files with standard options, then checks 'test/**/*' files with skiplibcheck enabled.
|
||||||
|
- Improved logging to indicate file discovery and check results, ensuring clear feedback for users.
|
||||||
|
|
||||||
|
## 2025-05-15 - 2.4.1 - fix(cli)
|
||||||
|
Improve TS folder compilation order display in CLI
|
||||||
|
|
||||||
|
- Refactor folder compilation output to use a bordered, tabular format with order numbering
|
||||||
|
- Enhance readability of TS folder compilation plan in the CLI output
|
||||||
|
|
||||||
|
## 2025-05-15 - 2.4.0 - feat(cli)
|
||||||
|
Add new 'check' command for type checking and update compiler options handling
|
||||||
|
|
||||||
|
- Introduced a new 'check' command to verify TypeScript files without emitting output
|
||||||
|
- Updated CLI error messages and logging for better clarity
|
||||||
|
- Replaced '--allowimplicitany' flag with '--disallowimplicitany' to reflect new default behavior
|
||||||
|
- Modified compiler options default settings (noImplicitAny now set to false) for more flexible type handling
|
||||||
|
- Refined diagnostic output in tsbuild class for improved error reporting
|
||||||
|
- Updated .gitignore to exclude the .claude file
|
||||||
|
- Enhanced documentation in readme and implementation plan files
|
||||||
|
|
||||||
|
## 2025-03-20 - 2.3.2 - fix(compileGlobStringObject)
|
||||||
|
Fix duplicate file outputs in glob pattern processing
|
||||||
|
|
||||||
|
- Removed duplicate concatenation of compiled files in compileGlobStringObject
|
||||||
|
- Ensured unique file paths are used during TypeScript compilation
|
||||||
|
|
||||||
|
## 2025-03-20 - 2.3.1 - fix(compiler)
|
||||||
|
Refactor compiler implementation with consolidated TsBuild class and improved diagnostics handling
|
||||||
|
|
||||||
|
- Removed legacy tsbuild.classes.compiler.ts and introduced tsbuild.classes.tsbuild.ts
|
||||||
|
- Unified compiler options merging, reading tsconfig.json, and diagnostics reporting within the TsBuild class
|
||||||
|
- Updated exports to reference the new compiler class implementation for backward compatibility
|
||||||
|
|
||||||
|
## 2025-03-20 - 2.3.0 - feat(cli)
|
||||||
|
Add emitcheck command to validate TS file emission without generating output
|
||||||
|
|
||||||
|
- Implemented the emitcheck CLI command to allow checking if TypeScript files can be emitted without producing files
|
||||||
|
- Updated tsbuild.classes.compiler.ts to include the emitCheck function
|
||||||
|
- Enhanced documentation in readme.md to describe the new emitcheck usage with examples
|
||||||
|
|
||||||
|
## 2025-03-17 - 2.2.7 - fix(compiler)
|
||||||
|
Improve diagnostic checking and error handling in the TypeScript compiler integration
|
||||||
|
|
||||||
|
- Added pre-emit diagnostics check to log errors before emitting
|
||||||
|
- Process exits on encountering pre-emit errors to ensure build correctness
|
||||||
|
- Enhanced logging for emit diagnostics to aid debugging
|
||||||
|
|
||||||
|
## 2025-03-04 - 2.2.6 - fix(package)
|
||||||
|
Fix repository URL in package.json
|
||||||
|
|
||||||
|
- Updated repository URL in package.json to point to the correct Git repository.
|
||||||
|
|
||||||
|
## 2025-03-04 - 2.2.5 - fix(package.json)
|
||||||
|
Update repository URLs in package metadata.
|
||||||
|
|
||||||
|
- Corrected the 'bugs.url' and 'homepage' fields with the accurate URLs.
|
||||||
|
|
||||||
|
## 2025-03-04 - 2.2.4 - fix(core)
|
||||||
|
Fix compiler logic to remove duplicate compiled files and improve glob pattern handling.
|
||||||
|
|
||||||
|
- Resolved an issue causing duplicate file compilations when using compileGlobStringObject.
|
||||||
|
- Improved handling of glob patterns to ensure accurate compilation paths.
|
||||||
|
|
||||||
|
## 2025-03-04 - 2.2.3 - fix(exports)
|
||||||
|
Fixed duplicate file compilation in compileGlobStringObject
|
||||||
|
|
||||||
|
- Enhanced type safety checks for glob pattern compilation keys.
|
||||||
|
- Ensured file list transformations include type checks.
|
||||||
|
- Fixed issue with duplicate compilation results in compileGlobStringObject.
|
||||||
|
|
||||||
|
## 2025-01-28 - 2.2.2 - fix(ci)
|
||||||
|
Remove GitLab CI configuration
|
||||||
|
|
||||||
|
|
||||||
|
## 2025-01-28 - 2.2.1 - fix(core)
|
||||||
|
Update dependencies to improve stability and performance.
|
||||||
|
|
||||||
|
- Updated @git.zone/tspublish from version ^1.7.5 to ^1.9.1.
|
||||||
|
- Updated @push.rocks/smartfile from version ^11.0.21 to ^11.1.5.
|
||||||
|
- Updated @push.rocks/smartpromise from version ^4.0.4 to ^4.2.2.
|
||||||
|
- Updated typescript from version 5.6.3 to 5.7.3.
|
||||||
|
- Updated @push.rocks/tapbundle from version ^5.0.23 to ^5.5.6.
|
||||||
|
- Updated @types/node from version ^22.8.7 to ^22.12.0.
|
||||||
|
|
||||||
|
## 2024-11-05 - 2.2.0 - feat(cli)
|
||||||
|
Enhance CLI for TypeScript folder compilation ordering based on rank and predefined rules.
|
||||||
|
|
||||||
|
- CLI now supports automatic ordering of TypeScript folders for compilation using tspublish.json based ranking.
|
||||||
|
- Ensures 'ts_interfaces' and 'ts_shared' are always transpiled first if certain conditions are met.
|
||||||
|
- Updated TypeScript compilerOptions to support additional path transformations.
|
||||||
|
- Updated dependencies versions and added '@git.zone/tspublish' in ts/plugins.ts.
|
||||||
|
|
||||||
|
## 2024-10-27 - 2.1.85 - fix(compiler)
|
||||||
|
Improve path handling in compiler options
|
||||||
|
|
||||||
|
- Refactored path import in tsbuild.classes.compiler.ts.
|
||||||
|
- Enhanced mergeCompilerOptions to read paths and baseUrl from tsconfig.json if present.
|
||||||
|
|
||||||
|
## 2024-07-22 - 2.1.84 - fix(cli)
|
||||||
|
Fixed transpilation order issue in tsfolders command
|
||||||
|
|
||||||
|
- Corrected the transpilation order so 'ts_shared' is processed before other folders in the 'tsfolders' CLI command.
|
||||||
|
|
||||||
|
## 2024-07-21 - 2.1.83 - fix(cli)
|
||||||
|
Ensure 'ts_shared' folder is compiled first if present
|
||||||
|
|
||||||
|
- Added logic to make sure the 'ts_shared' folder is compiled first when running 'tsfolders' command.
|
||||||
|
|
||||||
|
## 2024-06-24 - 2.1.82 - fix(core)
|
||||||
|
Minor improvements and optimizations in core TypeScript compiler integration.
|
||||||
|
|
||||||
|
- Updated TypeScript dependency to latest version 5.5.2.
|
||||||
|
- Enhanced logging in compiler process.
|
||||||
|
- Improved handling of CLI commands for better flexibility.
|
||||||
|
- Compiled output directories are now more structured.
|
||||||
|
- Refactored internal compiler options merge function.
|
||||||
|
|
||||||
|
## 2024-06-24 - 2.1.81 - fix(dependencies)
|
||||||
|
Update dependencies to latest versions
|
||||||
|
|
||||||
|
- Upgraded @push.rocks/smartcli from ^4.0.10 to ^4.0.11
|
||||||
|
- Upgraded @push.rocks/smartfile from ^11.0.14 to ^11.0.21
|
||||||
|
- Upgraded @push.rocks/smartlog from ^3.0.3 to ^3.0.7
|
||||||
|
- Upgraded @push.rocks/smartpromise from ^4.0.3 to ^4.0.4
|
||||||
|
- Upgraded typescript from 5.4.5 to 5.5.2
|
||||||
|
- Upgraded @git.zone/tsrun from ^1.2.46 to ^1.2.47
|
||||||
|
- Upgraded @types/node from ^20.12.11 to ^20.14.8
|
||||||
|
|
||||||
|
## 2024-05-17 - 2.1.80 - core
|
||||||
|
Fix multiple core issues.
|
||||||
|
|
||||||
|
- Various small fixes and updates to the core functionality.
|
||||||
|
|
||||||
|
## 2024-05-17 - 2.1.76 to 2.1.79 - core
|
||||||
|
Routine core updates and fixes.
|
||||||
|
|
||||||
|
- Several minor enhancements and bug fixes.
|
||||||
|
|
||||||
|
## 2024-05-14 - 2.1.74 to 2.1.75 - core
|
||||||
|
General core maintenance updates.
|
||||||
|
|
||||||
|
- Core updated to fix minor bugs.
|
||||||
|
|
||||||
|
## 2024-05-10 - 2.1.72 to 2.1.73 - core
|
||||||
|
Minor core updates.
|
||||||
|
|
||||||
|
- Improvements and fixes to core components.
|
||||||
|
|
||||||
|
## 2024-01-08 - 2.1.70 to 2.1.71 - core
|
||||||
|
Core functionality enhancements.
|
||||||
|
|
||||||
|
- Small fixes and updates in the core.
|
||||||
|
|
||||||
|
## 2023-08-26 - 2.1.66 to 2.1.69 - core
|
||||||
|
Regular core updates and fixes.
|
||||||
|
|
||||||
|
- Various updates to improve core functionality.
|
||||||
|
|
||||||
|
## 2023-06-03 - 2.1.65 - core
|
||||||
|
Core maintenance update.
|
||||||
|
|
||||||
|
- Fixed issues in core functionality.
|
||||||
|
|
||||||
|
## 2022-08-03 - 2.1.63 to 2.1.64 - core
|
||||||
|
Minor core updates and fixes.
|
||||||
|
|
||||||
|
- Updated core functionality with minor fixes.
|
||||||
|
|
||||||
|
## 2022-05-25 - 2.1.61 to 2.1.62 - core
|
||||||
|
Routine core updates.
|
||||||
|
|
||||||
|
- Fixed minor bugs in the core.
|
||||||
|
|
||||||
|
## 2022-03-24 - 2.1.60 - core
|
||||||
|
Core functionality update.
|
||||||
|
|
||||||
|
- Fixed various minor issues in core.
|
||||||
|
|
||||||
|
## 2022-03-18 - 2.1.57 to 2.1.59 - core
|
||||||
|
Minor core updates and enhancements.
|
||||||
|
|
||||||
|
- Updated core components with small fixes.
|
||||||
|
|
||||||
|
## 2022-03-15 - 2.1.50 to 2.1.56 - core
|
||||||
|
Several core bug fixes.
|
||||||
|
|
||||||
|
- Fixed various minor issues in the core functionality.
|
||||||
|
|
||||||
|
## 2022-03-14 - 2.1.49 - core
|
||||||
|
Core update.
|
||||||
|
|
||||||
|
- Fixed minor bugs in the core.
|
||||||
|
|
||||||
|
## 2022-03-12 - 2.1.43 to 2.1.48 - core
|
||||||
|
General core maintenance updates.
|
||||||
|
|
||||||
|
- Core updated to fix minor bugs and improve functionality.
|
||||||
|
|
||||||
|
## 2022-03-11 - 2.1.33 to 2.1.42 - core
|
||||||
|
Core functionality enhancements and fixes.
|
||||||
|
|
||||||
|
- Multiple updates to improve core functionality and fix bugs.
|
||||||
|
|
||||||
|
## 2022-03-11 - 2.1.29 to 2.1.32 - core
|
||||||
|
Routine core updates.
|
||||||
|
|
||||||
|
- Minor bug fixes and improvements in core functionality.
|
||||||
|
|
||||||
|
## 2022-01-19 - 2.1.28 to 2.1.29 - core
|
||||||
|
Core bug fixes.
|
||||||
|
|
||||||
|
- Updated core to address minor issues.
|
||||||
|
|
||||||
|
## 2021-10-06 - 2.1.27 - core
|
||||||
|
Minor core update.
|
||||||
|
|
||||||
|
- Fixed core bugs.
|
||||||
|
|
||||||
|
## 2021-09-08 - 2.1.26 - core
|
||||||
|
Core update.
|
||||||
|
|
||||||
|
- Fixed minor bugs in the core.
|
||||||
|
|
||||||
|
## 2021-08-17 - 2.1.25 - core
|
||||||
|
Core bug fixes.
|
||||||
|
|
||||||
|
- Small updates to improve core functionality.
|
||||||
|
|
||||||
|
## 2020-08-11 - 2.1.24 - core
|
||||||
|
Routine core update.
|
||||||
|
|
||||||
|
- Fixed minor bugs in the core.
|
||||||
|
|
||||||
|
## 2020-05-14 - 2.1.23 - core
|
||||||
|
General core updates.
|
||||||
|
|
||||||
|
- Fixes to improve core stability.
|
||||||
|
|
||||||
|
## 2020-03-13 - 2.1.20 to 2.1.22 - core
|
||||||
|
Minor core updates.
|
||||||
|
|
||||||
|
- Enhancements and fixes for core functionality.
|
||||||
|
|
||||||
|
## 2020-03-09 - 2.1.19 - core
|
||||||
|
Maintenance core update.
|
||||||
|
|
||||||
|
- Fixes addressing minor issues in core functionality.
|
||||||
|
|
||||||
|
## 2019-08-26 - 2.1.16 to 2.1.17 - core
|
||||||
|
Routine minor core updates.
|
||||||
|
|
||||||
|
- Improvement and fixes within the core functionality.
|
||||||
|
|
||||||
|
## 2019-01-27 - 2.1.6 - custom directory compilation
|
||||||
|
Now picking up TypeScript files correctly.
|
||||||
|
|
||||||
|
- Resolved compilation issues with custom directories.
|
||||||
|
|
||||||
|
## 2018-12-05 - 2.1.0 to 2.1.1 - core
|
||||||
|
Minor core updates.
|
||||||
|
|
||||||
|
- Small enhancements and fixes applied to core functionality.
|
||||||
|
|
||||||
|
## 2018-12-05 - 2.0.22 - cli options
|
||||||
|
Now support --web for web compilations targeting Google Chrome.
|
||||||
|
|
||||||
|
- Added new CLI option for web compilation.
|
||||||
|
|
||||||
|
## 2018-07-25 - 2.0.15 to 2.0.19 - various
|
||||||
|
Multiple fixes across core, dependency, and compiler modules.
|
||||||
|
|
||||||
|
- Packagename fix in core.
|
||||||
|
- Dependency updates.
|
||||||
|
- Compiler options fixed.
|
||||||
|
- Initial core updates.
|
||||||
4
cli.child.ts
Normal file
4
cli.child.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
process.env.CLI_CALL = 'true';
|
||||||
|
import * as cliTool from './ts/index.js';
|
||||||
|
cliTool.runCli();
|
||||||
5
cli.js
5
cli.js
@@ -1,3 +1,4 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
process.env.CLI_CALL_TSBUILD = 'true'
|
process.env.CLI_CALL = 'true';
|
||||||
var index = require("./dist/index.js");
|
const cliTool = await import('./dist_ts/index.js');
|
||||||
|
cliTool.runCli();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
process.env.CLI_CALL_TSBUILD = 'true';
|
process.env.CLI_CALL = 'true';
|
||||||
require('@gitzone/tsrun');
|
import * as tsrun from '@git.zone/tsrun';
|
||||||
require('./ts/index');
|
tsrun.runPath('./cli.child.js');
|
||||||
@@ -4,13 +4,28 @@
|
|||||||
"npmAccessLevel": "public"
|
"npmAccessLevel": "public"
|
||||||
},
|
},
|
||||||
"gitzone": {
|
"gitzone": {
|
||||||
|
"projectType": "npm",
|
||||||
"module": {
|
"module": {
|
||||||
"githost": "gitlab.com",
|
"githost": "gitlab.com",
|
||||||
"gitscope": "gitzone",
|
"gitscope": "gitzone",
|
||||||
"gitrepo": "tsbuild",
|
"gitrepo": "tsbuild",
|
||||||
"shortDescription": "TypeScript nightly to easily make use of latest features",
|
"description": "A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.",
|
||||||
"npmPackagename": "@gitzone/tsbuild",
|
"npmPackagename": "@git.zone/tsbuild",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
}
|
"keywords": [
|
||||||
|
"TypeScript",
|
||||||
|
"compilation",
|
||||||
|
"nightly features",
|
||||||
|
"CLI tool",
|
||||||
|
"file compilation",
|
||||||
|
"glob patterns",
|
||||||
|
"compiler options",
|
||||||
|
"development",
|
||||||
|
"API"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tsdoc": {
|
||||||
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1411
package-lock.json
generated
1411
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
80
package.json
80
package.json
@@ -1,55 +1,71 @@
|
|||||||
{
|
{
|
||||||
"name": "@gitzone/tsbuild",
|
"name": "@git.zone/tsbuild",
|
||||||
"version": "2.1.20",
|
"version": "4.0.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "TypeScript nightly to easily make use of latest features",
|
"description": "A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.",
|
||||||
"main": "dist/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsbuild": "cli.js"
|
"tsbuild": "./cli.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "tsrun test/test.ts",
|
"test": "tstest test/test.ts --verbose",
|
||||||
"testCustom": "node cli.ts.js custom ts_web",
|
"build": "node cli.ts.js --web",
|
||||||
"build": "node cli.ts.js"
|
"buildDocs": "tsdoc"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+ssh://git@gitlab.com/pushrocks/tsn.git"
|
"url": "https://code.foss.global/git.zone/tsbuild.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"TypeScript"
|
"TypeScript",
|
||||||
|
"compilation",
|
||||||
|
"nightly features",
|
||||||
|
"CLI tool",
|
||||||
|
"file compilation",
|
||||||
|
"glob patterns",
|
||||||
|
"compiler options",
|
||||||
|
"development",
|
||||||
|
"API"
|
||||||
],
|
],
|
||||||
"author": "Lossless GmbH",
|
"author": "Task Venture Capital GmbH",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://gitlab.com/pushrocks/tsn/issues"
|
"url": "https://code.foss.global/git.zone/tsbuild/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/pushrocks/tsn#README",
|
"homepage": "https://code.foss.global/git.zone/tsbuild#README",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pushrocks/smartcli": "^3.0.7",
|
"@git.zone/tspublish": "^1.10.3",
|
||||||
"@pushrocks/smartfile": "^7.0.2",
|
"@push.rocks/early": "^4.0.4",
|
||||||
"@pushrocks/smartlog": "^2.0.19",
|
"@push.rocks/smartcli": "^4.0.19",
|
||||||
"@pushrocks/smartpath": "^4.0.1",
|
"@push.rocks/smartdelay": "^3.0.5",
|
||||||
"@pushrocks/smartpromise": "^3.0.2",
|
"@push.rocks/smartfile": "^13.1.2",
|
||||||
"typescript": "^3.5.2"
|
"@push.rocks/smartfs": "^1.2.0",
|
||||||
|
"@push.rocks/smartlog": "^3.1.10",
|
||||||
|
"@push.rocks/smartpath": "^6.0.0",
|
||||||
|
"@push.rocks/smartpromise": "^4.2.3",
|
||||||
|
"typescript": "5.9.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@gitzone/tsrun": "^1.2.8",
|
"@git.zone/tsrun": "^2.0.1",
|
||||||
"@pushrocks/tapbundle": "^3.0.13",
|
"@git.zone/tstest": "^3.1.3",
|
||||||
"@types/node": "^12.7.2",
|
"@types/node": "^25.0.1"
|
||||||
"tslint": "^5.19.0",
|
|
||||||
"tslint-config-prettier": "^1.18.0"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"ts/*",
|
"ts/**/*",
|
||||||
"ts_web/*",
|
"ts_web/**/*",
|
||||||
"dist/*",
|
"dist/**/*",
|
||||||
"dist_web/*",
|
"dist_*/**/*",
|
||||||
"dist_ts_web/*",
|
"dist_ts/**/*",
|
||||||
"assets/*",
|
"dist_ts_web/**/*",
|
||||||
|
"assets/**/*",
|
||||||
"cli.js",
|
"cli.js",
|
||||||
"npmextra.json",
|
"npmextra.json",
|
||||||
"readme.md"
|
"readme.md"
|
||||||
]
|
],
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 chrome versions"
|
||||||
|
],
|
||||||
|
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
|
||||||
}
|
}
|
||||||
|
|||||||
8010
pnpm-lock.yaml
generated
Normal file
8010
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
215
readme.hints.md
Normal file
215
readme.hints.md
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
# @git.zone/tsbuild - Project Memory
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### Public API - Classes
|
||||||
|
1. **TsCompiler** - Main compilation class with compileFiles, compileGlob, checkTypes, checkEmit methods
|
||||||
|
2. **TsConfig** - TypeScript configuration management (tsconfig.json handling)
|
||||||
|
3. **TsPublishConfig** - TsPublish configuration (tspublish.json handling)
|
||||||
|
4. **TsUnpacker** - Output directory flattening
|
||||||
|
5. **FsHelpers** - Filesystem utilities (static methods)
|
||||||
|
6. **TsBuildCli** - CLI command handler
|
||||||
|
|
||||||
|
### CLI Commands (5)
|
||||||
|
1. **tsbuild** (default) - Compiles ./ts/**/*.ts → ./dist_ts/
|
||||||
|
2. **tsbuild custom <dir1> <dir2>** - Custom directory compilation
|
||||||
|
3. **tsbuild tsfolders** - Auto-discover ts_* folders, compile in order
|
||||||
|
4. **tsbuild emitcheck <pattern>** - Validate emit without output
|
||||||
|
5. **tsbuild check [pattern]** - Type check only
|
||||||
|
|
||||||
|
### CLI Flags
|
||||||
|
- `--skiplibcheck` - Skip .d.ts type checking (shows warning)
|
||||||
|
- `--confirmskiplibcheck` - Extended warning with 5s pause
|
||||||
|
- `--disallowimplicitany` - Stricter type checking
|
||||||
|
- `--commonjs` - Use CommonJS instead of ESNext
|
||||||
|
- `--quiet` - Suppress non-error output
|
||||||
|
- `--json` - JSON output format
|
||||||
|
|
||||||
|
## Architecture - Modular Structure
|
||||||
|
|
||||||
|
### Module Organization
|
||||||
|
```
|
||||||
|
ts/
|
||||||
|
index.ts # Main entry, re-exports all modules
|
||||||
|
plugins.ts # Dependency imports only
|
||||||
|
|
||||||
|
mod_fs/
|
||||||
|
index.ts # exports
|
||||||
|
classes.fshelpers.ts # FsHelpers - static filesystem utilities
|
||||||
|
|
||||||
|
mod_config/
|
||||||
|
index.ts # exports
|
||||||
|
classes.tsconfig.ts # TsConfig - tsconfig.json handling
|
||||||
|
classes.tspublishconfig.ts # TsPublishConfig - tspublish.json handling
|
||||||
|
|
||||||
|
mod_unpack/
|
||||||
|
index.ts # exports
|
||||||
|
classes.tsunpacker.ts # TsUnpacker - output flattening
|
||||||
|
|
||||||
|
mod_compiler/
|
||||||
|
index.ts # exports
|
||||||
|
classes.tscompiler.ts # TsCompiler + legacy compatibility functions
|
||||||
|
|
||||||
|
mod_cli/
|
||||||
|
index.ts # exports
|
||||||
|
classes.tsbuildcli.ts # TsBuildCli - CLI command handler
|
||||||
|
```
|
||||||
|
|
||||||
|
### Class Responsibilities
|
||||||
|
|
||||||
|
**TsCompiler** (`mod_compiler/classes.tscompiler.ts`)
|
||||||
|
- Core compilation with `compileFiles()`, `compileGlob()`
|
||||||
|
- Type checking with `checkTypes()`, `checkEmit()`
|
||||||
|
- Configuration via TsConfig
|
||||||
|
- Automatic unpacking via TsUnpacker
|
||||||
|
|
||||||
|
**TsConfig** (`mod_config/classes.tsconfig.ts`)
|
||||||
|
- Load and parse tsconfig.json
|
||||||
|
- Merge configuration with priority order
|
||||||
|
- Protected defaults handling
|
||||||
|
|
||||||
|
**TsPublishConfig** (`mod_config/classes.tspublishconfig.ts`)
|
||||||
|
- Load and parse tspublish.json
|
||||||
|
- `shouldUnpack` property (default true)
|
||||||
|
- `order` property for tsfolders ordering
|
||||||
|
|
||||||
|
**TsUnpacker** (`mod_unpack/classes.tsunpacker.ts`)
|
||||||
|
- Detect nested output structure
|
||||||
|
- Flatten output directories
|
||||||
|
- Configurable via TsPublishConfig
|
||||||
|
|
||||||
|
**FsHelpers** (`mod_fs/classes.fshelpers.ts`)
|
||||||
|
- `listFilesWithGlob()` - Glob pattern file listing
|
||||||
|
- `extractSourceFolder()` - Pattern parsing
|
||||||
|
- File/directory existence checks
|
||||||
|
- Directory operations
|
||||||
|
|
||||||
|
**TsBuildCli** (`mod_cli/classes.tsbuildcli.ts`)
|
||||||
|
- All CLI commands registered
|
||||||
|
- Uses TsCompiler for compilation
|
||||||
|
|
||||||
|
## Configuration Priority (5 levels)
|
||||||
|
1. Default options (hardcoded in TsConfig)
|
||||||
|
2. tsconfig.json (if exists)
|
||||||
|
3. Protected defaults (ensure integrity)
|
||||||
|
4. Programmatic options (function params)
|
||||||
|
5. CLI flags (highest priority)
|
||||||
|
|
||||||
|
### Protected Options
|
||||||
|
Cannot be overridden by tsconfig.json alone:
|
||||||
|
- `outDir: 'dist_ts/'` - Path transformation logic
|
||||||
|
- `noEmitOnError: true` - Build integrity
|
||||||
|
- `declaration: true` - Library support
|
||||||
|
- `inlineSourceMap: true` - Debugging
|
||||||
|
|
||||||
|
### Path Transformation
|
||||||
|
- Automatic: `./ts_interfaces` → `./dist_ts_interfaces`
|
||||||
|
- In tsconfig paths: `./ts_*` → `./dist_ts_*` (first array element only)
|
||||||
|
|
||||||
|
## Default Compiler Options
|
||||||
|
- Module: NodeNext (ESM with CommonJS fallback)
|
||||||
|
- Target: ESNext (latest JavaScript)
|
||||||
|
- Source Maps: Inline (no separate .map files)
|
||||||
|
- Declaration Files: ALWAYS generated (protected)
|
||||||
|
- Output: dist_ts/
|
||||||
|
- Implicit any: ALLOWED by default
|
||||||
|
- esModuleInterop: true
|
||||||
|
- verbatimModuleSyntax: true
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Error Summary Structure
|
||||||
|
```typescript
|
||||||
|
interface IErrorSummary {
|
||||||
|
errorsByFile: Record<string, Diagnostic[]>
|
||||||
|
generalErrors: Diagnostic[]
|
||||||
|
totalErrors: number
|
||||||
|
totalFiles: number
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compile Result Structure
|
||||||
|
```typescript
|
||||||
|
interface ICompileResult {
|
||||||
|
emittedFiles: string[]
|
||||||
|
errorSummary: IErrorSummary
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependencies Used
|
||||||
|
- @git.zone/tspublish@^1.10.3 - Module ordering
|
||||||
|
- @push.rocks/smartcli@^4.0.19 - CLI framework
|
||||||
|
- @push.rocks/smartfile@^13.1.2 - File content handling
|
||||||
|
- @push.rocks/smartfs@^1.2.0 - Filesystem operations
|
||||||
|
- @push.rocks/smartpath@^6.0.0 - Path transformation utilities
|
||||||
|
- @push.rocks/smartpromise@^4.2.3 - Promise utilities
|
||||||
|
- @push.rocks/smartdelay@^3.0.5 - Delay utilities
|
||||||
|
- typescript@5.9.3 - TypeScript compiler
|
||||||
|
|
||||||
|
### smartfs Usage
|
||||||
|
- File listing: `smartfs.directory(path).recursive().filter(pattern).list()`
|
||||||
|
- File existence: `smartfs.file(path).exists()`
|
||||||
|
- Directory existence: `smartfs.directory(path).exists()`
|
||||||
|
- FsHelpers wraps smartfs for glob pattern support
|
||||||
|
|
||||||
|
## Unpack Feature
|
||||||
|
|
||||||
|
When TypeScript compiles files that import from sibling directories, it creates nested output:
|
||||||
|
```
|
||||||
|
dist_ts_core/
|
||||||
|
ts_core/ ← nested output
|
||||||
|
ts_shared/ ← pulled-in dependency
|
||||||
|
```
|
||||||
|
|
||||||
|
The unpack feature automatically flattens this to:
|
||||||
|
```
|
||||||
|
dist_ts_core/
|
||||||
|
index.js ← flat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
- Reads `tspublish.json` from source folder
|
||||||
|
- `unpack: true` (default if not present) → flatten output
|
||||||
|
- `unpack: false` → skip unpacking
|
||||||
|
|
||||||
|
### Implementation
|
||||||
|
- `TsUnpacker` class in `mod_unpack/classes.tsunpacker.ts`
|
||||||
|
- Called automatically after each successful compilation in `TsCompiler.compileGlob()`
|
||||||
|
|
||||||
|
## Special Behaviors
|
||||||
|
|
||||||
|
### tsfolders Command Ordering
|
||||||
|
1. Always: ts_interfaces first (if no tspublish.json)
|
||||||
|
2. Always: ts_shared second (if no tspublish.json)
|
||||||
|
3. Then: Other folders by `order` property in their tspublish.json
|
||||||
|
4. Finally: Folders without order property (Infinity)
|
||||||
|
|
||||||
|
### check Command Default (No Arguments)
|
||||||
|
Two-phase check:
|
||||||
|
1. Phase 1: Type check ts/**/* (strict, include .d.ts)
|
||||||
|
2. Phase 2: Type check test/**/* (relaxed, skipLibCheck: true)
|
||||||
|
|
||||||
|
## Edge Cases
|
||||||
|
|
||||||
|
1. **Empty file list** - Returns [], no error
|
||||||
|
2. **Glob duplicates** - Files compile multiple times
|
||||||
|
3. **Non-existent files** - TypeScript "file not found" errors
|
||||||
|
4. **skipLibCheck warning** - 1-line default, 5s pause with --confirmskiplibcheck
|
||||||
|
5. **Missing tsconfig.json** - Graceful fallback, no error
|
||||||
|
6. **Module resolution** - --commonjs switches to NodeJs (not NodeNext)
|
||||||
|
7. **Source maps** - Inline only (not separate .map files)
|
||||||
|
8. **File filtering** - Only .ts and .tsx; .d.ts and .js ignored
|
||||||
|
|
||||||
|
## Build Safety Features
|
||||||
|
- `noEmitOnError: true` - Prevents broken builds
|
||||||
|
- Error aggregation before final output
|
||||||
|
- Protected options ensure integrity
|
||||||
|
- Pre-emit checks before emit phase
|
||||||
|
- CLI exit code handling (0=success, 1=error)
|
||||||
|
|
||||||
|
## Recent Changes
|
||||||
|
- 3.1.4+ - Major restructuring with mod_* modules
|
||||||
|
- Full OO architecture with TsCompiler, TsConfig, TsPublishConfig, TsUnpacker, TsBuildCli, FsHelpers
|
||||||
|
- Backward compatibility maintained for legacy functions
|
||||||
|
- Automatic "unpack" feature for nested output directories
|
||||||
|
- Migrated filesystem operations from smartfile to smartfs
|
||||||
633
readme.md
Normal file
633
readme.md
Normal file
@@ -0,0 +1,633 @@
|
|||||||
|
# @git.zone/tsbuild
|
||||||
|
|
||||||
|
A powerful, modern TypeScript build tool with smart defaults, full tsconfig.json support, and automatic output directory management.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using pnpm (recommended)
|
||||||
|
pnpm install @git.zone/tsbuild --save-dev
|
||||||
|
|
||||||
|
# Using npm
|
||||||
|
npm install @git.zone/tsbuild --save-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why tsbuild?
|
||||||
|
|
||||||
|
- **Smart tsconfig.json Integration** - Respects all your compiler options with intelligent merging
|
||||||
|
- **Protected Defaults** - Critical build settings are safeguarded while staying flexible
|
||||||
|
- **Zero Config** - Works perfectly without tsconfig.json
|
||||||
|
- **Glob Pattern Support** - Compile multiple directories with a single command
|
||||||
|
- **Dependency-Aware** - Automatically orders compilation based on module dependencies
|
||||||
|
- **Type Checking** - Validate code without emitting files
|
||||||
|
- **Clean Builds** - Automatically clears output directories before compilation
|
||||||
|
- **Auto-Unpack** - Flattens nested output directories automatically
|
||||||
|
- **CI/CD Ready** - JSON output mode and proper exit codes
|
||||||
|
- **Modern Defaults** - ESNext, NodeNext modules, decorators out of the box
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### CLI Usage
|
||||||
|
|
||||||
|
**Compile your TypeScript project:**
|
||||||
|
```bash
|
||||||
|
npx tsbuild
|
||||||
|
```
|
||||||
|
Compiles `./ts/**/*.ts` to `./dist_ts/`
|
||||||
|
|
||||||
|
**Custom directories:**
|
||||||
|
```bash
|
||||||
|
npx tsbuild custom src utils
|
||||||
|
```
|
||||||
|
Compiles:
|
||||||
|
- `./src/**/*.ts` to `./dist_src/`
|
||||||
|
- `./utils/**/*.ts` to `./dist_utils/`
|
||||||
|
|
||||||
|
**Auto-discover and compile in dependency order:**
|
||||||
|
```bash
|
||||||
|
npx tsbuild tsfolders
|
||||||
|
```
|
||||||
|
Finds all `ts_*` folders and compiles them respecting dependencies.
|
||||||
|
|
||||||
|
### Programmatic Usage
|
||||||
|
|
||||||
|
**Basic compilation:**
|
||||||
|
```typescript
|
||||||
|
import { TsCompiler } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
const compiler = new TsCompiler();
|
||||||
|
await compiler.compileFilesOrThrow([
|
||||||
|
'./src/index.ts',
|
||||||
|
'./src/utils.ts'
|
||||||
|
], { outDir: './dist' });
|
||||||
|
```
|
||||||
|
|
||||||
|
**Production-ready with error tracking (recommended):**
|
||||||
|
```typescript
|
||||||
|
import { TsCompiler } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
const compiler = new TsCompiler();
|
||||||
|
const result = await compiler.compileFiles([
|
||||||
|
'./src/index.ts',
|
||||||
|
'./src/utils.ts'
|
||||||
|
], { outDir: './dist' });
|
||||||
|
|
||||||
|
if (result.errorSummary.totalErrors > 0) {
|
||||||
|
console.error(`Compilation failed with ${result.errorSummary.totalErrors} errors`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Compiled ${result.emittedFiles.length} files successfully!`);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Glob pattern compilation:**
|
||||||
|
```typescript
|
||||||
|
import { TsCompiler } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
const compiler = new TsCompiler();
|
||||||
|
await compiler.compileGlob({
|
||||||
|
'./ts/**/*.ts': './dist_ts',
|
||||||
|
'./ts_web/**/*.ts': './dist_web'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## CLI Commands
|
||||||
|
|
||||||
|
### 1. Default Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
Compiles all TypeScript files from `./ts/` to `./dist_ts/`
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
- `--skiplibcheck` - Skip type checking of declaration files
|
||||||
|
- `--confirmskiplibcheck` - Skip lib check with extended warning (5s pause)
|
||||||
|
- `--disallowimplicitany` - Disallow implicit `any` types
|
||||||
|
- `--commonjs` - Use CommonJS instead of ESNext modules
|
||||||
|
- `--json` - Output results as JSON (for CI/CD)
|
||||||
|
- `--quiet` - Suppress console output
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
```bash
|
||||||
|
# Standard build
|
||||||
|
npx tsbuild
|
||||||
|
|
||||||
|
# Build with JSON output for CI
|
||||||
|
npx tsbuild --json --quiet
|
||||||
|
|
||||||
|
# CommonJS build
|
||||||
|
npx tsbuild --commonjs
|
||||||
|
|
||||||
|
# Strict mode
|
||||||
|
npx tsbuild --disallowimplicitany
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Custom Directories
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild custom <dir1> <dir2> ... [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
Compile specific directories to their corresponding `dist_` folders.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Compile src and utils
|
||||||
|
npx tsbuild custom src utils
|
||||||
|
# Creates: ./dist_src/ and ./dist_utils/
|
||||||
|
|
||||||
|
# Multiple directories with options
|
||||||
|
npx tsbuild custom api models services --commonjs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. TSFolders (Dependency-Aware)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild tsfolders [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
Automatically discovers and compiles all `ts_*` folders in dependency order:
|
||||||
|
|
||||||
|
1. Prioritizes `ts_interfaces` first (if no tspublish.json)
|
||||||
|
2. Prioritizes `ts_shared` second (if no tspublish.json)
|
||||||
|
3. Reads `tspublish.json` in each folder for `order` property
|
||||||
|
4. Compiles in correct sequence
|
||||||
|
|
||||||
|
**Example output:**
|
||||||
|
```
|
||||||
|
TypeScript Folder Compilation Plan (5 folders)
|
||||||
|
1/5 ts_interfaces
|
||||||
|
2/5 ts_shared
|
||||||
|
3/5 ts_core
|
||||||
|
4/5 ts_utils
|
||||||
|
5/5 ts_modules
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Emit Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild emitcheck <file_or_pattern> [more...] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
Validates TypeScript files can be compiled without actually emitting them.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check specific files
|
||||||
|
npx tsbuild emitcheck src/main.ts src/utils.ts
|
||||||
|
|
||||||
|
# Check with glob patterns
|
||||||
|
npx tsbuild emitcheck "src/**/*.ts" "test/**/*.ts"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exit codes:**
|
||||||
|
- `0` - All files can be emitted
|
||||||
|
- `1` - One or more files have errors
|
||||||
|
|
||||||
|
### 5. Type Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild check [pattern] [more...] [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
Performs type checking without emitting files.
|
||||||
|
|
||||||
|
**With arguments:** Check specified files/patterns
|
||||||
|
```bash
|
||||||
|
npx tsbuild check "ts/**/*.ts"
|
||||||
|
npx tsbuild check "src/**/*.ts" "test/**/*.ts"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Without arguments:** Two-phase default check
|
||||||
|
1. Phase 1: Type check `ts/**/*` (strict, includes .d.ts)
|
||||||
|
2. Phase 2: Type check `test/**/*` (relaxed, skipLibCheck: true)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild check
|
||||||
|
# Running default type checking sequence...
|
||||||
|
# Checking ts/**/* files...
|
||||||
|
# Checking test/**/* files with --skiplibcheck...
|
||||||
|
# All default type checks passed!
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### TsCompiler Class
|
||||||
|
|
||||||
|
The main class for TypeScript compilation.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { TsCompiler } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
const compiler = new TsCompiler(cwd?: string, argvArg?: any);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Constructor Parameters:**
|
||||||
|
- `cwd` - Working directory (defaults to `process.cwd()`)
|
||||||
|
- `argvArg` - CLI arguments object for flags like `--skiplibcheck`, `--quiet`, etc.
|
||||||
|
|
||||||
|
#### compileFiles(fileNames, customOptions?, taskInfo?)
|
||||||
|
|
||||||
|
Compile files with error tracking. Returns result instead of throwing.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await compiler.compileFiles(
|
||||||
|
['./src/index.ts', './src/utils.ts'],
|
||||||
|
{ outDir: './dist' }
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`Emitted: ${result.emittedFiles.length} files`);
|
||||||
|
console.log(`Errors: ${result.errorSummary.totalErrors}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Returns:** `Promise<ICompileResult>`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ICompileResult {
|
||||||
|
emittedFiles: string[];
|
||||||
|
errorSummary: IErrorSummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IErrorSummary {
|
||||||
|
errorsByFile: Record<string, Diagnostic[]>;
|
||||||
|
generalErrors: Diagnostic[];
|
||||||
|
totalErrors: number;
|
||||||
|
totalFiles: number;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### compileFilesOrThrow(fileNames, customOptions?)
|
||||||
|
|
||||||
|
Compile files and throw on error. For simple scripts.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
try {
|
||||||
|
const emittedFiles = await compiler.compileFilesOrThrow(
|
||||||
|
['./src/index.ts'],
|
||||||
|
{ outDir: './dist' }
|
||||||
|
);
|
||||||
|
console.log('Compiled:', emittedFiles);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Compilation failed!');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Returns:** `Promise<string[]>` - Array of emitted file paths
|
||||||
|
|
||||||
|
#### compileGlob(globPatterns, customOptions?)
|
||||||
|
|
||||||
|
Compile multiple glob patterns to different destinations. Automatically clears output directories before compilation and unpacks nested output.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await compiler.compileGlob({
|
||||||
|
'./ts/**/*.ts': './dist_ts',
|
||||||
|
'./ts_web/**/*.ts': './dist_web',
|
||||||
|
'./ts_node/**/*.ts': './dist_node'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Returns:** `Promise<ICompileResult>`
|
||||||
|
|
||||||
|
#### checkTypes(fileNames, customOptions?)
|
||||||
|
|
||||||
|
Type check files without emitting. Fast validation.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const success = await compiler.checkTypes(['./src/**/*.ts']);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
console.error('Type errors found!');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Returns:** `Promise<boolean>` - `true` if no errors
|
||||||
|
|
||||||
|
#### checkEmit(fileNames, customOptions?)
|
||||||
|
|
||||||
|
Validate files can be emitted without actually emitting.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const canEmit = await compiler.checkEmit(['./src/index.ts']);
|
||||||
|
|
||||||
|
if (!canEmit) {
|
||||||
|
console.error('Cannot emit these files!');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Returns:** `Promise<boolean>` - `true` if can emit
|
||||||
|
|
||||||
|
#### createOptions(customOptions?)
|
||||||
|
|
||||||
|
Get merged compiler options (useful for debugging).
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const options = compiler.createOptions({ strict: true });
|
||||||
|
console.log(options); // Shows merged options
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supporting Classes
|
||||||
|
|
||||||
|
#### TsConfig
|
||||||
|
|
||||||
|
TypeScript configuration management.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { TsConfig } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
const config = new TsConfig(process.cwd());
|
||||||
|
const options = config.merge({ target: 'ES2022' }, argvArg);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### TsPublishConfig
|
||||||
|
|
||||||
|
Reads `tspublish.json` for module configuration.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { TsPublishConfig } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
const pubConfig = new TsPublishConfig('./ts_core');
|
||||||
|
console.log(pubConfig.shouldUnpack); // true/false
|
||||||
|
console.log(pubConfig.order); // number or undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
#### TsUnpacker
|
||||||
|
|
||||||
|
Flattens nested TypeScript output directories.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { TsUnpacker } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
const unpacker = new TsUnpacker('./dist_ts', './ts');
|
||||||
|
await unpacker.unpack();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### FsHelpers
|
||||||
|
|
||||||
|
Static filesystem utilities.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { FsHelpers } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
const files = await FsHelpers.listFilesWithGlob('./', 'ts/**/*.ts');
|
||||||
|
const exists = await FsHelpers.fileExists('./tsconfig.json');
|
||||||
|
const dirExists = await FsHelpers.directoryExists('./ts');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### TsBuildCli
|
||||||
|
|
||||||
|
CLI command handler. Used internally by the CLI.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { TsBuildCli, runCli } from '@git.zone/tsbuild';
|
||||||
|
|
||||||
|
// Run the CLI
|
||||||
|
runCli();
|
||||||
|
|
||||||
|
// Or with custom working directory
|
||||||
|
const cli = new TsBuildCli('/path/to/project');
|
||||||
|
cli.run();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### tsconfig.json Support
|
||||||
|
|
||||||
|
tsbuild fully supports all compiler options from `tsconfig.json`. Your project configuration is respected and intelligently merged.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"verbatimModuleSyntax": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Priority (5 Levels)
|
||||||
|
|
||||||
|
When multiple configuration sources exist, they merge in this order (later overrides earlier):
|
||||||
|
|
||||||
|
1. **Default Options** - tsbuild's sensible defaults
|
||||||
|
2. **tsconfig.json** - All options from your tsconfig.json (if present)
|
||||||
|
3. **Protected Defaults** - Critical options for build integrity
|
||||||
|
4. **Programmatic Options** - Options passed to API functions
|
||||||
|
5. **CLI Flags** - Command-line arguments (highest priority)
|
||||||
|
|
||||||
|
### Protected Options
|
||||||
|
|
||||||
|
These options cannot be overridden by tsconfig.json alone (but can be overridden programmatically or via CLI):
|
||||||
|
|
||||||
|
- **`outDir: 'dist_ts/'`** - Required for automatic path transformations
|
||||||
|
- **`noEmitOnError: true`** - Prevents broken builds from being emitted
|
||||||
|
- **`declaration: true`** - Ensures `.d.ts` files for library consumers
|
||||||
|
- **`inlineSourceMap: true`** - Consistent debugging experience
|
||||||
|
|
||||||
|
### Default Compiler Options
|
||||||
|
|
||||||
|
When no tsconfig.json exists:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
declaration: true, // Generate .d.ts files
|
||||||
|
emitDecoratorMetadata: true, // Support DI frameworks
|
||||||
|
experimentalDecorators: true, // Enable decorators
|
||||||
|
inlineSourceMap: true, // Debug-friendly
|
||||||
|
noEmitOnError: true, // Fail-fast on errors
|
||||||
|
outDir: 'dist_ts/', // Output directory
|
||||||
|
module: 'NodeNext', // Modern Node.js modules
|
||||||
|
target: 'ESNext', // Latest JavaScript
|
||||||
|
moduleResolution: 'NodeNext',
|
||||||
|
noImplicitAny: false, // Flexible for quick development
|
||||||
|
esModuleInterop: true, // CJS/ESM interop
|
||||||
|
verbatimModuleSyntax: true // Explicit imports/exports
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Path Transformation
|
||||||
|
|
||||||
|
tsbuild automatically transforms path mappings:
|
||||||
|
|
||||||
|
**tsconfig.json:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@models/*": ["./ts_models/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Automatic transformation:**
|
||||||
|
```
|
||||||
|
./ts_models/* -> ./dist_ts_models/*
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### Clean Builds
|
||||||
|
|
||||||
|
Output directories are automatically cleared before compilation:
|
||||||
|
|
||||||
|
```
|
||||||
|
Clearing output directory: ./dist_ts
|
||||||
|
Compiling 14 files from ./ts/**/*.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures no stale files remain from previous builds.
|
||||||
|
|
||||||
|
### Auto-Unpack
|
||||||
|
|
||||||
|
When TypeScript compiles files that import from sibling directories, it creates nested output:
|
||||||
|
|
||||||
|
```
|
||||||
|
dist_ts_core/
|
||||||
|
ts_core/ <- nested output
|
||||||
|
ts_shared/ <- pulled-in dependency
|
||||||
|
```
|
||||||
|
|
||||||
|
tsbuild automatically flattens this to:
|
||||||
|
|
||||||
|
```
|
||||||
|
dist_ts_core/
|
||||||
|
index.js <- flat
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure via `tspublish.json` in source folder:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"unpack": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Set `"unpack": false` to disable.
|
||||||
|
|
||||||
|
### Decorator Support
|
||||||
|
|
||||||
|
First-class decorator support out of the box:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Injectable()
|
||||||
|
class UserService {
|
||||||
|
constructor(
|
||||||
|
@Inject('CONFIG') private config: Config,
|
||||||
|
private logger: Logger
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Works with NestJS, TypeORM, Inversify, Angular, and other DI frameworks.
|
||||||
|
|
||||||
|
## CI/CD Integration
|
||||||
|
|
||||||
|
### GitHub Actions
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Build
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- run: npx tsbuild
|
||||||
|
```
|
||||||
|
|
||||||
|
### JSON Output
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild --json --quiet
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"totals": {
|
||||||
|
"errors": 0,
|
||||||
|
"filesWithErrors": 0,
|
||||||
|
"tasks": 1
|
||||||
|
},
|
||||||
|
"errorsByFile": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Package.json Scripts
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsbuild",
|
||||||
|
"build:prod": "tsbuild --disallowimplicitany",
|
||||||
|
"typecheck": "tsbuild check",
|
||||||
|
"pretest": "tsbuild emitcheck 'test/**/*.ts'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
**"Cannot find module" errors in compiled output**
|
||||||
|
|
||||||
|
Make sure path mappings are configured in tsconfig.json. tsbuild automatically transforms them.
|
||||||
|
|
||||||
|
**Decorator errors**
|
||||||
|
|
||||||
|
Ensure your tsconfig.json has:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"emitDecoratorMetadata": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Slow compilation**
|
||||||
|
|
||||||
|
Use `--skiplibcheck` to skip declaration file checking:
|
||||||
|
```bash
|
||||||
|
npx tsbuild --skiplibcheck
|
||||||
|
```
|
||||||
|
|
||||||
|
Only use this if you trust your dependencies' type definitions.
|
||||||
|
|
||||||
|
## Issue Reporting
|
||||||
|
|
||||||
|
For reporting issues or vulnerabilities, please visit our community at [community.foss.global](https://community.foss.global). We're looking forward to your contribution!
|
||||||
|
|
||||||
|
For repository access: [code.foss.global/git.zone/tsbuild](https://code.foss.global/git.zone/tsbuild)
|
||||||
|
|
||||||
|
## License and Legal Information
|
||||||
|
|
||||||
|
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
||||||
|
|
||||||
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
### Trademarks
|
||||||
|
|
||||||
|
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
|
||||||
|
|
||||||
|
### Company Information
|
||||||
|
|
||||||
|
Task Venture Capital GmbH
|
||||||
|
Registered at District Court Bremen HRB 35230 HB, Germany
|
||||||
|
|
||||||
|
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||||||
|
|
||||||
|
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
||||||
45
readme.plan.md
Normal file
45
readme.plan.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# Implementation Plan for tsbuild `check` Command
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Add a new `check` command to tsbuild that allows checking TypeScript files against a glob pattern without emitting them, similar to running the TypeScript compiler with the `--noEmit` flag.
|
||||||
|
|
||||||
|
## Implementation Steps
|
||||||
|
|
||||||
|
1. **Reread CLAUDE.md** to ensure we follow project guidelines
|
||||||
|
|
||||||
|
2. **Extend TsBuild Class**
|
||||||
|
- The existing `TsBuild` class already has a `checkEmit()` method
|
||||||
|
- We can leverage this method for our implementation
|
||||||
|
|
||||||
|
3. **Implement Check Command in CLI**
|
||||||
|
- Add a new `check` command to `tsbuild.cli.ts`
|
||||||
|
- Command should accept glob patterns as arguments
|
||||||
|
- Process glob patterns to find matching TypeScript files
|
||||||
|
- Use the `TsBuild` class to check the files without emitting
|
||||||
|
|
||||||
|
4. **Update Exports**
|
||||||
|
- Ensure any new functionality is properly exported
|
||||||
|
|
||||||
|
5. **Testing**
|
||||||
|
- Test the command with various glob patterns
|
||||||
|
- Verify error reporting works correctly
|
||||||
|
|
||||||
|
## Differences from Existing `emitcheck` Command
|
||||||
|
The `emitcheck` command already exists and checks specific files without emitting. Our new `check` command will:
|
||||||
|
- Be designed specifically for checking files against glob patterns
|
||||||
|
- Use a simpler, more intuitive command name
|
||||||
|
- Potentially add additional benefits (like summary statistics of checked files)
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
Once implemented, the command would work like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx tsbuild check ts/**/*
|
||||||
|
npx tsbuild check "src/**/*.ts" "test/**/*.ts"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Expected Output
|
||||||
|
The command should:
|
||||||
|
- Report any TypeScript errors in the matched files
|
||||||
|
- Provide a count of files checked and any errors found
|
||||||
|
- Exit with code 0 if successful, or 1 if errors are found
|
||||||
5
test/assets/output/tocompile.d.ts
vendored
5
test/assets/output/tocompile.d.ts
vendored
@@ -1,5 +0,0 @@
|
|||||||
declare class test2 {
|
|
||||||
test: string[];
|
|
||||||
constructor();
|
|
||||||
}
|
|
||||||
declare const run: () => Promise<string>;
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
console.log('test');
|
|
||||||
console.log('test2');
|
|
||||||
class test2 {
|
|
||||||
constructor() {
|
|
||||||
this.test = [];
|
|
||||||
console.log('hi');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const run = async () => {
|
|
||||||
return 'hi';
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9jb21waWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdG9jb21waWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDcEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUNyQixNQUFNLEtBQUs7SUFFVDtRQURBLFNBQUksR0FBYSxFQUFFLENBQUM7UUFFbEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQixDQUFDO0NBQ0Y7QUFFRCxNQUFNLEdBQUcsR0FBRyxLQUFLLElBQXFCLEVBQUU7SUFDdEMsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDLENBQUMifQ==
|
|
||||||
0
test/assets/output/tocompile2.d.ts
vendored
0
test/assets/output/tocompile2.d.ts
vendored
@@ -1,2 +0,0 @@
|
|||||||
console.log('hello');
|
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9jb21waWxlMi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RvY29tcGlsZTIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyJ9
|
|
||||||
@@ -1,5 +1,14 @@
|
|||||||
console.log('test');
|
console.log('test');
|
||||||
console.log('test2');
|
console.log('test2');
|
||||||
|
|
||||||
|
import * as early from '@push.rocks/early';
|
||||||
|
|
||||||
|
early.start();
|
||||||
|
early.stop();
|
||||||
|
|
||||||
|
import { anExportedString } from './tocompile2.js';
|
||||||
|
console.log(anExportedString);
|
||||||
|
|
||||||
class test2 {
|
class test2 {
|
||||||
test: string[] = [];
|
test: string[] = [];
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
console.log('hello');
|
console.log('hello');
|
||||||
|
export const anExportedString = 'exported string';
|
||||||
|
|||||||
20
test/test.ts
20
test/test.ts
@@ -1,19 +1,21 @@
|
|||||||
import { tap, expect } from '@pushrocks/tapbundle';
|
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||||
|
|
||||||
import * as tsn from '../ts/index';
|
import { TsCompiler } from '../ts/index.js';
|
||||||
|
|
||||||
let assetfiles: string[] = ['./test/assets/tocompile.ts', './test/assets/tocompile2.ts'];
|
const assetfiles: string[] = ['./test/assets/tocompile.ts', './test/assets/tocompile2.ts'];
|
||||||
|
|
||||||
let assetfiles2 = {
|
const assetfiles2 = {
|
||||||
'./test/assets/**/!(*.d.ts|*.js|output)': './test/assets/output'
|
'./test/assets/**/!(*.d.ts|*.js|output)': './test/assets/output',
|
||||||
};
|
};
|
||||||
|
|
||||||
tap.test('should convert files from an array with single files to output', async tools => {
|
tap.test('should compile files from an array', async () => {
|
||||||
tsn.compileFileArray(assetfiles, { outDir: './test/assets/output' });
|
const compiler = new TsCompiler();
|
||||||
|
await compiler.compileFilesOrThrow(assetfiles, { outDir: './test/assets/output' });
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should convert files from an array with single files to output', async tools => {
|
tap.test('should compile files from glob pattern object', async () => {
|
||||||
tsn.compileGlobStringObject(assetfiles2);
|
const compiler = new TsCompiler();
|
||||||
|
await compiler.compileGlob(assetfiles2);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.start();
|
tap.start();
|
||||||
|
|||||||
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
|
*/
|
||||||
|
export const commitinfo = {
|
||||||
|
name: '@git.zone/tsbuild',
|
||||||
|
version: '4.0.2',
|
||||||
|
description: 'A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.'
|
||||||
|
}
|
||||||
15
ts/index.ts
15
ts/index.ts
@@ -1,3 +1,14 @@
|
|||||||
export * from './tsbuild.exports';
|
import * as early from '@push.rocks/early';
|
||||||
|
early.start('tsbuild');
|
||||||
|
|
||||||
import './tsbuild.cli';
|
// Export from new modular structure
|
||||||
|
export * from './mod_fs/index.js';
|
||||||
|
export * from './mod_config/index.js';
|
||||||
|
export * from './mod_unpack/index.js';
|
||||||
|
export * from './mod_compiler/index.js';
|
||||||
|
export * from './mod_cli/index.js';
|
||||||
|
|
||||||
|
// Re-export TypeScript types for convenience
|
||||||
|
export type { CompilerOptions, ScriptTarget, ModuleKind } from 'typescript';
|
||||||
|
|
||||||
|
early.stop();
|
||||||
|
|||||||
320
ts/mod_cli/classes.tsbuildcli.ts
Normal file
320
ts/mod_cli/classes.tsbuildcli.ts
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import * as smartcli from '@push.rocks/smartcli';
|
||||||
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
|
import * as tspublish from '@git.zone/tspublish';
|
||||||
|
|
||||||
|
import { TsCompiler } from '../mod_compiler/index.js';
|
||||||
|
import { FsHelpers } from '../mod_fs/index.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TsBuildCli handles all CLI commands for tsbuild.
|
||||||
|
* Provides commands for compiling, type checking, and emit validation.
|
||||||
|
*/
|
||||||
|
export class TsBuildCli {
|
||||||
|
private cli: smartcli.Smartcli;
|
||||||
|
private cwd: string;
|
||||||
|
|
||||||
|
constructor(cwd: string = process.cwd()) {
|
||||||
|
this.cwd = cwd;
|
||||||
|
this.cli = new smartcli.Smartcli();
|
||||||
|
this.registerCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register all CLI commands
|
||||||
|
*/
|
||||||
|
private registerCommands(): void {
|
||||||
|
this.registerStandardCommand();
|
||||||
|
this.registerCustomCommand();
|
||||||
|
this.registerEmitCheckCommand();
|
||||||
|
this.registerTsFoldersCommand();
|
||||||
|
this.registerCheckCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard command: compiles ts folder to dist_ts
|
||||||
|
*/
|
||||||
|
private registerStandardCommand(): void {
|
||||||
|
this.cli.standardCommand().subscribe(async (argvArg) => {
|
||||||
|
const compiler = new TsCompiler(this.cwd, argvArg);
|
||||||
|
await compiler.compileGlob({
|
||||||
|
'./ts/**/*.ts': './dist_ts',
|
||||||
|
});
|
||||||
|
const summary = (argvArg as any)?.__tsbuildFinalErrorSummary;
|
||||||
|
if (summary && summary.totalErrors > 0) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom command: compiles specified directories to dist_ prefixed directories
|
||||||
|
*/
|
||||||
|
private registerCustomCommand(): void {
|
||||||
|
this.cli.addCommand('custom').subscribe(async (argvArg) => {
|
||||||
|
const listedDirectories = argvArg._;
|
||||||
|
listedDirectories.shift(); // removes the first element that is "custom"
|
||||||
|
|
||||||
|
const compilationCommandObject: Record<string, string> = {};
|
||||||
|
for (const directory of listedDirectories) {
|
||||||
|
compilationCommandObject[`./${directory}/**/*.ts`] = `./dist_${directory}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const compiler = new TsCompiler(this.cwd, argvArg);
|
||||||
|
await compiler.compileGlob(compilationCommandObject);
|
||||||
|
|
||||||
|
const summary = (argvArg as any)?.__tsbuildFinalErrorSummary;
|
||||||
|
if (summary && summary.totalErrors > 0) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit check command: validates files can be emitted without producing output
|
||||||
|
*/
|
||||||
|
private registerEmitCheckCommand(): void {
|
||||||
|
this.cli.addCommand('emitcheck').subscribe(async (argvArg) => {
|
||||||
|
const patterns = argvArg._.slice(1);
|
||||||
|
|
||||||
|
if (patterns.length === 0) {
|
||||||
|
console.error('\n❌ Error: Please provide at least one TypeScript file path or glob pattern');
|
||||||
|
console.error(' Usage: tsbuild emitcheck <file_or_glob_pattern> [additional_patterns ...]\n');
|
||||||
|
console.error(' Example: tsbuild emitcheck "src/**/*.ts" "test/**/*.ts"\n');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const allFiles = await this.collectFilesFromPatterns(patterns);
|
||||||
|
|
||||||
|
if (allFiles.length === 0) {
|
||||||
|
console.error('\n❌ Error: No TypeScript files found to check');
|
||||||
|
console.error(' Please verify your file paths or glob patterns.\n');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`\n🔎 Found ${allFiles.length} TypeScript file${allFiles.length !== 1 ? 's' : ''} to check`);
|
||||||
|
|
||||||
|
const compiler = new TsCompiler(this.cwd, argvArg);
|
||||||
|
const success = await compiler.checkEmit(allFiles);
|
||||||
|
|
||||||
|
process.exit(success ? 0 : 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TsFolders command: compiles all ts_* directories in order
|
||||||
|
*/
|
||||||
|
private registerTsFoldersCommand(): void {
|
||||||
|
this.cli.addCommand('tsfolders').subscribe(async (argvArg) => {
|
||||||
|
// List folders matching /^ts/ regex
|
||||||
|
const allEntries = await FsHelpers.listDirectory(this.cwd);
|
||||||
|
const tsFolders = allEntries
|
||||||
|
.filter((e) => e.isDirectory && /^ts/.test(e.name))
|
||||||
|
.map((e) => e.name);
|
||||||
|
|
||||||
|
// Get tspublish.json based ranking
|
||||||
|
const tsPublishInstance = new tspublish.TsPublish();
|
||||||
|
const tsPublishModules = await tsPublishInstance.getModuleSubDirs(this.cwd);
|
||||||
|
|
||||||
|
// Create an array with folder names and their ranks
|
||||||
|
const foldersWithOrder: Array<{ folder: string; rank: number }> = [];
|
||||||
|
|
||||||
|
for (const folder of tsFolders) {
|
||||||
|
let rank = Infinity;
|
||||||
|
if (tsPublishModules[folder] && tsPublishModules[folder].order !== undefined) {
|
||||||
|
rank = tsPublishModules[folder].order;
|
||||||
|
}
|
||||||
|
foldersWithOrder.push({ folder, rank });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the folders based on rank
|
||||||
|
foldersWithOrder.sort((a, b) => a.rank - b.rank);
|
||||||
|
|
||||||
|
// Construct the sorted list of folders
|
||||||
|
const sortedTsFolders: string[] = [];
|
||||||
|
|
||||||
|
for (const item of foldersWithOrder) {
|
||||||
|
sortedTsFolders.push(item.folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure ts_interfaces is first and ts_shared is second if they exist
|
||||||
|
const ensurePosition = (folderName: string, position: number) => {
|
||||||
|
if (tsFolders.indexOf(folderName) > -1 && Object.keys(tsPublishModules).indexOf(folderName) === -1) {
|
||||||
|
const currentIndex = sortedTsFolders.indexOf(folderName);
|
||||||
|
if (currentIndex > -1) {
|
||||||
|
sortedTsFolders.splice(currentIndex, 1);
|
||||||
|
}
|
||||||
|
sortedTsFolders.splice(position, 0, folderName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ensurePosition('ts_interfaces', 0);
|
||||||
|
ensurePosition('ts_shared', 1);
|
||||||
|
|
||||||
|
// Display compilation plan
|
||||||
|
const folderCount = sortedTsFolders.length;
|
||||||
|
console.log(`\n📂 TypeScript Folder Compilation Plan (${folderCount} folder${folderCount !== 1 ? 's' : ''})`);
|
||||||
|
console.log('┌' + '─'.repeat(60) + '┐');
|
||||||
|
console.log('│ 🔄 Compilation Order │');
|
||||||
|
console.log('├' + '─'.repeat(60) + '┤');
|
||||||
|
|
||||||
|
sortedTsFolders.forEach((folder, index) => {
|
||||||
|
const prefix = index === folderCount - 1 ? '└─' : '├─';
|
||||||
|
const position = `${index + 1}/${folderCount}`;
|
||||||
|
console.log(`│ ${prefix} ${position.padStart(5)} ${folder.padEnd(46)} │`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('└' + '─'.repeat(60) + '┘\n');
|
||||||
|
|
||||||
|
// Build compilation object
|
||||||
|
const compilationCommandObject: Record<string, string> = {};
|
||||||
|
for (const tsFolder of sortedTsFolders) {
|
||||||
|
compilationCommandObject[`./${tsFolder}/**/*.ts`] = `./dist_${tsFolder}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const compiler = new TsCompiler(this.cwd, argvArg);
|
||||||
|
await compiler.compileGlob(compilationCommandObject);
|
||||||
|
|
||||||
|
const summary = (argvArg as any)?.__tsbuildFinalErrorSummary;
|
||||||
|
if (summary && summary.totalErrors > 0) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check command: type checks files without emitting
|
||||||
|
*/
|
||||||
|
private registerCheckCommand(): void {
|
||||||
|
this.cli.addCommand('check').subscribe(async (argvArg) => {
|
||||||
|
const patterns = argvArg._.slice(1);
|
||||||
|
|
||||||
|
// If no patterns provided, default to checking ts/**/* and then test/**/*
|
||||||
|
if (patterns.length === 0) {
|
||||||
|
await this.runDefaultTypeChecks(argvArg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allFiles = await this.collectFilesFromPatterns(patterns);
|
||||||
|
|
||||||
|
if (allFiles.length === 0) {
|
||||||
|
console.error('\n❌ Error: No TypeScript files found to check');
|
||||||
|
console.error(' Please verify your file paths or glob patterns.\n');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`\n🔎 Found ${allFiles.length} TypeScript file${allFiles.length !== 1 ? 's' : ''} to check`);
|
||||||
|
|
||||||
|
const compiler = new TsCompiler(this.cwd, argvArg);
|
||||||
|
const success = await compiler.checkTypes(allFiles);
|
||||||
|
|
||||||
|
process.exit(success ? 0 : 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run default type checks for ts/ and test/ directories
|
||||||
|
*/
|
||||||
|
private async runDefaultTypeChecks(argvArg: any): Promise<void> {
|
||||||
|
console.log('\n🔬 Running default type checking sequence...\n');
|
||||||
|
|
||||||
|
// First check ts/**/* without skiplibcheck
|
||||||
|
console.log('📂 Checking ts/**/* files...');
|
||||||
|
const tsTsFiles = await FsHelpers.listFilesWithGlob(this.cwd, 'ts/**/*.ts');
|
||||||
|
|
||||||
|
if (tsTsFiles.length > 0) {
|
||||||
|
console.log(` Found ${tsTsFiles.length} TypeScript files in ts/`);
|
||||||
|
const tsAbsoluteFiles = smartpath.transform.toAbsolute(tsTsFiles, this.cwd) as string[];
|
||||||
|
|
||||||
|
const tsCompiler = new TsCompiler(this.cwd, argvArg);
|
||||||
|
const tsSuccess = await tsCompiler.checkTypes(tsAbsoluteFiles);
|
||||||
|
|
||||||
|
if (!tsSuccess) {
|
||||||
|
console.error('❌ Type checking failed for ts/**/*');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log('✅ Type checking passed for ts/**/*\n');
|
||||||
|
} else {
|
||||||
|
console.log(' No TypeScript files found in ts/\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then check test/**/* with skiplibcheck
|
||||||
|
console.log('📂 Checking test/**/* files with --skiplibcheck...');
|
||||||
|
const testTsFiles = await FsHelpers.listFilesWithGlob(this.cwd, 'test/**/*.ts');
|
||||||
|
|
||||||
|
if (testTsFiles.length > 0) {
|
||||||
|
console.log(` Found ${testTsFiles.length} TypeScript files in test/`);
|
||||||
|
const testAbsoluteFiles = smartpath.transform.toAbsolute(testTsFiles, this.cwd) as string[];
|
||||||
|
|
||||||
|
const testArgvArg = { ...argvArg, skiplibcheck: true };
|
||||||
|
const testCompiler = new TsCompiler(this.cwd, testArgvArg);
|
||||||
|
const testSuccess = await testCompiler.checkTypes(testAbsoluteFiles);
|
||||||
|
|
||||||
|
if (!testSuccess) {
|
||||||
|
console.error('❌ Type checking failed for test/**/*');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log('✅ Type checking passed for test/**/*\n');
|
||||||
|
} else {
|
||||||
|
console.log(' No TypeScript files found in test/\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ All default type checks passed!\n');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect files from patterns (glob or direct paths)
|
||||||
|
*/
|
||||||
|
private async collectFilesFromPatterns(patterns: string[]): Promise<string[]> {
|
||||||
|
let allFiles: string[] = [];
|
||||||
|
|
||||||
|
for (const pattern of patterns) {
|
||||||
|
if (pattern.includes('*') || pattern.includes('{') || pattern.includes('?')) {
|
||||||
|
// Handle as glob pattern
|
||||||
|
console.log(`Processing glob pattern: ${pattern}`);
|
||||||
|
try {
|
||||||
|
const stringMatchedFiles = await FsHelpers.listFilesWithGlob(this.cwd, pattern);
|
||||||
|
|
||||||
|
if (stringMatchedFiles.length === 0) {
|
||||||
|
console.warn(`⚠️ Warning: No files matched the pattern '${pattern}'`);
|
||||||
|
} else {
|
||||||
|
console.log(`📂 Found ${stringMatchedFiles.length} files matching pattern '${pattern}'`);
|
||||||
|
const absoluteMatchedFiles = smartpath.transform.toAbsolute(stringMatchedFiles, this.cwd) as string[];
|
||||||
|
allFiles = allFiles.concat(absoluteMatchedFiles);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`❌ Error processing glob pattern '${pattern}': ${err}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle as direct file path
|
||||||
|
const filePath = path.isAbsolute(pattern) ? pattern : path.join(this.cwd, pattern);
|
||||||
|
const fileExists = await FsHelpers.fileExists(filePath);
|
||||||
|
if (fileExists) {
|
||||||
|
allFiles.push(filePath);
|
||||||
|
} else {
|
||||||
|
console.error(`❌ Error: File not found: ${filePath}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter to only TypeScript files
|
||||||
|
return allFiles.filter((file) => file.endsWith('.ts') || file.endsWith('.tsx'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start parsing CLI arguments
|
||||||
|
*/
|
||||||
|
public run(): void {
|
||||||
|
this.cli.startParse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the CLI
|
||||||
|
*/
|
||||||
|
export const runCli = async (): Promise<void> => {
|
||||||
|
const cli = new TsBuildCli();
|
||||||
|
cli.run();
|
||||||
|
};
|
||||||
1
ts/mod_cli/index.ts
Normal file
1
ts/mod_cli/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './classes.tsbuildcli.js';
|
||||||
544
ts/mod_compiler/classes.tscompiler.ts
Normal file
544
ts/mod_compiler/classes.tscompiler.ts
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
import type { CompilerOptions, Diagnostic, Program } from 'typescript';
|
||||||
|
import typescript from 'typescript';
|
||||||
|
import * as smartdelay from '@push.rocks/smartdelay';
|
||||||
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
|
|
||||||
|
import { TsConfig } from '../mod_config/index.js';
|
||||||
|
import { FsHelpers } from '../mod_fs/index.js';
|
||||||
|
import { performUnpack } from '../mod_unpack/index.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for error summary data
|
||||||
|
*/
|
||||||
|
export interface IErrorSummary {
|
||||||
|
errorsByFile: Record<string, Diagnostic[]>;
|
||||||
|
generalErrors: Diagnostic[];
|
||||||
|
totalErrors: number;
|
||||||
|
totalFiles: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for task information
|
||||||
|
*/
|
||||||
|
export interface ITaskInfo {
|
||||||
|
taskNumber: number;
|
||||||
|
totalTasks: number;
|
||||||
|
sourcePattern: string;
|
||||||
|
destDir: string;
|
||||||
|
fileCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for compilation result
|
||||||
|
*/
|
||||||
|
export interface ICompileResult {
|
||||||
|
emittedFiles: string[];
|
||||||
|
errorSummary: IErrorSummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TsCompiler handles TypeScript compilation with error tracking,
|
||||||
|
* configuration management, and output unpacking.
|
||||||
|
*/
|
||||||
|
export class TsCompiler {
|
||||||
|
private config: TsConfig;
|
||||||
|
private cwd: string;
|
||||||
|
private argvArg?: any;
|
||||||
|
|
||||||
|
constructor(cwd: string = process.cwd(), argvArg?: any) {
|
||||||
|
this.cwd = cwd;
|
||||||
|
this.config = new TsConfig(cwd);
|
||||||
|
this.argvArg = argvArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current working directory
|
||||||
|
*/
|
||||||
|
public getCwd(): string {
|
||||||
|
return this.cwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the TsConfig instance
|
||||||
|
*/
|
||||||
|
public getConfig(): TsConfig {
|
||||||
|
return this.config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create compiler options by merging defaults, tsconfig.json, and custom options
|
||||||
|
*/
|
||||||
|
public createOptions(customOptions: CompilerOptions = {}): CompilerOptions {
|
||||||
|
return this.config.merge(customOptions, this.argvArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TypeScript program from file names and options
|
||||||
|
*/
|
||||||
|
private createProgram(fileNames: string[], options: CompilerOptions): Program {
|
||||||
|
return typescript.createProgram(fileNames, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process TypeScript diagnostics and return error summary
|
||||||
|
*/
|
||||||
|
private processDiagnostics(diagnostics: readonly Diagnostic[]): IErrorSummary {
|
||||||
|
const errorsByFile: Record<string, Diagnostic[]> = {};
|
||||||
|
const generalErrors: Diagnostic[] = [];
|
||||||
|
|
||||||
|
diagnostics.forEach((diagnostic) => {
|
||||||
|
if (diagnostic.file) {
|
||||||
|
const fileName = diagnostic.file.fileName;
|
||||||
|
if (!errorsByFile[fileName]) {
|
||||||
|
errorsByFile[fileName] = [];
|
||||||
|
}
|
||||||
|
errorsByFile[fileName].push(diagnostic);
|
||||||
|
} else {
|
||||||
|
generalErrors.push(diagnostic);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
errorsByFile,
|
||||||
|
generalErrors,
|
||||||
|
totalErrors: diagnostics.length,
|
||||||
|
totalFiles: Object.keys(errorsByFile).length,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display error summary to console
|
||||||
|
*/
|
||||||
|
private displayErrorSummary(errorSummary: IErrorSummary): void {
|
||||||
|
if (errorSummary.totalErrors === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { errorsByFile, generalErrors, totalErrors, totalFiles } = errorSummary;
|
||||||
|
|
||||||
|
// Print error summary header
|
||||||
|
console.log('\n' + '='.repeat(80));
|
||||||
|
console.log(
|
||||||
|
`❌ Found ${totalErrors} error${totalErrors !== 1 ? 's' : ''} in ${totalFiles} file${totalFiles !== 1 ? 's' : ''}:`
|
||||||
|
);
|
||||||
|
console.log('='.repeat(80));
|
||||||
|
|
||||||
|
// Color codes for error formatting
|
||||||
|
const colors = {
|
||||||
|
reset: '\x1b[0m',
|
||||||
|
red: '\x1b[31m',
|
||||||
|
yellow: '\x1b[33m',
|
||||||
|
cyan: '\x1b[36m',
|
||||||
|
white: '\x1b[37m',
|
||||||
|
brightRed: '\x1b[91m',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Print file-specific errors
|
||||||
|
Object.entries(errorsByFile).forEach(([fileName, fileErrors]) => {
|
||||||
|
// Show relative path if possible for cleaner output
|
||||||
|
const displayPath = fileName.replace(process.cwd(), '').replace(/^\//, '');
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`\n${colors.cyan}File: ${displayPath} ${colors.yellow}(${fileErrors.length} error${fileErrors.length !== 1 ? 's' : ''})${colors.reset}`
|
||||||
|
);
|
||||||
|
console.log('-'.repeat(80));
|
||||||
|
|
||||||
|
fileErrors.forEach((diagnostic) => {
|
||||||
|
if (diagnostic.file && diagnostic.start !== undefined) {
|
||||||
|
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||||
|
const message = typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
|
const errorCode = diagnostic.code ? `TS${diagnostic.code}` : 'Error';
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`${colors.white}Line ${line + 1}, Col ${character + 1}${colors.reset}: ${colors.brightRed}${errorCode}${colors.reset} - ${message}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try to show the code snippet if possible
|
||||||
|
try {
|
||||||
|
const lineContent = diagnostic.file.text.split('\n')[line];
|
||||||
|
if (lineContent) {
|
||||||
|
console.log(` ${lineContent.trimEnd()}`);
|
||||||
|
const indicator = ' '.repeat(character) + `${colors.red}^${colors.reset}`;
|
||||||
|
console.log(` ${indicator}`);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Failed to get source text, skip showing the code snippet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Print general errors
|
||||||
|
if (generalErrors.length > 0) {
|
||||||
|
console.log(`\n${colors.yellow}General Errors:${colors.reset}`);
|
||||||
|
console.log('-'.repeat(80));
|
||||||
|
|
||||||
|
generalErrors.forEach((diagnostic) => {
|
||||||
|
const message = typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||||
|
const errorCode = diagnostic.code ? `TS${diagnostic.code}` : 'Error';
|
||||||
|
console.log(`${colors.brightRed}${errorCode}${colors.reset}: ${message}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(80) + '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle skipLibCheck warning display
|
||||||
|
*/
|
||||||
|
private async handleSkipLibCheckWarning(): Promise<void> {
|
||||||
|
if (this.argvArg?.confirmskiplibcheck) {
|
||||||
|
console.log('\n⚠️ WARNING ⚠️');
|
||||||
|
console.log('You are skipping libcheck... Is that really wanted?');
|
||||||
|
console.log('Continuing in 5 seconds...\n');
|
||||||
|
await smartdelay.delayFor(5000);
|
||||||
|
} else if (!this.argvArg?.quiet && !this.argvArg?.json) {
|
||||||
|
console.log('⚠️ skipLibCheck enabled; use --confirmskiplibcheck to pause with warning.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile files with error tracking (returns result instead of throwing)
|
||||||
|
*/
|
||||||
|
public async compileFiles(
|
||||||
|
fileNames: string[],
|
||||||
|
customOptions: CompilerOptions = {},
|
||||||
|
taskInfo?: ITaskInfo
|
||||||
|
): Promise<ICompileResult> {
|
||||||
|
const options = this.createOptions(customOptions);
|
||||||
|
|
||||||
|
if (options.skipLibCheck) {
|
||||||
|
await this.handleSkipLibCheckWarning();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enhanced logging with task info
|
||||||
|
const startTime = Date.now();
|
||||||
|
if (taskInfo) {
|
||||||
|
const { taskNumber, totalTasks, sourcePattern, fileCount } = taskInfo;
|
||||||
|
const relativeDestDir = taskInfo.destDir.replace(process.cwd(), '').replace(/^\//, '');
|
||||||
|
console.log(
|
||||||
|
`\n🔨 [${taskNumber}/${totalTasks}] Compiling ${fileCount} file${fileCount !== 1 ? 's' : ''} from ${sourcePattern}`
|
||||||
|
);
|
||||||
|
console.log(` 📁 Output: ${relativeDestDir}`);
|
||||||
|
} else {
|
||||||
|
console.log(`🔨 Compiling ${fileNames.length} files...`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const done = smartpromise.defer<ICompileResult>();
|
||||||
|
const program = this.createProgram(fileNames, options);
|
||||||
|
|
||||||
|
// Check for pre-emit diagnostics first
|
||||||
|
const preEmitDiagnostics = typescript.getPreEmitDiagnostics(program);
|
||||||
|
const preEmitErrorSummary = this.processDiagnostics(preEmitDiagnostics);
|
||||||
|
|
||||||
|
// Only continue to emit phase if no pre-emit errors
|
||||||
|
if (preEmitErrorSummary.totalErrors > 0) {
|
||||||
|
this.displayErrorSummary(preEmitErrorSummary);
|
||||||
|
console.error('\n❌ TypeScript pre-emit checks failed. Please fix the issues listed above before proceeding.');
|
||||||
|
console.error(' Type errors must be resolved before the compiler can emit output files.\n');
|
||||||
|
done.resolve({ emittedFiles: [], errorSummary: preEmitErrorSummary });
|
||||||
|
return done.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no pre-emit errors, proceed with emit
|
||||||
|
const emitResult = program.emit();
|
||||||
|
const emitErrorSummary = this.processDiagnostics(emitResult.diagnostics);
|
||||||
|
|
||||||
|
// Combine error summaries
|
||||||
|
const combinedErrorSummary: IErrorSummary = {
|
||||||
|
errorsByFile: { ...preEmitErrorSummary.errorsByFile, ...emitErrorSummary.errorsByFile },
|
||||||
|
generalErrors: [...preEmitErrorSummary.generalErrors, ...emitErrorSummary.generalErrors],
|
||||||
|
totalErrors: preEmitErrorSummary.totalErrors + emitErrorSummary.totalErrors,
|
||||||
|
totalFiles: Object.keys({ ...preEmitErrorSummary.errorsByFile, ...emitErrorSummary.errorsByFile }).length,
|
||||||
|
};
|
||||||
|
|
||||||
|
const exitCode = emitResult.emitSkipped ? 1 : 0;
|
||||||
|
if (exitCode === 0) {
|
||||||
|
const endTime = Date.now();
|
||||||
|
const duration = endTime - startTime;
|
||||||
|
|
||||||
|
if (taskInfo) {
|
||||||
|
const { taskNumber, totalTasks } = taskInfo;
|
||||||
|
console.log(`✅ [${taskNumber}/${totalTasks}] Task completed in ${duration}ms`);
|
||||||
|
} else {
|
||||||
|
console.log(`✅ TypeScript emit succeeded! (${duration}ms)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get count of emitted files by type
|
||||||
|
const jsFiles = emitResult.emittedFiles?.filter((f) => f.endsWith('.js')).length || 0;
|
||||||
|
const dtsFiles = emitResult.emittedFiles?.filter((f) => f.endsWith('.d.ts')).length || 0;
|
||||||
|
const mapFiles = emitResult.emittedFiles?.filter((f) => f.endsWith('.map')).length || 0;
|
||||||
|
|
||||||
|
if (emitResult.emittedFiles && emitResult.emittedFiles.length > 0) {
|
||||||
|
console.log(
|
||||||
|
` 📄 Generated ${emitResult.emittedFiles.length} files: ${jsFiles} .js, ${dtsFiles} .d.ts, ${mapFiles} source maps`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
done.resolve({ emittedFiles: emitResult.emittedFiles || [], errorSummary: combinedErrorSummary });
|
||||||
|
} else {
|
||||||
|
this.displayErrorSummary(combinedErrorSummary);
|
||||||
|
console.error('\n❌ TypeScript emit failed. Please investigate the errors listed above!');
|
||||||
|
console.error(' No output files have been generated.\n');
|
||||||
|
done.resolve({ emittedFiles: [], errorSummary: combinedErrorSummary });
|
||||||
|
}
|
||||||
|
|
||||||
|
return done.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile files (throws on error)
|
||||||
|
*/
|
||||||
|
public async compileFilesOrThrow(fileNames: string[], customOptions: CompilerOptions = {}): Promise<string[]> {
|
||||||
|
const result = await this.compileFiles(fileNames, customOptions);
|
||||||
|
if (result.errorSummary.totalErrors > 0) {
|
||||||
|
throw new Error('TypeScript compilation failed.');
|
||||||
|
}
|
||||||
|
return result.emittedFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile glob patterns with automatic unpacking
|
||||||
|
*/
|
||||||
|
public async compileGlob(
|
||||||
|
globPatterns: Record<string, string>,
|
||||||
|
customOptions: CompilerOptions = {}
|
||||||
|
): Promise<ICompileResult> {
|
||||||
|
const emittedFiles: string[] = [];
|
||||||
|
const errorSummaries: IErrorSummary[] = [];
|
||||||
|
|
||||||
|
const totalTasks = Object.keys(globPatterns).length;
|
||||||
|
let currentTask = 0;
|
||||||
|
|
||||||
|
const isQuiet = this.argvArg?.quiet === true;
|
||||||
|
const isJson = this.argvArg?.json === true;
|
||||||
|
|
||||||
|
if (!isQuiet && !isJson) {
|
||||||
|
console.log(`\n👷 TypeScript Compilation Tasks (${totalTasks} task${totalTasks !== 1 ? 's' : ''}):`);
|
||||||
|
Object.entries(globPatterns).forEach(([source, dest]) => {
|
||||||
|
console.log(` 📂 ${source} → ${dest}`);
|
||||||
|
});
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const pattern of Object.keys(globPatterns)) {
|
||||||
|
const destPath = globPatterns[pattern];
|
||||||
|
if (!pattern || !destPath) continue;
|
||||||
|
|
||||||
|
// Get files matching the glob pattern
|
||||||
|
const files = await FsHelpers.listFilesWithGlob(this.cwd, pattern);
|
||||||
|
|
||||||
|
// Transform to absolute paths
|
||||||
|
const absoluteFiles = smartpath.transform.toAbsolute(files, this.cwd) as string[];
|
||||||
|
|
||||||
|
// Get destination directory as absolute path
|
||||||
|
const destDir = smartpath.transform.toAbsolute(destPath, this.cwd) as string;
|
||||||
|
|
||||||
|
// Clear the destination directory before compilation if it exists
|
||||||
|
if (await FsHelpers.directoryExists(destDir)) {
|
||||||
|
if (!isQuiet && !isJson) {
|
||||||
|
console.log(`🧹 Clearing output directory: ${destPath}`);
|
||||||
|
}
|
||||||
|
await FsHelpers.removeDirectory(destDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update compiler options with the output directory
|
||||||
|
const options: CompilerOptions = {
|
||||||
|
...customOptions,
|
||||||
|
outDir: destDir,
|
||||||
|
};
|
||||||
|
|
||||||
|
currentTask++;
|
||||||
|
const taskInfo: ITaskInfo = {
|
||||||
|
taskNumber: currentTask,
|
||||||
|
totalTasks,
|
||||||
|
sourcePattern: pattern,
|
||||||
|
destDir: destPath,
|
||||||
|
fileCount: absoluteFiles.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await this.compileFiles(absoluteFiles, options, taskInfo);
|
||||||
|
emittedFiles.push(...result.emittedFiles);
|
||||||
|
errorSummaries.push(result.errorSummary);
|
||||||
|
|
||||||
|
// Perform unpack if compilation succeeded
|
||||||
|
if (result.errorSummary.totalErrors === 0) {
|
||||||
|
await performUnpack(pattern, destDir, this.cwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge all error summaries
|
||||||
|
const finalErrorSummary = this.mergeErrorSummaries(errorSummaries);
|
||||||
|
|
||||||
|
// Output summary based on mode
|
||||||
|
if (isJson) {
|
||||||
|
const result = {
|
||||||
|
success: finalErrorSummary.totalErrors === 0,
|
||||||
|
totals: {
|
||||||
|
errors: finalErrorSummary.totalErrors,
|
||||||
|
filesWithErrors: finalErrorSummary.totalFiles,
|
||||||
|
tasks: totalTasks,
|
||||||
|
},
|
||||||
|
errorsByFile: Object.fromEntries(
|
||||||
|
Object.entries(finalErrorSummary.errorsByFile).map(([file, diags]) => [
|
||||||
|
file,
|
||||||
|
diags.map((d) => ({
|
||||||
|
code: d.code,
|
||||||
|
message: typescript.flattenDiagnosticMessageText(d.messageText as any, '\n'),
|
||||||
|
})),
|
||||||
|
])
|
||||||
|
),
|
||||||
|
};
|
||||||
|
console.log(JSON.stringify(result));
|
||||||
|
} else if (!isQuiet) {
|
||||||
|
this.displayFinalSummary(finalErrorSummary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach summary to argvArg for CLI exit behavior
|
||||||
|
if (this.argvArg && typeof this.argvArg === 'object') {
|
||||||
|
(this.argvArg as any).__tsbuildFinalErrorSummary = finalErrorSummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
emittedFiles,
|
||||||
|
errorSummary: finalErrorSummary,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if files can be emitted without actually emitting
|
||||||
|
*/
|
||||||
|
public async checkEmit(fileNames: string[], customOptions: CompilerOptions = {}): Promise<boolean> {
|
||||||
|
const options = { ...this.createOptions(customOptions), noEmit: true };
|
||||||
|
const fileCount = fileNames.length;
|
||||||
|
|
||||||
|
console.log(`\n🔍 Checking if ${fileCount} file${fileCount !== 1 ? 's' : ''} can be emitted...`);
|
||||||
|
|
||||||
|
const program = this.createProgram(fileNames, options);
|
||||||
|
|
||||||
|
const preEmitDiagnostics = typescript.getPreEmitDiagnostics(program);
|
||||||
|
const preEmitErrorSummary = this.processDiagnostics(preEmitDiagnostics);
|
||||||
|
|
||||||
|
const emitResult = program.emit(undefined, undefined, undefined, true);
|
||||||
|
const emitErrorSummary = this.processDiagnostics(emitResult.diagnostics);
|
||||||
|
|
||||||
|
const combinedErrorSummary: IErrorSummary = {
|
||||||
|
errorsByFile: { ...preEmitErrorSummary.errorsByFile, ...emitErrorSummary.errorsByFile },
|
||||||
|
generalErrors: [...preEmitErrorSummary.generalErrors, ...emitErrorSummary.generalErrors],
|
||||||
|
totalErrors: preEmitErrorSummary.totalErrors + emitErrorSummary.totalErrors,
|
||||||
|
totalFiles: Object.keys({ ...preEmitErrorSummary.errorsByFile, ...emitErrorSummary.errorsByFile }).length,
|
||||||
|
};
|
||||||
|
|
||||||
|
const success = combinedErrorSummary.totalErrors === 0 && !emitResult.emitSkipped;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
console.log('\n✅ TypeScript emit check passed! All files can be emitted successfully.');
|
||||||
|
console.log(` ${fileCount} file${fileCount !== 1 ? 's' : ''} ${fileCount !== 1 ? 'are' : 'is'} ready to be compiled.\n`);
|
||||||
|
} else {
|
||||||
|
this.displayErrorSummary(combinedErrorSummary);
|
||||||
|
console.error('\n❌ TypeScript emit check failed. Please fix the issues listed above.');
|
||||||
|
console.error(' The compilation cannot proceed until these errors are resolved.\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check TypeScript files for type errors without emission
|
||||||
|
*/
|
||||||
|
public async checkTypes(fileNames: string[], customOptions: CompilerOptions = {}): Promise<boolean> {
|
||||||
|
const options = { ...this.createOptions(customOptions), noEmit: true };
|
||||||
|
const fileCount = fileNames.length;
|
||||||
|
|
||||||
|
console.log(`\n🔍 Type checking ${fileCount} TypeScript file${fileCount !== 1 ? 's' : ''}...`);
|
||||||
|
|
||||||
|
const program = this.createProgram(fileNames, options);
|
||||||
|
const diagnostics = typescript.getPreEmitDiagnostics(program);
|
||||||
|
const errorSummary = this.processDiagnostics(diagnostics);
|
||||||
|
|
||||||
|
const success = errorSummary.totalErrors === 0;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
console.log('\n✅ TypeScript type check passed! No type errors found.');
|
||||||
|
console.log(` All ${fileCount} file${fileCount !== 1 ? 's' : ''} passed type checking successfully.\n`);
|
||||||
|
} else {
|
||||||
|
this.displayErrorSummary(errorSummary);
|
||||||
|
console.error('\n❌ TypeScript type check failed. Please fix the type errors listed above.');
|
||||||
|
console.error(' The type checker found issues that need to be resolved.\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge multiple error summaries into one
|
||||||
|
*/
|
||||||
|
private mergeErrorSummaries(summaries: IErrorSummary[]): IErrorSummary {
|
||||||
|
const mergedErrorsByFile: Record<string, Diagnostic[]> = {};
|
||||||
|
const mergedGeneralErrors: Diagnostic[] = [];
|
||||||
|
let totalErrors = 0;
|
||||||
|
|
||||||
|
summaries.forEach((summary) => {
|
||||||
|
Object.entries(summary.errorsByFile).forEach(([fileName, errors]) => {
|
||||||
|
if (!mergedErrorsByFile[fileName]) {
|
||||||
|
mergedErrorsByFile[fileName] = [];
|
||||||
|
}
|
||||||
|
mergedErrorsByFile[fileName] = mergedErrorsByFile[fileName].concat(errors);
|
||||||
|
});
|
||||||
|
|
||||||
|
mergedGeneralErrors.push(...summary.generalErrors);
|
||||||
|
totalErrors += summary.totalErrors;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
errorsByFile: mergedErrorsByFile,
|
||||||
|
generalErrors: mergedGeneralErrors,
|
||||||
|
totalErrors,
|
||||||
|
totalFiles: Object.keys(mergedErrorsByFile).length,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display final compilation summary
|
||||||
|
*/
|
||||||
|
private displayFinalSummary(errorSummary: IErrorSummary): void {
|
||||||
|
if (errorSummary.totalErrors === 0) {
|
||||||
|
console.log('\n📊 \x1b[32mCompilation Summary: All tasks completed successfully! ✅\x1b[0m\n');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const colors = {
|
||||||
|
reset: '\x1b[0m',
|
||||||
|
red: '\x1b[31m',
|
||||||
|
yellow: '\x1b[33m',
|
||||||
|
cyan: '\x1b[36m',
|
||||||
|
brightRed: '\x1b[91m',
|
||||||
|
brightYellow: '\x1b[93m',
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('\n' + '='.repeat(80));
|
||||||
|
console.log(`📊 ${colors.brightYellow}Final Compilation Summary${colors.reset}`);
|
||||||
|
console.log('='.repeat(80));
|
||||||
|
|
||||||
|
if (errorSummary.totalFiles > 0) {
|
||||||
|
console.log(`${colors.brightRed}❌ Files with errors (${errorSummary.totalFiles}):${colors.reset}`);
|
||||||
|
|
||||||
|
Object.entries(errorSummary.errorsByFile).forEach(([fileName, errors]) => {
|
||||||
|
const displayPath = fileName.replace(process.cwd(), '').replace(/^\//, '');
|
||||||
|
console.log(
|
||||||
|
` ${colors.red}•${colors.reset} ${colors.cyan}${displayPath}${colors.reset} ${colors.yellow}(${errors.length} error${errors.length !== 1 ? 's' : ''})${colors.reset}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorSummary.generalErrors.length > 0) {
|
||||||
|
console.log(`${colors.brightRed}❌ General errors: ${errorSummary.generalErrors.length}${colors.reset}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`\n${colors.brightRed}Total: ${errorSummary.totalErrors} error${errorSummary.totalErrors !== 1 ? 's' : ''} across ${errorSummary.totalFiles} file${errorSummary.totalFiles !== 1 ? 's' : ''}${colors.reset}`
|
||||||
|
);
|
||||||
|
console.log('='.repeat(80) + '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
1
ts/mod_compiler/index.ts
Normal file
1
ts/mod_compiler/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './classes.tscompiler.js';
|
||||||
180
ts/mod_config/classes.tsconfig.ts
Normal file
180
ts/mod_config/classes.tsconfig.ts
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
import type { CompilerOptions } from 'typescript';
|
||||||
|
import typescript from 'typescript';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default compiler options for TypeScript compilation
|
||||||
|
*/
|
||||||
|
export const compilerOptionsDefault: CompilerOptions = {
|
||||||
|
declaration: true,
|
||||||
|
inlineSourceMap: true,
|
||||||
|
noEmitOnError: true,
|
||||||
|
outDir: 'dist_ts/',
|
||||||
|
module: typescript.ModuleKind.NodeNext,
|
||||||
|
target: typescript.ScriptTarget.ESNext,
|
||||||
|
moduleResolution: typescript.ModuleResolutionKind.NodeNext,
|
||||||
|
lib: ['lib.dom.d.ts', 'lib.esnext.d.ts'],
|
||||||
|
noImplicitAny: false,
|
||||||
|
esModuleInterop: true,
|
||||||
|
verbatimModuleSyntax: true,
|
||||||
|
baseUrl: './',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TsConfig handles loading and merging TypeScript compiler configurations.
|
||||||
|
* It supports reading tsconfig.json and merging with defaults and custom options.
|
||||||
|
*/
|
||||||
|
export class TsConfig {
|
||||||
|
private cwd: string;
|
||||||
|
private cachedTsConfig: CompilerOptions | null = null;
|
||||||
|
|
||||||
|
constructor(cwd: string = process.cwd()) {
|
||||||
|
this.cwd = cwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current working directory
|
||||||
|
*/
|
||||||
|
public getCwd(): string {
|
||||||
|
return this.cwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load and parse tsconfig.json from the current directory
|
||||||
|
*/
|
||||||
|
public load(): CompilerOptions {
|
||||||
|
if (this.cachedTsConfig !== null) {
|
||||||
|
return this.cachedTsConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tsconfig: any;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tsconfigPath = path.join(this.cwd, 'tsconfig.json');
|
||||||
|
const tsconfigContent = fs.readFileSync(tsconfigPath, 'utf8');
|
||||||
|
tsconfig = JSON.parse(tsconfigContent);
|
||||||
|
} catch {
|
||||||
|
this.cachedTsConfig = {};
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tsconfig || !tsconfig.compilerOptions) {
|
||||||
|
this.cachedTsConfig = {};
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const returnObject: CompilerOptions = { ...tsconfig.compilerOptions };
|
||||||
|
|
||||||
|
// Convert target string to enum
|
||||||
|
if (tsconfig.compilerOptions.target && typeof tsconfig.compilerOptions.target === 'string') {
|
||||||
|
const targetKey = tsconfig.compilerOptions.target.toUpperCase();
|
||||||
|
if (targetKey in typescript.ScriptTarget) {
|
||||||
|
returnObject.target = typescript.ScriptTarget[targetKey as keyof typeof typescript.ScriptTarget];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert module string to enum
|
||||||
|
if (tsconfig.compilerOptions.module && typeof tsconfig.compilerOptions.module === 'string') {
|
||||||
|
const moduleKey = tsconfig.compilerOptions.module.toUpperCase();
|
||||||
|
if (moduleKey in typescript.ModuleKind) {
|
||||||
|
returnObject.module = typescript.ModuleKind[moduleKey as keyof typeof typescript.ModuleKind];
|
||||||
|
} else if (moduleKey === 'NODENEXT') {
|
||||||
|
returnObject.module = typescript.ModuleKind.NodeNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert moduleResolution string to enum
|
||||||
|
if (tsconfig.compilerOptions.moduleResolution && typeof tsconfig.compilerOptions.moduleResolution === 'string') {
|
||||||
|
const moduleResolutionKey = tsconfig.compilerOptions.moduleResolution.toUpperCase();
|
||||||
|
if (moduleResolutionKey in typescript.ModuleResolutionKind) {
|
||||||
|
returnObject.moduleResolution = typescript.ModuleResolutionKind[
|
||||||
|
moduleResolutionKey as keyof typeof typescript.ModuleResolutionKind
|
||||||
|
];
|
||||||
|
} else if (moduleResolutionKey === 'NODENEXT') {
|
||||||
|
returnObject.moduleResolution = typescript.ModuleResolutionKind.NodeNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply path transformations (ts_ → dist_ts_)
|
||||||
|
if (tsconfig.compilerOptions.paths) {
|
||||||
|
returnObject.paths = { ...tsconfig.compilerOptions.paths };
|
||||||
|
for (const pathKey of Object.keys(returnObject.paths)) {
|
||||||
|
if (Array.isArray(returnObject.paths[pathKey]) && returnObject.paths[pathKey].length > 0) {
|
||||||
|
returnObject.paths[pathKey][0] = returnObject.paths[pathKey][0].replace('./ts_', './dist_ts_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cachedTsConfig = returnObject;
|
||||||
|
return returnObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default compiler options
|
||||||
|
*/
|
||||||
|
public getDefaultOptions(): CompilerOptions {
|
||||||
|
return { ...compilerOptionsDefault };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get critical/protected default options that shouldn't be overridden by tsconfig.json
|
||||||
|
*/
|
||||||
|
public getProtectedDefaults(): CompilerOptions {
|
||||||
|
return {
|
||||||
|
outDir: 'dist_ts/',
|
||||||
|
noEmitOnError: true,
|
||||||
|
declaration: true,
|
||||||
|
inlineSourceMap: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process command line arguments and return applicable compiler options
|
||||||
|
*/
|
||||||
|
public getCommandLineOptions(argvArg?: any): CompilerOptions {
|
||||||
|
if (!argvArg) return {};
|
||||||
|
|
||||||
|
const options: CompilerOptions = {};
|
||||||
|
|
||||||
|
if (argvArg.skiplibcheck) {
|
||||||
|
options.skipLibCheck = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvArg.disallowimplicitany) {
|
||||||
|
options.noImplicitAny = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvArg.commonjs) {
|
||||||
|
options.module = typescript.ModuleKind.CommonJS;
|
||||||
|
options.moduleResolution = typescript.ModuleResolutionKind.NodeJs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge compiler options with proper priority order:
|
||||||
|
* 1. Default options
|
||||||
|
* 2. tsconfig.json options
|
||||||
|
* 3. Protected defaults (cannot be overridden by tsconfig)
|
||||||
|
* 4. Custom options (programmatic)
|
||||||
|
* 5. CLI options (highest priority)
|
||||||
|
*/
|
||||||
|
public merge(customOptions: CompilerOptions = {}, argvArg?: any): CompilerOptions {
|
||||||
|
return {
|
||||||
|
...this.getDefaultOptions(),
|
||||||
|
...this.load(),
|
||||||
|
...this.getProtectedDefaults(),
|
||||||
|
...customOptions,
|
||||||
|
...this.getCommandLineOptions(argvArg),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the cached tsconfig (useful for reloading)
|
||||||
|
*/
|
||||||
|
public clearCache(): void {
|
||||||
|
this.cachedTsConfig = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
116
ts/mod_config/classes.tspublishconfig.ts
Normal file
116
ts/mod_config/classes.tspublishconfig.ts
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for tspublish.json configuration
|
||||||
|
*/
|
||||||
|
export interface ITsPublishJson {
|
||||||
|
order?: number;
|
||||||
|
unpack?: boolean;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TsPublishConfig handles loading and parsing tspublish.json files.
|
||||||
|
* These configuration files control module-specific settings like
|
||||||
|
* compilation order and output unpacking behavior.
|
||||||
|
*/
|
||||||
|
export class TsPublishConfig {
|
||||||
|
private folderPath: string;
|
||||||
|
private cachedConfig: ITsPublishJson | null | undefined = undefined;
|
||||||
|
|
||||||
|
constructor(folderPath: string) {
|
||||||
|
this.folderPath = folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the folder path this config is for
|
||||||
|
*/
|
||||||
|
public getFolderPath(): string {
|
||||||
|
return this.folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load and parse tspublish.json from the folder
|
||||||
|
* Returns null if file doesn't exist or is invalid
|
||||||
|
*/
|
||||||
|
public async load(): Promise<ITsPublishJson | null> {
|
||||||
|
if (this.cachedConfig !== undefined) {
|
||||||
|
return this.cachedConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const configPath = path.join(this.folderPath, 'tspublish.json');
|
||||||
|
const content = await fs.promises.readFile(configPath, 'utf8');
|
||||||
|
this.cachedConfig = JSON.parse(content);
|
||||||
|
return this.cachedConfig;
|
||||||
|
} catch {
|
||||||
|
this.cachedConfig = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously load and parse tspublish.json from the folder
|
||||||
|
* Returns null if file doesn't exist or is invalid
|
||||||
|
*/
|
||||||
|
public loadSync(): ITsPublishJson | null {
|
||||||
|
if (this.cachedConfig !== undefined) {
|
||||||
|
return this.cachedConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const configPath = path.join(this.folderPath, 'tspublish.json');
|
||||||
|
const content = fs.readFileSync(configPath, 'utf8');
|
||||||
|
this.cachedConfig = JSON.parse(content);
|
||||||
|
return this.cachedConfig;
|
||||||
|
} catch {
|
||||||
|
this.cachedConfig = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if output should be unpacked (flattened)
|
||||||
|
* Default is true if not specified
|
||||||
|
*/
|
||||||
|
public get shouldUnpack(): boolean {
|
||||||
|
const config = this.loadSync();
|
||||||
|
if (!config || config.unpack === undefined) {
|
||||||
|
return true; // Default to true
|
||||||
|
}
|
||||||
|
return config.unpack === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the compilation order for tsfolders command
|
||||||
|
* Returns Infinity if not specified (sorted last)
|
||||||
|
*/
|
||||||
|
public get order(): number {
|
||||||
|
const config = this.loadSync();
|
||||||
|
if (!config || config.order === undefined) {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
return config.order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if tspublish.json exists in the folder
|
||||||
|
*/
|
||||||
|
public async exists(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const configPath = path.join(this.folderPath, 'tspublish.json');
|
||||||
|
await fs.promises.access(configPath, fs.constants.F_OK);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the cached config (useful for reloading)
|
||||||
|
*/
|
||||||
|
public clearCache(): void {
|
||||||
|
this.cachedConfig = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
ts/mod_config/index.ts
Normal file
2
ts/mod_config/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './classes.tsconfig.js';
|
||||||
|
export * from './classes.tspublishconfig.js';
|
||||||
144
ts/mod_fs/classes.fshelpers.ts
Normal file
144
ts/mod_fs/classes.fshelpers.ts
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as smartfsModule from '@push.rocks/smartfs';
|
||||||
|
|
||||||
|
// Create a smartfs instance with Node.js provider
|
||||||
|
const smartfs = new smartfsModule.SmartFs(new smartfsModule.SmartFsProviderNode());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FsHelpers provides filesystem utility methods for tsbuild.
|
||||||
|
* All methods are static for convenience.
|
||||||
|
*/
|
||||||
|
export class FsHelpers {
|
||||||
|
/**
|
||||||
|
* The smartfs instance for filesystem operations
|
||||||
|
*/
|
||||||
|
public static readonly smartfs = smartfs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List files matching a glob pattern like './ts/**\/*.ts'
|
||||||
|
* Parses the pattern to extract base directory and filter pattern
|
||||||
|
*/
|
||||||
|
public static async listFilesWithGlob(basePath: string, globPattern: string): Promise<string[]> {
|
||||||
|
// Remove leading ./ if present
|
||||||
|
const pattern = globPattern.replace(/^\.\//, '');
|
||||||
|
|
||||||
|
// Find the first directory part before any glob characters
|
||||||
|
const globChars = ['*', '?', '{', '['];
|
||||||
|
let baseDir = basePath;
|
||||||
|
|
||||||
|
// Find where the glob pattern starts
|
||||||
|
const parts = pattern.split('/');
|
||||||
|
const staticParts: string[] = [];
|
||||||
|
const filterParts: string[] = [];
|
||||||
|
let foundGlob = false;
|
||||||
|
|
||||||
|
for (const part of parts) {
|
||||||
|
if (!foundGlob && !globChars.some(c => part.includes(c))) {
|
||||||
|
staticParts.push(part);
|
||||||
|
} else {
|
||||||
|
foundGlob = true;
|
||||||
|
filterParts.push(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the base directory
|
||||||
|
if (staticParts.length > 0) {
|
||||||
|
baseDir = path.join(basePath, ...staticParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the filter pattern (just the filename part, ignoring ** for directories)
|
||||||
|
// The recursive() handles the ** part
|
||||||
|
const fileFilter = filterParts[filterParts.length - 1] || '*';
|
||||||
|
|
||||||
|
// Check if we need recursive search
|
||||||
|
const needsRecursive = filterParts.some(p => p === '**' || p.includes('**'));
|
||||||
|
|
||||||
|
let dirBuilder = smartfs.directory(baseDir);
|
||||||
|
if (needsRecursive) {
|
||||||
|
dirBuilder = dirBuilder.recursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const entries = await dirBuilder.filter(fileFilter).list();
|
||||||
|
return entries.filter(e => e.isFile).map(e => e.path);
|
||||||
|
} catch {
|
||||||
|
// Directory doesn't exist or other error
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract source folder name from a glob pattern
|
||||||
|
* './ts_core/**\/*.ts' → 'ts_core'
|
||||||
|
* 'ts_foo/**\/*.ts' → 'ts_foo'
|
||||||
|
*/
|
||||||
|
public static extractSourceFolder(pattern: string): string | null {
|
||||||
|
const match = pattern.match(/^\.?\/?([^\/\*]+)/);
|
||||||
|
return match ? match[1] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current working directory
|
||||||
|
*/
|
||||||
|
public static getCwd(): string {
|
||||||
|
return process.cwd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the package directory (where package.json is located)
|
||||||
|
*/
|
||||||
|
public static getPackageDir(): string {
|
||||||
|
return path.resolve(__dirname, '../../');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a file exists
|
||||||
|
*/
|
||||||
|
public static async fileExists(filePath: string): Promise<boolean> {
|
||||||
|
return smartfs.file(filePath).exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a directory exists
|
||||||
|
*/
|
||||||
|
public static async directoryExists(dirPath: string): Promise<boolean> {
|
||||||
|
return smartfs.directory(dirPath).exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a JSON file and parse it
|
||||||
|
*/
|
||||||
|
public static readJsonSync<T = any>(filePath: string): T {
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8');
|
||||||
|
return JSON.parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List directory contents
|
||||||
|
*/
|
||||||
|
public static async listDirectory(dirPath: string) {
|
||||||
|
return smartfs.directory(dirPath).list();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a directory recursively
|
||||||
|
*/
|
||||||
|
public static async removeDirectory(dirPath: string): Promise<void> {
|
||||||
|
await fs.promises.rm(dirPath, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move/rename a file or directory
|
||||||
|
*/
|
||||||
|
public static async move(src: string, dest: string): Promise<void> {
|
||||||
|
await fs.promises.rename(src, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an empty directory
|
||||||
|
*/
|
||||||
|
public static async removeEmptyDirectory(dirPath: string): Promise<void> {
|
||||||
|
await fs.promises.rmdir(dirPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
ts/mod_fs/index.ts
Normal file
1
ts/mod_fs/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './classes.fshelpers.js';
|
||||||
153
ts/mod_unpack/classes.tsunpacker.ts
Normal file
153
ts/mod_unpack/classes.tsunpacker.ts
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
import { TsPublishConfig } from '../mod_config/index.js';
|
||||||
|
import { FsHelpers } from '../mod_fs/index.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TsUnpacker handles flattening of nested TypeScript output directories.
|
||||||
|
*
|
||||||
|
* When TypeScript compiles files that import from sibling directories,
|
||||||
|
* it creates a nested structure like:
|
||||||
|
* dist_ts_core/ts_core/index.js
|
||||||
|
* dist_ts_core/ts_shared/helper.js
|
||||||
|
*
|
||||||
|
* This class flattens it to:
|
||||||
|
* dist_ts_core/index.js
|
||||||
|
*/
|
||||||
|
export class TsUnpacker {
|
||||||
|
private sourceFolderName: string;
|
||||||
|
private destDir: string;
|
||||||
|
private cwd: string;
|
||||||
|
private config: TsPublishConfig;
|
||||||
|
|
||||||
|
constructor(sourceFolderName: string, destDir: string, cwd: string = process.cwd()) {
|
||||||
|
this.sourceFolderName = sourceFolderName;
|
||||||
|
this.destDir = destDir;
|
||||||
|
this.cwd = cwd;
|
||||||
|
this.config = new TsPublishConfig(path.join(cwd, sourceFolderName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an unpacker from a glob pattern
|
||||||
|
* './ts_core/**\/*.ts' → sourceFolderName = 'ts_core'
|
||||||
|
*/
|
||||||
|
public static fromGlobPattern(
|
||||||
|
sourcePattern: string,
|
||||||
|
destDir: string,
|
||||||
|
cwd: string = process.cwd()
|
||||||
|
): TsUnpacker | null {
|
||||||
|
const sourceFolderName = FsHelpers.extractSourceFolder(sourcePattern);
|
||||||
|
if (!sourceFolderName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new TsUnpacker(sourceFolderName, destDir, cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the source folder name
|
||||||
|
*/
|
||||||
|
public getSourceFolderName(): string {
|
||||||
|
return this.sourceFolderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the destination directory
|
||||||
|
*/
|
||||||
|
public getDestDir(): string {
|
||||||
|
return this.destDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if unpacking should be performed based on tspublish.json config
|
||||||
|
* Default is true if not specified
|
||||||
|
*/
|
||||||
|
public async shouldUnpack(): Promise<boolean> {
|
||||||
|
return this.config.shouldUnpack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if nested structure exists in the destination directory
|
||||||
|
*/
|
||||||
|
public async detectNesting(): Promise<boolean> {
|
||||||
|
const nestedPath = path.join(this.destDir, this.sourceFolderName);
|
||||||
|
return FsHelpers.directoryExists(nestedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to the nested directory
|
||||||
|
*/
|
||||||
|
public getNestedPath(): string {
|
||||||
|
return path.join(this.destDir, this.sourceFolderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the unpack operation - flatten nested output directories
|
||||||
|
* Returns true if unpacking was performed, false if skipped
|
||||||
|
*/
|
||||||
|
public async unpack(): Promise<boolean> {
|
||||||
|
// Check if we should unpack based on config
|
||||||
|
if (!(await this.shouldUnpack())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if nested structure exists
|
||||||
|
if (!(await this.detectNesting())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nestedPath = this.getNestedPath();
|
||||||
|
|
||||||
|
// Delete sibling folders (not the source folder)
|
||||||
|
await this.removeSiblingDirectories();
|
||||||
|
|
||||||
|
// Move contents from nested folder up
|
||||||
|
await this.moveNestedContentsUp();
|
||||||
|
|
||||||
|
// Remove empty nested folder
|
||||||
|
await FsHelpers.removeEmptyDirectory(nestedPath);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove sibling directories in the destination folder
|
||||||
|
* (directories other than the source folder being unpacked)
|
||||||
|
*/
|
||||||
|
private async removeSiblingDirectories(): Promise<void> {
|
||||||
|
const entries = await FsHelpers.listDirectory(this.destDir);
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.isDirectory && entry.name !== this.sourceFolderName) {
|
||||||
|
await FsHelpers.removeDirectory(path.join(this.destDir, entry.name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move contents from the nested folder up to the destination directory
|
||||||
|
*/
|
||||||
|
private async moveNestedContentsUp(): Promise<void> {
|
||||||
|
const nestedPath = this.getNestedPath();
|
||||||
|
const entries = await FsHelpers.listDirectory(nestedPath);
|
||||||
|
for (const entry of entries) {
|
||||||
|
const src = path.join(nestedPath, entry.name);
|
||||||
|
const dest = path.join(this.destDir, entry.name);
|
||||||
|
await FsHelpers.move(src, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to perform unpack operation
|
||||||
|
* Can be used directly without instantiating the class
|
||||||
|
*/
|
||||||
|
export async function performUnpack(
|
||||||
|
sourcePattern: string,
|
||||||
|
destDir: string,
|
||||||
|
cwd: string = process.cwd()
|
||||||
|
): Promise<boolean> {
|
||||||
|
const unpacker = TsUnpacker.fromGlobPattern(sourcePattern, destDir, cwd);
|
||||||
|
if (!unpacker) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return unpacker.unpack();
|
||||||
|
}
|
||||||
1
ts/mod_unpack/index.ts
Normal file
1
ts/mod_unpack/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './classes.tsunpacker.js';
|
||||||
24
ts/plugins.ts
Normal file
24
ts/plugins.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// node native
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export { fs, path };
|
||||||
|
|
||||||
|
// @git.zone scope
|
||||||
|
import * as tspublish from '@git.zone/tspublish';
|
||||||
|
|
||||||
|
export { tspublish };
|
||||||
|
|
||||||
|
// @push.rocks scope
|
||||||
|
import * as smartcli from '@push.rocks/smartcli';
|
||||||
|
import * as smartdelay from '@push.rocks/smartdelay';
|
||||||
|
import * as smartfile from '@push.rocks/smartfile';
|
||||||
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
|
|
||||||
|
export { smartcli, smartdelay, smartfile, smartpath, smartpromise };
|
||||||
|
|
||||||
|
// third party scope
|
||||||
|
import typescript from 'typescript';
|
||||||
|
|
||||||
|
export { typescript };
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
// import all the stuff we need
|
|
||||||
import * as plugins from './tsbuild.plugins';
|
|
||||||
import { CompilerOptions } from 'typescript';
|
|
||||||
export { CompilerOptions, ScriptTarget, ModuleKind } from 'typescript';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the default typescript compilerOptions
|
|
||||||
*/
|
|
||||||
export const compilerOptionsDefault: CompilerOptions = {
|
|
||||||
declaration: true,
|
|
||||||
emitDecoratorMetadata: true,
|
|
||||||
experimentalDecorators: true,
|
|
||||||
inlineSourceMap: true,
|
|
||||||
noEmitOnError: true,
|
|
||||||
outDir: 'dist/',
|
|
||||||
module: plugins.typescript.ModuleKind.CommonJS,
|
|
||||||
lib: ['lib.es2017.d.ts'],
|
|
||||||
noImplicitAny: false,
|
|
||||||
esModuleInterop: true,
|
|
||||||
target: plugins.typescript.ScriptTarget.ES2017
|
|
||||||
};
|
|
||||||
|
|
||||||
export const compilerOptionsWebDefault: CompilerOptions = {
|
|
||||||
...compilerOptionsDefault,
|
|
||||||
lib: [...compilerOptionsDefault.lib, 'lib.dom.d.ts']
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* merges compilerOptions with the default compiler options
|
|
||||||
*/
|
|
||||||
export const mergeCompilerOptions = (
|
|
||||||
customTsOptions: CompilerOptions,
|
|
||||||
argvArg?: any
|
|
||||||
): CompilerOptions => {
|
|
||||||
const defaultOptionsToMerge = (() => {
|
|
||||||
if (argvArg && argvArg.web) {
|
|
||||||
return compilerOptionsWebDefault;
|
|
||||||
} else {
|
|
||||||
return compilerOptionsDefault;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
// create merged options
|
|
||||||
let mergedOptions: CompilerOptions = {
|
|
||||||
...defaultOptionsToMerge,
|
|
||||||
...customTsOptions
|
|
||||||
};
|
|
||||||
|
|
||||||
return mergedOptions;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the internal main compiler function that compiles the files
|
|
||||||
*/
|
|
||||||
export const compiler = (
|
|
||||||
fileNames: string[],
|
|
||||||
options: plugins.typescript.CompilerOptions,
|
|
||||||
argvArg?: any
|
|
||||||
): Promise<any[]> => {
|
|
||||||
console.log(`Compiling ${fileNames.length} files...`);
|
|
||||||
let done = plugins.smartpromise.defer<any[]>();
|
|
||||||
let program = plugins.typescript.createProgram(fileNames, options);
|
|
||||||
let emitResult = program.emit();
|
|
||||||
|
|
||||||
// implement check only
|
|
||||||
/*let emitResult = program.emit(undefined,(args) => {
|
|
||||||
console.log(args)
|
|
||||||
});*/
|
|
||||||
|
|
||||||
let allDiagnostics = plugins.typescript
|
|
||||||
.getPreEmitDiagnostics(program)
|
|
||||||
.concat(emitResult.diagnostics);
|
|
||||||
allDiagnostics.forEach(diagnostic => {
|
|
||||||
if (diagnostic.file) {
|
|
||||||
let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);
|
|
||||||
let message = plugins.typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
|
||||||
console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
|
|
||||||
} else {
|
|
||||||
console.log(
|
|
||||||
`${plugins.typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let exitCode = emitResult.emitSkipped ? 1 : 0;
|
|
||||||
if (exitCode === 0) {
|
|
||||||
console.log('TypeScript emit succeeded!');
|
|
||||||
done.resolve(emitResult.emittedFiles);
|
|
||||||
} else {
|
|
||||||
console.error('TypeScript emit failed. Please investigate!');
|
|
||||||
process.exit(exitCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return done.promise;
|
|
||||||
};
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import * as plugins from './tsbuild.plugins';
|
|
||||||
import * as tsbuild from './tsbuild.exports';
|
|
||||||
|
|
||||||
const tsbuildCli = new plugins.smartcli.Smartcli();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the standard task compiles anything in ts/ directory to dist directory
|
|
||||||
*/
|
|
||||||
tsbuildCli.standardTask().subscribe(async argvArg => {
|
|
||||||
if (process.env.CLI_CALL_TSBUILD === 'true') {
|
|
||||||
tsbuild.compileGlobStringObject(
|
|
||||||
{
|
|
||||||
'./ts/**/*.ts': './dist'
|
|
||||||
},
|
|
||||||
{},
|
|
||||||
process.cwd(),
|
|
||||||
argvArg
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the custom command compiles any customDir to dist_customDir
|
|
||||||
*/
|
|
||||||
tsbuildCli.addCommand('custom').subscribe(async argvArg => {
|
|
||||||
const listedDirectories = argvArg._;
|
|
||||||
listedDirectories.shift();
|
|
||||||
const compilationCommandObject: { [key: string]: string } = {};
|
|
||||||
for (const directory of listedDirectories) {
|
|
||||||
compilationCommandObject[`./${directory}/**/*.ts`] = `./dist_${directory}`;
|
|
||||||
}
|
|
||||||
await tsbuild.compileGlobStringObject(compilationCommandObject, {}, process.cwd(), argvArg);
|
|
||||||
});
|
|
||||||
|
|
||||||
tsbuildCli.addCommand('element').subscribe(async argvArg => {
|
|
||||||
await tsbuild.compileGlobStringObject({
|
|
||||||
"./ts_web/**/*.ts": "dist_ts_web"
|
|
||||||
}, {}, process.cwd(), {web: true});
|
|
||||||
});
|
|
||||||
|
|
||||||
tsbuildCli.startParse();
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import * as plugins from './tsbuild.plugins';
|
|
||||||
import { compiler, CompilerOptions, mergeCompilerOptions } from './tsbuild.classes.compiler';
|
|
||||||
|
|
||||||
export * from './tsbuild.classes.compiler';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* compile am array of absolute file paths
|
|
||||||
*/
|
|
||||||
export let compileFileArray = (
|
|
||||||
fileStringArrayArg: string[],
|
|
||||||
compilerOptionsArg: CompilerOptions = {},
|
|
||||||
argvArg?: any
|
|
||||||
): Promise<any[]> => {
|
|
||||||
return compiler(fileStringArrayArg, mergeCompilerOptions(compilerOptionsArg, argvArg), argvArg);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* compile advanced glob configurations
|
|
||||||
* @param globStringArrayArg a array of glob strings
|
|
||||||
* {
|
|
||||||
* './some/origin/folder/**\/*.ts': './some/destination/folder'
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
export let compileGlobStringObject = async (
|
|
||||||
globStringObjectArg: any,
|
|
||||||
tsOptionsArg: CompilerOptions = {},
|
|
||||||
cwdArg: string = process.cwd(),
|
|
||||||
argvArg?: any
|
|
||||||
) => {
|
|
||||||
let compiledFiles = [];
|
|
||||||
for (const keyArg in globStringObjectArg) {
|
|
||||||
if (globStringObjectArg[keyArg]) {
|
|
||||||
console.log(
|
|
||||||
`TypeScript assignment: transpile from ${keyArg} to ${globStringObjectArg[keyArg]}`
|
|
||||||
);
|
|
||||||
const fileTreeArray = await plugins.smartfile.fs.listFileTree(cwdArg, keyArg);
|
|
||||||
let absoluteFilePathArray: string[] = plugins.smartpath.transform.toAbsolute(
|
|
||||||
fileTreeArray,
|
|
||||||
cwdArg
|
|
||||||
);
|
|
||||||
let destDir: string = plugins.smartpath.transform.toAbsolute(
|
|
||||||
globStringObjectArg[keyArg],
|
|
||||||
cwdArg
|
|
||||||
);
|
|
||||||
tsOptionsArg = {
|
|
||||||
...tsOptionsArg,
|
|
||||||
outDir: destDir
|
|
||||||
};
|
|
||||||
compiledFiles = compiledFiles.concat(
|
|
||||||
compiledFiles,
|
|
||||||
await compileFileArray(absoluteFilePathArray, tsOptionsArg, argvArg)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return compiledFiles;
|
|
||||||
};
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import * as smartcli from '@pushrocks/smartcli';
|
|
||||||
import * as smartfile from '@pushrocks/smartfile';
|
|
||||||
import * as smartpath from '@pushrocks/smartpath';
|
|
||||||
import * as smartpromise from '@pushrocks/smartpromise';
|
|
||||||
import * as typescript from 'typescript';
|
|
||||||
|
|
||||||
export { smartcli, smartfile, smartpath, smartpromise, typescript };
|
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "dist/",
|
"target": "ES2022",
|
||||||
"module": "commonjs",
|
"module": "NodeNext",
|
||||||
"target": "es2015",
|
"moduleResolution": "NodeNext",
|
||||||
"lib":[
|
"esModuleInterop": true,
|
||||||
"es2016",
|
"verbatimModuleSyntax": true
|
||||||
"es2017"
|
}
|
||||||
]
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"ts/**/*.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
17
tslint.json
17
tslint.json
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": ["tslint:latest", "tslint-config-prettier"],
|
|
||||||
"rules": {
|
|
||||||
"semicolon": [true, "always"],
|
|
||||||
"no-console": false,
|
|
||||||
"ordered-imports": false,
|
|
||||||
"object-literal-sort-keys": false,
|
|
||||||
"member-ordering": {
|
|
||||||
"options":{
|
|
||||||
"order": [
|
|
||||||
"static-method"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"defaultSeverity": "warning"
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user