Skip to content

Commit 60ee101

Browse files
feat: Add dependency changelog viewer and improve ESLint configuration for mixed TypeScript/JavaScript projects (#47)
* chore: upgrade ESLint to v9 and update config Upgrades ESLint and related TypeScript dependencies, adds flat config, and backs up the old setup. * chore: actualizar dependencias del proyecto Co-authored-by: aider (anthropic/claude-haiku-4-5) <aider@aider.chat> * chore: update guidelines and clean up configs Adds project coding and style guidelines; removes legacy ESLint and run scripts. * chore: update dependency versions Bumps numerous dependency versions for improved stability. * chore: bump dependency versions Upgrades ESLint, TypeScript, Prettier, and related packages * chore: upgrade dependencies Bump versions for telegraf, winston, nock, ts-jest, and others * chore: upgrade dependency versions Bumps numerous package versions in the lock file for improved stability and compatibility. * feat: add dependency changelog tool Adds a script that fetches and formats changelog URLs for updated dependencies. Updates package scripts accordingly. * chore: update ESLint config and deps Refines linting rules and file patterns, simplifies error handling in changelog, and upgrades dependency versions. * chore: upgrade dependency versions Updates cron, dotenv, and dotenv-cli to latest compatible versions. * chore: upgrade husky & update hook script Upgrades husky to v9 and refactors pre-commit hook script for consistency. * chore: update date-fns dependency * chore: upgrade dependency versions Updates various packages and their lockfile entries. * chore: upgrade dependencies Upgrade Express to 5.1.0 and update related packages in lock file. * fix: resolve codecov major issues * docs: update ESLint migration doc Updates markdown formatting and headings in ESLint migration guide * fix: move files * fix: move files --------- Co-authored-by: aider (anthropic/claude-haiku-4-5) <aider@aider.chat>
1 parent 26df343 commit 60ee101

16 files changed

Lines changed: 3995 additions & 2778 deletions

.clinerules

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Cline Rules for Espinoso Bot
2+
3+
## Code Style
4+
- Follow ESLint and Prettier configurations strictly (already set up in project)
5+
- Single quotes, 2-space indentation, 120 char line width
6+
- Organize imports: builtin → external → internal → parent → sibling → index
7+
- Alphabetize imports within groups
8+
- Use arrow functions without parens when single parameter
9+
- Prefix unused vars with underscore (_)
10+
11+
## TypeScript Conventions
12+
- Use TypeScript types but avoid over-engineering
13+
- No explicit function return types unless adding clarity
14+
- Allow `any` when pragmatic (not dogmatic about types)
15+
- Keep interfaces and types close to where they're used
16+
17+
## Project Structure
18+
- Controllers: API/webhook handlers
19+
- Core: Business logic (GPT, Holidays, Stickers, etc.)
20+
- Helpers: Utility functions
21+
- Lib: External service clients (GitHub, HTTP, logging)
22+
- Exceptions: Custom error classes
23+
- Keep separation of concerns clear
24+
25+
## Testing Philosophy
26+
- Currently: Unit tests only (Jest)
27+
- Future goal: Add integration test layer
28+
- Test files in `__tests__/` directory
29+
- Mock external services (using nock)
30+
- Keep fixtures in `__tests__/__fixtures__/`
31+
32+
## Documentation (Work in Progress)
33+
- TODO: Improve README with setup instructions
34+
- TODO: Create bot usage documentation
35+
- In code: Add comments when logic isn't obvious, but don't over-comment
36+
37+
## Communication Style
38+
- Be technical but friendly
39+
- Add some humor when appropriate 😄
40+
- It's okay to express uncertainty - nobody knows everything
41+
- Focus on learning together and teaching clearly
42+
- Concise explanations, but thorough when needed
43+
- No corporate speak or overly formal language
44+
45+
## Bot-Specific Guidelines
46+
- This is "Espinoso" (unfriendly bot) - embrace the personality
47+
- Handle Telegram webhooks through Express
48+
- Use Winston for logging
49+
- Environment variables via dotenv
50+
- Keep webhook handling efficient (quick responses)

.eslintignore

Lines changed: 0 additions & 3 deletions
This file was deleted.

.eslintrc.json

Lines changed: 0 additions & 65 deletions
This file was deleted.

.github/workflows/ci-stage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
matrix:
1717
os: [ubuntu-latest]
18-
node: ['20.10.0']
18+
node: ['20.17.0']
1919

2020
steps:
2121
- name: Checkout 🛎

.github/workflows/deploy-stage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
matrix:
1212
os: [ubuntu-latest]
13-
node: ['20.10.0']
13+
node: ['20.17.0']
1414
steps:
1515
- name: Checkout 🛎
1616
uses: actions/checkout@v3

.husky/pre-commit

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/bin/sh
2-
. "$(dirname "$0")/_/husky.sh"
32

4-
echo 'linting staged'
3+
echo '🐶 Husky pre-commit: npx lint-staged'
54
npx lint-staged

.scripts/ncu-changelog.js

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/usr/bin/env node
2+
3+
const { execSync } = require('child_process');
4+
const fs = require('fs');
5+
const path = require('path');
6+
7+
/**
8+
* Validates that a package name is safe (contains only valid npm package characters)
9+
*/
10+
function isValidPackageName(name) {
11+
// npm package names must be lowercase, can contain hyphens and underscores
12+
// This regex matches valid npm package names
13+
return /^(@?[a-z0-9]([a-z0-9-]*[a-z0-9])?\/)?[a-z0-9]([a-z0-9._-]*[a-z0-9])?$/.test(name);
14+
}
15+
16+
/**
17+
* Fetches the repository URL for a given package
18+
*/
19+
function getRepoUrl(packageName) {
20+
try {
21+
// Validate package name to prevent command injection
22+
if (!isValidPackageName(packageName)) {
23+
return null;
24+
}
25+
26+
const result = execSync(`npm view ${packageName} repository.url`, {
27+
encoding: 'utf-8',
28+
stdio: ['pipe', 'pipe', 'pipe'],
29+
});
30+
return result.trim();
31+
} catch {
32+
return null;
33+
}
34+
}
35+
36+
/**
37+
* Converts git URLs to HTTPS GitHub URLs and attempts to link to changelog
38+
*/
39+
function formatChangelogUrl(repoUrl) {
40+
if (!repoUrl) return null;
41+
42+
// Convert git:// or git+https:// to https://
43+
let url = repoUrl
44+
.replace('git+https://', 'https://')
45+
.replace('git://', 'https://')
46+
.replace('git@github.com:', 'https://github.com/')
47+
.replace(/\.git$/, '');
48+
49+
// Try to link to releases page for GitHub repos
50+
if (url.includes('github.com')) {
51+
return `${url}/releases`;
52+
}
53+
54+
return url;
55+
}
56+
57+
/**
58+
* Safely reads package.json from the current working directory
59+
*/
60+
function readPackageJson() {
61+
const cwd = process.cwd();
62+
const packageJsonPath = path.join(cwd, 'package.json');
63+
64+
// Validate that the resolved path is within the current working directory
65+
// to prevent directory traversal attacks
66+
const resolvedPath = path.resolve(packageJsonPath);
67+
const resolvedCwd = path.resolve(cwd);
68+
69+
if (!resolvedPath.startsWith(resolvedCwd)) {
70+
throw new Error('Invalid package.json path');
71+
}
72+
73+
return JSON.parse(fs.readFileSync(resolvedPath, 'utf-8'));
74+
}
75+
76+
/**
77+
* Main function
78+
*/
79+
async function main() {
80+
try {
81+
// Read current package.json
82+
const packageJson = readPackageJson();
83+
const currentDeps = { ...packageJson.dependencies, ...packageJson.devDependencies };
84+
85+
// Run ncu and get JSON output
86+
const ncuOutput = execSync('ncu --jsonUpgraded', {
87+
encoding: 'utf-8',
88+
});
89+
90+
const upgrades = JSON.parse(ncuOutput);
91+
92+
if (Object.keys(upgrades).length === 0) {
93+
console.log('✨ All dependencies are up to date!');
94+
return;
95+
}
96+
97+
console.log('\n📦 Outdated Dependencies:\n');
98+
99+
// Process each package
100+
for (const [packageName, latestVersion] of Object.entries(upgrades)) {
101+
const currentVersion = currentDeps[packageName] || 'unknown';
102+
103+
const repoUrl = getRepoUrl(packageName);
104+
const changelogUrl = formatChangelogUrl(repoUrl);
105+
106+
// Format output
107+
const packageInfo = `${packageName.padEnd(30)} ${currentVersion.padEnd(15)}${latestVersion.padEnd(15)}`;
108+
109+
if (changelogUrl) {
110+
console.log(`${packageInfo} ${changelogUrl}`);
111+
} else {
112+
console.log(`${packageInfo} (no repo found)`);
113+
}
114+
}
115+
116+
console.log('\n');
117+
} catch (error) {
118+
if (error.message.includes('No dependencies')) {
119+
console.log('✨ All dependencies are up to date!');
120+
} else {
121+
console.error('Error:', error.message);
122+
process.exit(1);
123+
}
124+
}
125+
}
126+
127+
main();

Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Building stage
2-
FROM node:20.10-alpine as builder
2+
FROM node:20.17-alpine as builder
33
WORKDIR /app
44

55
COPY package.json yarn.lock /app/
@@ -10,7 +10,7 @@ RUN yarn install --frozen-lockfile
1010
RUN yarn build
1111

1212
# Preparing stage
13-
FROM node:20.10-alpine as prod
13+
FROM node:20.17-alpine as prod
1414
ENV NODE_ENV=production
1515
WORKDIR /app
1616

@@ -19,7 +19,7 @@ RUN yarn install --frozen-lockfile
1919
COPY --from=builder /app/dist/ /app/dist/
2020

2121
# Deployed stage
22-
FROM node:20.10-alpine
22+
FROM node:20.17-alpine
2323
RUN apk add --no-cache bash=~5
2424

2525
ENV NODE_ENV=production

__tests__/setup-jest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import * as dotenv from 'dotenv';
22

3-
dotenv.config({ path: './.env.test' });
3+
dotenv.config({ path: './.env.test', quiet: true });

0 commit comments

Comments
 (0)