@reliverse/dler 2.0.6 → 2.0.7

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.
Files changed (46) hide show
  1. package/package.json +16 -12
  2. package/src/cli.ts +0 -8
  3. package/src/cmds/build/cmd.ts +0 -568
  4. package/src/cmds/clean/cmd.ts +0 -166
  5. package/src/cmds/clean/impl.ts +0 -900
  6. package/src/cmds/clean/presets.ts +0 -158
  7. package/src/cmds/clean/types.ts +0 -71
  8. package/src/cmds/init/cmd.ts +0 -68
  9. package/src/cmds/init/impl/config.ts +0 -105
  10. package/src/cmds/init/impl/generators.ts +0 -220
  11. package/src/cmds/init/impl/prompts.ts +0 -137
  12. package/src/cmds/init/impl/types.ts +0 -25
  13. package/src/cmds/init/impl/utils.ts +0 -17
  14. package/src/cmds/init/impl/validators.ts +0 -55
  15. package/src/cmds/integrate/cmd.ts +0 -82
  16. package/src/cmds/integrate/impl.ts +0 -204
  17. package/src/cmds/integrate/integrations/base.ts +0 -69
  18. package/src/cmds/integrate/integrations/nextjs.ts +0 -227
  19. package/src/cmds/integrate/integrations/registry.ts +0 -45
  20. package/src/cmds/integrate/integrations/ultracite.ts +0 -53
  21. package/src/cmds/integrate/types.ts +0 -48
  22. package/src/cmds/integrate/utils/biome.ts +0 -173
  23. package/src/cmds/integrate/utils/context.ts +0 -148
  24. package/src/cmds/integrate/utils/temp.ts +0 -47
  25. package/src/cmds/perf/analysis/bundle.ts +0 -311
  26. package/src/cmds/perf/analysis/filesystem.ts +0 -324
  27. package/src/cmds/perf/analysis/monorepo.ts +0 -439
  28. package/src/cmds/perf/benchmarks/command.ts +0 -230
  29. package/src/cmds/perf/benchmarks/memory.ts +0 -249
  30. package/src/cmds/perf/benchmarks/runner.ts +0 -220
  31. package/src/cmds/perf/cmd.ts +0 -285
  32. package/src/cmds/perf/impl.ts +0 -411
  33. package/src/cmds/perf/reporters/console.ts +0 -331
  34. package/src/cmds/perf/reporters/html.ts +0 -984
  35. package/src/cmds/perf/reporters/json.ts +0 -42
  36. package/src/cmds/perf/types.ts +0 -220
  37. package/src/cmds/perf/utils/cache.ts +0 -234
  38. package/src/cmds/perf/utils/formatter.ts +0 -190
  39. package/src/cmds/perf/utils/stats.ts +0 -153
  40. package/src/cmds/publish/cmd.ts +0 -213
  41. package/src/cmds/shell/cmd.ts +0 -61
  42. package/src/cmds/tsc/cache.ts +0 -237
  43. package/src/cmds/tsc/cmd.ts +0 -139
  44. package/src/cmds/tsc/impl.ts +0 -855
  45. package/src/cmds/tsc/types.ts +0 -66
  46. package/tsconfig.json +0 -9
@@ -1,439 +0,0 @@
1
- // apps/dler/src/cmds/perf/analysis/monorepo.ts
2
-
3
- import { existsSync } from "node:fs";
4
- import { join, resolve } from "node:path";
5
- import { logger } from "@reliverse/dler-logger";
6
- import { createIgnoreFilter } from "@reliverse/dler-matcher";
7
- import {
8
- getWorkspacePatterns,
9
- hasWorkspaces,
10
- readPackageJSON,
11
- } from "@reliverse/dler-pkg-tsc";
12
- import type {
13
- Bottleneck,
14
- CircularDependency,
15
- DependencyEdge,
16
- DependencyGraph,
17
- MonorepoAnalysisResult,
18
- PackageInfo,
19
- } from "../types";
20
-
21
- export interface MonorepoAnalysisOptions {
22
- cwd?: string;
23
- ignore?: string | string[];
24
- verbose?: boolean;
25
- includeDevDependencies?: boolean;
26
- analyzeBuildOrder?: boolean;
27
- }
28
-
29
- export class MonorepoAnalyzer {
30
- private options: MonorepoAnalysisOptions;
31
- private packages: PackageInfo[] = [];
32
- private dependencyGraph: DependencyGraph = {
33
- nodes: [],
34
- edges: [],
35
- levels: [],
36
- };
37
-
38
- constructor(options: MonorepoAnalysisOptions) {
39
- this.options = options;
40
- }
41
-
42
- async analyze(): Promise<MonorepoAnalysisResult> {
43
- const startTime = Date.now();
44
- const { cwd, verbose } = this.options;
45
-
46
- if (verbose) {
47
- logger.info("🔍 Analyzing monorepo structure...");
48
- }
49
-
50
- // Find monorepo root
51
- const monorepoRoot = await this.findMonorepoRoot(cwd);
52
- if (!monorepoRoot) {
53
- throw new Error(
54
- 'No monorepo found. Ensure package.json has "workspaces" field.',
55
- );
56
- }
57
-
58
- if (verbose) {
59
- logger.info(` Monorepo root: ${monorepoRoot}`);
60
- }
61
-
62
- // Discover packages
63
- this.packages = await this.discoverPackages(monorepoRoot);
64
-
65
- if (verbose) {
66
- logger.info(` Found ${this.packages.length} packages`);
67
- }
68
-
69
- // Build dependency graph
70
- this.dependencyGraph = await this.buildDependencyGraph();
71
-
72
- // Analyze circular dependencies
73
- const circularDependencies = this.findCircularDependencies();
74
-
75
- // Calculate build order
76
- const buildOrder = this.calculateBuildOrder();
77
-
78
- // Find critical path
79
- const criticalPath = this.findCriticalPath();
80
-
81
- // Identify bottlenecks
82
- const bottlenecks = this.identifyBottlenecks();
83
-
84
- // Suggest optimal concurrency
85
- const suggestedConcurrency = this.suggestOptimalConcurrency();
86
-
87
- const analysisTime = Date.now() - startTime;
88
-
89
- if (verbose) {
90
- logger.info(` Analysis completed in ${analysisTime}ms`);
91
- }
92
-
93
- return {
94
- packages: this.packages,
95
- dependencies: this.dependencyGraph,
96
- circularDependencies,
97
- criticalPath,
98
- buildOrder,
99
- bottlenecks,
100
- suggestedConcurrency,
101
- analysisTime,
102
- };
103
- }
104
-
105
- private async findMonorepoRoot(startDir?: string): Promise<string | null> {
106
- let currentDir = resolve(startDir ?? process.cwd());
107
-
108
- while (currentDir !== "/") {
109
- const pkgPath = join(currentDir, "package.json");
110
-
111
- if (existsSync(pkgPath)) {
112
- const pkg = await readPackageJSON(currentDir);
113
- if (pkg && hasWorkspaces(pkg)) {
114
- return currentDir;
115
- }
116
- }
117
-
118
- const parentDir = resolve(currentDir, "..");
119
- if (parentDir === currentDir) break;
120
- currentDir = parentDir;
121
- }
122
-
123
- return null;
124
- }
125
-
126
- private async discoverPackages(monorepoRoot: string): Promise<PackageInfo[]> {
127
- const rootPkg = await readPackageJSON(monorepoRoot);
128
- if (!rootPkg) {
129
- throw new Error("Could not read root package.json");
130
- }
131
-
132
- const patterns = getWorkspacePatterns(rootPkg);
133
- if (!patterns.length) {
134
- throw new Error("No workspace patterns found in package.json");
135
- }
136
-
137
- const packages: PackageInfo[] = [];
138
- const seenPaths = new Set<string>();
139
-
140
- for (const pattern of patterns) {
141
- const glob = new Bun.Glob(pattern);
142
- const matches = glob.scanSync({ cwd: monorepoRoot, onlyFiles: false });
143
-
144
- for (const match of matches) {
145
- const packagePath = resolve(monorepoRoot, match);
146
- if (seenPaths.has(packagePath)) continue;
147
- seenPaths.add(packagePath);
148
-
149
- const pkgInfo = await this.resolvePackageInfo(packagePath);
150
- if (pkgInfo) {
151
- packages.push(pkgInfo);
152
- }
153
- }
154
- }
155
-
156
- // Apply ignore filters
157
- if (this.options.ignore) {
158
- const ignoreFilter = createIgnoreFilter(this.options.ignore);
159
- return ignoreFilter(packages);
160
- }
161
-
162
- return packages;
163
- }
164
-
165
- private async resolvePackageInfo(
166
- packagePath: string,
167
- ): Promise<PackageInfo | null> {
168
- const pkgJsonPath = join(packagePath, "package.json");
169
- if (!existsSync(pkgJsonPath)) return null;
170
-
171
- try {
172
- const pkg = await readPackageJSON(packagePath);
173
- if (!pkg?.name) return null;
174
-
175
- const dependencies = [
176
- ...Object.keys(pkg.dependencies ?? {}),
177
- ...(this.options.includeDevDependencies
178
- ? Object.keys(pkg.devDependencies ?? {})
179
- : []),
180
- ...Object.keys(pkg.peerDependencies ?? {}),
181
- ];
182
-
183
- return {
184
- name: pkg.name,
185
- path: packagePath,
186
- dependencies,
187
- dependents: [], // Will be filled later
188
- buildTime: 0, // Would need to measure actual build time
189
- size: 0, // Would need to calculate package size
190
- };
191
- } catch {
192
- return null;
193
- }
194
- }
195
-
196
- private async buildDependencyGraph(): Promise<DependencyGraph> {
197
- const nodes = this.packages.map((pkg) => pkg.name);
198
- const edges: DependencyEdge[] = [];
199
-
200
- // Build dependency edges
201
- for (const pkg of this.packages) {
202
- for (const dep of pkg.dependencies) {
203
- // Check if dependency is within the monorepo
204
- const depPkg = this.packages.find((p) => p.name === dep);
205
- if (depPkg) {
206
- edges.push({
207
- from: pkg.name,
208
- to: dep,
209
- type: "dependency",
210
- });
211
-
212
- // Add to dependents
213
- depPkg.dependents.push(pkg.name);
214
- }
215
- }
216
- }
217
-
218
- // Calculate levels (topological sort)
219
- const levels = this.calculateLevels(nodes, edges);
220
-
221
- return {
222
- nodes,
223
- edges,
224
- levels,
225
- };
226
- }
227
-
228
- private calculateLevels(
229
- nodes: string[],
230
- edges: DependencyEdge[],
231
- ): string[][] {
232
- const inDegree = new Map<string, number>();
233
- const graph = new Map<string, string[]>();
234
-
235
- // Initialize
236
- for (const node of nodes) {
237
- inDegree.set(node, 0);
238
- graph.set(node, []);
239
- }
240
-
241
- // Build graph and calculate in-degrees
242
- for (const edge of edges) {
243
- const current = inDegree.get(edge.to) ?? 0;
244
- inDegree.set(edge.to, current + 1);
245
-
246
- const neighbors = graph.get(edge.from) ?? [];
247
- neighbors.push(edge.to);
248
- graph.set(edge.from, neighbors);
249
- }
250
-
251
- // Topological sort
252
- const levels: string[][] = [];
253
- const queue: string[] = [];
254
-
255
- // Start with nodes that have no dependencies
256
- for (const [node, degree] of inDegree) {
257
- if (degree === 0) {
258
- queue.push(node);
259
- }
260
- }
261
-
262
- while (queue.length > 0) {
263
- const currentLevel: string[] = [];
264
- const nextQueue: string[] = [];
265
-
266
- for (const node of queue) {
267
- currentLevel.push(node);
268
-
269
- // Process neighbors
270
- const neighbors = graph.get(node) ?? [];
271
- for (const neighbor of neighbors) {
272
- const degree = inDegree.get(neighbor) ?? 0;
273
- inDegree.set(neighbor, degree - 1);
274
-
275
- if (degree - 1 === 0) {
276
- nextQueue.push(neighbor);
277
- }
278
- }
279
- }
280
-
281
- levels.push(currentLevel);
282
- queue.length = 0;
283
- queue.push(...nextQueue);
284
- }
285
-
286
- return levels;
287
- }
288
-
289
- private findCircularDependencies(): CircularDependency[] {
290
- const circular: CircularDependency[] = [];
291
- const visited = new Set<string>();
292
- const recursionStack = new Set<string>();
293
-
294
- for (const pkg of this.packages) {
295
- if (!visited.has(pkg.name)) {
296
- const cycle = this.detectCycle(pkg.name, visited, recursionStack, []);
297
- if (cycle.length > 0) {
298
- circular.push({
299
- packages: cycle,
300
- cycle,
301
- severity: this.calculateCycleSeverity(cycle),
302
- });
303
- }
304
- }
305
- }
306
-
307
- return circular;
308
- }
309
-
310
- private detectCycle(
311
- node: string,
312
- visited: Set<string>,
313
- recursionStack: Set<string>,
314
- path: string[],
315
- ): string[] {
316
- visited.add(node);
317
- recursionStack.add(node);
318
- path.push(node);
319
-
320
- const pkg = this.packages.find((p) => p.name === node);
321
- if (pkg) {
322
- for (const dep of pkg.dependencies) {
323
- const depPkg = this.packages.find((p) => p.name === dep);
324
- if (depPkg) {
325
- if (!visited.has(dep)) {
326
- const cycle = this.detectCycle(dep, visited, recursionStack, [
327
- ...path,
328
- ]);
329
- if (cycle.length > 0) {
330
- return cycle;
331
- }
332
- } else if (recursionStack.has(dep)) {
333
- // Found a cycle
334
- const cycleStart = path.indexOf(dep);
335
- return path.slice(cycleStart);
336
- }
337
- }
338
- }
339
- }
340
-
341
- recursionStack.delete(node);
342
- return [];
343
- }
344
-
345
- private calculateCycleSeverity(cycle: string[]): "low" | "medium" | "high" {
346
- if (cycle.length <= 2) return "low";
347
- if (cycle.length <= 4) return "medium";
348
- return "high";
349
- }
350
-
351
- private calculateBuildOrder(): string[] {
352
- const order: string[] = [];
353
-
354
- for (const level of this.dependencyGraph.levels) {
355
- order.push(...level);
356
- }
357
-
358
- return order;
359
- }
360
-
361
- private findCriticalPath(): string[] {
362
- // Simple heuristic: packages with the most dependents
363
- const dependentCounts = new Map<string, number>();
364
-
365
- for (const pkg of this.packages) {
366
- dependentCounts.set(pkg.name, pkg.dependents.length);
367
- }
368
-
369
- return Array.from(dependentCounts.entries())
370
- .sort(([, a], [, b]) => b - a)
371
- .map(([name]) => name);
372
- }
373
-
374
- private identifyBottlenecks(): Bottleneck[] {
375
- const bottlenecks: Bottleneck[] = [];
376
-
377
- // Find packages with many dependencies
378
- for (const pkg of this.packages) {
379
- if (pkg.dependencies.length > 10) {
380
- bottlenecks.push({
381
- package: pkg.name,
382
- type: "many-dependencies",
383
- impact: pkg.dependencies.length,
384
- suggestion: `Consider splitting ${pkg.name} - it has ${pkg.dependencies.length} dependencies`,
385
- });
386
- }
387
- }
388
-
389
- // Find circular dependencies
390
- const circularDeps = this.findCircularDependencies();
391
- for (const circular of circularDeps) {
392
- bottlenecks.push({
393
- package: circular.packages[0]!,
394
- type: "circular-dependency",
395
- impact: circular.packages.length,
396
- suggestion: `Resolve circular dependency: ${circular.cycle.join(" → ")}`,
397
- });
398
- }
399
-
400
- // Find slow packages (heuristic based on dependents)
401
- for (const pkg of this.packages) {
402
- if (pkg.dependents.length > 5) {
403
- bottlenecks.push({
404
- package: pkg.name,
405
- type: "slow-build",
406
- impact: pkg.dependents.length,
407
- suggestion: `Optimize ${pkg.name} - it blocks ${pkg.dependents.length} other packages`,
408
- });
409
- }
410
- }
411
-
412
- return bottlenecks.sort((a, b) => b.impact - a.impact);
413
- }
414
-
415
- private suggestOptimalConcurrency(): number {
416
- // Simple heuristic based on dependency levels
417
- const maxLevel = this.dependencyGraph.levels.length;
418
- const avgLevelSize = this.packages.length / maxLevel;
419
-
420
- // Suggest concurrency based on level size and CPU cores
421
- const cpuCores = require("node:os").cpus().length;
422
- const suggested = Math.min(Math.ceil(avgLevelSize), cpuCores);
423
-
424
- return Math.max(1, suggested);
425
- }
426
- }
427
-
428
- export const analyzeMonorepo = async (
429
- options: MonorepoAnalysisOptions,
430
- ): Promise<MonorepoAnalysisResult> => {
431
- const analyzer = new MonorepoAnalyzer(options);
432
- return analyzer.analyze();
433
- };
434
-
435
- export const createMonorepoAnalyzer = (
436
- options: MonorepoAnalysisOptions,
437
- ): MonorepoAnalyzer => {
438
- return new MonorepoAnalyzer(options);
439
- };
@@ -1,230 +0,0 @@
1
- // apps/dler/src/cmds/perf/benchmarks/command.ts
2
-
3
- import { existsSync } from "node:fs";
4
- import { resolve } from "node:path";
5
- import { lookpath } from "lookpath";
6
- import type { Measurement, MemoryUsage } from "../types";
7
-
8
- export interface CommandExecutionOptions {
9
- cwd?: string;
10
- timeout?: number;
11
- env?: Record<string, string>;
12
- }
13
-
14
- export interface CommandResult {
15
- success: boolean;
16
- duration: number;
17
- memory: MemoryUsage;
18
- stdout: string;
19
- stderr: string;
20
- error?: string;
21
- exitCode: number;
22
- }
23
-
24
- export const executeCommand = async (
25
- command: string,
26
- options: CommandExecutionOptions = {},
27
- ): Promise<CommandResult> => {
28
- const startTime = process.hrtime.bigint();
29
-
30
- try {
31
- // Parse command and arguments
32
- const [cmd, ...args] = parseCommand(command);
33
-
34
- // Check if command exists
35
- if (!cmd) {
36
- throw new Error("Command is empty");
37
- }
38
-
39
- const commandPath = await findCommand(cmd);
40
- if (!commandPath) {
41
- throw new Error(`Command not found: ${cmd}`);
42
- }
43
-
44
- // Execute command
45
- const proc = Bun.spawn([commandPath, ...args], {
46
- cwd: options.cwd ?? process.cwd(),
47
- env: { ...process.env, ...options.env },
48
- stdout: "pipe",
49
- stderr: "pipe",
50
- });
51
-
52
- // Set timeout if specified
53
- let timeoutId: Timer | undefined;
54
- if (options.timeout) {
55
- timeoutId = setTimeout(() => {
56
- proc.kill();
57
- }, options.timeout);
58
- }
59
-
60
- // Wait for completion
61
- const [stdout, stderr] = await Promise.all([
62
- new Response(proc.stdout).text(),
63
- new Response(proc.stderr).text(),
64
- ]);
65
-
66
- const exitCode = await proc.exited;
67
- const endTime = process.hrtime.bigint();
68
- const endMemory = process.memoryUsage();
69
-
70
- // Clear timeout
71
- if (timeoutId) {
72
- clearTimeout(timeoutId);
73
- }
74
-
75
- const duration = Number(endTime - startTime) / 1_000_000; // Convert to milliseconds
76
-
77
- return {
78
- success: exitCode === 0,
79
- duration,
80
- memory: {
81
- rss: endMemory.rss,
82
- heapTotal: endMemory.heapTotal,
83
- heapUsed: endMemory.heapUsed,
84
- external: endMemory.external,
85
- arrayBuffers: endMemory.arrayBuffers,
86
- },
87
- stdout,
88
- stderr,
89
- exitCode,
90
- };
91
- } catch (error) {
92
- const endTime = process.hrtime.bigint();
93
- const endMemory = process.memoryUsage();
94
- const duration = Number(endTime - startTime) / 1_000_000;
95
-
96
- return {
97
- success: false,
98
- duration,
99
- memory: {
100
- rss: endMemory.rss,
101
- heapTotal: endMemory.heapTotal,
102
- heapUsed: endMemory.heapUsed,
103
- external: endMemory.external,
104
- arrayBuffers: endMemory.arrayBuffers,
105
- },
106
- stdout: "",
107
- stderr: "",
108
- error: error instanceof Error ? error.message : String(error),
109
- exitCode: 1,
110
- };
111
- }
112
- };
113
-
114
- export const executeCommandWithMemoryTracking = async (
115
- command: string,
116
- options: CommandExecutionOptions = {},
117
- ): Promise<Measurement> => {
118
- const result = await executeCommand(command, options);
119
- const endMemory = process.memoryUsage();
120
-
121
- return {
122
- run: 0, // Will be set by the runner
123
- duration: result.duration,
124
- memory: {
125
- rss: endMemory.rss,
126
- heapTotal: endMemory.heapTotal,
127
- heapUsed: endMemory.heapUsed,
128
- external: endMemory.external,
129
- arrayBuffers: endMemory.arrayBuffers,
130
- },
131
- success: result.success,
132
- error: result.error,
133
- stdout: result.stdout,
134
- stderr: result.stderr,
135
- };
136
- };
137
-
138
- const parseCommand = (command: string): string[] => {
139
- // Simple command parsing - handles basic cases
140
- // For more complex cases, consider using a proper shell parser
141
- const parts: string[] = [];
142
- let current = "";
143
- let inQuotes = false;
144
- let quoteChar = "";
145
-
146
- for (let i = 0; i < command.length; i++) {
147
- const char = command[i]!;
148
-
149
- if (char === '"' || char === "'") {
150
- if (!inQuotes) {
151
- inQuotes = true;
152
- quoteChar = char;
153
- } else if (char === quoteChar) {
154
- inQuotes = false;
155
- quoteChar = "";
156
- } else {
157
- current += char;
158
- }
159
- } else if (char === " " && !inQuotes) {
160
- if (current.trim()) {
161
- parts.push(current.trim());
162
- current = "";
163
- }
164
- } else {
165
- current += char;
166
- }
167
- }
168
-
169
- if (current.trim()) {
170
- parts.push(current.trim());
171
- }
172
-
173
- return parts;
174
- };
175
-
176
- const findCommand = async (cmd: string): Promise<string | null> => {
177
- if (!cmd) {
178
- return null;
179
- }
180
-
181
- // Check if it's a dler command first
182
- if (cmd === "dler") {
183
- return "bun";
184
- }
185
-
186
- // Check if it's a Bun command
187
- if (cmd === "bun") {
188
- return "bun";
189
- }
190
-
191
- // Check if it's a Node.js command
192
- if (cmd === "node") {
193
- return "node";
194
- }
195
-
196
- // Check if it's a direct executable
197
- if (cmd.includes("/") || cmd.includes("\\")) {
198
- const fullPath = resolve(cmd);
199
- return existsSync(fullPath) ? fullPath : null;
200
- }
201
-
202
- // Use lookpath to find the command
203
- try {
204
- const path = await lookpath(cmd);
205
- return path ?? null;
206
- } catch {
207
- return null;
208
- }
209
- };
210
-
211
- export const isDlerCommand = (command: string): boolean => {
212
- return command.startsWith("dler ") || command === "dler";
213
- };
214
-
215
- export const isBunCommand = (command: string): boolean => {
216
- return command.startsWith("bun ") || command === "bun";
217
- };
218
-
219
- export const isNodeCommand = (command: string): boolean => {
220
- return command.startsWith("node ") || command === "node";
221
- };
222
-
223
- export const getCommandType = (
224
- command: string,
225
- ): "dler" | "bun" | "node" | "external" => {
226
- if (isDlerCommand(command)) return "dler";
227
- if (isBunCommand(command)) return "bun";
228
- if (isNodeCommand(command)) return "node";
229
- return "external";
230
- };