tlc-claude-code 1.2.28 → 1.3.0
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 +9 -4
- package/dashboard/dist/components/UsagePane.d.ts +13 -0
- package/dashboard/dist/components/UsagePane.js +51 -0
- package/dashboard/dist/components/UsagePane.test.d.ts +1 -0
- package/dashboard/dist/components/UsagePane.test.js +142 -0
- package/dashboard/dist/components/WorkspaceDocsPane.d.ts +19 -0
- package/dashboard/dist/components/WorkspaceDocsPane.js +146 -0
- package/dashboard/dist/components/WorkspaceDocsPane.test.d.ts +1 -0
- package/dashboard/dist/components/WorkspaceDocsPane.test.js +242 -0
- package/dashboard/dist/components/WorkspacePane.d.ts +18 -0
- package/dashboard/dist/components/WorkspacePane.js +17 -0
- package/dashboard/dist/components/WorkspacePane.test.d.ts +1 -0
- package/dashboard/dist/components/WorkspacePane.test.js +84 -0
- package/package.json +15 -4
- package/scripts/capture-screenshots.js +170 -0
- package/scripts/docs-update.js +253 -0
- package/scripts/generate-screenshots.js +321 -0
- package/scripts/project-docs.js +377 -0
- package/scripts/vps-setup.sh +477 -0
- package/server/lib/architecture-command.js +450 -0
- package/server/lib/architecture-command.test.js +754 -0
- package/server/lib/ast-analyzer.js +324 -0
- package/server/lib/ast-analyzer.test.js +437 -0
- package/server/lib/auth-system.test.js +4 -1
- package/server/lib/boundary-detector.js +427 -0
- package/server/lib/boundary-detector.test.js +320 -0
- package/server/lib/budget-alerts.js +138 -0
- package/server/lib/budget-alerts.test.js +235 -0
- package/server/lib/candidates-tracker.js +210 -0
- package/server/lib/candidates-tracker.test.js +300 -0
- package/server/lib/checkpoint-manager.js +251 -0
- package/server/lib/checkpoint-manager.test.js +474 -0
- package/server/lib/circular-detector.js +337 -0
- package/server/lib/circular-detector.test.js +353 -0
- package/server/lib/cohesion-analyzer.js +310 -0
- package/server/lib/cohesion-analyzer.test.js +447 -0
- package/server/lib/contract-testing.js +625 -0
- package/server/lib/contract-testing.test.js +342 -0
- package/server/lib/conversion-planner.js +469 -0
- package/server/lib/conversion-planner.test.js +361 -0
- package/server/lib/convert-command.js +351 -0
- package/server/lib/convert-command.test.js +608 -0
- package/server/lib/coupling-calculator.js +189 -0
- package/server/lib/coupling-calculator.test.js +509 -0
- package/server/lib/dependency-graph.js +367 -0
- package/server/lib/dependency-graph.test.js +516 -0
- package/server/lib/duplication-detector.js +349 -0
- package/server/lib/duplication-detector.test.js +401 -0
- package/server/lib/example-service.js +616 -0
- package/server/lib/example-service.test.js +397 -0
- package/server/lib/impact-scorer.js +184 -0
- package/server/lib/impact-scorer.test.js +211 -0
- package/server/lib/mermaid-generator.js +358 -0
- package/server/lib/mermaid-generator.test.js +301 -0
- package/server/lib/messaging-patterns.js +750 -0
- package/server/lib/messaging-patterns.test.js +213 -0
- package/server/lib/microservice-template.js +386 -0
- package/server/lib/microservice-template.test.js +325 -0
- package/server/lib/new-project-microservice.js +450 -0
- package/server/lib/new-project-microservice.test.js +600 -0
- package/server/lib/refactor-command.js +326 -0
- package/server/lib/refactor-command.test.js +528 -0
- package/server/lib/refactor-executor.js +254 -0
- package/server/lib/refactor-executor.test.js +305 -0
- package/server/lib/refactor-observer.js +292 -0
- package/server/lib/refactor-observer.test.js +422 -0
- package/server/lib/refactor-progress.js +193 -0
- package/server/lib/refactor-progress.test.js +251 -0
- package/server/lib/refactor-reporter.js +237 -0
- package/server/lib/refactor-reporter.test.js +247 -0
- package/server/lib/semantic-analyzer.js +198 -0
- package/server/lib/semantic-analyzer.test.js +474 -0
- package/server/lib/service-scaffold.js +486 -0
- package/server/lib/service-scaffold.test.js +373 -0
- package/server/lib/shared-kernel.js +578 -0
- package/server/lib/shared-kernel.test.js +255 -0
- package/server/lib/traefik-config.js +282 -0
- package/server/lib/traefik-config.test.js +312 -0
- package/server/lib/usage-command.js +218 -0
- package/server/lib/usage-command.test.js +391 -0
- package/server/lib/usage-formatter.js +192 -0
- package/server/lib/usage-formatter.test.js +267 -0
- package/server/lib/usage-history.js +122 -0
- package/server/lib/usage-history.test.js +206 -0
- package/server/package-lock.json +14 -0
- package/server/package.json +1 -0
- package/templates/docs-sync.yml +91 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Microservice Template Generator Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
|
|
7
|
+
describe('MicroserviceTemplate', () => {
|
|
8
|
+
describe('generateStructure', () => {
|
|
9
|
+
it('creates correct directory structure', async () => {
|
|
10
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
11
|
+
const template = new MicroserviceTemplate();
|
|
12
|
+
|
|
13
|
+
const config = {
|
|
14
|
+
projectName: 'my-platform',
|
|
15
|
+
services: ['user', 'order', 'notification'],
|
|
16
|
+
database: 'postgres',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const result = template.generateStructure(config);
|
|
20
|
+
|
|
21
|
+
expect(result.directories).toContain('my-platform');
|
|
22
|
+
expect(result.directories).toContain('my-platform/services');
|
|
23
|
+
expect(result.directories).toContain('my-platform/shared');
|
|
24
|
+
expect(result.directories).toContain('my-platform/shared/types');
|
|
25
|
+
expect(result.directories).toContain('my-platform/shared/contracts');
|
|
26
|
+
expect(result.directories).toContain('my-platform/shared/events');
|
|
27
|
+
expect(result.directories).toContain('my-platform/gateway');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('services array creates service directories', async () => {
|
|
31
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
32
|
+
const template = new MicroserviceTemplate();
|
|
33
|
+
|
|
34
|
+
const config = {
|
|
35
|
+
projectName: 'ecommerce',
|
|
36
|
+
services: ['user', 'order', 'notification'],
|
|
37
|
+
database: 'postgres',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const result = template.generateStructure(config);
|
|
41
|
+
|
|
42
|
+
expect(result.directories).toContain('ecommerce/services/user');
|
|
43
|
+
expect(result.directories).toContain('ecommerce/services/order');
|
|
44
|
+
expect(result.directories).toContain('ecommerce/services/notification');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('handles empty services array', async () => {
|
|
48
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
49
|
+
const template = new MicroserviceTemplate();
|
|
50
|
+
|
|
51
|
+
const config = {
|
|
52
|
+
projectName: 'empty-project',
|
|
53
|
+
services: [],
|
|
54
|
+
database: 'postgres',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const result = template.generateStructure(config);
|
|
58
|
+
|
|
59
|
+
expect(result.directories).toContain('empty-project');
|
|
60
|
+
expect(result.directories).toContain('empty-project/services');
|
|
61
|
+
// No service subdirectories
|
|
62
|
+
const serviceSubdirs = result.directories.filter(d => d.startsWith('empty-project/services/'));
|
|
63
|
+
expect(serviceSubdirs.length).toBe(0);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('handles single service', async () => {
|
|
67
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
68
|
+
const template = new MicroserviceTemplate();
|
|
69
|
+
|
|
70
|
+
const config = {
|
|
71
|
+
projectName: 'single-service',
|
|
72
|
+
services: ['api'],
|
|
73
|
+
database: 'postgres',
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const result = template.generateStructure(config);
|
|
77
|
+
|
|
78
|
+
expect(result.directories).toContain('single-service/services/api');
|
|
79
|
+
const serviceSubdirs = result.directories.filter(d => d.startsWith('single-service/services/') && d !== 'single-service/services/');
|
|
80
|
+
expect(serviceSubdirs.length).toBe(1);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('generateRootPackageJson', () => {
|
|
85
|
+
it('has workspace configuration', async () => {
|
|
86
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
87
|
+
const template = new MicroserviceTemplate();
|
|
88
|
+
|
|
89
|
+
const config = {
|
|
90
|
+
projectName: 'workspace-project',
|
|
91
|
+
services: ['user', 'order'],
|
|
92
|
+
database: 'postgres',
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const result = template.generateRootPackageJson(config);
|
|
96
|
+
const pkg = JSON.parse(result);
|
|
97
|
+
|
|
98
|
+
expect(pkg.name).toBe('workspace-project');
|
|
99
|
+
expect(pkg.workspaces).toContain('services/*');
|
|
100
|
+
expect(pkg.workspaces).toContain('shared');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('has correct scripts', async () => {
|
|
104
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
105
|
+
const template = new MicroserviceTemplate();
|
|
106
|
+
|
|
107
|
+
const config = {
|
|
108
|
+
projectName: 'scripts-project',
|
|
109
|
+
services: ['user'],
|
|
110
|
+
database: 'postgres',
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const result = template.generateRootPackageJson(config);
|
|
114
|
+
const pkg = JSON.parse(result);
|
|
115
|
+
|
|
116
|
+
expect(pkg.scripts.dev).toBeDefined();
|
|
117
|
+
expect(pkg.scripts.build).toBeDefined();
|
|
118
|
+
expect(pkg.scripts.test).toBeDefined();
|
|
119
|
+
expect(pkg.scripts['docker:up']).toBeDefined();
|
|
120
|
+
expect(pkg.scripts['docker:down']).toBeDefined();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('generateDockerCompose', () => {
|
|
125
|
+
it('includes all services', async () => {
|
|
126
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
127
|
+
const template = new MicroserviceTemplate();
|
|
128
|
+
|
|
129
|
+
const config = {
|
|
130
|
+
projectName: 'docker-project',
|
|
131
|
+
services: ['user', 'order', 'notification'],
|
|
132
|
+
database: 'postgres',
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const result = template.generateDockerCompose(config);
|
|
136
|
+
|
|
137
|
+
expect(result).toContain('user:');
|
|
138
|
+
expect(result).toContain('order:');
|
|
139
|
+
expect(result).toContain('notification:');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('includes postgres when database is postgres', async () => {
|
|
143
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
144
|
+
const template = new MicroserviceTemplate();
|
|
145
|
+
|
|
146
|
+
const config = {
|
|
147
|
+
projectName: 'postgres-project',
|
|
148
|
+
services: ['user'],
|
|
149
|
+
database: 'postgres',
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const result = template.generateDockerCompose(config);
|
|
153
|
+
|
|
154
|
+
expect(result).toContain('postgres:');
|
|
155
|
+
expect(result).toContain('postgres:15-alpine');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('includes redis', async () => {
|
|
159
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
160
|
+
const template = new MicroserviceTemplate();
|
|
161
|
+
|
|
162
|
+
const config = {
|
|
163
|
+
projectName: 'redis-project',
|
|
164
|
+
services: ['user'],
|
|
165
|
+
database: 'postgres',
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const result = template.generateDockerCompose(config);
|
|
169
|
+
|
|
170
|
+
expect(result).toContain('redis:');
|
|
171
|
+
expect(result).toContain('redis:7-alpine');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('includes traefik gateway', async () => {
|
|
175
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
176
|
+
const template = new MicroserviceTemplate();
|
|
177
|
+
|
|
178
|
+
const config = {
|
|
179
|
+
projectName: 'gateway-project',
|
|
180
|
+
services: ['user'],
|
|
181
|
+
database: 'postgres',
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const result = template.generateDockerCompose(config);
|
|
185
|
+
|
|
186
|
+
expect(result).toContain('traefik:');
|
|
187
|
+
expect(result).toContain('traefik:v2');
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('generateEnvExample', () => {
|
|
192
|
+
it('has all service URLs', async () => {
|
|
193
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
194
|
+
const template = new MicroserviceTemplate();
|
|
195
|
+
|
|
196
|
+
const config = {
|
|
197
|
+
projectName: 'env-project',
|
|
198
|
+
services: ['user', 'order', 'notification'],
|
|
199
|
+
database: 'postgres',
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const result = template.generateEnvExample(config);
|
|
203
|
+
|
|
204
|
+
expect(result).toContain('USER_SERVICE_URL');
|
|
205
|
+
expect(result).toContain('ORDER_SERVICE_URL');
|
|
206
|
+
expect(result).toContain('NOTIFICATION_SERVICE_URL');
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('has database URL', async () => {
|
|
210
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
211
|
+
const template = new MicroserviceTemplate();
|
|
212
|
+
|
|
213
|
+
const config = {
|
|
214
|
+
projectName: 'db-env-project',
|
|
215
|
+
services: ['user'],
|
|
216
|
+
database: 'postgres',
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const result = template.generateEnvExample(config);
|
|
220
|
+
|
|
221
|
+
expect(result).toContain('DATABASE_URL');
|
|
222
|
+
expect(result).toContain('postgres://');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('has redis URL', async () => {
|
|
226
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
227
|
+
const template = new MicroserviceTemplate();
|
|
228
|
+
|
|
229
|
+
const config = {
|
|
230
|
+
projectName: 'redis-env-project',
|
|
231
|
+
services: ['user'],
|
|
232
|
+
database: 'postgres',
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const result = template.generateEnvExample(config);
|
|
236
|
+
|
|
237
|
+
expect(result).toContain('REDIS_URL');
|
|
238
|
+
expect(result).toContain('redis://');
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe('generateReadme', () => {
|
|
243
|
+
it('includes project name', async () => {
|
|
244
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
245
|
+
const template = new MicroserviceTemplate();
|
|
246
|
+
|
|
247
|
+
const config = {
|
|
248
|
+
projectName: 'readme-project',
|
|
249
|
+
services: ['user', 'order'],
|
|
250
|
+
database: 'postgres',
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const result = template.generateReadme(config);
|
|
254
|
+
|
|
255
|
+
expect(result).toContain('# readme-project');
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('includes Mermaid architecture diagram', async () => {
|
|
259
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
260
|
+
const template = new MicroserviceTemplate();
|
|
261
|
+
|
|
262
|
+
const config = {
|
|
263
|
+
projectName: 'diagram-project',
|
|
264
|
+
services: ['user', 'order'],
|
|
265
|
+
database: 'postgres',
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const result = template.generateReadme(config);
|
|
269
|
+
|
|
270
|
+
expect(result).toContain('```mermaid');
|
|
271
|
+
expect(result).toContain('graph');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('lists all services', async () => {
|
|
275
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
276
|
+
const template = new MicroserviceTemplate();
|
|
277
|
+
|
|
278
|
+
const config = {
|
|
279
|
+
projectName: 'services-project',
|
|
280
|
+
services: ['user', 'order', 'notification'],
|
|
281
|
+
database: 'postgres',
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
const result = template.generateReadme(config);
|
|
285
|
+
|
|
286
|
+
expect(result).toContain('user');
|
|
287
|
+
expect(result).toContain('order');
|
|
288
|
+
expect(result).toContain('notification');
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('includes quick start instructions', async () => {
|
|
292
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
293
|
+
const template = new MicroserviceTemplate();
|
|
294
|
+
|
|
295
|
+
const config = {
|
|
296
|
+
projectName: 'quickstart-project',
|
|
297
|
+
services: ['user'],
|
|
298
|
+
database: 'postgres',
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const result = template.generateReadme(config);
|
|
302
|
+
|
|
303
|
+
expect(result).toContain('Quick Start');
|
|
304
|
+
expect(result).toContain('npm install');
|
|
305
|
+
expect(result).toContain('docker');
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
describe('defaults', () => {
|
|
310
|
+
it('default database is postgres', async () => {
|
|
311
|
+
const { MicroserviceTemplate } = await import('./microservice-template.js');
|
|
312
|
+
const template = new MicroserviceTemplate();
|
|
313
|
+
|
|
314
|
+
const config = {
|
|
315
|
+
projectName: 'default-db-project',
|
|
316
|
+
services: ['user'],
|
|
317
|
+
// No database specified
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const result = template.generateDockerCompose(config);
|
|
321
|
+
|
|
322
|
+
expect(result).toContain('postgres:');
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
});
|