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,33 @@
|
|
|
1
|
+
import type { PortAllocation } from './types.js';
|
|
2
|
+
export declare function allocatePort(project: string, service: string, type: string): Promise<number>;
|
|
3
|
+
/**
|
|
4
|
+
* Get existing port allocation for a project/service combination
|
|
5
|
+
*/
|
|
6
|
+
export declare function getExistingAllocation(project: string, service: string): Promise<number | null>;
|
|
7
|
+
/**
|
|
8
|
+
* Get or allocate a port for a project/service combination
|
|
9
|
+
* This function first checks for existing allocations and returns them,
|
|
10
|
+
* only allocating new ports when needed. Used by render command.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getOrAllocatePort(project: string, service: string, type: string): Promise<number>;
|
|
13
|
+
export declare function releasePort(project: string, service?: string, all?: boolean): Promise<number>;
|
|
14
|
+
export declare function releasePortByNumber(port: number): Promise<boolean>;
|
|
15
|
+
export declare function listAllocations(filters?: {
|
|
16
|
+
project?: string;
|
|
17
|
+
type?: string;
|
|
18
|
+
}): PortAllocation[];
|
|
19
|
+
export declare function getStatus(): {
|
|
20
|
+
types: Record<string, {
|
|
21
|
+
available: number;
|
|
22
|
+
used: number;
|
|
23
|
+
next: number | null;
|
|
24
|
+
}>;
|
|
25
|
+
};
|
|
26
|
+
export declare function reservePort(port: number, reason: string): Promise<void>;
|
|
27
|
+
export declare function unreservePort(port: number): Promise<boolean>;
|
|
28
|
+
export declare function listReservations(): Array<{
|
|
29
|
+
port: number;
|
|
30
|
+
reason: string;
|
|
31
|
+
reservedAt: string;
|
|
32
|
+
}>;
|
|
33
|
+
//# sourceMappingURL=port-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-manager.d.ts","sourceRoot":"","sources":["../src/port-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAmEjB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,GAAG,UAAQ,GACV,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAaxE;AAED,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,cAAc,EAAE,CAcnB;AAED,wBAAgB,SAAS,IAAI;IAC3B,KAAK,EAAE,MAAM,CACX,MAAM,EACN;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CACzD,CAAC;CACH,CA+BA;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB7E;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAelE;AAED,wBAAgB,gBAAgB,IAAI,KAAK,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAGD"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { LockManager } from './services/lock-manager.js';
|
|
2
|
+
import { loadConfig, loadRegistry } from './config.js';
|
|
3
|
+
import { findAvailablePort, checkPortInUse } from './port-utils.js';
|
|
4
|
+
export async function allocatePort(project, service, type) {
|
|
5
|
+
const config = loadConfig();
|
|
6
|
+
const serviceType = type;
|
|
7
|
+
// Validate port type exists in config
|
|
8
|
+
if (!config.ranges[serviceType]) {
|
|
9
|
+
// Provide helpful error message with valid types
|
|
10
|
+
const validTypes = Object.keys(config.ranges).join(', ');
|
|
11
|
+
throw new Error(`No port range configured for type "${serviceType}". ` +
|
|
12
|
+
`Valid types: ${validTypes}`);
|
|
13
|
+
}
|
|
14
|
+
return await LockManager.withRegistryLock(async (registry) => {
|
|
15
|
+
const range = config.ranges[serviceType];
|
|
16
|
+
// Check if this project/service already has an allocation
|
|
17
|
+
const existing = registry.allocations.find((a) => a.project === project && a.service === service);
|
|
18
|
+
if (existing) {
|
|
19
|
+
throw new Error(`Port ${existing.port} already allocated for ${project}/${service}. ` +
|
|
20
|
+
`Use 'devports release ${project} ${service}' first.`);
|
|
21
|
+
}
|
|
22
|
+
// Find next available port (checking both devports allocations and actual port usage)
|
|
23
|
+
const usedPorts = new Set([
|
|
24
|
+
...registry.allocations.map((a) => a.port),
|
|
25
|
+
...registry.reservations.map((r) => r.port),
|
|
26
|
+
]);
|
|
27
|
+
const port = await findAvailablePort(range.start, range.end, usedPorts);
|
|
28
|
+
if (!port) {
|
|
29
|
+
throw new Error(`No available ports in range ${range.start}-${range.end} for ${serviceType}. ` +
|
|
30
|
+
`All ports are either allocated by devports or in use by other processes.`);
|
|
31
|
+
}
|
|
32
|
+
// Double-check if the port is actually in use and warn if so
|
|
33
|
+
const isInUse = await checkPortInUse(port);
|
|
34
|
+
if (isInUse) {
|
|
35
|
+
console.warn(`⚠️ Warning: Port ${port} is currently in use by another process. ` +
|
|
36
|
+
`You may need to stop that process before using this port.`);
|
|
37
|
+
}
|
|
38
|
+
// Allocate the port
|
|
39
|
+
const allocation = {
|
|
40
|
+
port,
|
|
41
|
+
project,
|
|
42
|
+
service,
|
|
43
|
+
type: serviceType,
|
|
44
|
+
allocatedAt: new Date().toISOString(),
|
|
45
|
+
};
|
|
46
|
+
registry.allocations.push(allocation);
|
|
47
|
+
return port;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get existing port allocation for a project/service combination
|
|
52
|
+
*/
|
|
53
|
+
export async function getExistingAllocation(project, service) {
|
|
54
|
+
return await LockManager.withRegistryLock((registry) => {
|
|
55
|
+
const existing = registry.allocations.find((a) => a.project === project && a.service === service);
|
|
56
|
+
return existing ? existing.port : null;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get or allocate a port for a project/service combination
|
|
61
|
+
* This function first checks for existing allocations and returns them,
|
|
62
|
+
* only allocating new ports when needed. Used by render command.
|
|
63
|
+
*/
|
|
64
|
+
export async function getOrAllocatePort(project, service, type) {
|
|
65
|
+
// First check if we already have an allocation
|
|
66
|
+
const existingPort = await getExistingAllocation(project, service);
|
|
67
|
+
if (existingPort !== null) {
|
|
68
|
+
return existingPort;
|
|
69
|
+
}
|
|
70
|
+
// No existing allocation, so allocate a new port
|
|
71
|
+
return await allocatePort(project, service, type);
|
|
72
|
+
}
|
|
73
|
+
export async function releasePort(project, service, all = false) {
|
|
74
|
+
return await LockManager.withRegistryLock((registry) => {
|
|
75
|
+
const before = registry.allocations.length;
|
|
76
|
+
if (all) {
|
|
77
|
+
// Release all ports for this project
|
|
78
|
+
registry.allocations = registry.allocations.filter((a) => a.project !== project);
|
|
79
|
+
}
|
|
80
|
+
else if (service) {
|
|
81
|
+
// Release specific service
|
|
82
|
+
registry.allocations = registry.allocations.filter((a) => !(a.project === project && a.service === service));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new Error('Must specify --all or provide a service name');
|
|
86
|
+
}
|
|
87
|
+
const released = before - registry.allocations.length;
|
|
88
|
+
return released;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
export async function releasePortByNumber(port) {
|
|
92
|
+
return await LockManager.withRegistryLockConditional((registry) => {
|
|
93
|
+
const before = registry.allocations.length;
|
|
94
|
+
registry.allocations = registry.allocations.filter((a) => a.port !== port);
|
|
95
|
+
const released = before > registry.allocations.length;
|
|
96
|
+
return {
|
|
97
|
+
result: released,
|
|
98
|
+
shouldSave: released, // Only save if something was actually released
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
export function listAllocations(filters) {
|
|
103
|
+
const registry = loadRegistry();
|
|
104
|
+
let allocations = registry.allocations;
|
|
105
|
+
if (filters?.project) {
|
|
106
|
+
allocations = allocations.filter((a) => a.project === filters.project);
|
|
107
|
+
}
|
|
108
|
+
if (filters?.type) {
|
|
109
|
+
allocations = allocations.filter((a) => a.type === filters.type);
|
|
110
|
+
}
|
|
111
|
+
return allocations.sort((a, b) => a.port - b.port);
|
|
112
|
+
}
|
|
113
|
+
export function getStatus() {
|
|
114
|
+
const config = loadConfig();
|
|
115
|
+
const registry = loadRegistry();
|
|
116
|
+
const usedPorts = new Set([
|
|
117
|
+
...registry.allocations.map((a) => a.port),
|
|
118
|
+
...registry.reservations.map((r) => r.port),
|
|
119
|
+
]);
|
|
120
|
+
const types = {};
|
|
121
|
+
for (const [typeName, range] of Object.entries(config.ranges)) {
|
|
122
|
+
const total = range.end - range.start + 1;
|
|
123
|
+
const used = registry.allocations.filter((a) => a.type === typeName).length;
|
|
124
|
+
const available = total - used;
|
|
125
|
+
let next = null;
|
|
126
|
+
for (let p = range.start; p <= range.end; p++) {
|
|
127
|
+
if (!usedPorts.has(p)) {
|
|
128
|
+
next = p;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
types[typeName] = { available, used, next };
|
|
133
|
+
}
|
|
134
|
+
return { types };
|
|
135
|
+
}
|
|
136
|
+
export async function reservePort(port, reason) {
|
|
137
|
+
return await LockManager.withRegistryLock((registry) => {
|
|
138
|
+
// Check if port is already allocated or reserved
|
|
139
|
+
const allocated = registry.allocations.find((a) => a.port === port);
|
|
140
|
+
if (allocated) {
|
|
141
|
+
throw new Error(`Port ${port} is already allocated to ${allocated.project}/${allocated.service}`);
|
|
142
|
+
}
|
|
143
|
+
const reserved = registry.reservations.find((r) => r.port === port);
|
|
144
|
+
if (reserved) {
|
|
145
|
+
throw new Error(`Port ${port} is already reserved: ${reserved.reason}`);
|
|
146
|
+
}
|
|
147
|
+
registry.reservations.push({
|
|
148
|
+
port,
|
|
149
|
+
reason,
|
|
150
|
+
reservedAt: new Date().toISOString(),
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
export async function unreservePort(port) {
|
|
155
|
+
return await LockManager.withRegistryLockConditional((registry) => {
|
|
156
|
+
const before = registry.reservations.length;
|
|
157
|
+
registry.reservations = registry.reservations.filter((r) => r.port !== port);
|
|
158
|
+
const unreserved = before > registry.reservations.length;
|
|
159
|
+
return {
|
|
160
|
+
result: unreserved,
|
|
161
|
+
shouldSave: unreserved, // Only save if something was actually unreserved
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
export function listReservations() {
|
|
166
|
+
const registry = loadRegistry();
|
|
167
|
+
return [...registry.reservations];
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=port-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-manager.js","sourceRoot":"","sources":["../src/port-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if a port is actually in use (not just allocated by devports)
|
|
3
|
+
*/
|
|
4
|
+
export declare function checkPortInUse(port: number, host?: string): Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Find the next available port in a range that's not in actual use
|
|
7
|
+
*/
|
|
8
|
+
export declare function findAvailablePort(start: number, end: number, usedPorts: Set<number>, host?: string): Promise<number | null>;
|
|
9
|
+
//# sourceMappingURL=port-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-utils.d.ts","sourceRoot":"","sources":["../src/port-utils.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,SAAc,GACjB,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,IAAI,SAAc,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYxB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createConnection } from 'net';
|
|
2
|
+
/**
|
|
3
|
+
* Check if a port is actually in use (not just allocated by devports)
|
|
4
|
+
*/
|
|
5
|
+
export function checkPortInUse(port, host = 'localhost') {
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
const socket = createConnection({ port, host }, () => {
|
|
8
|
+
// Connection successful means port is in use
|
|
9
|
+
socket.destroy();
|
|
10
|
+
resolve(true);
|
|
11
|
+
});
|
|
12
|
+
socket.on('error', () => {
|
|
13
|
+
// Connection failed means port is available
|
|
14
|
+
resolve(false);
|
|
15
|
+
});
|
|
16
|
+
// Set timeout to avoid hanging
|
|
17
|
+
socket.setTimeout(1000, () => {
|
|
18
|
+
socket.destroy();
|
|
19
|
+
resolve(false);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Find the next available port in a range that's not in actual use
|
|
25
|
+
*/
|
|
26
|
+
export async function findAvailablePort(start, end, usedPorts, host = 'localhost') {
|
|
27
|
+
for (let port = start; port <= end; port++) {
|
|
28
|
+
if (usedPorts.has(port)) {
|
|
29
|
+
continue; // Skip devports-allocated ports
|
|
30
|
+
}
|
|
31
|
+
const inUse = await checkPortInUse(port, host);
|
|
32
|
+
if (!inUse) {
|
|
33
|
+
return port;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=port-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-utils.js","sourceRoot":"","sources":["../src/port-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAEvC;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,IAAI,GAAG,WAAW;IAElB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE;YACnD,6CAA6C;YAC7C,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,4CAA4C;YAC5C,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QAEH,+BAA+B;QAC/B,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE;YAC3B,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,GAAW,EACX,SAAsB,EACtB,IAAI,GAAG,WAAW;IAElB,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;QAC3C,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,SAAS,CAAC,gCAAgC;QAC5C,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export interface RenderOptions {
|
|
2
|
+
projectName?: string;
|
|
3
|
+
outputFile?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface RenderResult {
|
|
6
|
+
content: string;
|
|
7
|
+
allocatedPorts: Record<string, number>;
|
|
8
|
+
projectName: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Render a template file by replacing {devports:type:service-name} patterns with allocated ports
|
|
12
|
+
*/
|
|
13
|
+
export declare function renderFile(filePath: string, options?: RenderOptions): Promise<RenderResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Process template content using magic-string for efficient manipulation
|
|
16
|
+
*/
|
|
17
|
+
export declare function processTemplate(templateContent: string, ports: Record<string, number>, projectName: string, filePath?: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Extract DEVPORTS_PROJECT_NAME from template content
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractProjectNameFromTemplate(templateContent: string): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Detect services from template file with {devports:type:service-name} patterns
|
|
24
|
+
*/
|
|
25
|
+
export declare function detectServicesFromTemplate(templateContent: string, filePath?: string): string[];
|
|
26
|
+
/**
|
|
27
|
+
* Comment style configuration for different file types
|
|
28
|
+
*/
|
|
29
|
+
interface CommentStyle {
|
|
30
|
+
lineComment?: string;
|
|
31
|
+
blockStart?: string;
|
|
32
|
+
blockEnd?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Represents a range in the source text
|
|
36
|
+
*/
|
|
37
|
+
interface Range {
|
|
38
|
+
start: number;
|
|
39
|
+
end: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get comment style configuration for a file based on its extension
|
|
43
|
+
*/
|
|
44
|
+
export declare function getCommentStyleForFile(filePath?: string): CommentStyle;
|
|
45
|
+
/**
|
|
46
|
+
* Find all comment ranges in the content, respecting string literals
|
|
47
|
+
*/
|
|
48
|
+
export declare function findCommentRanges(content: string, filePath?: string): Range[];
|
|
49
|
+
/**
|
|
50
|
+
* Make string URL/hostname safe
|
|
51
|
+
*/
|
|
52
|
+
export declare function makeUrlSafe(str: string): string;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA4CvB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAsDR;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,eAAe,EAAE,MAAM,GACtB,MAAM,GAAG,IAAI,CAuBf;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,EAAE,CAqCV;AAED;;GAEG;AACH,UAAU,YAAY;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CA4EtE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,CAqF7E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM/C"}
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { getOrAllocatePort } from './port-manager.js';
|
|
3
|
+
import MagicString from 'magic-string';
|
|
4
|
+
/**
|
|
5
|
+
* Render a template file by replacing {devports:type:service-name} patterns with allocated ports
|
|
6
|
+
*/
|
|
7
|
+
export async function renderFile(filePath, options = {}) {
|
|
8
|
+
const templateContent = readFileSync(filePath, 'utf-8');
|
|
9
|
+
// Extract project name from template or use provided option
|
|
10
|
+
let projectName = options.projectName ?? extractProjectNameFromTemplate(templateContent);
|
|
11
|
+
if (!projectName) {
|
|
12
|
+
throw new Error('No DEVPORTS_PROJECT_NAME found in template and none provided via options');
|
|
13
|
+
}
|
|
14
|
+
// Make project name URL-safe
|
|
15
|
+
projectName = makeUrlSafe(projectName);
|
|
16
|
+
// Detect services from template patterns
|
|
17
|
+
const services = detectServicesFromTemplate(templateContent, filePath);
|
|
18
|
+
// Get or allocate ports for each service (reuses existing allocations)
|
|
19
|
+
const allocatedPorts = {};
|
|
20
|
+
for (const service of services) {
|
|
21
|
+
const [serviceName, serviceType] = service.split(':');
|
|
22
|
+
const port = await getOrAllocatePort(projectName, serviceName, serviceType);
|
|
23
|
+
allocatedPorts[serviceName] = port;
|
|
24
|
+
}
|
|
25
|
+
// Process template content
|
|
26
|
+
const renderedContent = processTemplate(templateContent, allocatedPorts, projectName, filePath);
|
|
27
|
+
// Write to output file if specified
|
|
28
|
+
if (options.outputFile) {
|
|
29
|
+
writeFileSync(options.outputFile, renderedContent);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
content: renderedContent,
|
|
33
|
+
allocatedPorts,
|
|
34
|
+
projectName,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Process template content using magic-string for efficient manipulation
|
|
39
|
+
*/
|
|
40
|
+
export function processTemplate(templateContent, ports, projectName, filePath) {
|
|
41
|
+
const s = new MagicString(templateContent);
|
|
42
|
+
const commentRanges = findCommentRanges(templateContent, filePath);
|
|
43
|
+
// Find all template patterns
|
|
44
|
+
const patterns = [
|
|
45
|
+
{
|
|
46
|
+
regex: /\{devports:([^}]+)\}/g,
|
|
47
|
+
replacement: (match, serviceDef) => {
|
|
48
|
+
const parts = serviceDef.split(':');
|
|
49
|
+
// Handle project syntax: {devports:project}
|
|
50
|
+
if (parts.length === 1 && parts[0] === 'project') {
|
|
51
|
+
return projectName;
|
|
52
|
+
}
|
|
53
|
+
// Handle service syntax: {devports:type:service-name}
|
|
54
|
+
if (parts.length !== 2) {
|
|
55
|
+
console.warn(`⚠️ Invalid devports pattern: ${match} - must be {devports:type:service-name} or {devports:project}`);
|
|
56
|
+
return match;
|
|
57
|
+
}
|
|
58
|
+
const [, serviceName] = parts;
|
|
59
|
+
return ports[serviceName]?.toString() || match;
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
patterns.forEach(({ regex, replacement }) => {
|
|
64
|
+
let match;
|
|
65
|
+
regex.lastIndex = 0; // Reset regex state
|
|
66
|
+
while ((match = regex.exec(templateContent)) !== null) {
|
|
67
|
+
const start = match.index;
|
|
68
|
+
const end = start + match[0].length;
|
|
69
|
+
// Skip if inside a comment
|
|
70
|
+
if (commentRanges.some((range) => start >= range.start && end <= range.end)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const replacementText = typeof replacement === 'function'
|
|
74
|
+
? replacement(match[0], match[1])
|
|
75
|
+
: replacement;
|
|
76
|
+
s.overwrite(start, end, replacementText);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return s.toString();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Extract DEVPORTS_PROJECT_NAME from template content
|
|
83
|
+
*/
|
|
84
|
+
export function extractProjectNameFromTemplate(templateContent) {
|
|
85
|
+
const lines = templateContent.split('\n');
|
|
86
|
+
for (const line of lines) {
|
|
87
|
+
const trimmedLine = line.trim();
|
|
88
|
+
if (trimmedLine.startsWith('DEVPORTS_PROJECT_NAME=')) {
|
|
89
|
+
const value = trimmedLine.split('=')[1];
|
|
90
|
+
// Remove quotes if present
|
|
91
|
+
const cleanValue = value?.replace(/^["']|["']$/g, '') || null;
|
|
92
|
+
// If the value is a placeholder (like {devports:project}),
|
|
93
|
+
// treat it as if no project name was specified
|
|
94
|
+
if (cleanValue &&
|
|
95
|
+
cleanValue.startsWith('{') &&
|
|
96
|
+
cleanValue.endsWith('}')) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return cleanValue;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Detect services from template file with {devports:type:service-name} patterns
|
|
106
|
+
*/
|
|
107
|
+
export function detectServicesFromTemplate(templateContent, filePath) {
|
|
108
|
+
const services = [];
|
|
109
|
+
const commentRanges = findCommentRanges(templateContent, filePath);
|
|
110
|
+
const servicePattern = /\{devports:([^}]+)\}/g;
|
|
111
|
+
let match;
|
|
112
|
+
while ((match = servicePattern.exec(templateContent)) !== null) {
|
|
113
|
+
const start = match.index;
|
|
114
|
+
const end = start + match[0].length;
|
|
115
|
+
// Skip if inside a comment
|
|
116
|
+
if (commentRanges.some((range) => start >= range.start && end <= range.end)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const serviceDef = match[1];
|
|
120
|
+
const parts = serviceDef.split(':');
|
|
121
|
+
// Skip the special {devports:project} placeholder
|
|
122
|
+
if (parts.length === 1 && parts[0] === 'project') {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (parts.length !== 2) {
|
|
126
|
+
console.warn(`⚠️ Invalid devports pattern: {devports:${serviceDef}} - must be {devports:type:service-name} or {devports:project}`);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const [serviceType, serviceName] = parts;
|
|
130
|
+
services.push(`${serviceName}:${serviceType}`);
|
|
131
|
+
}
|
|
132
|
+
return [...new Set(services)];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get comment style configuration for a file based on its extension
|
|
136
|
+
*/
|
|
137
|
+
export function getCommentStyleForFile(filePath) {
|
|
138
|
+
if (!filePath) {
|
|
139
|
+
// Default to shell/env style comments
|
|
140
|
+
return { lineComment: '#' };
|
|
141
|
+
}
|
|
142
|
+
// Remove .devports suffix to get the actual file type
|
|
143
|
+
const actualPath = filePath.replace(/\.devports$/, '');
|
|
144
|
+
const ext = actualPath.split('.').pop()?.toLowerCase();
|
|
145
|
+
switch (ext) {
|
|
146
|
+
case 'env':
|
|
147
|
+
case 'sh':
|
|
148
|
+
case 'bash':
|
|
149
|
+
case 'zsh':
|
|
150
|
+
case 'conf':
|
|
151
|
+
case 'config':
|
|
152
|
+
case 'yml':
|
|
153
|
+
case 'yaml':
|
|
154
|
+
case 'py':
|
|
155
|
+
case 'rb':
|
|
156
|
+
case 'r':
|
|
157
|
+
return { lineComment: '#' };
|
|
158
|
+
case 'js':
|
|
159
|
+
case 'jsx':
|
|
160
|
+
case 'ts':
|
|
161
|
+
case 'tsx':
|
|
162
|
+
case 'java':
|
|
163
|
+
case 'c':
|
|
164
|
+
case 'cpp':
|
|
165
|
+
case 'cc':
|
|
166
|
+
case 'cxx':
|
|
167
|
+
case 'h':
|
|
168
|
+
case 'hpp':
|
|
169
|
+
case 'cs':
|
|
170
|
+
case 'php':
|
|
171
|
+
case 'go':
|
|
172
|
+
case 'rs':
|
|
173
|
+
case 'scala':
|
|
174
|
+
case 'swift':
|
|
175
|
+
return {
|
|
176
|
+
lineComment: '//',
|
|
177
|
+
blockStart: '/*',
|
|
178
|
+
blockEnd: '*/',
|
|
179
|
+
};
|
|
180
|
+
case 'json':
|
|
181
|
+
// JSON doesn't officially support comments, but some parsers allow //
|
|
182
|
+
return { lineComment: '//' };
|
|
183
|
+
case 'html':
|
|
184
|
+
case 'xml':
|
|
185
|
+
case 'svg':
|
|
186
|
+
return {
|
|
187
|
+
blockStart: '<!--',
|
|
188
|
+
blockEnd: '-->',
|
|
189
|
+
};
|
|
190
|
+
case 'sql':
|
|
191
|
+
return {
|
|
192
|
+
lineComment: '--',
|
|
193
|
+
blockStart: '/*',
|
|
194
|
+
blockEnd: '*/',
|
|
195
|
+
};
|
|
196
|
+
case 'lua':
|
|
197
|
+
return { lineComment: '--' };
|
|
198
|
+
case 'vim':
|
|
199
|
+
return { lineComment: '"' };
|
|
200
|
+
default:
|
|
201
|
+
// For unknown extensions, detect based on content patterns
|
|
202
|
+
return { lineComment: '#' }; // Most common default
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Find all comment ranges in the content, respecting string literals
|
|
207
|
+
*/
|
|
208
|
+
export function findCommentRanges(content, filePath) {
|
|
209
|
+
const commentStyle = getCommentStyleForFile(filePath);
|
|
210
|
+
const ranges = [];
|
|
211
|
+
let i = 0;
|
|
212
|
+
let inSingleQuote = false;
|
|
213
|
+
let inDoubleQuote = false;
|
|
214
|
+
let escaped = false;
|
|
215
|
+
while (i < content.length) {
|
|
216
|
+
const char = content[i];
|
|
217
|
+
// Handle escape sequences in strings
|
|
218
|
+
if (escaped) {
|
|
219
|
+
escaped = false;
|
|
220
|
+
i++;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (char === '\\' && (inSingleQuote || inDoubleQuote)) {
|
|
224
|
+
escaped = true;
|
|
225
|
+
i++;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
// Handle string literals
|
|
229
|
+
if (char === '"' && !inSingleQuote) {
|
|
230
|
+
inDoubleQuote = !inDoubleQuote;
|
|
231
|
+
i++;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (char === "'" && !inDoubleQuote) {
|
|
235
|
+
inSingleQuote = !inSingleQuote;
|
|
236
|
+
i++;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
// Skip comment detection inside string literals
|
|
240
|
+
if (inSingleQuote || inDoubleQuote) {
|
|
241
|
+
i++;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
// Check for line comments
|
|
245
|
+
if (commentStyle.lineComment &&
|
|
246
|
+
content.slice(i).startsWith(commentStyle.lineComment)) {
|
|
247
|
+
const start = i;
|
|
248
|
+
// Find end of line
|
|
249
|
+
const lineEnd = content.indexOf('\n', i);
|
|
250
|
+
const end = lineEnd === -1 ? content.length : lineEnd;
|
|
251
|
+
ranges.push({ start, end });
|
|
252
|
+
i = end;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
// Check for block comments
|
|
256
|
+
if (commentStyle.blockStart &&
|
|
257
|
+
content.slice(i).startsWith(commentStyle.blockStart)) {
|
|
258
|
+
const start = i;
|
|
259
|
+
const blockEndPos = content.indexOf(commentStyle.blockEnd ?? '', i + commentStyle.blockStart.length);
|
|
260
|
+
if (blockEndPos === -1) {
|
|
261
|
+
// Block comment doesn't end - goes to end of file
|
|
262
|
+
ranges.push({ start, end: content.length });
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
const end = blockEndPos + (commentStyle.blockEnd ?? '').length;
|
|
267
|
+
ranges.push({ start, end });
|
|
268
|
+
i = end;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
i++;
|
|
273
|
+
}
|
|
274
|
+
return ranges;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Make string URL/hostname safe
|
|
278
|
+
*/
|
|
279
|
+
export function makeUrlSafe(str) {
|
|
280
|
+
return str
|
|
281
|
+
.toLowerCase()
|
|
282
|
+
.replace(/[^a-z0-9-]/g, '-') // Replace non-alphanumeric with hyphens
|
|
283
|
+
.replace(/-+/g, '-') // Collapse multiple hyphens
|
|
284
|
+
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|