Skip to content

Commit 89f1250

Browse files
fengmk2Copilot
andauthored
refactor: use all in one egg v4 (#855)
required eggjs/egg#5654 --------- Signed-off-by: MK (fengmk2) <fengmk2@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent e1848c7 commit 89f1250

File tree

165 files changed

+840
-587
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

165 files changed

+840
-587
lines changed

.docker/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
node -v && npm -v \
44
&& npm install -g npminstall --registry=https://registry.npmmirror.com \
5-
&& NODE_DEBUG=egg-bin*,egg/bin* npminstall -c --foreground-scripts \
5+
&& npminstall -c \
66
&& npm run tsc \
77
&& npmupdate -c --production

.github/copilot-instructions.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,7 @@ These adapters allow cnpmcore to integrate with different cloud providers and en
424424
**Example Controller Implementation:**
425425
```typescript
426426
import { AbstractController } from './AbstractController';
427-
import { Inject } from '@eggjs/tegg';
428-
import { HTTPController, HTTPMethod, HTTPQuery } from '@eggjs/tegg-controller-plugin';
427+
import { HTTPController, HTTPMethod, HTTPQuery, Inject } from 'egg';
429428

430429
@HTTPController()
431430
export class YourController extends AbstractController {

.github/workflows/nodejs.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ jobs:
1414
typecheck:
1515
runs-on: ubuntu-latest
1616

17+
concurrency:
18+
group: typecheck-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}
19+
cancel-in-progress: true
20+
1721
steps:
1822
- name: Checkout Git Source
1923
uses: actions/checkout@v5
@@ -46,6 +50,9 @@ jobs:
4650
shardTotal: [3]
4751

4852
name: test on postgresql (node@${{ matrix.node-version }}, shard@${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
53+
concurrency:
54+
group: test-postgresql-fs-nfs-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-${{ matrix.node-version }}-${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
55+
cancel-in-progress: true
4956

5057
runs-on: ${{ matrix.os }}
5158

@@ -139,6 +146,9 @@ jobs:
139146
shardTotal: [3]
140147

141148
name: test on mysql (node@${{ matrix.node-version }}, shard@${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
149+
concurrency:
150+
group: test-mysql57-fs-nfs-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-${{ matrix.node-version }}-${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
151+
cancel-in-progress: true
142152

143153
runs-on: ${{ matrix.os }}
144154

@@ -190,6 +200,10 @@ jobs:
190200
node-version: [20, 22]
191201
os: [ubuntu-latest]
192202

203+
concurrency:
204+
group: test-mysql57-s3-nfs-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}-${{ matrix.node-version }}
205+
cancel-in-progress: true
206+
193207
runs-on: ${{ matrix.os }}
194208

195209
services:

.github/workflows/release-image.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ env:
1717
jobs:
1818
build-and-push-image:
1919
runs-on: ubuntu-latest
20+
concurrency:
21+
group: build-and-push-image-${{ github.workflow }}-#${{ github.event.pull_request.number || github.head_ref || github.ref }}
22+
cancel-in-progress: true
2023
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
2124
permissions:
2225
contents: read

CLAUDE.md

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
cnpmcore is a TypeScript-based private NPM registry implementation for enterprise use. It's built on the Egg.js framework using Domain-Driven Design (DDD) architecture principles and supports both MySQL and PostgreSQL databases.
8+
9+
## Essential Commands
10+
11+
### Development
12+
```bash
13+
# Start development server (MySQL)
14+
npm run dev
15+
16+
# Start development server (PostgreSQL)
17+
npm run dev:postgresql
18+
19+
# Lint code
20+
npm run lint
21+
22+
# Fix linting issues
23+
npm run lint:fix
24+
25+
# TypeScript type checking
26+
npm run typecheck
27+
```
28+
29+
### Testing
30+
```bash
31+
# Run all tests with MySQL (takes 4+ minutes)
32+
npm run test
33+
34+
# Run all tests with PostgreSQL (takes 4+ minutes)
35+
npm run test:postgresql
36+
37+
# Run single test file (faster iteration, ~12 seconds)
38+
npm run test:local test/path/to/file.test.ts
39+
40+
# Generate coverage report
41+
npm run cov
42+
```
43+
44+
### Database Setup
45+
```bash
46+
# MySQL setup
47+
docker compose -f docker-compose.yml up -d
48+
CNPMCORE_DATABASE_NAME=cnpmcore bash ./prepare-database-mysql.sh
49+
50+
# PostgreSQL setup
51+
docker compose -f docker-compose-postgres.yml up -d
52+
CNPMCORE_DATABASE_NAME=cnpmcore bash ./prepare-database-postgresql.sh
53+
```
54+
55+
### Build
56+
```bash
57+
# Clean build artifacts
58+
npm run clean
59+
60+
# Development build
61+
npm run tsc
62+
63+
# Production build
64+
npm run tsc:prod
65+
```
66+
67+
## Architecture - Domain-Driven Design (DDD)
68+
69+
The codebase follows strict DDD layering with clear separation of concerns:
70+
71+
```
72+
Controller (app/port/controller/) ← HTTP interface, validation, auth
73+
↓ depends on
74+
Service (app/core/service/) ← Business logic orchestration
75+
↓ depends on
76+
Repository (app/repository/) ← Data access layer
77+
↓ depends on
78+
Model (app/repository/model/) ← ORM/Database mapping
79+
80+
Entity (app/core/entity/) ← Pure domain models (no dependencies)
81+
Common (app/common/) ← Utilities and adapters (all layers)
82+
```
83+
84+
### Layer Responsibilities
85+
86+
**Controller Layer** (`app/port/controller/`):
87+
- Handle HTTP requests/responses
88+
- Validate inputs using `@eggjs/typebox-validate`
89+
- Authenticate users and verify authorization
90+
- Delegate business logic to Services
91+
- All controllers extend `AbstractController`
92+
93+
**Service Layer** (`app/core/service/`):
94+
- Implement core business logic
95+
- Orchestrate multiple repositories
96+
- Publish domain events
97+
- Manage transactions
98+
99+
**Repository Layer** (`app/repository/`):
100+
- CRUD operations on Models
101+
- Data access and persistence
102+
- Query building and optimization
103+
- Methods named: `findX`, `saveX`, `removeX`, `listXs`
104+
105+
**Entity Layer** (`app/core/entity/`):
106+
- Pure domain models with business behavior
107+
- No infrastructure dependencies
108+
- Immutable data structures preferred
109+
110+
**Model Layer** (`app/repository/model/`):
111+
- ORM definitions using Leoric
112+
- Database schema mapping
113+
- No business logic
114+
115+
### Infrastructure Adapters (`app/infra/`)
116+
Enterprise customization layer for PaaS integration:
117+
- **NFSClientAdapter**: File storage (local/S3/OSS)
118+
- **QueueAdapter**: Message queue integration
119+
- **AuthAdapter**: Authentication system
120+
- **BinaryAdapter**: Binary package storage
121+
122+
## Key Development Patterns
123+
124+
### Request Validation Trilogy
125+
Always validate requests in this exact order:
126+
1. **Parameter Validation** - Use `@eggjs/typebox-validate` for type-safe validation
127+
2. **Authentication** - Get authorized user with token role verification
128+
3. **Authorization** - Check resource-level permissions to prevent privilege escalation
129+
130+
```typescript
131+
// Example controller method
132+
async someMethod(@HTTPQuery() params: QueryType) {
133+
// 1. Params already validated by @HTTPQuery with typebox
134+
// 2. Authenticate
135+
const user = await this.userRoleManager.requiredAuthorizedUser(this.ctx, 'publish');
136+
// 3. Authorize (if needed)
137+
const { pkg } = await this.ensurePublishAccess(this.ctx, fullname);
138+
// 4. Execute business logic
139+
return await this.service.doSomething(params);
140+
}
141+
```
142+
143+
### Repository Method Naming
144+
- `findSomething` - Query single entity
145+
- `saveSomething` - Create or update entity
146+
- `removeSomething` - Delete entity
147+
- `listSomethings` - Query multiple entities (plural)
148+
149+
### Modifying Database Models
150+
When changing a Model, update all 3 locations:
151+
1. SQL migrations: `sql/mysql/*.sql` AND `sql/postgresql/*.sql`
152+
2. ORM Model: `app/repository/model/*.ts`
153+
3. Domain Entity: `app/core/entity/*.ts`
154+
155+
## Code Style
156+
157+
### Linting
158+
- **Linter**: Oxlint (Rust-based, very fast)
159+
- **Formatter**: Prettier
160+
- **Pre-commit**: Husky + lint-staged (auto-format on commit)
161+
162+
Style rules:
163+
- Single quotes (`'`)
164+
- 2-space indentation
165+
- 120 character line width
166+
- ES5 trailing commas
167+
- Max 6 function parameters
168+
- No console statements (use logger)
169+
170+
### TypeScript
171+
- Strict TypeScript enabled
172+
- Avoid `any` types - use proper typing or `unknown`
173+
- ES modules (`import/export`) throughout
174+
- Comprehensive type definitions in all files
175+
176+
### Testing
177+
- Test files use `.test.ts` suffix
178+
- Tests mirror source structure in `test/` directory
179+
- Use `@eggjs/mock` for mocking
180+
- Use `assert` from `node:assert/strict`
181+
- Test both success and error cases
182+
183+
Pattern:
184+
```typescript
185+
describe('test/path/to/SourceFile.test.ts', () => {
186+
describe('[HTTP_METHOD /api/path] functionName()', () => {
187+
it('should handle expected behavior', async () => {
188+
// Test implementation
189+
});
190+
});
191+
});
192+
```
193+
194+
## Project Structure
195+
196+
```
197+
app/
198+
├── common/ # Global utilities and adapters
199+
│ ├── adapter/ # External service adapters
200+
│ └── enum/ # Shared enumerations
201+
├── core/ # Business logic layer
202+
│ ├── entity/ # Domain models
203+
│ ├── event/ # Event handlers
204+
│ ├── service/ # Business services
205+
│ └── util/ # Internal utilities
206+
├── port/ # Interface layer
207+
│ ├── controller/ # HTTP controllers
208+
│ ├── middleware/ # Middleware
209+
│ └── schedule/ # Background jobs
210+
├── repository/ # Data access layer
211+
│ └── model/ # ORM models
212+
└── infra/ # Infrastructure adapters
213+
214+
config/ # Configuration files
215+
sql/ # Database migrations
216+
├── mysql/ # MySQL migrations
217+
└── postgresql/ # PostgreSQL migrations
218+
test/ # Test files (mirrors app/ structure)
219+
```
220+
221+
## Important Configuration
222+
223+
- `config/config.default.ts` - Main application configuration
224+
- `config/database.ts` - Database connection settings
225+
- `config/binaries.ts` - Binary package mirror configurations
226+
- `.env` - Environment-specific variables (copy from `.env.example`)
227+
- `tsconfig.json` - TypeScript settings (target: ES2021 for Leoric compatibility)
228+
229+
## Development Workflow
230+
231+
1. **Setup**: Copy `.env.example` to `.env`, start Docker services, initialize database
232+
2. **Feature Development**: Follow bottom-up approach (Model → Entity → Repository → Service → Controller)
233+
3. **Testing**: Write tests at appropriate layer, run individual tests for fast iteration
234+
4. **Validation**: Run linter, typecheck, relevant tests before committing
235+
5. **Commit**: Use semantic commit messages (feat/fix/docs/test/chore)
236+
237+
## Integration as NPM Package
238+
239+
cnpmcore can be integrated into Egg.js/Tegg applications as an NPM package, allowing enterprises to:
240+
- Customize infrastructure adapters (storage, auth, queue)
241+
- Override default behavior while receiving updates
242+
- Integrate with existing enterprise systems
243+
244+
See INTEGRATE.md for detailed integration guide.
245+
246+
## Performance Notes
247+
248+
Typical command execution times:
249+
- Development server startup: ~20 seconds
250+
- TypeScript build: ~6 seconds
251+
- Full test suite: 4-15 minutes
252+
- Single test file: ~12 seconds
253+
- Linting: <1 second
254+
- Database initialization: <2 seconds
255+
256+
## Prerequisites
257+
258+
- Node.js: 20.18.0+ or 22.18.0+
259+
- Database: MySQL 5.7+ or PostgreSQL 17+
260+
- Cache: Redis 6+
261+
- Optional: Elasticsearch 8.x
262+
263+
## Key Services & Controllers
264+
265+
Core components to understand:
266+
- **PackageController**: Package CRUD operations
267+
- **PackageManagerService**: Core package management logic
268+
- **BinarySyncerService**: Binary package synchronization
269+
- **ChangesStreamService**: NPM registry change stream processing
270+
- **UserController**: User authentication and profiles

0 commit comments

Comments
 (0)