linxus fs fixes

This commit is contained in:
Boki 2025-06-09 22:55:51 -04:00
parent ac23b70146
commit 0b7846fe67
292 changed files with 41947 additions and 41947 deletions

View file

@ -1,202 +1,202 @@
# @stock-bot/shutdown
Shutdown management library for Node.js applications in the Stock Bot platform.
## Features
- ✅ **Automatic Signal Handling** - SIGTERM, SIGINT, SIGUSR2 (Unix), uncaught exceptions
- ✅ **Platform Support** - Windows and Unix/Linux compatible
- ✅ **Multiple Callbacks** - Register multiple cleanup functions
- ✅ **Timeout Protection** - Configurable shutdown timeout
- ✅ **Error Handling** - Failed callbacks don't block shutdown
- ✅ **TypeScript Support** - Full type definitions
- ✅ **Zero Dependencies** - Lightweight and efficient
## Installation
```bash
bun add @stock-bot/shutdown
```
## Quick Start
```typescript
import { onShutdown, setShutdownTimeout } from '@stock-bot/shutdown';
// Configure shutdown timeout (optional, default: 30 seconds)
setShutdownTimeout(15000); // 15 seconds
// Register cleanup callbacks
onShutdown(async () => {
console.log('Closing database connections...');
await database.close();
});
onShutdown(async () => {
console.log('Stopping background jobs...');
await jobQueue.stop();
});
onShutdown(() => {
console.log('Final cleanup...');
// Synchronous cleanup
});
console.log('Application started. Press Ctrl+C to test graceful shutdown.');
```
## API Reference
### Convenience Functions
#### `onShutdown(callback)`
Register a cleanup callback.
```typescript
onShutdown(async () => {
await cleanup();
});
```
#### `setShutdownTimeout(timeout)`
Set shutdown timeout in milliseconds.
```typescript
setShutdownTimeout(30000); // 30 seconds
```
#### `initiateShutdown(signal?)`
Manually trigger shutdown.
```typescript
const result = await initiateShutdown('manual');
console.log(result.success); // true/false
```
#### `shutdownAndExit(signal?, exitCode?)`
Trigger shutdown and exit process.
```typescript
await shutdownAndExit('manual', 0);
```
### Advanced Usage
#### Manual Instance Management
```typescript
import { Shutdown } from '@stock-bot/shutdown';
const shutdown = new Shutdown({
timeout: 20000,
autoRegister: true
});
shutdown.onShutdown(async () => {
await cleanup();
});
// Manual shutdown
const result = await shutdown.shutdown('manual');
```
#### Configuration Options
```typescript
interface ShutdownOptions {
timeout?: number; // Timeout in ms (default: 30000)
autoRegister?: boolean; // Auto-register signals (default: true)
}
```
#### Shutdown Result
```typescript
interface ShutdownResult {
success: boolean;
callbacksExecuted: number;
callbacksFailed: number;
duration: number;
error?: string;
}
```
## Examples
### Express Server
```typescript
import express from 'express';
import { onShutdown, setShutdownTimeout } from '@stock-bot/shutdown';
const app = express();
const server = app.listen(3000);
setShutdownTimeout(10000);
onShutdown(async () => {
console.log('Closing HTTP server...');
await new Promise(resolve => server.close(resolve));
});
onShutdown(async () => {
console.log('Closing database...');
await database.close();
});
```
### Worker Process
```typescript
import { onShutdown } from '@stock-bot/shutdown';
let isRunning = true;
onShutdown(() => {
console.log('Stopping worker...');
isRunning = false;
});
// Worker loop
while (isRunning) {
await processJob();
await new Promise(resolve => setTimeout(resolve, 1000));
}
```
## Signal Handling
The library automatically handles these signals:
- **SIGTERM** - Termination request
- **SIGINT** - Interrupt (Ctrl+C)
- **SIGUSR2** - User-defined signal (Unix only)
- **uncaughtException** - Unhandled exceptions
- **unhandledRejection** - Unhandled promise rejections
On Windows, only SIGTERM and SIGINT are supported due to platform limitations.
## Best Practices
1. **Register callbacks early** in your application startup
2. **Keep callbacks simple** and focused on cleanup
3. **Use appropriate timeouts** based on your cleanup needs
4. **Handle errors gracefully** in callbacks
5. **Test shutdown behavior** in your CI/CD pipeline
## Testing
```typescript
import { resetShutdown, onShutdown } from '@stock-bot/shutdown';
beforeEach(() => {
resetShutdown(); // Clear previous state
});
test('should register shutdown callback', () => {
let cleaned = false;
onShutdown(() => { cleaned = true; });
// Test shutdown behavior
});
```
# @stock-bot/shutdown
Shutdown management library for Node.js applications in the Stock Bot platform.
## Features
- ✅ **Automatic Signal Handling** - SIGTERM, SIGINT, SIGUSR2 (Unix), uncaught exceptions
- ✅ **Platform Support** - Windows and Unix/Linux compatible
- ✅ **Multiple Callbacks** - Register multiple cleanup functions
- ✅ **Timeout Protection** - Configurable shutdown timeout
- ✅ **Error Handling** - Failed callbacks don't block shutdown
- ✅ **TypeScript Support** - Full type definitions
- ✅ **Zero Dependencies** - Lightweight and efficient
## Installation
```bash
bun add @stock-bot/shutdown
```
## Quick Start
```typescript
import { onShutdown, setShutdownTimeout } from '@stock-bot/shutdown';
// Configure shutdown timeout (optional, default: 30 seconds)
setShutdownTimeout(15000); // 15 seconds
// Register cleanup callbacks
onShutdown(async () => {
console.log('Closing database connections...');
await database.close();
});
onShutdown(async () => {
console.log('Stopping background jobs...');
await jobQueue.stop();
});
onShutdown(() => {
console.log('Final cleanup...');
// Synchronous cleanup
});
console.log('Application started. Press Ctrl+C to test graceful shutdown.');
```
## API Reference
### Convenience Functions
#### `onShutdown(callback)`
Register a cleanup callback.
```typescript
onShutdown(async () => {
await cleanup();
});
```
#### `setShutdownTimeout(timeout)`
Set shutdown timeout in milliseconds.
```typescript
setShutdownTimeout(30000); // 30 seconds
```
#### `initiateShutdown(signal?)`
Manually trigger shutdown.
```typescript
const result = await initiateShutdown('manual');
console.log(result.success); // true/false
```
#### `shutdownAndExit(signal?, exitCode?)`
Trigger shutdown and exit process.
```typescript
await shutdownAndExit('manual', 0);
```
### Advanced Usage
#### Manual Instance Management
```typescript
import { Shutdown } from '@stock-bot/shutdown';
const shutdown = new Shutdown({
timeout: 20000,
autoRegister: true
});
shutdown.onShutdown(async () => {
await cleanup();
});
// Manual shutdown
const result = await shutdown.shutdown('manual');
```
#### Configuration Options
```typescript
interface ShutdownOptions {
timeout?: number; // Timeout in ms (default: 30000)
autoRegister?: boolean; // Auto-register signals (default: true)
}
```
#### Shutdown Result
```typescript
interface ShutdownResult {
success: boolean;
callbacksExecuted: number;
callbacksFailed: number;
duration: number;
error?: string;
}
```
## Examples
### Express Server
```typescript
import express from 'express';
import { onShutdown, setShutdownTimeout } from '@stock-bot/shutdown';
const app = express();
const server = app.listen(3000);
setShutdownTimeout(10000);
onShutdown(async () => {
console.log('Closing HTTP server...');
await new Promise(resolve => server.close(resolve));
});
onShutdown(async () => {
console.log('Closing database...');
await database.close();
});
```
### Worker Process
```typescript
import { onShutdown } from '@stock-bot/shutdown';
let isRunning = true;
onShutdown(() => {
console.log('Stopping worker...');
isRunning = false;
});
// Worker loop
while (isRunning) {
await processJob();
await new Promise(resolve => setTimeout(resolve, 1000));
}
```
## Signal Handling
The library automatically handles these signals:
- **SIGTERM** - Termination request
- **SIGINT** - Interrupt (Ctrl+C)
- **SIGUSR2** - User-defined signal (Unix only)
- **uncaughtException** - Unhandled exceptions
- **unhandledRejection** - Unhandled promise rejections
On Windows, only SIGTERM and SIGINT are supported due to platform limitations.
## Best Practices
1. **Register callbacks early** in your application startup
2. **Keep callbacks simple** and focused on cleanup
3. **Use appropriate timeouts** based on your cleanup needs
4. **Handle errors gracefully** in callbacks
5. **Test shutdown behavior** in your CI/CD pipeline
## Testing
```typescript
import { resetShutdown, onShutdown } from '@stock-bot/shutdown';
beforeEach(() => {
resetShutdown(); // Clear previous state
});
test('should register shutdown callback', () => {
let cleaned = false;
onShutdown(() => { cleaned = true; });
// Test shutdown behavior
});
```

View file

@ -1,26 +1,26 @@
{
"name": "@stock-bot/shutdown",
"version": "1.0.0",
"description": "Graceful shutdown management for Stock Bot platform",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts", "scripts": {
"build": "tsc",
"clean": "rm -rf dist",
"test": "bun test"
},
"dependencies": {},
"devDependencies": {
"typescript": "^5.0.0",
"@types/node": "^20.0.0"
},
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"files": [
"dist"
]
}
{
"name": "@stock-bot/shutdown",
"version": "1.0.0",
"description": "Graceful shutdown management for Stock Bot platform",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts", "scripts": {
"build": "tsc",
"clean": "rm -rf dist",
"test": "bun test"
},
"dependencies": {},
"devDependencies": {
"typescript": "^5.0.0",
"@types/node": "^20.0.0"
},
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"files": [
"dist"
]
}

View file

@ -1,79 +1,79 @@
/**
* @stock-bot/shutdown - Shutdown management library
*
* Main exports for the shutdown library
*/
// Core shutdown classes and types
export { Shutdown } from './shutdown';
export type { ShutdownCallback, ShutdownOptions, ShutdownResult } from './types';
import { Shutdown } from './shutdown';
import type { ShutdownResult } from './types';
// Global singleton instance
let globalInstance: Shutdown | null = null;
/**
* Get the global shutdown instance (creates one if it doesn't exist)
*/
function getGlobalInstance(): Shutdown {
if (!globalInstance) {
globalInstance = Shutdown.getInstance();
}
return globalInstance;
}
/**
* Convenience functions for global shutdown management
*/
/**
* Register a cleanup callback that will be executed during shutdown
*/
export function onShutdown(callback: () => Promise<void> | void): void {
getGlobalInstance().onShutdown(callback);
}
/**
* Set the shutdown timeout in milliseconds
*/
export function setShutdownTimeout(timeout: number): void {
getGlobalInstance().setTimeout(timeout);
}
/**
* Check if shutdown is currently in progress
*/
export function isShuttingDown(): boolean {
return globalInstance?.isShutdownInProgress() || false;
}
/**
* Get the number of registered shutdown callbacks
*/
export function getShutdownCallbackCount(): number {
return globalInstance?.getCallbackCount() || 0;
}
/**
* Manually initiate graceful shutdown
*/
export function initiateShutdown(signal?: string): Promise<ShutdownResult> {
return getGlobalInstance().shutdown(signal);
}
/**
* Manually initiate graceful shutdown and exit the process
*/
export function shutdownAndExit(signal?: string, exitCode = 0): Promise<never> {
return getGlobalInstance().shutdownAndExit(signal, exitCode);
}
/**
* Reset the global instance (mainly for testing)
*/
export function resetShutdown(): void {
globalInstance = null;
Shutdown.reset();
}
/**
* @stock-bot/shutdown - Shutdown management library
*
* Main exports for the shutdown library
*/
// Core shutdown classes and types
export { Shutdown } from './shutdown';
export type { ShutdownCallback, ShutdownOptions, ShutdownResult } from './types';
import { Shutdown } from './shutdown';
import type { ShutdownResult } from './types';
// Global singleton instance
let globalInstance: Shutdown | null = null;
/**
* Get the global shutdown instance (creates one if it doesn't exist)
*/
function getGlobalInstance(): Shutdown {
if (!globalInstance) {
globalInstance = Shutdown.getInstance();
}
return globalInstance;
}
/**
* Convenience functions for global shutdown management
*/
/**
* Register a cleanup callback that will be executed during shutdown
*/
export function onShutdown(callback: () => Promise<void> | void): void {
getGlobalInstance().onShutdown(callback);
}
/**
* Set the shutdown timeout in milliseconds
*/
export function setShutdownTimeout(timeout: number): void {
getGlobalInstance().setTimeout(timeout);
}
/**
* Check if shutdown is currently in progress
*/
export function isShuttingDown(): boolean {
return globalInstance?.isShutdownInProgress() || false;
}
/**
* Get the number of registered shutdown callbacks
*/
export function getShutdownCallbackCount(): number {
return globalInstance?.getCallbackCount() || 0;
}
/**
* Manually initiate graceful shutdown
*/
export function initiateShutdown(signal?: string): Promise<ShutdownResult> {
return getGlobalInstance().shutdown(signal);
}
/**
* Manually initiate graceful shutdown and exit the process
*/
export function shutdownAndExit(signal?: string, exitCode = 0): Promise<never> {
return getGlobalInstance().shutdownAndExit(signal, exitCode);
}
/**
* Reset the global instance (mainly for testing)
*/
export function resetShutdown(): void {
globalInstance = null;
Shutdown.reset();
}

View file

@ -1,198 +1,198 @@
/**
* Shutdown management for Node.js applications
*
* Features:
* - Automatic signal handling (SIGTERM, SIGINT, etc.)
* - Configurable shutdown timeout
* - Multiple cleanup callbacks with error handling
* - Platform-specific signal support (Windows/Unix)
*/
import type { ShutdownCallback, ShutdownOptions, ShutdownResult } from './types';
export class Shutdown {
private static instance: Shutdown | null = null;
private isShuttingDown = false;
private shutdownTimeout = 30000; // 30 seconds default
private callbacks: ShutdownCallback[] = [];
private signalHandlersRegistered = false;
constructor(options: ShutdownOptions = {}) {
this.shutdownTimeout = options.timeout || 30000;
if (options.autoRegister !== false) {
this.setupSignalHandlers();
}
}
/**
* Get or create singleton instance
*/
static getInstance(options?: ShutdownOptions): Shutdown {
if (!Shutdown.instance) {
Shutdown.instance = new Shutdown(options);
}
return Shutdown.instance;
}
/**
* Reset singleton instance (mainly for testing)
*/
static reset(): void {
Shutdown.instance = null;
}
/**
* Register a cleanup callback
*/
onShutdown(callback: ShutdownCallback): void {
if (this.isShuttingDown) {
return;
}
this.callbacks.push(callback);
}
/**
* Set shutdown timeout in milliseconds
*/
setTimeout(timeout: number): void {
if (timeout <= 0) {
throw new Error('Shutdown timeout must be positive');
}
this.shutdownTimeout = timeout;
}
/**
* Get current shutdown state
*/
isShutdownInProgress(): boolean {
return this.isShuttingDown;
}
/**
* Get number of registered callbacks
*/
getCallbackCount(): number {
return this.callbacks.length;
}
/**
* Initiate graceful shutdown
*/
async shutdown(signal?: string): Promise<ShutdownResult> {
if (this.isShuttingDown) {
return {
success: false,
callbacksExecuted: 0,
callbacksFailed: 0,
duration: 0,
error: 'Shutdown already in progress'
};
}
this.isShuttingDown = true;
const startTime = Date.now();
const shutdownPromise = this.executeCallbacks();
const timeoutPromise = new Promise<never>((_, reject) => {
setTimeout(() => reject(new Error('Shutdown timeout')), this.shutdownTimeout);
});
let result: ShutdownResult;
try {
const callbackResult = await Promise.race([shutdownPromise, timeoutPromise]);
const duration = Date.now() - startTime;
result = {
success: true,
callbacksExecuted: callbackResult.executed,
callbacksFailed: callbackResult.failed,
duration,
error: callbackResult.failed > 0 ? `${callbackResult.failed} callbacks failed` : undefined
};
} catch (error) {
const duration = Date.now() - startTime;
const errorMessage = error instanceof Error ? error.message : String(error);
result = {
success: false,
callbacksExecuted: 0,
callbacksFailed: 0,
duration,
error: errorMessage
};
}
// Don't call process.exit here - let the caller decide
return result;
}
/**
* Initiate shutdown and exit process
*/
async shutdownAndExit(signal?: string, exitCode = 0): Promise<never> {
const result = await this.shutdown(signal);
const finalExitCode = result.success ? exitCode : 1;
process.exit(finalExitCode);
}
/**
* Execute all registered callbacks
*/
private async executeCallbacks(): Promise<{ executed: number; failed: number }> {
if (this.callbacks.length === 0) {
return { executed: 0, failed: 0 };
}
const results = await Promise.allSettled(
this.callbacks.map(async (callback) => {
await callback();
})
);
const failed = results.filter(result => result.status === 'rejected').length;
const executed = results.length;
return { executed, failed };
}
/**
* Setup signal handlers for graceful shutdown
*/
private setupSignalHandlers(): void {
if (this.signalHandlersRegistered) {
return;
}
// Platform-specific signals
const signals: NodeJS.Signals[] = process.platform === 'win32'
? ['SIGINT', 'SIGTERM']
: ['SIGTERM', 'SIGINT', 'SIGUSR2'];
signals.forEach(signal => {
process.on(signal, () => {
this.shutdownAndExit(signal).catch(() => {
process.exit(1);
});
});
});
// Handle uncaught exceptions
process.on('uncaughtException', () => {
this.shutdownAndExit('uncaughtException', 1).catch(() => {
process.exit(1);
});
});
// Handle unhandled promise rejections
process.on('unhandledRejection', () => {
this.shutdownAndExit('unhandledRejection', 1).catch(() => {
process.exit(1);
});
});
this.signalHandlersRegistered = true;
}
}
/**
* Shutdown management for Node.js applications
*
* Features:
* - Automatic signal handling (SIGTERM, SIGINT, etc.)
* - Configurable shutdown timeout
* - Multiple cleanup callbacks with error handling
* - Platform-specific signal support (Windows/Unix)
*/
import type { ShutdownCallback, ShutdownOptions, ShutdownResult } from './types';
export class Shutdown {
private static instance: Shutdown | null = null;
private isShuttingDown = false;
private shutdownTimeout = 30000; // 30 seconds default
private callbacks: ShutdownCallback[] = [];
private signalHandlersRegistered = false;
constructor(options: ShutdownOptions = {}) {
this.shutdownTimeout = options.timeout || 30000;
if (options.autoRegister !== false) {
this.setupSignalHandlers();
}
}
/**
* Get or create singleton instance
*/
static getInstance(options?: ShutdownOptions): Shutdown {
if (!Shutdown.instance) {
Shutdown.instance = new Shutdown(options);
}
return Shutdown.instance;
}
/**
* Reset singleton instance (mainly for testing)
*/
static reset(): void {
Shutdown.instance = null;
}
/**
* Register a cleanup callback
*/
onShutdown(callback: ShutdownCallback): void {
if (this.isShuttingDown) {
return;
}
this.callbacks.push(callback);
}
/**
* Set shutdown timeout in milliseconds
*/
setTimeout(timeout: number): void {
if (timeout <= 0) {
throw new Error('Shutdown timeout must be positive');
}
this.shutdownTimeout = timeout;
}
/**
* Get current shutdown state
*/
isShutdownInProgress(): boolean {
return this.isShuttingDown;
}
/**
* Get number of registered callbacks
*/
getCallbackCount(): number {
return this.callbacks.length;
}
/**
* Initiate graceful shutdown
*/
async shutdown(signal?: string): Promise<ShutdownResult> {
if (this.isShuttingDown) {
return {
success: false,
callbacksExecuted: 0,
callbacksFailed: 0,
duration: 0,
error: 'Shutdown already in progress'
};
}
this.isShuttingDown = true;
const startTime = Date.now();
const shutdownPromise = this.executeCallbacks();
const timeoutPromise = new Promise<never>((_, reject) => {
setTimeout(() => reject(new Error('Shutdown timeout')), this.shutdownTimeout);
});
let result: ShutdownResult;
try {
const callbackResult = await Promise.race([shutdownPromise, timeoutPromise]);
const duration = Date.now() - startTime;
result = {
success: true,
callbacksExecuted: callbackResult.executed,
callbacksFailed: callbackResult.failed,
duration,
error: callbackResult.failed > 0 ? `${callbackResult.failed} callbacks failed` : undefined
};
} catch (error) {
const duration = Date.now() - startTime;
const errorMessage = error instanceof Error ? error.message : String(error);
result = {
success: false,
callbacksExecuted: 0,
callbacksFailed: 0,
duration,
error: errorMessage
};
}
// Don't call process.exit here - let the caller decide
return result;
}
/**
* Initiate shutdown and exit process
*/
async shutdownAndExit(signal?: string, exitCode = 0): Promise<never> {
const result = await this.shutdown(signal);
const finalExitCode = result.success ? exitCode : 1;
process.exit(finalExitCode);
}
/**
* Execute all registered callbacks
*/
private async executeCallbacks(): Promise<{ executed: number; failed: number }> {
if (this.callbacks.length === 0) {
return { executed: 0, failed: 0 };
}
const results = await Promise.allSettled(
this.callbacks.map(async (callback) => {
await callback();
})
);
const failed = results.filter(result => result.status === 'rejected').length;
const executed = results.length;
return { executed, failed };
}
/**
* Setup signal handlers for graceful shutdown
*/
private setupSignalHandlers(): void {
if (this.signalHandlersRegistered) {
return;
}
// Platform-specific signals
const signals: NodeJS.Signals[] = process.platform === 'win32'
? ['SIGINT', 'SIGTERM']
: ['SIGTERM', 'SIGINT', 'SIGUSR2'];
signals.forEach(signal => {
process.on(signal, () => {
this.shutdownAndExit(signal).catch(() => {
process.exit(1);
});
});
});
// Handle uncaught exceptions
process.on('uncaughtException', () => {
this.shutdownAndExit('uncaughtException', 1).catch(() => {
process.exit(1);
});
});
// Handle unhandled promise rejections
process.on('unhandledRejection', () => {
this.shutdownAndExit('unhandledRejection', 1).catch(() => {
process.exit(1);
});
});
this.signalHandlersRegistered = true;
}
}

View file

@ -1,34 +1,34 @@
/**
* Types for shutdown functionality
*/
/**
* Callback function for shutdown cleanup
*/
export type ShutdownCallback = () => Promise<void> | void;
/**
* Options for configuring shutdown behavior
*/
export interface ShutdownOptions {
/** Timeout in milliseconds before forcing shutdown (default: 30000) */
timeout?: number;
/** Whether to automatically register signal handlers (default: true) */
autoRegister?: boolean;
}
/**
* Shutdown result information
*/
export interface ShutdownResult {
/** Whether shutdown completed successfully */
success: boolean;
/** Number of callbacks executed */
callbacksExecuted: number;
/** Number of callbacks that failed */
callbacksFailed: number;
/** Time taken for shutdown in milliseconds */
duration: number;
/** Error message if shutdown failed */
error?: string;
}
/**
* Types for shutdown functionality
*/
/**
* Callback function for shutdown cleanup
*/
export type ShutdownCallback = () => Promise<void> | void;
/**
* Options for configuring shutdown behavior
*/
export interface ShutdownOptions {
/** Timeout in milliseconds before forcing shutdown (default: 30000) */
timeout?: number;
/** Whether to automatically register signal handlers (default: true) */
autoRegister?: boolean;
}
/**
* Shutdown result information
*/
export interface ShutdownResult {
/** Whether shutdown completed successfully */
success: boolean;
/** Number of callbacks executed */
callbacksExecuted: number;
/** Number of callbacks that failed */
callbacksFailed: number;
/** Time taken for shutdown in milliseconds */
duration: number;
/** Error message if shutdown failed */
error?: string;
}

View file

@ -1,13 +1,13 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"references": [
{ "path": "../types" },
{ "path": "../config" },
{ "path": "../logger" }
]
}
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"references": [
{ "path": "../types" },
{ "path": "../config" },
{ "path": "../logger" }
]
}

View file

@ -1,10 +1,10 @@
{
"extends": ["//"],
"tasks": {
"build": {
"dependsOn": ["@stock-bot/types#build", "@stock-bot/logger#build"],
"outputs": ["dist/**"],
"inputs": ["src/**", "package.json", "tsconfig.json", "!**/*.test.ts", "!**/*.spec.ts", "!**/test/**", "!**/tests/**", "!**/__tests__/**"]
}
}
}
{
"extends": ["//"],
"tasks": {
"build": {
"dependsOn": ["@stock-bot/types#build", "@stock-bot/logger#build"],
"outputs": ["dist/**"],
"inputs": ["src/**", "package.json", "tsconfig.json", "!**/*.test.ts", "!**/*.spec.ts", "!**/test/**", "!**/tests/**", "!**/__tests__/**"]
}
}
}