devports 0.0.1 → 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/CHANGELOG.md +87 -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.1.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 +245 -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,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consolidated validation service - eliminates duplication in validation logic
|
|
3
|
+
* Implements configurable validation patterns for DRY compliance
|
|
4
|
+
*/
|
|
5
|
+
export class ValidationError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'ValidationError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Common validation patterns
|
|
13
|
+
*/
|
|
14
|
+
export const ValidationPatterns = {
|
|
15
|
+
PROJECT_SERVICE: /^[a-zA-Z0-9._-]+$/,
|
|
16
|
+
BRANCH_NAME: /^[a-zA-Z0-9._/-]+$/,
|
|
17
|
+
SAFE_PATH: /^[a-zA-Z0-9._/-]+$/,
|
|
18
|
+
SHELL_DANGEROUS: /[;|&$`<>(){}[\]"'\\*?~]/,
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Predefined validation configurations for common use cases
|
|
22
|
+
*/
|
|
23
|
+
export const ValidationConfigs = {
|
|
24
|
+
PROJECT_NAME: {
|
|
25
|
+
name: 'Project name',
|
|
26
|
+
maxLength: 50,
|
|
27
|
+
pattern: ValidationPatterns.PROJECT_SERVICE,
|
|
28
|
+
disallowedPrefixes: ['.', '-'],
|
|
29
|
+
required: true,
|
|
30
|
+
},
|
|
31
|
+
SERVICE_NAME: {
|
|
32
|
+
name: 'Service name',
|
|
33
|
+
maxLength: 30,
|
|
34
|
+
pattern: ValidationPatterns.PROJECT_SERVICE,
|
|
35
|
+
disallowedPrefixes: ['.', '-'],
|
|
36
|
+
required: true,
|
|
37
|
+
},
|
|
38
|
+
BRANCH_NAME: {
|
|
39
|
+
name: 'Branch name',
|
|
40
|
+
maxLength: 100,
|
|
41
|
+
pattern: ValidationPatterns.BRANCH_NAME,
|
|
42
|
+
required: true,
|
|
43
|
+
},
|
|
44
|
+
PORT_NUMBER: {
|
|
45
|
+
name: 'Port number',
|
|
46
|
+
min: 1024,
|
|
47
|
+
max: 65535,
|
|
48
|
+
integer: true,
|
|
49
|
+
required: true,
|
|
50
|
+
},
|
|
51
|
+
TEMPLATE_PATH: {
|
|
52
|
+
name: 'Template path',
|
|
53
|
+
allowedExtensions: ['.devports'],
|
|
54
|
+
maxLength: 500,
|
|
55
|
+
allowRelative: true,
|
|
56
|
+
},
|
|
57
|
+
WORKTREE_PATH: {
|
|
58
|
+
name: 'Worktree path',
|
|
59
|
+
maxLength: 500,
|
|
60
|
+
allowRelative: true,
|
|
61
|
+
},
|
|
62
|
+
OUTPUT_PATH: {
|
|
63
|
+
name: 'Output path',
|
|
64
|
+
maxLength: 500,
|
|
65
|
+
allowRelative: true,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Centralized validation service with configurable validators
|
|
70
|
+
*/
|
|
71
|
+
export class ValidationService {
|
|
72
|
+
/**
|
|
73
|
+
* Validate a string value with configurable rules
|
|
74
|
+
*/
|
|
75
|
+
static validateString(value, config) {
|
|
76
|
+
// Required check
|
|
77
|
+
if (config.required && (!value || typeof value !== 'string')) {
|
|
78
|
+
throw new ValidationError(config.customErrorMessage ?? `${config.name} is required`);
|
|
79
|
+
}
|
|
80
|
+
if (!value) {
|
|
81
|
+
return '';
|
|
82
|
+
}
|
|
83
|
+
// Length validation
|
|
84
|
+
if (config.maxLength && value.length > config.maxLength) {
|
|
85
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
86
|
+
`${config.name} must be ${config.maxLength} characters or less`);
|
|
87
|
+
}
|
|
88
|
+
if (config.minLength && value.length < config.minLength) {
|
|
89
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
90
|
+
`${config.name} must be at least ${config.minLength} characters`);
|
|
91
|
+
}
|
|
92
|
+
// Pattern validation
|
|
93
|
+
if (config.pattern && !config.pattern.test(value)) {
|
|
94
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
95
|
+
`${config.name} can only contain letters, numbers, dots, underscores, and hyphens`);
|
|
96
|
+
}
|
|
97
|
+
// Prefix validation
|
|
98
|
+
if (config.disallowedPrefixes) {
|
|
99
|
+
for (const prefix of config.disallowedPrefixes) {
|
|
100
|
+
if (value.startsWith(prefix)) {
|
|
101
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
102
|
+
`${config.name} cannot start with "${prefix}"`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return value.trim();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Validate a numeric value with configurable rules
|
|
110
|
+
*/
|
|
111
|
+
static validateNumber(value, config) {
|
|
112
|
+
// Required check
|
|
113
|
+
if (config.required &&
|
|
114
|
+
(value === undefined || value === null || value === '')) {
|
|
115
|
+
throw new ValidationError(config.customErrorMessage ?? `${config.name} is required`);
|
|
116
|
+
}
|
|
117
|
+
const numValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
118
|
+
if (isNaN(numValue)) {
|
|
119
|
+
throw new ValidationError(config.customErrorMessage ?? `${config.name} must be a valid number`);
|
|
120
|
+
}
|
|
121
|
+
// Integer check
|
|
122
|
+
if (config.integer && !Number.isInteger(numValue)) {
|
|
123
|
+
throw new ValidationError(config.customErrorMessage ?? `${config.name} must be an integer`);
|
|
124
|
+
}
|
|
125
|
+
// Range validation
|
|
126
|
+
if (config.min !== undefined && numValue < config.min) {
|
|
127
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
128
|
+
`${config.name} must be at least ${config.min}`);
|
|
129
|
+
}
|
|
130
|
+
if (config.max !== undefined && numValue > config.max) {
|
|
131
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
132
|
+
`${config.name} must be at most ${config.max}`);
|
|
133
|
+
}
|
|
134
|
+
return numValue;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Validate a path with configurable rules
|
|
138
|
+
*/
|
|
139
|
+
static validatePath(value, config) {
|
|
140
|
+
if (!value || typeof value !== 'string') {
|
|
141
|
+
throw new ValidationError(config.customErrorMessage ?? `${config.name} is required`);
|
|
142
|
+
}
|
|
143
|
+
// Length validation
|
|
144
|
+
if (config.maxLength && value.length > config.maxLength) {
|
|
145
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
146
|
+
`${config.name} must be ${config.maxLength} characters or less`);
|
|
147
|
+
}
|
|
148
|
+
// Extension validation
|
|
149
|
+
if (config.allowedExtensions && config.allowedExtensions.length > 0) {
|
|
150
|
+
const hasValidExtension = config.allowedExtensions.some((ext) => value.endsWith(ext));
|
|
151
|
+
if (!hasValidExtension) {
|
|
152
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
153
|
+
`${config.name} must have one of these extensions: ${config.allowedExtensions.join(', ')}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Shell metacharacter check for security
|
|
157
|
+
if (ValidationPatterns.SHELL_DANGEROUS.test(value)) {
|
|
158
|
+
throw new ValidationError(config.customErrorMessage ??
|
|
159
|
+
`${config.name} contains dangerous characters that could be used for shell injection`);
|
|
160
|
+
}
|
|
161
|
+
return value.trim();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Convenience methods using predefined configurations
|
|
165
|
+
*/
|
|
166
|
+
static validateProjectName(value) {
|
|
167
|
+
return this.validateString(value, ValidationConfigs.PROJECT_NAME);
|
|
168
|
+
}
|
|
169
|
+
static validateServiceName(value) {
|
|
170
|
+
return this.validateString(value, ValidationConfigs.SERVICE_NAME);
|
|
171
|
+
}
|
|
172
|
+
static validateBranchName(value) {
|
|
173
|
+
return this.validateString(value, ValidationConfigs.BRANCH_NAME);
|
|
174
|
+
}
|
|
175
|
+
static validatePort(value) {
|
|
176
|
+
return this.validateNumber(value, ValidationConfigs.PORT_NUMBER);
|
|
177
|
+
}
|
|
178
|
+
static validateTemplatePath(value) {
|
|
179
|
+
return this.validatePath(value, ValidationConfigs.TEMPLATE_PATH);
|
|
180
|
+
}
|
|
181
|
+
static validateWorktreePath(value) {
|
|
182
|
+
return this.validatePath(value, ValidationConfigs.WORKTREE_PATH);
|
|
183
|
+
}
|
|
184
|
+
static validateOutputPath(value) {
|
|
185
|
+
return this.validatePath(value, ValidationConfigs.OUTPUT_PATH);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Validate service type against allowed types
|
|
189
|
+
*/
|
|
190
|
+
static validateServiceType(type) {
|
|
191
|
+
if (!type || typeof type !== 'string') {
|
|
192
|
+
throw new ValidationError('Service type is required');
|
|
193
|
+
}
|
|
194
|
+
const validTypes = ['postgres', 'mysql', 'redis', 'api', 'app', 'custom'];
|
|
195
|
+
const normalizedType = type.toLowerCase().trim();
|
|
196
|
+
if (!validTypes.includes(normalizedType)) {
|
|
197
|
+
throw new ValidationError(`Invalid service type. Must be one of: ${validTypes.join(', ')}`);
|
|
198
|
+
}
|
|
199
|
+
return normalizedType;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Validate script file path for post-hooks and similar
|
|
203
|
+
*/
|
|
204
|
+
static validateScriptPath(path) {
|
|
205
|
+
// Uses the same validation logic as template paths but with script-specific extensions
|
|
206
|
+
return this.validatePath(path, {
|
|
207
|
+
name: 'script path',
|
|
208
|
+
maxLength: 200,
|
|
209
|
+
mustExist: true,
|
|
210
|
+
allowRelative: true,
|
|
211
|
+
allowedExtensions: [
|
|
212
|
+
'.sh',
|
|
213
|
+
'.bash',
|
|
214
|
+
'.zsh',
|
|
215
|
+
'.js',
|
|
216
|
+
'.mjs',
|
|
217
|
+
'.ts',
|
|
218
|
+
'.py',
|
|
219
|
+
'.rb',
|
|
220
|
+
],
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Validate an array of service definitions in "service" or "service:type" format
|
|
225
|
+
*/
|
|
226
|
+
static validateServices(services) {
|
|
227
|
+
if (!Array.isArray(services)) {
|
|
228
|
+
throw new ValidationError('Services must be an array');
|
|
229
|
+
}
|
|
230
|
+
return services.map((serviceStr, index) => {
|
|
231
|
+
if (!serviceStr || typeof serviceStr !== 'string') {
|
|
232
|
+
throw new ValidationError(`Service at index ${index} is invalid`);
|
|
233
|
+
}
|
|
234
|
+
const trimmed = serviceStr.trim();
|
|
235
|
+
const parts = trimmed.split(':');
|
|
236
|
+
if (parts.length === 1) {
|
|
237
|
+
// Format: service (use same name for type)
|
|
238
|
+
const service = this.validateServiceName(parts[0]);
|
|
239
|
+
const type = this.validateServiceType(parts[0]);
|
|
240
|
+
return { service, type };
|
|
241
|
+
}
|
|
242
|
+
else if (parts.length === 2) {
|
|
243
|
+
// Format: service:type
|
|
244
|
+
const service = this.validateServiceName(parts[0]);
|
|
245
|
+
const type = this.validateServiceType(parts[1]);
|
|
246
|
+
return { service, type };
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
throw new ValidationError(`Invalid service format at index ${index}. Use 'service' or 'service:type'`);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Sanitize string for safe display/logging, removing dangerous characters
|
|
255
|
+
*/
|
|
256
|
+
static sanitizeForDisplay(input, maxLength = 100) {
|
|
257
|
+
if (!input || typeof input !== 'string') {
|
|
258
|
+
return '';
|
|
259
|
+
}
|
|
260
|
+
// Remove control characters and limit length
|
|
261
|
+
return (input
|
|
262
|
+
// eslint-disable-next-line no-control-regex
|
|
263
|
+
.replace(/[\x00-\x1F\x7F]/g, '') // Remove control characters
|
|
264
|
+
.substring(0, maxLength));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=validation-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-service.js","sourceRoot":"","sources":["../../src/services/validation-service.ts"],"names":[],"mappings":"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"}
|
package/dist/setup.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure setup operations with input validation and safe command execution
|
|
3
|
+
*/
|
|
4
|
+
export interface SetupOptions {
|
|
5
|
+
template?: string;
|
|
6
|
+
services?: string[];
|
|
7
|
+
force?: boolean;
|
|
8
|
+
skipRender?: boolean;
|
|
9
|
+
postHook?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SetupResult {
|
|
12
|
+
projectName: string;
|
|
13
|
+
allocatedPorts: Record<string, number>;
|
|
14
|
+
renderedFiles: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Secure version of setupCurrentDirectory with input validation and safe execution
|
|
18
|
+
*/
|
|
19
|
+
export declare function setupCurrentDirectory(options?: SetupOptions): Promise<SetupResult>;
|
|
20
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CAmKtB"}
|
package/dist/setup.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure setup operations with input validation and safe command execution
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, statSync } from 'fs';
|
|
5
|
+
import { basename, join } from 'path';
|
|
6
|
+
import { glob } from 'glob';
|
|
7
|
+
import { allocatePort, getOrAllocatePort } from './port-manager.js';
|
|
8
|
+
import { detectServicesFromTemplate, extractProjectNameFromTemplate, makeUrlSafe, processTemplate, } from './render.js';
|
|
9
|
+
import { safeScriptExecution } from './execution.js';
|
|
10
|
+
import { validateServices, validateTemplatePath, validateScriptPath, } from './validation.js';
|
|
11
|
+
/**
|
|
12
|
+
* Secure version of setupCurrentDirectory with input validation and safe execution
|
|
13
|
+
*/
|
|
14
|
+
export async function setupCurrentDirectory(options = {}) {
|
|
15
|
+
// Safety check: ensure we're in a main clone, not a worktree
|
|
16
|
+
if (!isMainClone()) {
|
|
17
|
+
throw new Error('Setup can only be run in the main repository clone. ' +
|
|
18
|
+
'Use "devports worktree add" to create worktrees with port allocation.');
|
|
19
|
+
}
|
|
20
|
+
// Validate all inputs first (but don't check template existence yet - handled later)
|
|
21
|
+
const validatedTemplate = options.template;
|
|
22
|
+
const validatedPostHook = options.postHook
|
|
23
|
+
? validateScriptPath(options.postHook)
|
|
24
|
+
: undefined;
|
|
25
|
+
let validatedServices;
|
|
26
|
+
if (options.services) {
|
|
27
|
+
const validatedServiceList = validateServices(options.services);
|
|
28
|
+
validatedServices = validatedServiceList.map((s) => `${s.service}:${s.type}`);
|
|
29
|
+
}
|
|
30
|
+
const currentDir = process.cwd();
|
|
31
|
+
const envPath = join(currentDir, '.env');
|
|
32
|
+
const backupPath = join(currentDir, '.env.backup');
|
|
33
|
+
// Check if .env already exists
|
|
34
|
+
if (existsSync(envPath) && !options.force) {
|
|
35
|
+
throw new Error('.env file already exists. Use --force to overwrite (this will create .env.backup).');
|
|
36
|
+
}
|
|
37
|
+
// Backup existing .env if using --force
|
|
38
|
+
if (existsSync(envPath) && options.force) {
|
|
39
|
+
writeFileSync(backupPath, readFileSync(envPath, 'utf-8'));
|
|
40
|
+
console.log(`📋 Backed up existing .env to .env.backup`);
|
|
41
|
+
}
|
|
42
|
+
// Determine template and extract project info
|
|
43
|
+
const templatePath = validatedTemplate
|
|
44
|
+
? validatedTemplate.startsWith('/')
|
|
45
|
+
? validatedTemplate
|
|
46
|
+
: join(currentDir, validatedTemplate)
|
|
47
|
+
: join(currentDir, '.env.devports');
|
|
48
|
+
let templateContent = null;
|
|
49
|
+
let projectName = null;
|
|
50
|
+
let services;
|
|
51
|
+
if (existsSync(templatePath)) {
|
|
52
|
+
// Validate template path if it exists
|
|
53
|
+
if (validatedTemplate) {
|
|
54
|
+
validateTemplatePath(templatePath);
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
templateContent = readFileSync(templatePath, 'utf-8');
|
|
58
|
+
services =
|
|
59
|
+
validatedServices ??
|
|
60
|
+
detectServicesFromTemplate(templateContent, templatePath);
|
|
61
|
+
// If no services detected from template, fall back to default
|
|
62
|
+
if (!validatedServices && services.length === 0) {
|
|
63
|
+
services = detectServicesFromEnv();
|
|
64
|
+
}
|
|
65
|
+
projectName = extractProjectNameFromTemplate(templateContent);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
console.warn(`⚠️ Could not read template ${templatePath}, falling back to detection`);
|
|
69
|
+
services = validatedServices ?? detectServicesFromEnv();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else if (validatedServices) {
|
|
73
|
+
services = validatedServices;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
services = detectServicesFromEnv();
|
|
77
|
+
}
|
|
78
|
+
// Use project name from template or directory name
|
|
79
|
+
const finalProjectName = projectName ?? basename(process.cwd());
|
|
80
|
+
const urlSafeProjectName = makeUrlSafe(finalProjectName);
|
|
81
|
+
console.log(`✅ Setting up ${finalProjectName}...`);
|
|
82
|
+
if (services.length > 0) {
|
|
83
|
+
console.log(`📍 Detected services: ${services.map((s) => s.split(':')[0]).join(', ')}`);
|
|
84
|
+
}
|
|
85
|
+
// Allocate ports for each service
|
|
86
|
+
const allocatedPorts = {};
|
|
87
|
+
const serviceTypes = {};
|
|
88
|
+
for (const service of services) {
|
|
89
|
+
const [serviceName, serviceType] = service.split(':');
|
|
90
|
+
const port = options.force
|
|
91
|
+
? await getOrAllocatePort(urlSafeProjectName, serviceName, serviceType)
|
|
92
|
+
: await allocatePort(urlSafeProjectName, serviceName, serviceType);
|
|
93
|
+
allocatedPorts[serviceName] = port;
|
|
94
|
+
serviceTypes[serviceName] = serviceType;
|
|
95
|
+
}
|
|
96
|
+
if (Object.keys(allocatedPorts).length > 0) {
|
|
97
|
+
console.log('🔌 Allocated ports:');
|
|
98
|
+
for (const [service, port] of Object.entries(allocatedPorts)) {
|
|
99
|
+
const type = serviceTypes[service];
|
|
100
|
+
console.log(` ${service}: ${port} (${type})`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Generate .env file
|
|
104
|
+
if (templateContent) {
|
|
105
|
+
const processedContent = processTemplate(templateContent, allocatedPorts, urlSafeProjectName, templatePath);
|
|
106
|
+
writeFileSync(envPath, processedContent);
|
|
107
|
+
console.log(`📝 Generated .env from ${basename(templatePath)}`);
|
|
108
|
+
}
|
|
109
|
+
else if (Object.keys(allocatedPorts).length > 0) {
|
|
110
|
+
// Create basic .env with just port variables
|
|
111
|
+
const envContent = `${[
|
|
112
|
+
'# Generated by devports setup',
|
|
113
|
+
`DEVPORTS_PROJECT_NAME=${finalProjectName}`,
|
|
114
|
+
'',
|
|
115
|
+
...Object.entries(allocatedPorts).map(([serviceName, port]) => `${serviceName.toUpperCase()}_PORT=${port}`),
|
|
116
|
+
].join('\n')}\n`;
|
|
117
|
+
writeFileSync(envPath, envContent);
|
|
118
|
+
console.log('📝 Generated basic .env with allocated ports');
|
|
119
|
+
}
|
|
120
|
+
// Auto-render *.devports files
|
|
121
|
+
const renderedFiles = [];
|
|
122
|
+
if (!options.skipRender) {
|
|
123
|
+
const rendered = await autoRenderDevportsFiles(process.cwd(), allocatedPorts, urlSafeProjectName);
|
|
124
|
+
renderedFiles.push(...rendered);
|
|
125
|
+
}
|
|
126
|
+
// Run post-hook if available
|
|
127
|
+
if (validatedPostHook || existsSync('.devports/hooks/post-setup')) {
|
|
128
|
+
await runPostHook(process.cwd(), allocatedPorts, urlSafeProjectName, validatedPostHook);
|
|
129
|
+
}
|
|
130
|
+
console.log('✅ Setup complete!');
|
|
131
|
+
return {
|
|
132
|
+
projectName: finalProjectName,
|
|
133
|
+
allocatedPorts,
|
|
134
|
+
renderedFiles,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Check if we're in the main clone (not a worktree)
|
|
139
|
+
*/
|
|
140
|
+
function isMainClone() {
|
|
141
|
+
try {
|
|
142
|
+
// In main clone, .git is a directory
|
|
143
|
+
// In worktree, .git is a file containing path to main .git
|
|
144
|
+
const gitPath = join(process.cwd(), '.git');
|
|
145
|
+
return existsSync(gitPath) && statSync(gitPath).isDirectory();
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Detect services from existing .env file in current directory
|
|
153
|
+
*/
|
|
154
|
+
function detectServicesFromEnv() {
|
|
155
|
+
const services = [];
|
|
156
|
+
const envPath = join(process.cwd(), '.env');
|
|
157
|
+
if (existsSync(envPath)) {
|
|
158
|
+
const envContent = readFileSync(envPath, 'utf-8');
|
|
159
|
+
const portPatterns = [
|
|
160
|
+
{ regex: /DATABASE_PORT|POSTGRES_PORT/i, service: 'postgres:postgres' },
|
|
161
|
+
{ regex: /MYSQL_PORT/i, service: 'mysql:mysql' },
|
|
162
|
+
{ regex: /REDIS_PORT/i, service: 'redis:redis' },
|
|
163
|
+
{ regex: /API_PORT/i, service: 'api:api' },
|
|
164
|
+
{ regex: /APP_PORT|WEB_PORT/i, service: 'app:app' },
|
|
165
|
+
];
|
|
166
|
+
for (const pattern of portPatterns) {
|
|
167
|
+
if (pattern.regex.test(envContent) &&
|
|
168
|
+
!services.includes(pattern.service)) {
|
|
169
|
+
services.push(pattern.service);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Default to postgres if nothing detected
|
|
174
|
+
if (services.length === 0) {
|
|
175
|
+
services.push('postgres:postgres');
|
|
176
|
+
}
|
|
177
|
+
return services;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Auto-render any *.devports files found in the current directory
|
|
181
|
+
*/
|
|
182
|
+
async function autoRenderDevportsFiles(currentPath, allocatedPorts, projectName) {
|
|
183
|
+
try {
|
|
184
|
+
const devportsFiles = await glob('**/*.devports', {
|
|
185
|
+
cwd: currentPath,
|
|
186
|
+
ignore: ['node_modules/**', '.git/**'],
|
|
187
|
+
});
|
|
188
|
+
if (devportsFiles.length === 0) {
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
console.log(`🔄 Auto-rendering ${devportsFiles.length} *.devports files...`);
|
|
192
|
+
const renderedFiles = [];
|
|
193
|
+
for (const devportsFile of devportsFiles) {
|
|
194
|
+
const fullDevportsPath = join(currentPath, devportsFile);
|
|
195
|
+
const outputPath = join(currentPath, devportsFile.replace(/\.devports$/, ''));
|
|
196
|
+
try {
|
|
197
|
+
const templateContent = readFileSync(fullDevportsPath, 'utf-8');
|
|
198
|
+
const processedContent = processTemplate(templateContent, allocatedPorts, projectName, devportsFile);
|
|
199
|
+
writeFileSync(outputPath, processedContent);
|
|
200
|
+
const outputFileName = devportsFile.replace(/\.devports$/, '');
|
|
201
|
+
console.log(` ${outputFileName} (from ${devportsFile})`);
|
|
202
|
+
renderedFiles.push(outputFileName);
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
console.warn(`⚠️ Failed to render ${devportsFile}: ${error.message}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return renderedFiles;
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.warn(`⚠️ Error during auto-rendering: ${error.message}`);
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Run post-setup hook if available (secure version)
|
|
217
|
+
*/
|
|
218
|
+
async function runPostHook(currentPath, allocatedPorts, projectName, customHook) {
|
|
219
|
+
const hookScript = customHook ?? '.devports/hooks/post-setup';
|
|
220
|
+
if (!existsSync(hookScript)) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
console.log('🔗 Running post-setup hook...');
|
|
225
|
+
// Prepare environment variables
|
|
226
|
+
const hookEnv = {
|
|
227
|
+
DEVPORTS_PROJECT_NAME: projectName,
|
|
228
|
+
DEVPORTS_SETUP_PATH: currentPath,
|
|
229
|
+
};
|
|
230
|
+
// Add all port variables
|
|
231
|
+
for (const [service, port] of Object.entries(allocatedPorts)) {
|
|
232
|
+
const varName = `${service.toUpperCase().replace(/-/g, '_')}_PORT`;
|
|
233
|
+
hookEnv[varName] = port.toString();
|
|
234
|
+
}
|
|
235
|
+
// Execute hook script safely
|
|
236
|
+
await safeScriptExecution(hookScript, hookEnv, {
|
|
237
|
+
cwd: currentPath,
|
|
238
|
+
});
|
|
239
|
+
console.log('✅ Post-setup hook completed');
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
console.warn(`⚠️ Post-setup hook failed: ${error.message}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface PortRange {
|
|
2
|
+
start: number;
|
|
3
|
+
end: number;
|
|
4
|
+
}
|
|
5
|
+
export interface Config {
|
|
6
|
+
ranges: Record<string, PortRange>;
|
|
7
|
+
registryPath: string;
|
|
8
|
+
}
|
|
9
|
+
export interface PortAllocation {
|
|
10
|
+
port: number;
|
|
11
|
+
project: string;
|
|
12
|
+
service: string;
|
|
13
|
+
type: string;
|
|
14
|
+
allocatedAt: string;
|
|
15
|
+
note?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface Registry {
|
|
18
|
+
allocations: PortAllocation[];
|
|
19
|
+
reservations: {
|
|
20
|
+
port: number;
|
|
21
|
+
reason: string;
|
|
22
|
+
reservedAt: string;
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
export declare const VALID_PORT_TYPES: readonly ["postgres", "mysql", "redis", "api", "app", "custom"];
|
|
26
|
+
export type PortType = (typeof VALID_PORT_TYPES)[number];
|
|
27
|
+
export declare function isValidPortType(type: string): type is PortType;
|
|
28
|
+
export declare function getValidPortTypes(): string;
|
|
29
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,YAAY,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CAAC;CACL;AAGD,eAAO,MAAM,gBAAgB,iEAOnB,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAGzD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,QAAQ,CAE9D;AAGD,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Valid port types - exported for validation
|
|
2
|
+
export const VALID_PORT_TYPES = [
|
|
3
|
+
'postgres',
|
|
4
|
+
'mysql',
|
|
5
|
+
'redis',
|
|
6
|
+
'api',
|
|
7
|
+
'app',
|
|
8
|
+
'custom',
|
|
9
|
+
];
|
|
10
|
+
// Helper to validate port type
|
|
11
|
+
export function isValidPortType(type) {
|
|
12
|
+
return VALID_PORT_TYPES.includes(type);
|
|
13
|
+
}
|
|
14
|
+
// Helper to get valid types as string
|
|
15
|
+
export function getValidPortTypes() {
|
|
16
|
+
return VALID_PORT_TYPES.join(', ');
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA4BA,6CAA6C;AAC7C,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU;IACV,OAAO;IACP,OAAO;IACP,KAAK;IACL,KAAK;IACL,QAAQ;CACA,CAAC;AAIX,+BAA+B;AAC/B,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,gBAAgB,CAAC,QAAQ,CAAC,IAAgB,CAAC,CAAC;AACrD,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,iBAAiB;IAC/B,OAAO,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC"}
|