devports 0.0.1 → 1.0.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/CHANGELOG.md +80 -0
- package/LICENSE +21 -0
- package/README.md +810 -29
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +329 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/allocate.command.d.ts +8 -0
- package/dist/commands/allocate.command.d.ts.map +1 -0
- package/dist/commands/allocate.command.js +84 -0
- package/dist/commands/allocate.command.js.map +1 -0
- package/dist/commands/base-command.d.ts +28 -0
- package/dist/commands/base-command.d.ts.map +1 -0
- package/dist/commands/base-command.js +33 -0
- package/dist/commands/base-command.js.map +1 -0
- package/dist/commands/check.command.d.ts +7 -0
- package/dist/commands/check.command.d.ts.map +1 -0
- package/dist/commands/check.command.js +44 -0
- package/dist/commands/check.command.js.map +1 -0
- package/dist/commands/completion.command.d.ts +7 -0
- package/dist/commands/completion.command.d.ts.map +1 -0
- package/dist/commands/completion.command.js +116 -0
- package/dist/commands/completion.command.js.map +1 -0
- package/dist/commands/gitignore.command.d.ts +7 -0
- package/dist/commands/gitignore.command.d.ts.map +1 -0
- package/dist/commands/gitignore.command.js +61 -0
- package/dist/commands/gitignore.command.js.map +1 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +35 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/info.command.d.ts +7 -0
- package/dist/commands/info.command.d.ts.map +1 -0
- package/dist/commands/info.command.js +40 -0
- package/dist/commands/info.command.js.map +1 -0
- package/dist/commands/list.command.d.ts +8 -0
- package/dist/commands/list.command.d.ts.map +1 -0
- package/dist/commands/list.command.js +165 -0
- package/dist/commands/list.command.js.map +1 -0
- package/dist/commands/release.command.d.ts +8 -0
- package/dist/commands/release.command.d.ts.map +1 -0
- package/dist/commands/release.command.js +89 -0
- package/dist/commands/release.command.js.map +1 -0
- package/dist/commands/render.command.d.ts +7 -0
- package/dist/commands/render.command.d.ts.map +1 -0
- package/dist/commands/render.command.js +53 -0
- package/dist/commands/render.command.js.map +1 -0
- package/dist/commands/reserve.command.d.ts +7 -0
- package/dist/commands/reserve.command.d.ts.map +1 -0
- package/dist/commands/reserve.command.js +42 -0
- package/dist/commands/reserve.command.js.map +1 -0
- package/dist/commands/setup.command.d.ts +7 -0
- package/dist/commands/setup.command.d.ts.map +1 -0
- package/dist/commands/setup.command.js +43 -0
- package/dist/commands/setup.command.js.map +1 -0
- package/dist/commands/status.command.d.ts +7 -0
- package/dist/commands/status.command.d.ts.map +1 -0
- package/dist/commands/status.command.js +41 -0
- package/dist/commands/status.command.js.map +1 -0
- package/dist/commands/unreserve.command.d.ts +7 -0
- package/dist/commands/unreserve.command.d.ts.map +1 -0
- package/dist/commands/unreserve.command.js +38 -0
- package/dist/commands/unreserve.command.js.map +1 -0
- package/dist/commands/worktree-add.command.d.ts +7 -0
- package/dist/commands/worktree-add.command.d.ts.map +1 -0
- package/dist/commands/worktree-add.command.js +68 -0
- package/dist/commands/worktree-add.command.js.map +1 -0
- package/dist/commands/worktree-remove.command.d.ts +7 -0
- package/dist/commands/worktree-remove.command.d.ts.map +1 -0
- package/dist/commands/worktree-remove.command.js +33 -0
- package/dist/commands/worktree-remove.command.js.map +1 -0
- package/dist/completion/bash-completion-template.d.ts +5 -0
- package/dist/completion/bash-completion-template.d.ts.map +1 -0
- package/dist/completion/bash-completion-template.js +14 -0
- package/dist/completion/bash-completion-template.js.map +1 -0
- package/dist/completion/bash.sh +208 -0
- package/dist/completion/completion-data.d.ts +16 -0
- package/dist/completion/completion-data.d.ts.map +1 -0
- package/dist/completion/completion-data.js +38 -0
- package/dist/completion/completion-data.js.map +1 -0
- package/dist/completion/index.d.ts +24 -0
- package/dist/completion/index.d.ts.map +1 -0
- package/dist/completion/index.js +30 -0
- package/dist/completion/index.js.map +1 -0
- package/dist/completion/shell-config.d.ts +27 -0
- package/dist/completion/shell-config.d.ts.map +1 -0
- package/dist/completion/shell-config.js +243 -0
- package/dist/completion/shell-config.js.map +1 -0
- package/dist/completion/zsh-completion-template.d.ts +5 -0
- package/dist/completion/zsh-completion-template.d.ts.map +1 -0
- package/dist/completion/zsh-completion-template.js +14 -0
- package/dist/completion/zsh-completion-template.js.map +1 -0
- package/dist/completion/zsh.sh +164 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +111 -0
- package/dist/config.js.map +1 -0
- package/dist/devports-1.0.0.tgz +0 -0
- package/dist/execution.d.ts +31 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +110 -0
- package/dist/execution.js.map +1 -0
- package/dist/gitignore.d.ts +22 -0
- package/dist/gitignore.d.ts.map +1 -0
- package/dist/gitignore.js +142 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/port-manager.d.ts +33 -0
- package/dist/port-manager.d.ts.map +1 -0
- package/dist/port-manager.js +169 -0
- package/dist/port-manager.js.map +1 -0
- package/dist/port-utils.d.ts +9 -0
- package/dist/port-utils.d.ts.map +1 -0
- package/dist/port-utils.js +38 -0
- package/dist/port-utils.js.map +1 -0
- package/dist/render.d.ts +54 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +286 -0
- package/dist/render.js.map +1 -0
- package/dist/services/lock-manager.d.ts +46 -0
- package/dist/services/lock-manager.d.ts.map +1 -0
- package/dist/services/lock-manager.js +118 -0
- package/dist/services/lock-manager.js.map +1 -0
- package/dist/services/response-formatter.d.ts +45 -0
- package/dist/services/response-formatter.d.ts.map +1 -0
- package/dist/services/response-formatter.js +102 -0
- package/dist/services/response-formatter.js.map +1 -0
- package/dist/services/validation-service.d.ts +109 -0
- package/dist/services/validation-service.d.ts.map +1 -0
- package/dist/services/validation-service.js +267 -0
- package/dist/services/validation-service.js.map +1 -0
- package/dist/setup.d.ts +20 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +243 -0
- package/dist/setup.js.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +69 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +344 -0
- package/dist/validation.js.map +1 -0
- package/dist/worktree.d.ts +24 -0
- package/dist/worktree.d.ts.map +1 -0
- package/dist/worktree.js +245 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +90 -6
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lock management service for coordinating file access
|
|
3
|
+
* Abstracts the common lock/unlock patterns used throughout the application
|
|
4
|
+
*/
|
|
5
|
+
import type { Registry } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for lock operations
|
|
8
|
+
*/
|
|
9
|
+
export interface LockOptions {
|
|
10
|
+
retries?: number;
|
|
11
|
+
stale?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Operation result that controls whether registry is saved
|
|
15
|
+
*/
|
|
16
|
+
export interface RegistryOperationResult<T> {
|
|
17
|
+
result: T;
|
|
18
|
+
shouldSave?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Lock manager for coordinating registry file access
|
|
22
|
+
* Ensures thread-safe operations on the port registry
|
|
23
|
+
*/
|
|
24
|
+
export declare class LockManager {
|
|
25
|
+
/**
|
|
26
|
+
* Execute an operation with exclusive access to the registry file
|
|
27
|
+
* Handles the complete lock/load/save/unlock cycle
|
|
28
|
+
*/
|
|
29
|
+
static withRegistryLock<T>(operation: (registry: Registry) => Promise<T> | T, options?: LockOptions): Promise<T>;
|
|
30
|
+
/**
|
|
31
|
+
* Execute an operation with conditional saving
|
|
32
|
+
* Save registry only if the operation indicates it should be saved
|
|
33
|
+
*/
|
|
34
|
+
static withRegistryLockConditional<T>(operation: (registry: Registry) => Promise<RegistryOperationResult<T>> | RegistryOperationResult<T>, options?: LockOptions): Promise<T>;
|
|
35
|
+
/**
|
|
36
|
+
* Execute a read-only operation with shared access to the registry
|
|
37
|
+
* Loads registry without saving changes
|
|
38
|
+
*/
|
|
39
|
+
static withRegistryReadLock<T>(operation: (registry: Registry) => Promise<T> | T, options?: LockOptions): Promise<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Execute an operation with a custom file lock
|
|
42
|
+
* Generic lock manager for other file operations
|
|
43
|
+
*/
|
|
44
|
+
static withFileLock<T>(filePath: string, operation: () => Promise<T> | T, options?: LockOptions): Promise<T>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=lock-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-manager.d.ts","sourceRoot":"","sources":["../../src/services/lock-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD;;GAEG;AACH,MAAM,WAAW,uBAAuB,CAAC,CAAC;IACxC,MAAM,EAAE,CAAC,CAAC;IACV,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB;;;OAGG;WACU,gBAAgB,CAAC,CAAC,EAC7B,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACjD,OAAO,GAAE,WAAkC,GAC1C,OAAO,CAAC,CAAC,CAAC;IA6Bb;;;OAGG;WACU,2BAA2B,CAAC,CAAC,EACxC,SAAS,EAAE,CACT,QAAQ,EAAE,QAAQ,KACf,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,GAAG,uBAAuB,CAAC,CAAC,CAAC,EACrE,OAAO,GAAE,WAAkC,GAC1C,OAAO,CAAC,CAAC,CAAC;IA+Bb;;;OAGG;WACU,oBAAoB,CAAC,CAAC,EACjC,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACjD,OAAO,GAAE,WAAkC,GAC1C,OAAO,CAAC,CAAC,CAAC;IA2Bb;;;OAGG;WACU,YAAY,CAAC,CAAC,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAC/B,OAAO,GAAE,WAAkC,GAC1C,OAAO,CAAC,CAAC,CAAC;CAYd"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lock management service for coordinating file access
|
|
3
|
+
* Abstracts the common lock/unlock patterns used throughout the application
|
|
4
|
+
*/
|
|
5
|
+
import lockfile from 'proper-lockfile';
|
|
6
|
+
import { loadConfig, loadRegistry, saveRegistry } from '../config.js';
|
|
7
|
+
/**
|
|
8
|
+
* Default lock options used throughout the application
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_LOCK_OPTIONS = {
|
|
11
|
+
retries: 5,
|
|
12
|
+
stale: 10000,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Lock manager for coordinating registry file access
|
|
16
|
+
* Ensures thread-safe operations on the port registry
|
|
17
|
+
*/
|
|
18
|
+
export class LockManager {
|
|
19
|
+
/**
|
|
20
|
+
* Execute an operation with exclusive access to the registry file
|
|
21
|
+
* Handles the complete lock/load/save/unlock cycle
|
|
22
|
+
*/
|
|
23
|
+
static async withRegistryLock(operation, options = DEFAULT_LOCK_OPTIONS) {
|
|
24
|
+
const config = loadConfig();
|
|
25
|
+
// Ensure registry exists before locking
|
|
26
|
+
loadRegistry();
|
|
27
|
+
// Lock the registry file
|
|
28
|
+
const release = await lockfile.lock(config.registryPath, {
|
|
29
|
+
retries: options.retries,
|
|
30
|
+
stale: options.stale,
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
// Load fresh registry data while holding the lock
|
|
34
|
+
const registry = loadRegistry();
|
|
35
|
+
// Execute the operation with the registry
|
|
36
|
+
const result = await operation(registry);
|
|
37
|
+
// Save the registry after the operation
|
|
38
|
+
saveRegistry(registry);
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
// Always release the lock
|
|
43
|
+
await release();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Execute an operation with conditional saving
|
|
48
|
+
* Save registry only if the operation indicates it should be saved
|
|
49
|
+
*/
|
|
50
|
+
static async withRegistryLockConditional(operation, options = DEFAULT_LOCK_OPTIONS) {
|
|
51
|
+
const config = loadConfig();
|
|
52
|
+
// Ensure registry exists before locking
|
|
53
|
+
loadRegistry();
|
|
54
|
+
// Lock the registry file
|
|
55
|
+
const release = await lockfile.lock(config.registryPath, {
|
|
56
|
+
retries: options.retries,
|
|
57
|
+
stale: options.stale,
|
|
58
|
+
});
|
|
59
|
+
try {
|
|
60
|
+
// Load fresh registry data while holding the lock
|
|
61
|
+
const registry = loadRegistry();
|
|
62
|
+
// Execute the operation with the registry
|
|
63
|
+
const operationResult = await operation(registry);
|
|
64
|
+
// Save the registry only if requested
|
|
65
|
+
if (operationResult.shouldSave !== false) {
|
|
66
|
+
saveRegistry(registry);
|
|
67
|
+
}
|
|
68
|
+
return operationResult.result;
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
// Always release the lock
|
|
72
|
+
await release();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Execute a read-only operation with shared access to the registry
|
|
77
|
+
* Loads registry without saving changes
|
|
78
|
+
*/
|
|
79
|
+
static async withRegistryReadLock(operation, options = DEFAULT_LOCK_OPTIONS) {
|
|
80
|
+
const config = loadConfig();
|
|
81
|
+
// Ensure registry exists before locking
|
|
82
|
+
loadRegistry();
|
|
83
|
+
// Lock the registry file (even for reads to ensure consistency)
|
|
84
|
+
const release = await lockfile.lock(config.registryPath, {
|
|
85
|
+
retries: options.retries,
|
|
86
|
+
stale: options.stale,
|
|
87
|
+
});
|
|
88
|
+
try {
|
|
89
|
+
// Load fresh registry data while holding the lock
|
|
90
|
+
const registry = loadRegistry();
|
|
91
|
+
// Execute the read-only operation
|
|
92
|
+
const result = await operation(registry);
|
|
93
|
+
// No need to save for read-only operations
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
// Always release the lock
|
|
98
|
+
await release();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Execute an operation with a custom file lock
|
|
103
|
+
* Generic lock manager for other file operations
|
|
104
|
+
*/
|
|
105
|
+
static async withFileLock(filePath, operation, options = DEFAULT_LOCK_OPTIONS) {
|
|
106
|
+
const release = await lockfile.lock(filePath, {
|
|
107
|
+
retries: options.retries,
|
|
108
|
+
stale: options.stale,
|
|
109
|
+
});
|
|
110
|
+
try {
|
|
111
|
+
return await operation();
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
await release();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=lock-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-manager.js","sourceRoot":"","sources":["../../src/services/lock-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response formatter service - centralizes JSON/console output patterns
|
|
3
|
+
* Consolidates the repeated logic across all commands for DRY compliance
|
|
4
|
+
*/
|
|
5
|
+
export interface ResponseOptions {
|
|
6
|
+
json?: boolean;
|
|
7
|
+
quiet?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ResponseData {
|
|
10
|
+
success: boolean;
|
|
11
|
+
message?: string;
|
|
12
|
+
data?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export declare class ResponseFormatter {
|
|
15
|
+
/**
|
|
16
|
+
* Format and output a response based on options
|
|
17
|
+
* Handles both JSON and console output patterns
|
|
18
|
+
*/
|
|
19
|
+
static format(response: ResponseData, options?: ResponseOptions): ResponseData;
|
|
20
|
+
/**
|
|
21
|
+
* Format success response with message
|
|
22
|
+
*/
|
|
23
|
+
static success(message: string, data?: unknown): ResponseData;
|
|
24
|
+
/**
|
|
25
|
+
* Format error response with message
|
|
26
|
+
*/
|
|
27
|
+
static error(message: string, data?: unknown): ResponseData;
|
|
28
|
+
/**
|
|
29
|
+
* Format data-only response (for list operations, etc.)
|
|
30
|
+
*/
|
|
31
|
+
static data(data: unknown, message?: string): ResponseData;
|
|
32
|
+
/**
|
|
33
|
+
* Handle quiet-specific output (like port numbers only)
|
|
34
|
+
*/
|
|
35
|
+
static quiet(value: string | number, data?: unknown): ResponseData;
|
|
36
|
+
/**
|
|
37
|
+
* Format port allocation response (common pattern)
|
|
38
|
+
*/
|
|
39
|
+
static portAllocation(port: number, project: string, service: string, type?: string): ResponseData;
|
|
40
|
+
/**
|
|
41
|
+
* Format port release response (common pattern)
|
|
42
|
+
*/
|
|
43
|
+
static portRelease(count: number, target?: string): ResponseData;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=response-formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-formatter.d.ts","sourceRoot":"","sources":["../../src/services/response-formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,iBAAiB;IAC5B;;;OAGG;IACH,MAAM,CAAC,MAAM,CACX,QAAQ,EAAE,YAAY,EACtB,OAAO,GAAE,eAAoB,GAC5B,YAAY;IAwBf;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY;IAQ7D;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY;IAQ3D;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY;IAQ1D;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,YAAY;IAQlE;;OAEG;IACH,MAAM,CAAC,cAAc,CACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,GACZ,YAAY;IAiBf;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY;CAYjE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response formatter service - centralizes JSON/console output patterns
|
|
3
|
+
* Consolidates the repeated logic across all commands for DRY compliance
|
|
4
|
+
*/
|
|
5
|
+
export class ResponseFormatter {
|
|
6
|
+
/**
|
|
7
|
+
* Format and output a response based on options
|
|
8
|
+
* Handles both JSON and console output patterns
|
|
9
|
+
*/
|
|
10
|
+
static format(response, options = {}) {
|
|
11
|
+
if (options.json) {
|
|
12
|
+
// JSON output - consistent across all commands
|
|
13
|
+
const jsonData = response.data ?? {
|
|
14
|
+
success: response.success,
|
|
15
|
+
message: response.message,
|
|
16
|
+
};
|
|
17
|
+
console.log(JSON.stringify(jsonData, null, 2));
|
|
18
|
+
return response;
|
|
19
|
+
}
|
|
20
|
+
if (options.quiet) {
|
|
21
|
+
// Quiet mode - minimal or no output
|
|
22
|
+
return response;
|
|
23
|
+
}
|
|
24
|
+
// Console output - show message if present
|
|
25
|
+
if (response.message) {
|
|
26
|
+
console.log(response.message);
|
|
27
|
+
}
|
|
28
|
+
return response;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Format success response with message
|
|
32
|
+
*/
|
|
33
|
+
static success(message, data) {
|
|
34
|
+
return {
|
|
35
|
+
success: true,
|
|
36
|
+
message,
|
|
37
|
+
data,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Format error response with message
|
|
42
|
+
*/
|
|
43
|
+
static error(message, data) {
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
message,
|
|
47
|
+
data,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Format data-only response (for list operations, etc.)
|
|
52
|
+
*/
|
|
53
|
+
static data(data, message) {
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
data,
|
|
57
|
+
message,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Handle quiet-specific output (like port numbers only)
|
|
62
|
+
*/
|
|
63
|
+
static quiet(value, data) {
|
|
64
|
+
console.log(value);
|
|
65
|
+
return {
|
|
66
|
+
success: true,
|
|
67
|
+
data,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Format port allocation response (common pattern)
|
|
72
|
+
*/
|
|
73
|
+
static portAllocation(port, project, service, type) {
|
|
74
|
+
const message = `✅ Allocated port ${port} for ${project}/${service}`;
|
|
75
|
+
const data = {
|
|
76
|
+
port,
|
|
77
|
+
project,
|
|
78
|
+
service,
|
|
79
|
+
type,
|
|
80
|
+
allocatedAt: new Date().toISOString(),
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
message,
|
|
85
|
+
data,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Format port release response (common pattern)
|
|
90
|
+
*/
|
|
91
|
+
static portRelease(count, target) {
|
|
92
|
+
const message = count > 0
|
|
93
|
+
? `✅ Released ${count} port(s)${target ? ` for ${target}` : ''}`
|
|
94
|
+
: `⚠️ No ports found${target ? ` for ${target}` : ''}`;
|
|
95
|
+
return {
|
|
96
|
+
success: count > 0,
|
|
97
|
+
message,
|
|
98
|
+
data: { releasedCount: count },
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=response-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-formatter.js","sourceRoot":"","sources":["../../src/services/response-formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,MAAM,OAAO,iBAAiB;IAC5B;;;OAGG;IACH,MAAM,CAAC,MAAM,CACX,QAAsB,EACtB,UAA2B,EAAE;QAE7B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,+CAA+C;YAC/C,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,IAAI;gBAChC,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,OAAO,EAAE,QAAQ,CAAC,OAAO;aAC1B,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/C,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,oCAAoC;YACpC,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,2CAA2C;QAC3C,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAe,EAAE,IAAc;QAC5C,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO;YACP,IAAI;SACL,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAe,EAAE,IAAc;QAC1C,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO;YACP,IAAI;SACL,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,IAAa,EAAE,OAAgB;QACzC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI;YACJ,OAAO;SACR,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,KAAsB,EAAE,IAAc;QACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI;SACL,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CACnB,IAAY,EACZ,OAAe,EACf,OAAe,EACf,IAAa;QAEb,MAAM,OAAO,GAAG,oBAAoB,IAAI,QAAQ,OAAO,IAAI,OAAO,EAAE,CAAC;QACrE,MAAM,IAAI,GAAG;YACX,IAAI;YACJ,OAAO;YACP,OAAO;YACP,IAAI;YACJ,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACtC,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO;YACP,IAAI;SACL,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAa,EAAE,MAAe;QAC/C,MAAM,OAAO,GACX,KAAK,GAAG,CAAC;YACP,CAAC,CAAC,cAAc,KAAK,WAAW,MAAM,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YAChE,CAAC,CAAC,qBAAqB,MAAM,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAE5D,OAAO;YACL,OAAO,EAAE,KAAK,GAAG,CAAC;YAClB,OAAO;YACP,IAAI,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE;SAC/B,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consolidated validation service - eliminates duplication in validation logic
|
|
3
|
+
* Implements configurable validation patterns for DRY compliance
|
|
4
|
+
*/
|
|
5
|
+
export declare class ValidationError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for string validation
|
|
10
|
+
*/
|
|
11
|
+
export interface StringValidationConfig {
|
|
12
|
+
name: string;
|
|
13
|
+
maxLength?: number;
|
|
14
|
+
minLength?: number;
|
|
15
|
+
pattern?: RegExp;
|
|
16
|
+
disallowedPrefixes?: string[];
|
|
17
|
+
required?: boolean;
|
|
18
|
+
customErrorMessage?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for path validation
|
|
22
|
+
*/
|
|
23
|
+
export interface PathValidationConfig {
|
|
24
|
+
name: string;
|
|
25
|
+
mustExist?: boolean;
|
|
26
|
+
allowRelative?: boolean;
|
|
27
|
+
allowedExtensions?: string[];
|
|
28
|
+
maxLength?: number;
|
|
29
|
+
customErrorMessage?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Configuration for numeric validation
|
|
33
|
+
*/
|
|
34
|
+
export interface NumericValidationConfig {
|
|
35
|
+
name: string;
|
|
36
|
+
min?: number;
|
|
37
|
+
max?: number;
|
|
38
|
+
integer?: boolean;
|
|
39
|
+
required?: boolean;
|
|
40
|
+
customErrorMessage?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Common validation patterns
|
|
44
|
+
*/
|
|
45
|
+
export declare const ValidationPatterns: {
|
|
46
|
+
readonly PROJECT_SERVICE: RegExp;
|
|
47
|
+
readonly BRANCH_NAME: RegExp;
|
|
48
|
+
readonly SAFE_PATH: RegExp;
|
|
49
|
+
readonly SHELL_DANGEROUS: RegExp;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Predefined validation configurations for common use cases
|
|
53
|
+
*/
|
|
54
|
+
export declare const ValidationConfigs: {
|
|
55
|
+
readonly PROJECT_NAME: StringValidationConfig;
|
|
56
|
+
readonly SERVICE_NAME: StringValidationConfig;
|
|
57
|
+
readonly BRANCH_NAME: StringValidationConfig;
|
|
58
|
+
readonly PORT_NUMBER: NumericValidationConfig;
|
|
59
|
+
readonly TEMPLATE_PATH: PathValidationConfig;
|
|
60
|
+
readonly WORKTREE_PATH: PathValidationConfig;
|
|
61
|
+
readonly OUTPUT_PATH: PathValidationConfig;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Centralized validation service with configurable validators
|
|
65
|
+
*/
|
|
66
|
+
export declare class ValidationService {
|
|
67
|
+
/**
|
|
68
|
+
* Validate a string value with configurable rules
|
|
69
|
+
*/
|
|
70
|
+
static validateString(value: string, config: StringValidationConfig): string;
|
|
71
|
+
/**
|
|
72
|
+
* Validate a numeric value with configurable rules
|
|
73
|
+
*/
|
|
74
|
+
static validateNumber(value: string | number, config: NumericValidationConfig): number;
|
|
75
|
+
/**
|
|
76
|
+
* Validate a path with configurable rules
|
|
77
|
+
*/
|
|
78
|
+
static validatePath(value: string, config: PathValidationConfig): string;
|
|
79
|
+
/**
|
|
80
|
+
* Convenience methods using predefined configurations
|
|
81
|
+
*/
|
|
82
|
+
static validateProjectName(value: string): string;
|
|
83
|
+
static validateServiceName(value: string): string;
|
|
84
|
+
static validateBranchName(value: string): string;
|
|
85
|
+
static validatePort(value: string | number): number;
|
|
86
|
+
static validateTemplatePath(value: string): string;
|
|
87
|
+
static validateWorktreePath(value: string): string;
|
|
88
|
+
static validateOutputPath(value: string): string;
|
|
89
|
+
/**
|
|
90
|
+
* Validate service type against allowed types
|
|
91
|
+
*/
|
|
92
|
+
static validateServiceType(type: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* Validate script file path for post-hooks and similar
|
|
95
|
+
*/
|
|
96
|
+
static validateScriptPath(path: string): string;
|
|
97
|
+
/**
|
|
98
|
+
* Validate an array of service definitions in "service" or "service:type" format
|
|
99
|
+
*/
|
|
100
|
+
static validateServices(services: string[]): Array<{
|
|
101
|
+
service: string;
|
|
102
|
+
type: string;
|
|
103
|
+
}>;
|
|
104
|
+
/**
|
|
105
|
+
* Sanitize string for safe display/logging, removing dangerous characters
|
|
106
|
+
*/
|
|
107
|
+
static sanitizeForDisplay(input: string, maxLength?: number): string;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=validation-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-service.d.ts","sourceRoot":"","sources":["../../src/services/validation-service.ts"],"names":[],"mappings":"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"}
|