typerd 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{existsSync}from"node:fs";import{AbstractWatchableAction}from"../abstract.watchable-action.js";import{cleanDirectory,ensureSwcInstalled,resolveAndValidateDirectory,resolveTsConfig}from"../../lib/utils/index.js";import{TypeChecker}from"../../lib/type-checker/type-checker.js";import{CompilerFactory}from"../../lib/compilers/compiler.factory.js";import{TscCompiler}from"../../lib/compilers/tsc.compiler.js";import{SourceNotFoundError}from"../../lib/errors/index.js";import{logger}from"../../lib/logger/index.js";export class BuildAction extends AbstractWatchableAction{async setup(_,options){if(options.compiler==="swc"){ensureSwcInstalled()}const tsconfig=resolveTsConfig(process.cwd());const sourcedir=resolveAndValidateDirectory(options.source,process.cwd());const outputdir=resolveAndValidateDirectory(options.output,process.cwd());if(!existsSync(sourcedir))throw new SourceNotFoundError(sourcedir);logger.verbose(`Build directories: source=${sourcedir}, output=${outputdir}`);if(options.clean)cleanDirectory(outputdir);const isSwc=options.compiler==="swc";const config={source:sourcedir,output:outputdir,tsconfig:options.tsconfig||tsconfig.path,hasPathAliases:tsconfig.hasPathAliases,emitTypes:isSwc?options.emitTypes:undefined};const compiler=CompilerFactory.create(options.compiler);return{compiler,config,options}}async runOnce(ctx){const isSwc=ctx.options.compiler==="swc";if(isSwc){if(ctx.options.emitTypes){const tscCompiler=new TscCompiler;tscCompiler.emitDeclarations(ctx.config)}else if(ctx.options.typeCheck){const typeChecker=new TypeChecker(ctx.config.tsconfig);typeChecker.check()}}await ctx.compiler.compile(ctx.config)}async runWatch(ctx){const isSwc=ctx.options.compiler==="swc";if(isSwc&&ctx.options.emitTypes){const tscCompiler=new TscCompiler;tscCompiler.watchDeclarations(ctx.config,{onSuccess:()=>{void this.compileAndLog(ctx)}})}else if(isSwc&&ctx.options.typeCheck){this.typeChecker=new TypeChecker(ctx.config.tsconfig);this.typeChecker.fork({onDiagnostics:result=>{if(!result.success)return;void this.compileAndLog(ctx)}})}else{await ctx.compiler.watch(ctx.config)}}getProcess(){return null}cleanup(){this.typeChecker?.stop()}async compileAndLog(ctx){await ctx.compiler.compile(ctx.config);logger.swc("Waiting for file changes.")}constructor(...args){super(...args),this.typeChecker=null}}
|
|
1
|
+
import{existsSync}from"node:fs";import{AbstractWatchableAction}from"../abstract.watchable-action.js";import{cleanDirectory,ensureSwcInstalled,resolveAndValidateDirectory,resolveTsConfig}from"../../lib/utils/index.js";import{TypeChecker}from"../../lib/type-checker/type-checker.js";import{CompilerFactory}from"../../lib/compilers/compiler.factory.js";import{TscCompiler}from"../../lib/compilers/tsc.compiler.js";import{SourceNotFoundError}from"../../lib/errors/index.js";import{logger}from"../../lib/logger/index.js";export class BuildAction extends AbstractWatchableAction{async setup(_,options){if(options.compiler==="swc"){ensureSwcInstalled()}const tsconfig=resolveTsConfig(process.cwd());const sourcedir=resolveAndValidateDirectory(options.source,process.cwd());const outputdir=resolveAndValidateDirectory(options.output,process.cwd());if(!existsSync(sourcedir))throw new SourceNotFoundError(sourcedir);logger.verbose(`Build directories: source=${sourcedir}, output=${outputdir}`);if(options.clean)cleanDirectory(outputdir);const isSwc=options.compiler==="swc";const config={source:sourcedir,output:outputdir,tsconfig:options.tsconfig||tsconfig.path,hasPathAliases:tsconfig.hasPathAliases,emitTypes:isSwc?options.emitTypes:undefined};const compiler=CompilerFactory.create(options.compiler);return Promise.resolve({compiler,config,options})}async runOnce(ctx){const isSwc=ctx.options.compiler==="swc";if(isSwc){if(ctx.options.emitTypes){const tscCompiler=new TscCompiler;tscCompiler.emitDeclarations(ctx.config)}else if(ctx.options.typeCheck){const typeChecker=new TypeChecker(ctx.config.tsconfig);typeChecker.check()}}await ctx.compiler.compile(ctx.config)}async runWatch(ctx){const isSwc=ctx.options.compiler==="swc";if(isSwc&&ctx.options.emitTypes){const tscCompiler=new TscCompiler;tscCompiler.watchDeclarations(ctx.config,{onSuccess:()=>{void this.compileAndLog(ctx)}})}else if(isSwc&&ctx.options.typeCheck){this.typeChecker=new TypeChecker(ctx.config.tsconfig);this.typeChecker.fork({onDiagnostics:result=>{if(!result.success)return;void this.compileAndLog(ctx)}})}else{await ctx.compiler.watch(ctx.config)}}getProcess(){return null}async cleanup(){await this.typeChecker?.stop()}async compileAndLog(ctx){await ctx.compiler.compile(ctx.config);logger.swc("Waiting for file changes.")}constructor(...args){super(...args),this.typeChecker=null}}
|
|
2
2
|
//# sourceMappingURL=build.action.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{existsSync}from"node:fs";import{join}from"node:path";import{AbstractWatchableAction}from"../abstract.watchable-action.js";import{TscCompiler}from"../../lib/compilers/tsc.compiler.js";import{CompilerFactory}from"../../lib/compilers/compiler.factory.js";import{cleanDirectory,ensureSwcInstalled,getErrorMessage,isPathWithinBoundary,killProcessTree,resolveAndValidateDirectory,resolveSwcConfig,resolveTsConfig}from"../../lib/utils/index.js";import{TypeChecker}from"../../lib/type-checker/type-checker.js";import{NodeRunner}from"../../lib/runners/node.runner.js";import{OutputWatcher}from"../../lib/watchers/output.watcher.js";import{logger}from"../../lib/logger/index.js";import{TIMING}from"../../lib/config/index.js";import{EntryNotFoundError,PathTraversalError,SourceNotFoundError}from"../../lib/errors/index.js";const CRASH_LOOP_THRESHOLD=3;const CRASH_LOOP_WINDOW_MS=5e3;export class StartAction extends AbstractWatchableAction{async setup(inputs,options){if(options.compiler==="swc"){ensureSwcInstalled()}const tsconfig=resolveTsConfig(process.cwd());const sourcedir=resolveAndValidateDirectory(options.source,process.cwd());const outputdir=resolveAndValidateDirectory(options.output,process.cwd());if(!existsSync(sourcedir))throw new SourceNotFoundError(sourcedir);logger.verbose(`Start directories: source=${sourcedir}, output=${outputdir}`);const entryInput=this.getRequiredInput(inputs,"entry");const sourceEntry=join(sourcedir,entryInput);if(!isPathWithinBoundary(sourceEntry,sourcedir)){throw new PathTraversalError(entryInput,sourcedir)}if(!existsSync(sourceEntry))throw new EntryNotFoundError(sourceEntry);logger.verbose(`Entry: source=${sourceEntry}, compiled=${this.getCompiledEntry(entryInput,outputdir)}`);if(options.clean)cleanDirectory(outputdir);const compiledEntry=this.getCompiledEntry(entryInput,outputdir);const useSourceMaps=options.compiler==="swc"?resolveSwcConfig(process.cwd()).sourceMaps:tsconfig.sourceMap;const config={source:sourcedir,output:outputdir,tsconfig:options.tsconfig||tsconfig.path,hasPathAliases:!options.watch&&tsconfig.hasPathAliases};const runner=new NodeRunner({entry:compiledEntry,cwd:process.cwd(),useSourceMaps,useTsConfigPaths:options.watch&&tsconfig.hasPathAliases,moduleType:options.moduleType,tsconfig:config.tsconfig,inspect:options.debug,inspectBrk:options.debugBrk});this.runner=runner;const compiler=CompilerFactory.create(options.compiler);return{runner,compiler,config,options}}async runOnce(ctx){if(ctx.options.typeCheck&&!(ctx.compiler instanceof TscCompiler)){const typeChecker=new TypeChecker(ctx.config.tsconfig);typeChecker.check()}await ctx.compiler.compile(ctx.config);await ctx.runner.run()}async runWatch(ctx){const useTypeChecker=ctx.options.typeCheck&&!(ctx.compiler instanceof TscCompiler);let isFirstRun=true;if(useTypeChecker){this.typeChecker=new TypeChecker(ctx.config.tsconfig);this.typeChecker.fork({onDiagnostics:result=>{if(!result.success)return;void this.handleSuccessfulTypeCheck(ctx,isFirstRun);isFirstRun=false}})}else if(ctx.compiler instanceof TscCompiler){ctx.compiler.watch(ctx.config,{onReady:()=>{this.startNodeProcess()},onSuccess:()=>{if(!isFirstRun){this.restartNodeProcess().catch(err=>{logger.error(`Failed to restart: ${getErrorMessage(err)}`)})}isFirstRun=false}})}else{this.outputWatcher=new OutputWatcher({watchDir:ctx.config.output,debounceMs:TIMING.FILE_CHANGE_DEBOUNCE_MS,onChange:()=>{this.restartNodeProcess().catch(err=>{logger.error(`Failed to restart: ${getErrorMessage(err)}`)})}});await ctx.compiler.watch(ctx.config,{onReady:async()=>{this.startNodeProcess();await this.outputWatcher.start()}})}}getProcess(){return this.runner?.getProcess??null}async cleanup(){await this.outputWatcher?.stop();await this.typeChecker?.stop()}startNodeProcess(){if(!this.runner)return;const proc=this.runner.start();proc.on("error",err=>{if(err.code==="ENOENT"){logger.error("Node.js not found in PATH");process.exit(1)}else{logger.error(`Failed to start process: ${err.message}`);process.exit(1)}});proc.on("exit",code=>{if(!this.isRestarting&&code!==null&&code!==0){logger.warn(`Application exited with code ${code}`)}})}async restartNodeProcess(){if(!this.runner)return;const now=Date.now();this.restartTimestamps=this.restartTimestamps.filter(t=>now-t<CRASH_LOOP_WINDOW_MS);if(this.restartTimestamps.length>=CRASH_LOOP_THRESHOLD){logger.warn(`Crash loop detected (${this.restartTimestamps.length} restarts in `+`${CRASH_LOOP_WINDOW_MS/1e3}s). Waiting for file changes before restarting...`);this.restartTimestamps=[];const proc=this.runner.getProcess;if(proc?.pid){await killProcessTree(proc.pid)}return}this.restartTimestamps.push(now);this.restartController?.abort();const controller=new AbortController;this.restartController=controller;const signal=controller.signal;this.isRestarting=true;const proc=this.runner.getProcess;if(proc?.pid){await killProcessTree(proc.pid)}if(signal.aborted)return;this.isRestarting=false;this.startNodeProcess()}async handleSuccessfulTypeCheck(ctx,isFirstRun){await ctx.compiler.compile(ctx.config);logger.swc("Waiting for file changes.");if(isFirstRun){this.startNodeProcess()}else{await this.restartNodeProcess()}}getCompiledEntry(entryInput,outDir){const extMap={".mts":".mjs",".cts":".cjs",".ts":".js",".tsx":".jsx"};const jsEntry=entryInput.replace(/\.(ts|tsx|mts|cts)$/,m=>extMap[m]??".js");return join(outDir,jsEntry)}constructor(...args){super(...args),this.runner=null,this.outputWatcher=null,this.typeChecker=null,this.isRestarting=false,this.restartController=null,this.restartTimestamps=[]}}
|
|
1
|
+
import{existsSync}from"node:fs";import{join}from"node:path";import{AbstractWatchableAction}from"../abstract.watchable-action.js";import{TscCompiler}from"../../lib/compilers/tsc.compiler.js";import{CompilerFactory}from"../../lib/compilers/compiler.factory.js";import{cleanDirectory,ensureSwcInstalled,getErrorMessage,isPathWithinBoundary,killProcessTree,resolveAndValidateDirectory,resolveSwcConfig,resolveTsConfig}from"../../lib/utils/index.js";import{TypeChecker}from"../../lib/type-checker/type-checker.js";import{NodeRunner}from"../../lib/runners/node.runner.js";import{OutputWatcher}from"../../lib/watchers/output.watcher.js";import{logger}from"../../lib/logger/index.js";import{TIMING}from"../../lib/config/index.js";import{EntryNotFoundError,PathTraversalError,SourceNotFoundError}from"../../lib/errors/index.js";const CRASH_LOOP_THRESHOLD=3;const CRASH_LOOP_WINDOW_MS=5e3;export class StartAction extends AbstractWatchableAction{async setup(inputs,options){if(options.compiler==="swc"){ensureSwcInstalled()}const tsconfig=resolveTsConfig(process.cwd());const sourcedir=resolveAndValidateDirectory(options.source,process.cwd());const outputdir=resolveAndValidateDirectory(options.output,process.cwd());if(!existsSync(sourcedir))throw new SourceNotFoundError(sourcedir);logger.verbose(`Start directories: source=${sourcedir}, output=${outputdir}`);const entryInput=this.getRequiredInput(inputs,"entry");const sourceEntry=join(sourcedir,entryInput);if(!isPathWithinBoundary(sourceEntry,sourcedir)){throw new PathTraversalError(entryInput,sourcedir)}if(!existsSync(sourceEntry))throw new EntryNotFoundError(sourceEntry);logger.verbose(`Entry: source=${sourceEntry}, compiled=${this.getCompiledEntry(entryInput,outputdir)}`);if(options.clean)cleanDirectory(outputdir);const compiledEntry=this.getCompiledEntry(entryInput,outputdir);const useSourceMaps=options.compiler==="swc"?resolveSwcConfig(process.cwd()).sourceMaps:tsconfig.sourceMap;const config={source:sourcedir,output:outputdir,tsconfig:options.tsconfig||tsconfig.path,hasPathAliases:!options.watch&&tsconfig.hasPathAliases};const runner=new NodeRunner({entry:compiledEntry,cwd:process.cwd(),useSourceMaps,useTsConfigPaths:options.watch&&tsconfig.hasPathAliases,moduleType:options.moduleType,tsconfig:config.tsconfig,inspect:options.debug,inspectBrk:options.debugBrk});this.runner=runner;const compiler=CompilerFactory.create(options.compiler);return Promise.resolve({runner,compiler,config,options})}async runOnce(ctx){if(ctx.options.typeCheck&&!(ctx.compiler instanceof TscCompiler)){const typeChecker=new TypeChecker(ctx.config.tsconfig);typeChecker.check()}await ctx.compiler.compile(ctx.config);await ctx.runner.run()}async runWatch(ctx){const useTypeChecker=ctx.options.typeCheck&&!(ctx.compiler instanceof TscCompiler);let isFirstRun=true;if(useTypeChecker){this.typeChecker=new TypeChecker(ctx.config.tsconfig);this.typeChecker.fork({onDiagnostics:result=>{if(!result.success)return;void this.handleSuccessfulTypeCheck(ctx,isFirstRun);isFirstRun=false}})}else if(ctx.compiler instanceof TscCompiler){ctx.compiler.watch(ctx.config,{onReady:()=>{this.startNodeProcess()},onSuccess:()=>{if(!isFirstRun){this.restartNodeProcess().catch(err=>{logger.error(`Failed to restart: ${getErrorMessage(err)}`)})}isFirstRun=false}})}else{this.outputWatcher=new OutputWatcher({watchDir:ctx.config.output,debounceMs:TIMING.FILE_CHANGE_DEBOUNCE_MS,onChange:()=>{this.restartNodeProcess().catch(err=>{logger.error(`Failed to restart: ${getErrorMessage(err)}`)})}});await ctx.compiler.watch(ctx.config,{onReady:async()=>{this.startNodeProcess();await this.outputWatcher.start()}})}}getProcess(){return this.runner?.getProcess??null}async cleanup(){await this.outputWatcher?.stop();await this.typeChecker?.stop()}startNodeProcess(){if(!this.runner)return;const proc=this.runner.start();proc.on("error",err=>{if(err.code==="ENOENT"){logger.error("Node.js not found in PATH");process.exit(1)}else{logger.error(`Failed to start process: ${err.message}`);process.exit(1)}});proc.on("exit",code=>{if(!this.isRestarting&&code!==null&&code!==0){logger.warn(`Application exited with code ${code}`)}})}async restartNodeProcess(){if(!this.runner)return;const now=Date.now();this.restartTimestamps=this.restartTimestamps.filter(t=>now-t<CRASH_LOOP_WINDOW_MS);if(this.restartTimestamps.length>=CRASH_LOOP_THRESHOLD){logger.warn(`Crash loop detected (${this.restartTimestamps.length} restarts in `+`${CRASH_LOOP_WINDOW_MS/1e3}s). Waiting for file changes before restarting...`);this.restartTimestamps=[];const proc=this.runner.getProcess;if(proc?.pid){await killProcessTree(proc.pid)}return}this.restartTimestamps.push(now);this.restartController?.abort();const controller=new AbortController;this.restartController=controller;const signal=controller.signal;this.isRestarting=true;const proc=this.runner.getProcess;if(proc?.pid){await killProcessTree(proc.pid)}if(signal.aborted)return;this.isRestarting=false;this.startNodeProcess()}async handleSuccessfulTypeCheck(ctx,isFirstRun){await ctx.compiler.compile(ctx.config);logger.swc("Waiting for file changes.");if(isFirstRun){this.startNodeProcess()}else{await this.restartNodeProcess()}}getCompiledEntry(entryInput,outDir){const extMap={".mts":".mjs",".cts":".cjs",".ts":".js",".tsx":".jsx"};const jsEntry=entryInput.replace(/\.(ts|tsx|mts|cts)$/,m=>extMap[m]??".js");return join(outDir,jsEntry)}constructor(...args){super(...args),this.runner=null,this.outputWatcher=null,this.typeChecker=null,this.isRestarting=false,this.restartController=null,this.restartTimestamps=[]}}
|
|
2
2
|
//# sourceMappingURL=start.action.js.map
|
package/dist/main.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createRequire}from"node:module";import{Command}from"commander";import{Commands}from"./commands/index.js";import{logger}from"./lib/logger/index.js";const require=createRequire(import.meta.url);const{name,version,description}=require("../package.json");const cmd=new Command().name(name).version(version).description(description);cmd.option("-
|
|
1
|
+
import{createRequire}from"node:module";import{Command}from"commander";import{Commands}from"./commands/index.js";import{logger}from"./lib/logger/index.js";const require=createRequire(import.meta.url);const{name,version,description}=require("../package.json");const cmd=new Command().name(name).version(version).description(description);cmd.option("-v, --verbose","Enable verbose output",false);cmd.hook("preAction",thisCommand=>{const opts=thisCommand.opts();logger.setVerbose(opts.verbose)});Commands.forEach(command=>{cmd.addCommand(command)});cmd.parse(process.argv);
|
|
2
2
|
//# sourceMappingURL=main.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typerd",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "CLI development tools for building and running TypeScript projects",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "hexac",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"type": "git",
|
|
16
16
|
"url": "https://github.com/01hexac/typerd.git"
|
|
17
17
|
},
|
|
18
|
-
"homepage": "https://github.com/01hexac/typerd
|
|
18
|
+
"homepage": "https://github.com/01hexac/typerd#readme",
|
|
19
19
|
"bugs": "https://github.com/01hexac/typerd/issues",
|
|
20
20
|
"files": [
|
|
21
21
|
"bin",
|
|
@@ -29,16 +29,6 @@
|
|
|
29
29
|
"typerd": "./bin/typerd"
|
|
30
30
|
},
|
|
31
31
|
"type": "module",
|
|
32
|
-
"scripts": {
|
|
33
|
-
"build": "tsc --noEmit && rimraf dist && swc src -d dist --strip-leading-paths",
|
|
34
|
-
"start": "node dist/main.js",
|
|
35
|
-
"type:check": "tsc --noEmit",
|
|
36
|
-
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
37
|
-
"lint": "eslint \"{src,test}/**/*.ts\"",
|
|
38
|
-
"lint:fix": "eslint \"{src,test}/**/*.ts\" --fix",
|
|
39
|
-
"prepare": "husky",
|
|
40
|
-
"release": "release-it"
|
|
41
|
-
},
|
|
42
32
|
"lint-staged": {
|
|
43
33
|
"*.ts": [
|
|
44
34
|
"eslint",
|
|
@@ -93,5 +83,13 @@
|
|
|
93
83
|
"engines": {
|
|
94
84
|
"node": ">=18.0.0"
|
|
95
85
|
},
|
|
96
|
-
"
|
|
97
|
-
|
|
86
|
+
"scripts": {
|
|
87
|
+
"build": "tsc --noEmit && rimraf dist && swc src -d dist --strip-leading-paths",
|
|
88
|
+
"start": "node dist/main.js",
|
|
89
|
+
"type:check": "tsc --noEmit",
|
|
90
|
+
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
91
|
+
"lint": "eslint \"{src,test}/**/*.ts\"",
|
|
92
|
+
"lint:fix": "eslint \"{src,test}/**/*.ts\" --fix",
|
|
93
|
+
"release": "release-it"
|
|
94
|
+
}
|
|
95
|
+
}
|