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,164 @@
|
|
|
1
|
+
#!/bin/zsh
|
|
2
|
+
#compdef devports
|
|
3
|
+
|
|
4
|
+
_devports() {
|
|
5
|
+
local curcontext="$curcontext" state line
|
|
6
|
+
typeset -A opt_args
|
|
7
|
+
|
|
8
|
+
local cmd=$words[2]
|
|
9
|
+
local subcmd=$words[3]
|
|
10
|
+
|
|
11
|
+
# Handle first argument (command)
|
|
12
|
+
if [[ $CURRENT -eq 2 ]]; then
|
|
13
|
+
compadd allocate release list status check reserve unreserve info render gitignore setup worktree completion
|
|
14
|
+
return 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Handle arguments for specific commands
|
|
18
|
+
case $cmd in
|
|
19
|
+
allocate)
|
|
20
|
+
_arguments \
|
|
21
|
+
'1:project name:($(devports allocate --completion projects 2>/dev/null))' \
|
|
22
|
+
'2:service name:' \
|
|
23
|
+
'(-t --type)'{-t,--type}'[Service type]:type:($(devports allocate --completion types 2>/dev/null | tr '\''\n'\'' '\'' '\''))' \
|
|
24
|
+
'(-q --quiet)'{-q,--quiet}'[Only output the port number]' \
|
|
25
|
+
'--json[Output result as JSON]'
|
|
26
|
+
;;
|
|
27
|
+
release)
|
|
28
|
+
# Skip completion if --port flag is used
|
|
29
|
+
if [[ ${words[*]} =~ "--port" ]] || [[ ${words[*]} =~ " -p " ]]; then
|
|
30
|
+
_arguments \
|
|
31
|
+
'(-a --all)'{-a,--all}'[Release all ports for the project]' \
|
|
32
|
+
'(-p --port)'{-p,--port}'[Release port by number]' \
|
|
33
|
+
'(-q --quiet)'{-q,--quiet}'[Only output the result]' \
|
|
34
|
+
'--json[Output result as JSON]'
|
|
35
|
+
return 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
if [[ $CURRENT -eq 3 ]]; then
|
|
39
|
+
# First argument: project name
|
|
40
|
+
local projects=($(devports release --completion projects 2>/dev/null))
|
|
41
|
+
compadd -a projects
|
|
42
|
+
return 0
|
|
43
|
+
elif [[ $CURRENT -eq 4 ]]; then
|
|
44
|
+
# Second argument: service name for the specific project
|
|
45
|
+
local project=$words[3]
|
|
46
|
+
local services=($(devports release --completion services --project "$project" 2>/dev/null))
|
|
47
|
+
compadd -a services
|
|
48
|
+
return 0
|
|
49
|
+
fi
|
|
50
|
+
_arguments \
|
|
51
|
+
'(-a --all)'{-a,--all}'[Release all ports for the project]' \
|
|
52
|
+
'(-p --port)'{-p,--port}'[Release port by number]' \
|
|
53
|
+
'(-q --quiet)'{-q,--quiet}'[Only output the result]' \
|
|
54
|
+
'--json[Output result as JSON]'
|
|
55
|
+
;;
|
|
56
|
+
list)
|
|
57
|
+
_arguments \
|
|
58
|
+
'(-p --project)'{-p,--project}'[Filter by project]:project:($(devports list --completion projects 2>/dev/null | tr '\''\n'\'' '\'' '\''))' \
|
|
59
|
+
'(-t --type)'{-t,--type}'[Filter by service type]:type:($(devports list --completion types 2>/dev/null | tr '\''\n'\'' '\'' '\''))' \
|
|
60
|
+
'(-q --quiet)'{-q,--quiet}'[Only output port numbers]' \
|
|
61
|
+
'--json[Output result as JSON]'
|
|
62
|
+
;;
|
|
63
|
+
status)
|
|
64
|
+
_arguments \
|
|
65
|
+
'--json[Output result as JSON]'
|
|
66
|
+
;;
|
|
67
|
+
check)
|
|
68
|
+
_arguments \
|
|
69
|
+
'1:port number: ' \
|
|
70
|
+
'(-q --quiet)'{-q,--quiet}'[Only output the result]' \
|
|
71
|
+
'--json[Output result as JSON]'
|
|
72
|
+
;;
|
|
73
|
+
reserve)
|
|
74
|
+
_arguments \
|
|
75
|
+
'1:port number: ' \
|
|
76
|
+
'2:reason: ' \
|
|
77
|
+
'(-q --quiet)'{-q,--quiet}'[Only output the result]' \
|
|
78
|
+
'--json[Output result as JSON]'
|
|
79
|
+
;;
|
|
80
|
+
unreserve)
|
|
81
|
+
_arguments \
|
|
82
|
+
'1:port number: ' \
|
|
83
|
+
'(-q --quiet)'{-q,--quiet}'[Only output the result]' \
|
|
84
|
+
'--json[Output result as JSON]'
|
|
85
|
+
;;
|
|
86
|
+
info)
|
|
87
|
+
if [[ $CURRENT -eq 3 ]]; then
|
|
88
|
+
# Complete project names
|
|
89
|
+
local projects=($(devports list --completion projects 2>/dev/null))
|
|
90
|
+
compadd -a projects
|
|
91
|
+
elif [[ $CURRENT -eq 4 ]]; then
|
|
92
|
+
# Complete service names for the project
|
|
93
|
+
local project=$words[3]
|
|
94
|
+
local services=($(devports list --project "$project" --completion services 2>/dev/null))
|
|
95
|
+
compadd -a services
|
|
96
|
+
fi
|
|
97
|
+
_arguments \
|
|
98
|
+
'--json[Output result as JSON]'
|
|
99
|
+
;;
|
|
100
|
+
render)
|
|
101
|
+
# Complete .devports files
|
|
102
|
+
_arguments \
|
|
103
|
+
'1:template file:_files -g "*.devports"' \
|
|
104
|
+
'(-p --project)'{-p,--project}'[Project name]: ' \
|
|
105
|
+
'(-o --output)'{-o,--output}'[Output file]:file:_files' \
|
|
106
|
+
'--json[Output result as JSON]'
|
|
107
|
+
;;
|
|
108
|
+
gitignore)
|
|
109
|
+
_arguments \
|
|
110
|
+
'(-c --clean)'{-c,--clean}'[Remove devports entries from .gitignore]' \
|
|
111
|
+
'(-p --preview)'{-p,--preview}'[Preview changes without modifying files]' \
|
|
112
|
+
'--json[Output result as JSON]'
|
|
113
|
+
;;
|
|
114
|
+
setup)
|
|
115
|
+
_arguments \
|
|
116
|
+
'(-t --template)'{-t,--template}'[Template file]:template:_files -g "*.devports"' \
|
|
117
|
+
'(-s --services)'{-s,--services}'[Services to set up (comma-separated)]: ' \
|
|
118
|
+
'(-f --force)'{-f,--force}'[Overwrite existing files]' \
|
|
119
|
+
'--skip-render[Skip auto-rendering *.devports files]' \
|
|
120
|
+
'(-h --post-hook)'{-h,--post-hook}'[Script to run after setup]:script:_files' \
|
|
121
|
+
'--json[Output result as JSON]'
|
|
122
|
+
;;
|
|
123
|
+
worktree)
|
|
124
|
+
if [[ $CURRENT -eq 3 ]]; then
|
|
125
|
+
_values 'worktree command' \
|
|
126
|
+
'add:Create a git worktree' \
|
|
127
|
+
'remove:Remove a git worktree'
|
|
128
|
+
else
|
|
129
|
+
case $subcmd in
|
|
130
|
+
add)
|
|
131
|
+
_arguments \
|
|
132
|
+
'1:worktree path:_directories' \
|
|
133
|
+
'(-b --branch)'{-b,--branch}'[Branch name]: ' \
|
|
134
|
+
'(-s --services)'{-s,--services}'[Services to set up (comma-separated)]: ' \
|
|
135
|
+
'(-e --env-file)'{-e,--env-file}'[Custom .env file name]: ' \
|
|
136
|
+
'(-t --template)'{-t,--template}'[Template file]:template:_files -g "*.devports"' \
|
|
137
|
+
'(-h --post-hook)'{-h,--post-hook}'[Script to run after setup]:script:_files' \
|
|
138
|
+
'--no-env[Skip .env file creation]' \
|
|
139
|
+
'--json[Output result as JSON]'
|
|
140
|
+
;;
|
|
141
|
+
remove)
|
|
142
|
+
_arguments \
|
|
143
|
+
'1:worktree path:_directories' \
|
|
144
|
+
'(-f --force)'{-f,--force}'[Force removal even if directory has changes]' \
|
|
145
|
+
'--json[Output result as JSON]'
|
|
146
|
+
;;
|
|
147
|
+
esac
|
|
148
|
+
fi
|
|
149
|
+
;;
|
|
150
|
+
completion)
|
|
151
|
+
if [[ $CURRENT -eq 3 ]]; then
|
|
152
|
+
compadd bash zsh
|
|
153
|
+
else
|
|
154
|
+
_arguments \
|
|
155
|
+
'(-i --install)'{-i,--install}'[Install completion to shell configuration]' \
|
|
156
|
+
'(-u --uninstall)'{-u,--uninstall}'[Remove completion from shell configuration]' \
|
|
157
|
+
'(-c --check)'{-c,--check}'[Check if completion is installed]' \
|
|
158
|
+
'--json[Output result as JSON]'
|
|
159
|
+
fi
|
|
160
|
+
;;
|
|
161
|
+
esac
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
compdef _devports devports
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Config, Registry } from './types.js';
|
|
2
|
+
export declare function ensureConfigDir(): void;
|
|
3
|
+
export declare function loadConfig(): Config;
|
|
4
|
+
export declare function loadRegistry(): Registry;
|
|
5
|
+
export declare function saveRegistry(registry: Registry): void;
|
|
6
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAsCnD,wBAAgB,eAAe,IAAI,IAAI,CAWtC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAgCnC;AAED,wBAAgB,YAAY,IAAI,QAAQ,CAwCvC;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CASrD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
4
|
+
function getConfigDir() {
|
|
5
|
+
return (process.env.DEVPORTS_CONFIG_DIR ?? join(homedir(), '.config', 'devports'));
|
|
6
|
+
}
|
|
7
|
+
function getConfigFile() {
|
|
8
|
+
return join(getConfigDir(), 'config.json');
|
|
9
|
+
}
|
|
10
|
+
function getRegistryFile() {
|
|
11
|
+
return join(getConfigDir(), 'ports.json');
|
|
12
|
+
}
|
|
13
|
+
const DEFAULT_CONFIG = {
|
|
14
|
+
ranges: {
|
|
15
|
+
postgres: { start: 5434, end: 5499 },
|
|
16
|
+
mysql: { start: 3308, end: 3399 },
|
|
17
|
+
redis: { start: 6381, end: 6399 },
|
|
18
|
+
api: { start: 3002, end: 3099 },
|
|
19
|
+
app: { start: 5002, end: 5999 },
|
|
20
|
+
custom: { start: 8002, end: 8999 },
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
const DEFAULT_REGISTRY = {
|
|
24
|
+
allocations: [],
|
|
25
|
+
reservations: [
|
|
26
|
+
{
|
|
27
|
+
port: 8080,
|
|
28
|
+
reason: 'Common development server port',
|
|
29
|
+
reservedAt: new Date().toISOString(),
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
export function ensureConfigDir() {
|
|
34
|
+
const configDir = getConfigDir();
|
|
35
|
+
if (!existsSync(configDir)) {
|
|
36
|
+
try {
|
|
37
|
+
mkdirSync(configDir, { recursive: true });
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
throw new Error(`Failed to create config directory at ${configDir}: ${error.message}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function loadConfig() {
|
|
45
|
+
ensureConfigDir();
|
|
46
|
+
const configFile = getConfigFile();
|
|
47
|
+
if (!existsSync(configFile)) {
|
|
48
|
+
try {
|
|
49
|
+
const defaultConfig = {
|
|
50
|
+
...DEFAULT_CONFIG,
|
|
51
|
+
registryPath: getRegistryFile(),
|
|
52
|
+
};
|
|
53
|
+
writeFileSync(configFile, JSON.stringify(defaultConfig, null, 2));
|
|
54
|
+
return defaultConfig;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw new Error(`Failed to create config file at ${configFile}: ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const content = readFileSync(configFile, 'utf-8');
|
|
62
|
+
return JSON.parse(content);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (error instanceof SyntaxError) {
|
|
66
|
+
throw new Error(`Config file ${configFile} contains invalid JSON: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
throw new Error(`Failed to read config file ${configFile}: ${error.message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function loadRegistry() {
|
|
72
|
+
const config = loadConfig();
|
|
73
|
+
const registryPath = config.registryPath;
|
|
74
|
+
if (!existsSync(registryPath)) {
|
|
75
|
+
try {
|
|
76
|
+
writeFileSync(registryPath, JSON.stringify(DEFAULT_REGISTRY, null, 2));
|
|
77
|
+
return DEFAULT_REGISTRY;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
throw new Error(`Failed to create registry file at ${registryPath}: ${error.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const content = readFileSync(registryPath, 'utf-8');
|
|
85
|
+
const registry = JSON.parse(content);
|
|
86
|
+
// Validate registry structure
|
|
87
|
+
if (!registry.allocations || !Array.isArray(registry.allocations)) {
|
|
88
|
+
throw new Error('Registry file is corrupted: missing or invalid allocations array');
|
|
89
|
+
}
|
|
90
|
+
if (!registry.reservations || !Array.isArray(registry.reservations)) {
|
|
91
|
+
throw new Error('Registry file is corrupted: missing or invalid reservations array');
|
|
92
|
+
}
|
|
93
|
+
return registry;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (error instanceof SyntaxError) {
|
|
97
|
+
throw new Error(`Registry file ${registryPath} contains invalid JSON: ${error.message}`);
|
|
98
|
+
}
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export function saveRegistry(registry) {
|
|
103
|
+
const config = loadConfig();
|
|
104
|
+
try {
|
|
105
|
+
writeFileSync(config.registryPath, JSON.stringify(registry, null, 2));
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
throw new Error(`Failed to save registry to ${config.registryPath}: ${error.message}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure command execution utilities
|
|
3
|
+
* Provides safe alternatives to execSync for command injection prevention
|
|
4
|
+
*/
|
|
5
|
+
import { SpawnOptions } from 'child_process';
|
|
6
|
+
/**
|
|
7
|
+
* Safe command execution using spawn with argument arrays
|
|
8
|
+
* Prevents shell injection by not using shell interpolation
|
|
9
|
+
*/
|
|
10
|
+
export declare function safeExec(command: string, args: string[], options?: SpawnOptions): Promise<{
|
|
11
|
+
stdout: string;
|
|
12
|
+
stderr: string;
|
|
13
|
+
exitCode: number;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Safe git worktree add command
|
|
17
|
+
*/
|
|
18
|
+
export declare function safeGitWorktreeAdd(path: string, branch: string, options?: SpawnOptions): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Safe git worktree remove command
|
|
21
|
+
*/
|
|
22
|
+
export declare function safeGitWorktreeRemove(path: string, force?: boolean, options?: SpawnOptions): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Safe script execution with controlled environment
|
|
25
|
+
*/
|
|
26
|
+
export declare function safeScriptExecution(scriptPath: string, env?: Record<string, string>, options?: SpawnOptions): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Validate that a file is safe to execute as a script
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateExecutableScript(scriptPath: string): void;
|
|
31
|
+
//# sourceMappingURL=execution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAS,YAAY,EAAE,MAAM,eAAe,CAAC;AAGpD;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAkC/D;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,OAAe,EACtB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAChC,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAkBjE"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure command execution utilities
|
|
3
|
+
* Provides safe alternatives to execSync for command injection prevention
|
|
4
|
+
*/
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
import { statSync } from 'fs';
|
|
7
|
+
/**
|
|
8
|
+
* Safe command execution using spawn with argument arrays
|
|
9
|
+
* Prevents shell injection by not using shell interpolation
|
|
10
|
+
*/
|
|
11
|
+
export async function safeExec(command, args, options = {}) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const child = spawn(command, args, {
|
|
14
|
+
...options,
|
|
15
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
16
|
+
});
|
|
17
|
+
let stdout = '';
|
|
18
|
+
let stderr = '';
|
|
19
|
+
if (child.stdout) {
|
|
20
|
+
child.stdout.on('data', (data) => {
|
|
21
|
+
stdout += data.toString();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (child.stderr) {
|
|
25
|
+
child.stderr.on('data', (data) => {
|
|
26
|
+
stderr += data.toString();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
child.on('close', (code) => {
|
|
30
|
+
resolve({
|
|
31
|
+
stdout: stdout.trim(),
|
|
32
|
+
stderr: stderr.trim(),
|
|
33
|
+
exitCode: code ?? 0,
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
child.on('error', (error) => {
|
|
37
|
+
reject(error);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Safe git worktree add command
|
|
43
|
+
*/
|
|
44
|
+
export async function safeGitWorktreeAdd(path, branch, options = {}) {
|
|
45
|
+
const result = await safeExec('git', ['worktree', 'add', path, '-b', branch], {
|
|
46
|
+
...options,
|
|
47
|
+
stdio: 'inherit',
|
|
48
|
+
});
|
|
49
|
+
if (result.exitCode !== 0) {
|
|
50
|
+
throw new Error(`Git worktree add failed: ${result.stderr || 'Unknown error'}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Safe git worktree remove command
|
|
55
|
+
*/
|
|
56
|
+
export async function safeGitWorktreeRemove(path, force = false, options = {}) {
|
|
57
|
+
const args = ['worktree', 'remove'];
|
|
58
|
+
if (force) {
|
|
59
|
+
args.push('--force');
|
|
60
|
+
}
|
|
61
|
+
args.push(path);
|
|
62
|
+
const result = await safeExec('git', args, {
|
|
63
|
+
...options,
|
|
64
|
+
stdio: 'inherit',
|
|
65
|
+
});
|
|
66
|
+
if (result.exitCode !== 0) {
|
|
67
|
+
throw new Error(`Git worktree remove failed: ${result.stderr || 'Unknown error'}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Safe script execution with controlled environment
|
|
72
|
+
*/
|
|
73
|
+
export async function safeScriptExecution(scriptPath, env = {}, options = {}) {
|
|
74
|
+
// First make the script executable
|
|
75
|
+
await safeExec('chmod', ['+x', scriptPath]);
|
|
76
|
+
// Then execute it with controlled environment
|
|
77
|
+
const result = await safeExec(scriptPath, [], {
|
|
78
|
+
...options,
|
|
79
|
+
env: {
|
|
80
|
+
...process.env,
|
|
81
|
+
...env,
|
|
82
|
+
},
|
|
83
|
+
stdio: 'inherit',
|
|
84
|
+
});
|
|
85
|
+
if (result.exitCode !== 0) {
|
|
86
|
+
throw new Error(`Script execution failed: ${result.stderr || 'Unknown error'}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validate that a file is safe to execute as a script
|
|
91
|
+
*/
|
|
92
|
+
export function validateExecutableScript(scriptPath) {
|
|
93
|
+
try {
|
|
94
|
+
const stats = statSync(scriptPath);
|
|
95
|
+
if (!stats.isFile()) {
|
|
96
|
+
throw new Error('Script path is not a file');
|
|
97
|
+
}
|
|
98
|
+
// Check if executable on Unix-like systems
|
|
99
|
+
if (process.platform !== 'win32') {
|
|
100
|
+
const mode = stats.mode;
|
|
101
|
+
if (!(mode & parseInt('0100', 8))) {
|
|
102
|
+
throw new Error('Script is not executable');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw new Error(`Script validation failed: ${error.message}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface GitignoreResult {
|
|
2
|
+
added: string[];
|
|
3
|
+
existing: string[];
|
|
4
|
+
devportsFiles: string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Find all *.devports files and add corresponding entries to .gitignore
|
|
8
|
+
*/
|
|
9
|
+
export declare function updateGitignore(options?: {
|
|
10
|
+
dryRun?: boolean;
|
|
11
|
+
}): Promise<GitignoreResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Remove devports-related entries from .gitignore
|
|
14
|
+
*/
|
|
15
|
+
export declare function cleanGitignore(options?: {
|
|
16
|
+
dryRun?: boolean;
|
|
17
|
+
}): Promise<GitignoreResult>;
|
|
18
|
+
/**
|
|
19
|
+
* List what would be added to .gitignore without making changes
|
|
20
|
+
*/
|
|
21
|
+
export declare function previewGitignore(): Promise<GitignoreResult>;
|
|
22
|
+
//# sourceMappingURL=gitignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../src/gitignore.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,eAAe,CAAC,CA6E1B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,eAAe,CAAC,CAkF1B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,eAAe,CAAC,CAEjE"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { glob } from 'glob';
|
|
3
|
+
/**
|
|
4
|
+
* Find all *.devports files and add corresponding entries to .gitignore
|
|
5
|
+
*/
|
|
6
|
+
export async function updateGitignore(options = {}) {
|
|
7
|
+
// Find all *.devports files
|
|
8
|
+
const devportsFiles = await glob('**/*.devports', {
|
|
9
|
+
ignore: ['node_modules/**', '.git/**'],
|
|
10
|
+
});
|
|
11
|
+
if (devportsFiles.length === 0) {
|
|
12
|
+
return {
|
|
13
|
+
added: [],
|
|
14
|
+
existing: [],
|
|
15
|
+
devportsFiles: [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
// Generate target filenames (remove .devports extension)
|
|
19
|
+
const targetFiles = devportsFiles.map((file) => file.replace(/\.devports$/, ''));
|
|
20
|
+
// Read existing .gitignore
|
|
21
|
+
const gitignorePath = '.gitignore';
|
|
22
|
+
let gitignoreContent = '';
|
|
23
|
+
const existingEntries = new Set();
|
|
24
|
+
if (existsSync(gitignorePath)) {
|
|
25
|
+
gitignoreContent = readFileSync(gitignorePath, 'utf-8');
|
|
26
|
+
// Parse existing entries (ignore comments and empty lines)
|
|
27
|
+
const lines = gitignoreContent
|
|
28
|
+
.split('\n')
|
|
29
|
+
.map((line) => line.trim())
|
|
30
|
+
.filter((line) => line && !line.startsWith('#'));
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
existingEntries.add(line);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Determine which entries to add
|
|
36
|
+
const toAdd = [];
|
|
37
|
+
const existing = [];
|
|
38
|
+
for (const targetFile of targetFiles) {
|
|
39
|
+
if (existingEntries.has(targetFile)) {
|
|
40
|
+
existing.push(targetFile);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
toAdd.push(targetFile);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Add new entries if not in dry-run mode
|
|
47
|
+
if (!options.dryRun && toAdd.length > 0) {
|
|
48
|
+
let newContent = gitignoreContent;
|
|
49
|
+
// Add header comment if this is the first devports entry
|
|
50
|
+
const hasDevportsComment = gitignoreContent.includes('# devports generated files');
|
|
51
|
+
if (!hasDevportsComment && toAdd.length > 0) {
|
|
52
|
+
if (newContent && !newContent.endsWith('\n')) {
|
|
53
|
+
newContent += '\n';
|
|
54
|
+
}
|
|
55
|
+
newContent += '\n# devports generated files\n';
|
|
56
|
+
}
|
|
57
|
+
// Add new entries
|
|
58
|
+
for (const file of toAdd) {
|
|
59
|
+
newContent += `${file}\n`;
|
|
60
|
+
}
|
|
61
|
+
writeFileSync(gitignorePath, newContent);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
added: toAdd,
|
|
65
|
+
existing,
|
|
66
|
+
devportsFiles,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Remove devports-related entries from .gitignore
|
|
71
|
+
*/
|
|
72
|
+
export async function cleanGitignore(options = {}) {
|
|
73
|
+
const gitignorePath = '.gitignore';
|
|
74
|
+
if (!existsSync(gitignorePath)) {
|
|
75
|
+
return {
|
|
76
|
+
added: [],
|
|
77
|
+
existing: [],
|
|
78
|
+
devportsFiles: [],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// Find all *.devports files to determine what should be in gitignore
|
|
82
|
+
const devportsFiles = await glob('**/*.devports', {
|
|
83
|
+
ignore: ['node_modules/**', '.git/**'],
|
|
84
|
+
});
|
|
85
|
+
const targetFiles = devportsFiles.map((file) => file.replace(/\.devports$/, ''));
|
|
86
|
+
// Read and parse .gitignore
|
|
87
|
+
const gitignoreContent = readFileSync(gitignorePath, 'utf-8');
|
|
88
|
+
const lines = gitignoreContent.split('\n');
|
|
89
|
+
const newLines = [];
|
|
90
|
+
const removed = [];
|
|
91
|
+
let inDevportsSection = false;
|
|
92
|
+
for (const line of lines) {
|
|
93
|
+
const trimmedLine = line.trim();
|
|
94
|
+
// Track if we're in the devports section
|
|
95
|
+
if (trimmedLine === '# devports generated files') {
|
|
96
|
+
inDevportsSection = true;
|
|
97
|
+
// Skip the header if no devports files exist
|
|
98
|
+
if (devportsFiles.length > 0) {
|
|
99
|
+
newLines.push(line);
|
|
100
|
+
}
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// If we hit a new section comment or end of devports entries
|
|
104
|
+
if (inDevportsSection &&
|
|
105
|
+
trimmedLine.startsWith('#') &&
|
|
106
|
+
trimmedLine !== '# devports generated files') {
|
|
107
|
+
inDevportsSection = false;
|
|
108
|
+
}
|
|
109
|
+
// Remove entries that correspond to existing .devports files
|
|
110
|
+
if (inDevportsSection && trimmedLine && !trimmedLine.startsWith('#')) {
|
|
111
|
+
if (targetFiles.includes(trimmedLine)) {
|
|
112
|
+
removed.push(trimmedLine);
|
|
113
|
+
continue; // Skip this line
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Check if this is a stale entry (target file exists but no .devports file)
|
|
117
|
+
if (inDevportsSection && trimmedLine && !trimmedLine.startsWith('#')) {
|
|
118
|
+
const hasDevportsFile = devportsFiles.some((devFile) => devFile.replace(/\.devports$/, '') === trimmedLine);
|
|
119
|
+
if (!hasDevportsFile) {
|
|
120
|
+
removed.push(trimmedLine);
|
|
121
|
+
continue; // Skip stale entries
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
newLines.push(line);
|
|
125
|
+
}
|
|
126
|
+
// Write updated .gitignore if not in dry-run mode
|
|
127
|
+
if (!options.dryRun && removed.length > 0) {
|
|
128
|
+
writeFileSync(gitignorePath, newLines.join('\n'));
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
added: [],
|
|
132
|
+
existing: targetFiles.filter((file) => !removed.includes(file)),
|
|
133
|
+
devportsFiles,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* List what would be added to .gitignore without making changes
|
|
138
|
+
*/
|
|
139
|
+
export async function previewGitignore() {
|
|
140
|
+
return updateGitignore({ dryRun: true });
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=gitignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../src/gitignore.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { allocatePort, releasePort, releasePortByNumber, listAllocations, getStatus, reservePort, unreservePort, } from './port-manager.js';
|
|
2
|
+
export { loadConfig, loadRegistry, saveRegistry, ensureConfigDir, } from './config.js';
|
|
3
|
+
export { checkPortInUse, findAvailablePort } from './port-utils.js';
|
|
4
|
+
export { setupCurrentDirectory } from './setup.js';
|
|
5
|
+
export type { SetupOptions, SetupResult } from './setup.js';
|
|
6
|
+
export type { PortRange, Config, PortAllocation, Registry } from './types.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Public API for programmatic usage
|
|
2
|
+
export { allocatePort, releasePort, releasePortByNumber, listAllocations, getStatus, reservePort, unreservePort, } from './port-manager.js';
|
|
3
|
+
export { loadConfig, loadRegistry, saveRegistry, ensureConfigDir, } from './config.js';
|
|
4
|
+
export { checkPortInUse, findAvailablePort } from './port-utils.js';
|
|
5
|
+
export { setupCurrentDirectory } from './setup.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,OAAO,EACL,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
|