Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

- Deleted stray artifacts from the working tree: `autotask-node-2.0.0.tgz`, `npm-debug-403.log`, and the empty `logs/` directory.

### Fixed

- **Cleared the 17 real ESLint errors (`preserve-caught-error`, `no-useless-assignment`) that a bumped `eslint`/`@typescript-eslint/eslint-plugin` devDependency newly surfaces on pre-existing code, blocking dependabot dev-dependency PRs (#233 and any future bump hitting the same two rules).** 8 `preserve-caught-error` sites now attach `{ cause: <caughtError> }` to the re-thrown `Error`. 8 `no-useless-assignment` sites were genuine dead stores (a `let` initializer or intermediate assignment never read before being overwritten or falling out of scope) and had the dead assignment removed. One site (`test/base.test.ts`, a `WeakRef` GC test) is an intentional false positive — nulling the variable has a real side effect (dropping the last strong reference so `global.gc()` can collect it) even though the linter can't see a subsequent read — kept via a scoped `eslint-disable-next-line` with an inline explanation rather than removed.
- Added `ES2022.Error` to `tsconfig.json`'s `lib` array (alongside the existing `ES2021`) — the two-argument `Error(message, { cause })` constructor form needs it for type-checking; `target` is unchanged (still `ES2020`), so output syntax is unaffected.

### Security

- **Closed GHSA-r292-9mhp-454m (node-tar uncontrolled recursion, high, stack-overflow DoS via crafted long-path tar).** Bundled `tar` (pulled in transitively via the `npm` CLI devDependency, itself pulled in via `@semantic-release/npm`) was at 7.5.19/7.5.20, just short of the 7.5.21 patch. A plain `npm audit fix` (no `--force`) re-resolved `npm` to 11.19.1 (bundled tar 7.5.22) within the existing declared range — lockfile-only change, no `package.json`/direct-dependency edits, no semver-major bump. `npm audit`'s own suggested remediation path (`semantic-release@24.2.9`, flagged `isSemVerMajor`) was a red herring — the currently-resolved `semantic-release` (25.0.3, newer than that suggestion) was never at risk and is unchanged by this fix.
Expand Down
2 changes: 1 addition & 1 deletion examples/shared/auth/autotask-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class AutotaskAuthManager {
logger.info('Autotask connection initialized successfully');
} catch (error) {
logger.error('Failed to initialize Autotask connection:', error);
throw new Error(`Autotask authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
throw new Error(`Autotask authentication failed: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error });
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/caching/TTLManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export class TTLManager {
hour >= this.businessHours.startHour &&
hour < this.businessHours.endHour;

let ttlMultiplier = 1;
let ttlMultiplier: number;
let confidence = 0.7;
let reason: string;

Expand Down
2 changes: 1 addition & 1 deletion src/caching/stores/FileCacheStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ export class FileCacheStore implements ICacheStore {
*/
private async performCleanup(): Promise<number> {
const now = Date.now();
let deletedCount = 0;
let deletedCount: number;
const expiredKeys: string[] = [];

// Find expired keys
Expand Down
2 changes: 1 addition & 1 deletion src/migration/cli/MigrationCLI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ async function loadConfig(): Promise<MigrationConfig> {
const configContent = await fs.readFile(configPath, 'utf8');
return JSON.parse(configContent);
} catch (error) {
throw new Error(`Failed to load configuration from ${configPath}. Run 'autotask-migrate init' first.`);
throw new Error(`Failed to load configuration from ${configPath}. Run 'autotask-migrate init' first.`, { cause: error });
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/performance/monitoring/ConnectionPoolMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,8 @@ export class ConnectionPoolMonitor extends EventEmitter {
// In a real implementation, this would query actual HTTP agents
// For now, we'll simulate metrics based on recorded events

let totalConnections = 0;
let activeConnections = 0;
let totalConnections: number;
let activeConnections: number;
let connectionsCreated = 0;
let connectionsDestroyed = 0;
let totalAcquisitionTime = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/relationships/loading/SmartLoadingEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ export class SmartLoadingEngine {
}

// Execute query based on relationship type
let relatedData: any[] = [];
let relatedData: any[];

try {
switch (relationship.relationshipType) {
Expand All @@ -562,7 +562,7 @@ export class SmartLoadingEngine {
}

} catch (error) {
throw new Error(`Failed to load ${relationshipName}: ${(error as Error).message}`);
throw new Error(`Failed to load ${relationshipName}: ${(error as Error).message}`, { cause: error });
}

return relatedData;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/client-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class ClientGenerator {
const data = fs.readFileSync(this.dataFile, 'utf8');
return JSON.parse(data) as EntitiesData;
} catch (error) {
throw new Error(`Failed to load entity data: ${error}`);
throw new Error(`Failed to load entity data: ${error}`, { cause: error });
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/tools/entity-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class EntityGenerator {
const data = fs.readFileSync(this.dataFile, 'utf8');
return JSON.parse(data) as EntitiesData;
} catch (error) {
throw new Error(`Failed to load entity data: ${error}`);
throw new Error(`Failed to load entity data: ${error}`, { cause: error });
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/validation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,8 @@ export class ValidationDecorators {
}
} catch (error) {
throw new Error(
`Validation error: ${error instanceof Error ? error.message : String(error)}`
`Validation error: ${error instanceof Error ? error.message : String(error)}`,
{ cause: error }
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/validation/security/SecurityValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ export class SecurityValidator {
return 'ENC:' + CryptoJS.AES.encrypt(value, this.encryptionKey).toString();
} catch (error) {
this.logger.error('Encryption error:', error);
throw new Error('Failed to encrypt value');
throw new Error('Failed to encrypt value', { cause: error });
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/webhooks/reliability/EventStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ export class EventStore extends EventEmitter implements IEventStore {

public async getByFilter(filter: EventStoreFilter): Promise<WebhookEvent[]> {
const startTime = Date.now();
let eventIds: Set<string> = new Set();
let eventIds: Set<string>;

try {
// Use index for efficient filtering if available
Expand Down Expand Up @@ -402,7 +402,6 @@ export class EventStore extends EventEmitter implements IEventStore {
candidateIds = firstFilter
? dateIds
: this.intersect(candidateIds, dateIds);
firstFilter = false;
}

return candidateIds;
Expand Down
5 changes: 4 additions & 1 deletion test/base.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,10 @@ describe('BaseEntity - Comprehensive Tests', () => {

await testEntity.testExecuteRequest(requestFn, '/test', 'GET');

requestFn = null; // Remove our reference
// Intentional dead-looking store: drops the last strong reference so
// `global.gc()` below can actually collect it for the WeakRef check.
// eslint-disable-next-line no-useless-assignment
requestFn = null;

// Force garbage collection if available (for testing environments)
if (global.gc) {
Expand Down
2 changes: 1 addition & 1 deletion test/integration/framework/TestEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class TestEnvironment {
// Test basic connectivity with a simple list operation
await this.client.version.list({ pageSize: 1 });
} catch (error) {
throw new Error(`Connection validation failed: ${error}`);
throw new Error(`Connection validation failed: ${error}`, { cause: error });
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/integration/setup-enhanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default async function globalSetup(): Promise<void> {
console.log('✅ API connection successful');
} catch (error) {
console.error('❌ API connection failed:', error);
throw new Error('API connection validation failed');
throw new Error('API connection validation failed', { cause: error });
}

// Store global instances
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"compilerOptions": {
"target": "ES2020",
"lib": [
"ES2021"
"ES2021",
"ES2022.Error"
],
"module": "CommonJS",
"moduleResolution": "Node",
Expand Down
Loading