Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e40bd5882 | |||
| 4ccb7ea9d6 | |||
| 0040325914 | |||
| f2980dc00f | |||
| 681f2b4c54 | |||
| fb6bd614d3 | |||
| 0eaca1f3d1 |
17
changelog.md
17
changelog.md
@@ -1,5 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-01-04 - 4.1.0 - feat(docs)
|
||||
update README with improved docs and monorepo/tspublish guidance; namespace and extend npmextra.json with release registries; bump several dependencies
|
||||
|
||||
- Bumped dependencies: @git.zone/tspublish ^1.10.3 → ^1.11.0, @push.rocks/smartfs ^1.2.0 → ^1.3.1, @git.zone/tstest ^3.1.3 → ^3.1.4, @types/node ^25.0.1 → ^25.0.3
|
||||
- npmextra.json reorganized: replaced legacy keys with namespaced entries (@git.zone/cli, @git.zone/tsdoc) and added @ship.zone/szci; added release configuration with registries [https://verdaccio.lossless.digital, https://registry.npmjs.org] and public accessLevel
|
||||
- README rewritten: improved formatting, added emojis and tables, new 'Issue Reporting and Security' section, monorepo/tspublish usage docs, auto-unpack and decorator guidance, CI/CD and troubleshooting improvements
|
||||
- Non-breaking changes; recommended next semantic version bump is minor
|
||||
|
||||
## 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)
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
{
|
||||
"npmci": {
|
||||
"npmGlobalTools": [],
|
||||
"npmAccessLevel": "public"
|
||||
},
|
||||
"gitzone": {
|
||||
"@git.zone/cli": {
|
||||
"projectType": "npm",
|
||||
"module": {
|
||||
"githost": "gitlab.com",
|
||||
@@ -23,9 +19,19 @@
|
||||
"development",
|
||||
"API"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"registries": [
|
||||
"https://verdaccio.lossless.digital",
|
||||
"https://registry.npmjs.org"
|
||||
],
|
||||
"accessLevel": "public"
|
||||
}
|
||||
},
|
||||
"tsdoc": {
|
||||
"@git.zone/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"
|
||||
},
|
||||
"@ship.zone/szci": {
|
||||
"npmGlobalTools": []
|
||||
}
|
||||
}
|
||||
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@git.zone/tsbuild",
|
||||
"version": "4.0.0",
|
||||
"version": "4.1.1",
|
||||
"private": false,
|
||||
"description": "A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.",
|
||||
"main": "dist_ts/index.js",
|
||||
@@ -36,12 +36,12 @@
|
||||
},
|
||||
"homepage": "https://code.foss.global/git.zone/tsbuild#README",
|
||||
"dependencies": {
|
||||
"@git.zone/tspublish": "^1.10.3",
|
||||
"@git.zone/tspublish": "^1.11.0",
|
||||
"@push.rocks/early": "^4.0.4",
|
||||
"@push.rocks/smartcli": "^4.0.19",
|
||||
"@push.rocks/smartdelay": "^3.0.5",
|
||||
"@push.rocks/smartfile": "^13.1.2",
|
||||
"@push.rocks/smartfs": "^1.2.0",
|
||||
"@push.rocks/smartfs": "^1.3.1",
|
||||
"@push.rocks/smartlog": "^3.1.10",
|
||||
"@push.rocks/smartpath": "^6.0.0",
|
||||
"@push.rocks/smartpromise": "^4.2.3",
|
||||
@@ -49,8 +49,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsrun": "^2.0.1",
|
||||
"@git.zone/tstest": "^3.1.3",
|
||||
"@types/node": "^25.0.1"
|
||||
"@git.zone/tstest": "^3.1.4",
|
||||
"@types/node": "^25.0.3"
|
||||
},
|
||||
"files": [
|
||||
"ts/**/*",
|
||||
|
||||
1997
pnpm-lock.yaml
generated
1997
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
1
test/assets/output/tocompile.d.ts
vendored
1
test/assets/output/tocompile.d.ts
vendored
@@ -1 +0,0 @@
|
||||
export {};
|
||||
@@ -1,17 +0,0 @@
|
||||
console.log('test');
|
||||
console.log('test2');
|
||||
import * as early from '@push.rocks/early';
|
||||
early.start();
|
||||
early.stop();
|
||||
import { anExportedString } from './tocompile2.js';
|
||||
console.log(anExportedString);
|
||||
class test2 {
|
||||
test = [];
|
||||
constructor() {
|
||||
console.log('hi');
|
||||
}
|
||||
}
|
||||
const run = async () => {
|
||||
return 'hi';
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9jb21waWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdG9jb21waWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDcEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUVyQixPQUFPLEtBQUssS0FBSyxNQUFNLG1CQUFtQixDQUFDO0FBRTNDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUNkLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUViLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUU5QixNQUFNLEtBQUs7SUFDVCxJQUFJLEdBQWEsRUFBRSxDQUFDO0lBQ3BCO1FBQ0UsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQixDQUFDO0NBQ0Y7QUFFRCxNQUFNLEdBQUcsR0FBRyxLQUFLLElBQXFCLEVBQUU7SUFDdEMsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDLENBQUMifQ==
|
||||
1
test/assets/output/tocompile2.d.ts
vendored
1
test/assets/output/tocompile2.d.ts
vendored
@@ -1 +0,0 @@
|
||||
export declare const anExportedString = "exported string";
|
||||
@@ -1,3 +0,0 @@
|
||||
console.log('hello');
|
||||
export const anExportedString = 'exported string';
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9jb21waWxlMi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RvY29tcGlsZTIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUNyQixNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxpQkFBaUIsQ0FBQyJ9
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@git.zone/tsbuild',
|
||||
version: '3.1.3',
|
||||
version: '4.1.0',
|
||||
description: 'A tool for compiling TypeScript files using the latest nightly features, offering flexible APIs and a CLI for streamlined development.'
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ early.start('tsbuild');
|
||||
export * from './mod_fs/index.js';
|
||||
export * from './mod_config/index.js';
|
||||
export * from './mod_unpack/index.js';
|
||||
export * from './mod_pathrewrite/index.js';
|
||||
export * from './mod_compiler/index.js';
|
||||
export * from './mod_cli/index.js';
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ 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';
|
||||
import { TsPathRewriter } from '../mod_pathrewrite/index.js';
|
||||
|
||||
/**
|
||||
* Interface for error summary data
|
||||
@@ -307,6 +308,7 @@ export class TsCompiler {
|
||||
): Promise<ICompileResult> {
|
||||
const emittedFiles: string[] = [];
|
||||
const errorSummaries: IErrorSummary[] = [];
|
||||
const successfulOutputDirs: string[] = [];
|
||||
|
||||
const totalTasks = Object.keys(globPatterns).length;
|
||||
let currentTask = 0;
|
||||
@@ -335,6 +337,14 @@ export class TsCompiler {
|
||||
// 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,
|
||||
@@ -357,6 +367,20 @@ export class TsCompiler {
|
||||
// Perform unpack if compilation succeeded
|
||||
if (result.errorSummary.totalErrors === 0) {
|
||||
await performUnpack(pattern, destDir, this.cwd);
|
||||
successfulOutputDirs.push(destDir);
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite import paths in all output directories to handle cross-module references
|
||||
// This must happen after ALL compilations so all destination folders exist
|
||||
if (successfulOutputDirs.length > 0) {
|
||||
const rewriter = TsPathRewriter.fromGlobPatterns(globPatterns);
|
||||
let totalRewritten = 0;
|
||||
for (const outputDir of successfulOutputDirs) {
|
||||
totalRewritten += await rewriter.rewriteDirectory(outputDir);
|
||||
}
|
||||
if (totalRewritten > 0 && !isQuiet && !isJson) {
|
||||
console.log(` 🔄 Rewrote import paths in ${totalRewritten} file${totalRewritten !== 1 ? 's' : ''}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
200
ts/mod_pathrewrite/classes.tspathrewriter.ts
Normal file
200
ts/mod_pathrewrite/classes.tspathrewriter.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { FsHelpers } from '../mod_fs/index.js';
|
||||
|
||||
/**
|
||||
* Interface for folder mapping between source and destination
|
||||
*/
|
||||
export interface IFolderMapping {
|
||||
sourceFolder: string; // e.g., 'ts_shared'
|
||||
destFolder: string; // e.g., 'dist_ts_shared'
|
||||
}
|
||||
|
||||
/**
|
||||
* TsPathRewriter handles rewriting import paths in compiled JavaScript files.
|
||||
*
|
||||
* When TypeScript compiles files that import from sibling directories like:
|
||||
* import { helper } from '../ts_shared/helper.js';
|
||||
*
|
||||
* This class rewrites them to point to the compiled output directories:
|
||||
* import { helper } from '../dist_ts_shared/helper.js';
|
||||
*
|
||||
* This is necessary because the unpack feature flattens nested output structures,
|
||||
* changing the relative paths between modules.
|
||||
*/
|
||||
export class TsPathRewriter {
|
||||
private mappings: IFolderMapping[];
|
||||
|
||||
constructor(mappings: IFolderMapping[]) {
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TsPathRewriter from glob patterns used in compilation
|
||||
*
|
||||
* @param globPatterns - Map of source patterns to destination directories
|
||||
* e.g., { './ts_core/**\/*.ts': './dist_ts_core', './ts_shared/**\/*.ts': './dist_ts_shared' }
|
||||
* @returns TsPathRewriter instance with extracted folder mappings
|
||||
*/
|
||||
public static fromGlobPatterns(globPatterns: Record<string, string>): TsPathRewriter {
|
||||
const mappings: IFolderMapping[] = [];
|
||||
|
||||
for (const [sourcePattern, destDir] of Object.entries(globPatterns)) {
|
||||
const sourceFolder = FsHelpers.extractSourceFolder(sourcePattern);
|
||||
const destFolder = FsHelpers.extractSourceFolder(destDir);
|
||||
|
||||
if (sourceFolder && destFolder) {
|
||||
mappings.push({ sourceFolder, destFolder });
|
||||
}
|
||||
}
|
||||
|
||||
return new TsPathRewriter(mappings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current folder mappings
|
||||
*/
|
||||
public getMappings(): IFolderMapping[] {
|
||||
return [...this.mappings];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite import paths in a single file
|
||||
*
|
||||
* @param filePath - Absolute path to the file to rewrite
|
||||
* @returns true if file was modified, false otherwise
|
||||
*/
|
||||
public async rewriteFile(filePath: string): Promise<boolean> {
|
||||
// Only process .js and .d.ts files
|
||||
if (!filePath.endsWith('.js') && !filePath.endsWith('.d.ts')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const content = await fs.promises.readFile(filePath, 'utf8');
|
||||
const rewritten = this.rewriteContent(content);
|
||||
|
||||
if (rewritten !== content) {
|
||||
await fs.promises.writeFile(filePath, rewritten, 'utf8');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (error) {
|
||||
// File doesn't exist or other error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite import paths in all .js and .d.ts files in a directory (recursively)
|
||||
*
|
||||
* @param dirPath - Absolute path to the directory
|
||||
* @returns Number of files modified
|
||||
*/
|
||||
public async rewriteDirectory(dirPath: string): Promise<number> {
|
||||
let modifiedCount = 0;
|
||||
|
||||
const processDir = async (currentDir: string): Promise<void> => {
|
||||
const entries = await FsHelpers.listDirectory(currentDir);
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(currentDir, entry.name);
|
||||
|
||||
if (entry.isDirectory) {
|
||||
await processDir(fullPath);
|
||||
} else if (entry.isFile && (entry.name.endsWith('.js') || entry.name.endsWith('.d.ts'))) {
|
||||
const wasModified = await this.rewriteFile(fullPath);
|
||||
if (wasModified) {
|
||||
modifiedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (await FsHelpers.directoryExists(dirPath)) {
|
||||
await processDir(dirPath);
|
||||
}
|
||||
|
||||
return modifiedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite import paths in content string
|
||||
*
|
||||
* This method only modifies actual import/export/require statements,
|
||||
* not arbitrary strings or comments that might contain similar patterns.
|
||||
*
|
||||
* @param content - File content to process
|
||||
* @returns Rewritten content
|
||||
*/
|
||||
public rewriteContent(content: string): string {
|
||||
if (this.mappings.length === 0) {
|
||||
return content;
|
||||
}
|
||||
|
||||
let result = content;
|
||||
|
||||
for (const { sourceFolder, destFolder } of this.mappings) {
|
||||
// Skip if source and dest are the same
|
||||
if (sourceFolder === destFolder) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Pattern 1: ES Module imports/exports with 'from'
|
||||
// Matches: from '../ts_shared/...' or from '../../ts_shared/...'
|
||||
// Also handles: export { x } from '../ts_shared/...'
|
||||
const fromPattern = new RegExp(
|
||||
`(from\\s*['"])((?:\\.\\.\\/)+)${this.escapeRegex(sourceFolder)}(\\/[^'"]*['"])`,
|
||||
'g'
|
||||
);
|
||||
result = result.replace(fromPattern, `$1$2${destFolder}$3`);
|
||||
|
||||
// Pattern 2: Dynamic imports
|
||||
// Matches: import('../ts_shared/...')
|
||||
const dynamicImportPattern = new RegExp(
|
||||
`(import\\s*\\(\\s*['"])((?:\\.\\.\\/)+)${this.escapeRegex(sourceFolder)}(\\/[^'"]*['"]\\s*\\))`,
|
||||
'g'
|
||||
);
|
||||
result = result.replace(dynamicImportPattern, `$1$2${destFolder}$3`);
|
||||
|
||||
// Pattern 3: CommonJS require
|
||||
// Matches: require('../ts_shared/...')
|
||||
const requirePattern = new RegExp(
|
||||
`(require\\s*\\(\\s*['"])((?:\\.\\.\\/)+)${this.escapeRegex(sourceFolder)}(\\/[^'"]*['"]\\s*\\))`,
|
||||
'g'
|
||||
);
|
||||
result = result.replace(requirePattern, `$1$2${destFolder}$3`);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape special regex characters in a string
|
||||
*/
|
||||
private escapeRegex(str: string): string {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to rewrite import paths in output directories
|
||||
*
|
||||
* @param globPatterns - Map of source patterns to destination directories
|
||||
* @param outputDirs - List of output directories to process
|
||||
* @returns Total number of files modified
|
||||
*/
|
||||
export async function rewriteImportPaths(
|
||||
globPatterns: Record<string, string>,
|
||||
outputDirs: string[]
|
||||
): Promise<number> {
|
||||
const rewriter = TsPathRewriter.fromGlobPatterns(globPatterns);
|
||||
let totalModified = 0;
|
||||
|
||||
for (const dir of outputDirs) {
|
||||
totalModified += await rewriter.rewriteDirectory(dir);
|
||||
}
|
||||
|
||||
return totalModified;
|
||||
}
|
||||
1
ts/mod_pathrewrite/index.ts
Normal file
1
ts/mod_pathrewrite/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './classes.tspathrewriter.js';
|
||||
Reference in New Issue
Block a user