ccgx-workflow 1.0.0 → 1.0.1
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.
- package/README.md +37 -5
- package/README.zh-CN.md +35 -5
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +2 -2
- package/dist/shared/{ccgx-workflow.WgUzkiC3.mjs → ccgx-workflow.SJPbUy5_.mjs} +17 -110
- package/package.json +2 -1
- package/templates/commands/agents/phase-runner.md +321 -321
- package/templates/commands/autonomous.md +792 -792
- package/templates/commands/cancel.md +132 -132
- package/templates/commands/debug.md +226 -226
- package/templates/commands/status.md +206 -206
- package/templates/commands/team.md +484 -0
- package/templates/hooks/ccg-session-state.cjs +510 -510
- package/templates/scripts/ccg-phase-runner-launcher.mjs +467 -467
- package/templates/scripts/invoke-model.mjs +64 -0
- package/templates/skills/domains/ai/SKILL.md +35 -35
- package/templates/skills/domains/ai/agent-dev.md +242 -242
- package/templates/skills/domains/ai/llm-security.md +288 -288
- package/templates/skills/domains/ai/rag-system.md +542 -542
- package/templates/skills/domains/architecture/SKILL.md +43 -43
- package/templates/skills/domains/architecture/api-design.md +225 -225
- package/templates/skills/domains/architecture/cloud-native.md +285 -285
- package/templates/skills/domains/architecture/security-arch.md +297 -297
- package/templates/skills/domains/data-engineering/SKILL.md +208 -208
- package/templates/skills/domains/development/SKILL.md +47 -47
- package/templates/skills/domains/development/cpp.md +246 -246
- package/templates/skills/domains/development/go.md +323 -323
- package/templates/skills/domains/development/java.md +277 -277
- package/templates/skills/domains/development/python.md +288 -288
- package/templates/skills/domains/development/rust.md +313 -313
- package/templates/skills/domains/development/shell.md +313 -313
- package/templates/skills/domains/development/typescript.md +277 -277
- package/templates/skills/domains/devops/SKILL.md +40 -40
- package/templates/skills/domains/devops/database.md +217 -217
- package/templates/skills/domains/devops/devsecops.md +198 -198
- package/templates/skills/domains/devops/git-workflow.md +181 -181
- package/templates/skills/domains/devops/testing.md +283 -283
- package/templates/skills/domains/frontend-design/SKILL.md +244 -244
- package/templates/skills/domains/frontend-design/claymorphism/SKILL.md +121 -121
- package/templates/skills/domains/frontend-design/component-patterns.md +202 -202
- package/templates/skills/domains/frontend-design/glassmorphism/SKILL.md +142 -142
- package/templates/skills/domains/frontend-design/liquid-glass/SKILL.md +139 -139
- package/templates/skills/domains/frontend-design/neubrutalism/SKILL.md +145 -145
- package/templates/skills/domains/frontend-design/state-management.md +680 -680
- package/templates/skills/domains/frontend-design/ui-aesthetics.md +110 -110
- package/templates/skills/domains/frontend-design/ux-principles.md +156 -156
- package/templates/skills/domains/infrastructure/SKILL.md +201 -201
- package/templates/skills/domains/mobile/SKILL.md +225 -225
- package/templates/skills/domains/orchestration/SKILL.md +30 -30
- package/templates/skills/domains/orchestration/multi-agent.md +228 -228
- package/templates/skills/domains/security/SKILL.md +73 -73
- package/templates/skills/domains/security/blue-team.md +436 -436
- package/templates/skills/domains/security/code-audit.md +265 -265
- package/templates/skills/domains/security/pentest.md +226 -226
- package/templates/skills/domains/security/red-team.md +374 -374
- package/templates/skills/domains/security/threat-intel.md +372 -372
- package/templates/skills/domains/security/vuln-research.md +369 -369
- package/templates/skills/tools/lib/shared.js +98 -98
- package/templates/skills/tools/override-refusal/SKILL.md +53 -53
- package/templates/skills/tools/override-refusal/scripts/refusal_rewriter.js +226 -226
|
@@ -1,277 +1,277 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: typescript
|
|
3
|
-
description: TypeScript/JavaScript 开发。前后端、Node.js、React、Vue。当用户提到 TypeScript、JavaScript、Node、React、Vue、Next.js 时使用。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# 📜 符箓秘典 · TypeScript/JavaScript
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## TypeScript 基础
|
|
10
|
-
|
|
11
|
-
### 类型系统
|
|
12
|
-
```typescript
|
|
13
|
-
// 基础类型
|
|
14
|
-
let name: string = "Alice";
|
|
15
|
-
let age: number = 25;
|
|
16
|
-
let active: boolean = true;
|
|
17
|
-
let items: string[] = ["a", "b"];
|
|
18
|
-
let tuple: [string, number] = ["hello", 10];
|
|
19
|
-
|
|
20
|
-
// 接口
|
|
21
|
-
interface User {
|
|
22
|
-
id: number;
|
|
23
|
-
name: string;
|
|
24
|
-
email?: string; // 可选
|
|
25
|
-
readonly createdAt: Date; // 只读
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// 类型别名
|
|
29
|
-
type ID = string | number;
|
|
30
|
-
type Status = "pending" | "active" | "inactive";
|
|
31
|
-
|
|
32
|
-
// 泛型
|
|
33
|
-
function identity<T>(arg: T): T {
|
|
34
|
-
return arg;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
interface Response<T> {
|
|
38
|
-
data: T;
|
|
39
|
-
status: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// 工具类型
|
|
43
|
-
type Partial<T> = { [P in keyof T]?: T[P] };
|
|
44
|
-
type Required<T> = { [P in keyof T]-?: T[P] };
|
|
45
|
-
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
|
|
46
|
-
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Node.js 后端
|
|
50
|
-
|
|
51
|
-
### Express
|
|
52
|
-
```typescript
|
|
53
|
-
import express, { Request, Response, NextFunction } from 'express';
|
|
54
|
-
|
|
55
|
-
const app = express();
|
|
56
|
-
app.use(express.json());
|
|
57
|
-
|
|
58
|
-
// 中间件
|
|
59
|
-
const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
|
60
|
-
const token = req.headers.authorization;
|
|
61
|
-
if (!token) {
|
|
62
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
63
|
-
}
|
|
64
|
-
next();
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// 路由
|
|
68
|
-
app.get('/api/users/:id', async (req: Request, res: Response) => {
|
|
69
|
-
const { id } = req.params;
|
|
70
|
-
const user = await getUserById(id);
|
|
71
|
-
res.json(user);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
app.post('/api/users', async (req: Request, res: Response) => {
|
|
75
|
-
const user = await createUser(req.body);
|
|
76
|
-
res.status(201).json(user);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// 错误处理
|
|
80
|
-
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
|
|
81
|
-
console.error(err.stack);
|
|
82
|
-
res.status(500).json({ error: 'Internal Server Error' });
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
app.listen(3000);
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Fastify
|
|
89
|
-
```typescript
|
|
90
|
-
import Fastify from 'fastify';
|
|
91
|
-
|
|
92
|
-
const fastify = Fastify({ logger: true });
|
|
93
|
-
|
|
94
|
-
fastify.get('/users/:id', async (request, reply) => {
|
|
95
|
-
const { id } = request.params as { id: string };
|
|
96
|
-
return { id };
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
fastify.listen({ port: 3000 });
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## React
|
|
103
|
-
|
|
104
|
-
### 函数组件
|
|
105
|
-
```tsx
|
|
106
|
-
import React, { useState, useEffect, useCallback } from 'react';
|
|
107
|
-
|
|
108
|
-
interface User {
|
|
109
|
-
id: number;
|
|
110
|
-
name: string;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
interface Props {
|
|
114
|
-
userId: number;
|
|
115
|
-
onSelect?: (user: User) => void;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const UserCard: React.FC<Props> = ({ userId, onSelect }) => {
|
|
119
|
-
const [user, setUser] = useState<User | null>(null);
|
|
120
|
-
const [loading, setLoading] = useState(true);
|
|
121
|
-
|
|
122
|
-
useEffect(() => {
|
|
123
|
-
fetchUser(userId).then(data => {
|
|
124
|
-
setUser(data);
|
|
125
|
-
setLoading(false);
|
|
126
|
-
});
|
|
127
|
-
}, [userId]);
|
|
128
|
-
|
|
129
|
-
const handleClick = useCallback(() => {
|
|
130
|
-
if (user && onSelect) {
|
|
131
|
-
onSelect(user);
|
|
132
|
-
}
|
|
133
|
-
}, [user, onSelect]);
|
|
134
|
-
|
|
135
|
-
if (loading) return <div>Loading...</div>;
|
|
136
|
-
if (!user) return <div>User not found</div>;
|
|
137
|
-
|
|
138
|
-
return (
|
|
139
|
-
<div onClick={handleClick}>
|
|
140
|
-
<h2>{user.name}</h2>
|
|
141
|
-
</div>
|
|
142
|
-
);
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
export default UserCard;
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Hooks
|
|
149
|
-
```tsx
|
|
150
|
-
// 自定义 Hook
|
|
151
|
-
function useFetch<T>(url: string) {
|
|
152
|
-
const [data, setData] = useState<T | null>(null);
|
|
153
|
-
const [loading, setLoading] = useState(true);
|
|
154
|
-
const [error, setError] = useState<Error | null>(null);
|
|
155
|
-
|
|
156
|
-
useEffect(() => {
|
|
157
|
-
fetch(url)
|
|
158
|
-
.then(res => res.json())
|
|
159
|
-
.then(setData)
|
|
160
|
-
.catch(setError)
|
|
161
|
-
.finally(() => setLoading(false));
|
|
162
|
-
}, [url]);
|
|
163
|
-
|
|
164
|
-
return { data, loading, error };
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// 使用
|
|
168
|
-
const { data, loading } = useFetch<User[]>('/api/users');
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
## Vue 3
|
|
172
|
-
|
|
173
|
-
### Composition API
|
|
174
|
-
```vue
|
|
175
|
-
<script setup lang="ts">
|
|
176
|
-
import { ref, computed, onMounted } from 'vue';
|
|
177
|
-
|
|
178
|
-
interface User {
|
|
179
|
-
id: number;
|
|
180
|
-
name: string;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const props = defineProps<{
|
|
184
|
-
userId: number;
|
|
185
|
-
}>();
|
|
186
|
-
|
|
187
|
-
const emit = defineEmits<{
|
|
188
|
-
(e: 'select', user: User): void;
|
|
189
|
-
}>();
|
|
190
|
-
|
|
191
|
-
const user = ref<User | null>(null);
|
|
192
|
-
const loading = ref(true);
|
|
193
|
-
|
|
194
|
-
const displayName = computed(() => user.value?.name ?? 'Unknown');
|
|
195
|
-
|
|
196
|
-
onMounted(async () => {
|
|
197
|
-
user.value = await fetchUser(props.userId);
|
|
198
|
-
loading.value = false;
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
const handleClick = () => {
|
|
202
|
-
if (user.value) {
|
|
203
|
-
emit('select', user.value);
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
</script>
|
|
207
|
-
|
|
208
|
-
<template>
|
|
209
|
-
<div v-if="loading">Loading...</div>
|
|
210
|
-
<div v-else-if="user" @click="handleClick">
|
|
211
|
-
<h2>{{ displayName }}</h2>
|
|
212
|
-
</div>
|
|
213
|
-
</template>
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## 测试
|
|
217
|
-
|
|
218
|
-
### Jest/Vitest
|
|
219
|
-
```typescript
|
|
220
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
221
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
222
|
-
import UserCard from './UserCard';
|
|
223
|
-
|
|
224
|
-
describe('UserCard', () => {
|
|
225
|
-
it('should render user name', async () => {
|
|
226
|
-
render(<UserCard userId={1} />);
|
|
227
|
-
expect(await screen.findByText('Alice')).toBeInTheDocument();
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it('should call onSelect when clicked', async () => {
|
|
231
|
-
const onSelect = vi.fn();
|
|
232
|
-
render(<UserCard userId={1} onSelect={onSelect} />);
|
|
233
|
-
|
|
234
|
-
const card = await screen.findByRole('button');
|
|
235
|
-
fireEvent.click(card);
|
|
236
|
-
|
|
237
|
-
expect(onSelect).toHaveBeenCalledWith({ id: 1, name: 'Alice' });
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
// Mock
|
|
242
|
-
vi.mock('./api', () => ({
|
|
243
|
-
fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Alice' })
|
|
244
|
-
}));
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## 项目结构
|
|
248
|
-
|
|
249
|
-
```
|
|
250
|
-
myproject/
|
|
251
|
-
├── package.json
|
|
252
|
-
├── tsconfig.json
|
|
253
|
-
├── src/
|
|
254
|
-
│ ├── index.ts
|
|
255
|
-
│ ├── components/
|
|
256
|
-
│ ├── hooks/
|
|
257
|
-
│ ├── services/
|
|
258
|
-
│ ├── types/
|
|
259
|
-
│ └── utils/
|
|
260
|
-
├── tests/
|
|
261
|
-
└── public/
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
## 常用库
|
|
265
|
-
|
|
266
|
-
| 库 | 用途 |
|
|
267
|
-
|---|------|
|
|
268
|
-
| Express/Fastify | Node.js 框架 |
|
|
269
|
-
| React/Vue | 前端框架 |
|
|
270
|
-
| Next.js/Nuxt | 全栈框架 |
|
|
271
|
-
| Prisma | ORM |
|
|
272
|
-
| Zod | 数据验证 |
|
|
273
|
-
| Vitest/Jest | 测试 |
|
|
274
|
-
| ESLint/Prettier | 代码规范 |
|
|
275
|
-
|
|
276
|
-
---
|
|
277
|
-
|
|
1
|
+
---
|
|
2
|
+
name: typescript
|
|
3
|
+
description: TypeScript/JavaScript 开发。前后端、Node.js、React、Vue。当用户提到 TypeScript、JavaScript、Node、React、Vue、Next.js 时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 📜 符箓秘典 · TypeScript/JavaScript
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## TypeScript 基础
|
|
10
|
+
|
|
11
|
+
### 类型系统
|
|
12
|
+
```typescript
|
|
13
|
+
// 基础类型
|
|
14
|
+
let name: string = "Alice";
|
|
15
|
+
let age: number = 25;
|
|
16
|
+
let active: boolean = true;
|
|
17
|
+
let items: string[] = ["a", "b"];
|
|
18
|
+
let tuple: [string, number] = ["hello", 10];
|
|
19
|
+
|
|
20
|
+
// 接口
|
|
21
|
+
interface User {
|
|
22
|
+
id: number;
|
|
23
|
+
name: string;
|
|
24
|
+
email?: string; // 可选
|
|
25
|
+
readonly createdAt: Date; // 只读
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 类型别名
|
|
29
|
+
type ID = string | number;
|
|
30
|
+
type Status = "pending" | "active" | "inactive";
|
|
31
|
+
|
|
32
|
+
// 泛型
|
|
33
|
+
function identity<T>(arg: T): T {
|
|
34
|
+
return arg;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface Response<T> {
|
|
38
|
+
data: T;
|
|
39
|
+
status: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 工具类型
|
|
43
|
+
type Partial<T> = { [P in keyof T]?: T[P] };
|
|
44
|
+
type Required<T> = { [P in keyof T]-?: T[P] };
|
|
45
|
+
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
|
|
46
|
+
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Node.js 后端
|
|
50
|
+
|
|
51
|
+
### Express
|
|
52
|
+
```typescript
|
|
53
|
+
import express, { Request, Response, NextFunction } from 'express';
|
|
54
|
+
|
|
55
|
+
const app = express();
|
|
56
|
+
app.use(express.json());
|
|
57
|
+
|
|
58
|
+
// 中间件
|
|
59
|
+
const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
|
60
|
+
const token = req.headers.authorization;
|
|
61
|
+
if (!token) {
|
|
62
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
63
|
+
}
|
|
64
|
+
next();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// 路由
|
|
68
|
+
app.get('/api/users/:id', async (req: Request, res: Response) => {
|
|
69
|
+
const { id } = req.params;
|
|
70
|
+
const user = await getUserById(id);
|
|
71
|
+
res.json(user);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
app.post('/api/users', async (req: Request, res: Response) => {
|
|
75
|
+
const user = await createUser(req.body);
|
|
76
|
+
res.status(201).json(user);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// 错误处理
|
|
80
|
+
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
|
|
81
|
+
console.error(err.stack);
|
|
82
|
+
res.status(500).json({ error: 'Internal Server Error' });
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
app.listen(3000);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Fastify
|
|
89
|
+
```typescript
|
|
90
|
+
import Fastify from 'fastify';
|
|
91
|
+
|
|
92
|
+
const fastify = Fastify({ logger: true });
|
|
93
|
+
|
|
94
|
+
fastify.get('/users/:id', async (request, reply) => {
|
|
95
|
+
const { id } = request.params as { id: string };
|
|
96
|
+
return { id };
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
fastify.listen({ port: 3000 });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## React
|
|
103
|
+
|
|
104
|
+
### 函数组件
|
|
105
|
+
```tsx
|
|
106
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
107
|
+
|
|
108
|
+
interface User {
|
|
109
|
+
id: number;
|
|
110
|
+
name: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
interface Props {
|
|
114
|
+
userId: number;
|
|
115
|
+
onSelect?: (user: User) => void;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const UserCard: React.FC<Props> = ({ userId, onSelect }) => {
|
|
119
|
+
const [user, setUser] = useState<User | null>(null);
|
|
120
|
+
const [loading, setLoading] = useState(true);
|
|
121
|
+
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
fetchUser(userId).then(data => {
|
|
124
|
+
setUser(data);
|
|
125
|
+
setLoading(false);
|
|
126
|
+
});
|
|
127
|
+
}, [userId]);
|
|
128
|
+
|
|
129
|
+
const handleClick = useCallback(() => {
|
|
130
|
+
if (user && onSelect) {
|
|
131
|
+
onSelect(user);
|
|
132
|
+
}
|
|
133
|
+
}, [user, onSelect]);
|
|
134
|
+
|
|
135
|
+
if (loading) return <div>Loading...</div>;
|
|
136
|
+
if (!user) return <div>User not found</div>;
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<div onClick={handleClick}>
|
|
140
|
+
<h2>{user.name}</h2>
|
|
141
|
+
</div>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default UserCard;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Hooks
|
|
149
|
+
```tsx
|
|
150
|
+
// 自定义 Hook
|
|
151
|
+
function useFetch<T>(url: string) {
|
|
152
|
+
const [data, setData] = useState<T | null>(null);
|
|
153
|
+
const [loading, setLoading] = useState(true);
|
|
154
|
+
const [error, setError] = useState<Error | null>(null);
|
|
155
|
+
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
fetch(url)
|
|
158
|
+
.then(res => res.json())
|
|
159
|
+
.then(setData)
|
|
160
|
+
.catch(setError)
|
|
161
|
+
.finally(() => setLoading(false));
|
|
162
|
+
}, [url]);
|
|
163
|
+
|
|
164
|
+
return { data, loading, error };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// 使用
|
|
168
|
+
const { data, loading } = useFetch<User[]>('/api/users');
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Vue 3
|
|
172
|
+
|
|
173
|
+
### Composition API
|
|
174
|
+
```vue
|
|
175
|
+
<script setup lang="ts">
|
|
176
|
+
import { ref, computed, onMounted } from 'vue';
|
|
177
|
+
|
|
178
|
+
interface User {
|
|
179
|
+
id: number;
|
|
180
|
+
name: string;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const props = defineProps<{
|
|
184
|
+
userId: number;
|
|
185
|
+
}>();
|
|
186
|
+
|
|
187
|
+
const emit = defineEmits<{
|
|
188
|
+
(e: 'select', user: User): void;
|
|
189
|
+
}>();
|
|
190
|
+
|
|
191
|
+
const user = ref<User | null>(null);
|
|
192
|
+
const loading = ref(true);
|
|
193
|
+
|
|
194
|
+
const displayName = computed(() => user.value?.name ?? 'Unknown');
|
|
195
|
+
|
|
196
|
+
onMounted(async () => {
|
|
197
|
+
user.value = await fetchUser(props.userId);
|
|
198
|
+
loading.value = false;
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const handleClick = () => {
|
|
202
|
+
if (user.value) {
|
|
203
|
+
emit('select', user.value);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
<template>
|
|
209
|
+
<div v-if="loading">Loading...</div>
|
|
210
|
+
<div v-else-if="user" @click="handleClick">
|
|
211
|
+
<h2>{{ displayName }}</h2>
|
|
212
|
+
</div>
|
|
213
|
+
</template>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## 测试
|
|
217
|
+
|
|
218
|
+
### Jest/Vitest
|
|
219
|
+
```typescript
|
|
220
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
221
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
222
|
+
import UserCard from './UserCard';
|
|
223
|
+
|
|
224
|
+
describe('UserCard', () => {
|
|
225
|
+
it('should render user name', async () => {
|
|
226
|
+
render(<UserCard userId={1} />);
|
|
227
|
+
expect(await screen.findByText('Alice')).toBeInTheDocument();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should call onSelect when clicked', async () => {
|
|
231
|
+
const onSelect = vi.fn();
|
|
232
|
+
render(<UserCard userId={1} onSelect={onSelect} />);
|
|
233
|
+
|
|
234
|
+
const card = await screen.findByRole('button');
|
|
235
|
+
fireEvent.click(card);
|
|
236
|
+
|
|
237
|
+
expect(onSelect).toHaveBeenCalledWith({ id: 1, name: 'Alice' });
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Mock
|
|
242
|
+
vi.mock('./api', () => ({
|
|
243
|
+
fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Alice' })
|
|
244
|
+
}));
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## 项目结构
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
myproject/
|
|
251
|
+
├── package.json
|
|
252
|
+
├── tsconfig.json
|
|
253
|
+
├── src/
|
|
254
|
+
│ ├── index.ts
|
|
255
|
+
│ ├── components/
|
|
256
|
+
│ ├── hooks/
|
|
257
|
+
│ ├── services/
|
|
258
|
+
│ ├── types/
|
|
259
|
+
│ └── utils/
|
|
260
|
+
├── tests/
|
|
261
|
+
└── public/
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## 常用库
|
|
265
|
+
|
|
266
|
+
| 库 | 用途 |
|
|
267
|
+
|---|------|
|
|
268
|
+
| Express/Fastify | Node.js 框架 |
|
|
269
|
+
| React/Vue | 前端框架 |
|
|
270
|
+
| Next.js/Nuxt | 全栈框架 |
|
|
271
|
+
| Prisma | ORM |
|
|
272
|
+
| Zod | 数据验证 |
|
|
273
|
+
| Vitest/Jest | 测试 |
|
|
274
|
+
| ESLint/Prettier | 代码规范 |
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: devops
|
|
3
|
-
description: DevOps 能力索引(Git/CI/CD、测试、DevSecOps、数据库、可观测性)。
|
|
4
|
-
license: MIT
|
|
5
|
-
user-invocable: false
|
|
6
|
-
disable-model-invocation: false
|
|
7
|
-
context: fork
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# 🔧 炼器秘典 · DevOps 能力中枢
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## 能力矩阵
|
|
14
|
-
|
|
15
|
-
| Skill | 定位 | 核心能力 |
|
|
16
|
-
|-------|------|----------|
|
|
17
|
-
| [git-workflow](git-workflow.md) | 版本控制 | Git、分支策略、PR |
|
|
18
|
-
| [testing](testing.md) | 软件测试 | 单元测试、集成测试、TDD、测试策略、E2E测试 |
|
|
19
|
-
| [devsecops](devsecops.md) | 安全开发 | CI/CD安全、供应链安全 |
|
|
20
|
-
| [database](database.md) | 数据库 | SQL、NoSQL、优化 |
|
|
21
|
-
| [performance](performance.md) | 性能优化 | Profiling、火焰图、基准测试、负载测试、性能测试 |
|
|
22
|
-
| [observability](observability.md) | 可观测性 | 日志、指标、追踪、SLO |
|
|
23
|
-
| [cost-optimization](cost-optimization.md) | 成本优化 | FinOps、右尺寸、Spot、伸缩 |
|
|
24
|
-
|
|
25
|
-
## DevOps 原则
|
|
26
|
-
|
|
27
|
-
```yaml
|
|
28
|
-
文化:
|
|
29
|
-
- 协作与共享
|
|
30
|
-
- 持续改进
|
|
31
|
-
- 自动化一切
|
|
32
|
-
- 快速反馈
|
|
33
|
-
|
|
34
|
-
实践:
|
|
35
|
-
- 持续集成 (CI)
|
|
36
|
-
- 持续交付 (CD)
|
|
37
|
-
- 基础设施即代码
|
|
38
|
-
- 监控与可观测性
|
|
39
|
-
```
|
|
40
|
-
|
|
1
|
+
---
|
|
2
|
+
name: devops
|
|
3
|
+
description: DevOps 能力索引(Git/CI/CD、测试、DevSecOps、数据库、可观测性)。
|
|
4
|
+
license: MIT
|
|
5
|
+
user-invocable: false
|
|
6
|
+
disable-model-invocation: false
|
|
7
|
+
context: fork
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 🔧 炼器秘典 · DevOps 能力中枢
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## 能力矩阵
|
|
14
|
+
|
|
15
|
+
| Skill | 定位 | 核心能力 |
|
|
16
|
+
|-------|------|----------|
|
|
17
|
+
| [git-workflow](git-workflow.md) | 版本控制 | Git、分支策略、PR |
|
|
18
|
+
| [testing](testing.md) | 软件测试 | 单元测试、集成测试、TDD、测试策略、E2E测试 |
|
|
19
|
+
| [devsecops](devsecops.md) | 安全开发 | CI/CD安全、供应链安全 |
|
|
20
|
+
| [database](database.md) | 数据库 | SQL、NoSQL、优化 |
|
|
21
|
+
| [performance](performance.md) | 性能优化 | Profiling、火焰图、基准测试、负载测试、性能测试 |
|
|
22
|
+
| [observability](observability.md) | 可观测性 | 日志、指标、追踪、SLO |
|
|
23
|
+
| [cost-optimization](cost-optimization.md) | 成本优化 | FinOps、右尺寸、Spot、伸缩 |
|
|
24
|
+
|
|
25
|
+
## DevOps 原则
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
文化:
|
|
29
|
+
- 协作与共享
|
|
30
|
+
- 持续改进
|
|
31
|
+
- 自动化一切
|
|
32
|
+
- 快速反馈
|
|
33
|
+
|
|
34
|
+
实践:
|
|
35
|
+
- 持续集成 (CI)
|
|
36
|
+
- 持续交付 (CD)
|
|
37
|
+
- 基础设施即代码
|
|
38
|
+
- 监控与可观测性
|
|
39
|
+
```
|
|
40
|
+
|