@mdulghier/devtree 0.1.5
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/README.md +152 -0
- package/bin/devtree.mjs +21 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +425 -0
- package/dist/cli.js.map +1 -0
- package/dist/command-builder.d.ts +11 -0
- package/dist/command-builder.js +23 -0
- package/dist/command-builder.js.map +1 -0
- package/dist/config-command.d.ts +5 -0
- package/dist/config-command.js +181 -0
- package/dist/config-command.js.map +1 -0
- package/dist/config.d.ts +77 -0
- package/dist/config.js +43 -0
- package/dist/config.js.map +1 -0
- package/dist/env-file.d.ts +12 -0
- package/dist/env-file.js +114 -0
- package/dist/env-file.js.map +1 -0
- package/dist/gc.d.ts +23 -0
- package/dist/gc.js +243 -0
- package/dist/gc.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/instance.d.ts +18 -0
- package/dist/instance.js +98 -0
- package/dist/instance.js.map +1 -0
- package/dist/process.d.ts +13 -0
- package/dist/process.js +43 -0
- package/dist/process.js.map +1 -0
- package/dist/registry.d.ts +9 -0
- package/dist/registry.js +34 -0
- package/dist/registry.js.map +1 -0
- package/dist/tailscale.d.ts +10 -0
- package/dist/tailscale.js +65 -0
- package/dist/tailscale.js.map +1 -0
- package/dist/vite.d.ts +3 -0
- package/dist/vite.js +72 -0
- package/dist/vite.js.map +1 -0
- package/package.json +82 -0
- package/skills/devtree-run-and-operate-devtree/SKILL.md +179 -0
- package/skills/devtree-set-up-devtree/SKILL.md +355 -0
package/dist/gc.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { list_registered_compose_projects, unregister_compose_project } from "./registry.js";
|
|
3
|
+
import { run_command_capture, run_command_inherit } from "./process.js";
|
|
4
|
+
function get_label_keys(label_prefix) {
|
|
5
|
+
return {
|
|
6
|
+
managed: `${label_prefix}.managed`,
|
|
7
|
+
namespace: `${label_prefix}.namespace`,
|
|
8
|
+
worktree_path: `${label_prefix}.worktree-path`,
|
|
9
|
+
compose_project: `${label_prefix}.compose-project`,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function get_labels(record) {
|
|
13
|
+
return record.Config?.Labels ?? record.Labels ?? {};
|
|
14
|
+
}
|
|
15
|
+
function run_json_command(command, args) {
|
|
16
|
+
const result = run_command_capture(command, args);
|
|
17
|
+
if (!result.stdout) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
return JSON.parse(result.stdout);
|
|
21
|
+
}
|
|
22
|
+
function ensure_project_entry(projects, project_name, registry_namespace, worktree_path) {
|
|
23
|
+
const existing_project = projects.get(project_name);
|
|
24
|
+
if (existing_project) {
|
|
25
|
+
if (!existing_project.registry_namespace && registry_namespace) {
|
|
26
|
+
existing_project.registry_namespace = registry_namespace;
|
|
27
|
+
}
|
|
28
|
+
if (!existing_project.worktree_path && worktree_path) {
|
|
29
|
+
existing_project.worktree_path = worktree_path;
|
|
30
|
+
}
|
|
31
|
+
return existing_project;
|
|
32
|
+
}
|
|
33
|
+
const project = {
|
|
34
|
+
project_name,
|
|
35
|
+
registry_namespace,
|
|
36
|
+
worktree_path,
|
|
37
|
+
containers: [],
|
|
38
|
+
networks: [],
|
|
39
|
+
volumes: [],
|
|
40
|
+
sources: new Set(),
|
|
41
|
+
};
|
|
42
|
+
projects.set(project_name, project);
|
|
43
|
+
return project;
|
|
44
|
+
}
|
|
45
|
+
function read_git_worktree_paths() {
|
|
46
|
+
const worktree_result = run_command_capture("git", ["worktree", "list", "--porcelain"]);
|
|
47
|
+
const worktree_paths = new Set();
|
|
48
|
+
for (const line of worktree_result.stdout.split("\n")) {
|
|
49
|
+
if (line.startsWith("worktree ")) {
|
|
50
|
+
worktree_paths.add(line.slice("worktree ".length).trim());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return worktree_paths;
|
|
54
|
+
}
|
|
55
|
+
function read_container_projects(instance) {
|
|
56
|
+
const container_ids = run_command_capture("docker", ["ps", "-aq"])
|
|
57
|
+
.stdout.split("\n")
|
|
58
|
+
.filter(Boolean);
|
|
59
|
+
if (container_ids.length === 0) {
|
|
60
|
+
return new Map();
|
|
61
|
+
}
|
|
62
|
+
const label_keys = get_label_keys(instance.label_prefix);
|
|
63
|
+
const containers = run_json_command("docker", ["inspect", ...container_ids]);
|
|
64
|
+
const projects = new Map();
|
|
65
|
+
for (const container of containers) {
|
|
66
|
+
const labels = get_labels(container);
|
|
67
|
+
const project_name = labels["com.docker.compose.project"] ?? labels[label_keys.compose_project];
|
|
68
|
+
const registry_namespace = labels[label_keys.namespace] ?? null;
|
|
69
|
+
const worktree_path = labels[label_keys.worktree_path] ?? labels["com.docker.compose.project.working_dir"] ?? null;
|
|
70
|
+
if (!project_name) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if ((registry_namespace && registry_namespace !== instance.registry_namespace) ||
|
|
74
|
+
(!registry_namespace && !project_name.startsWith(instance.registry_namespace))) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const project = ensure_project_entry(projects, project_name, registry_namespace, worktree_path);
|
|
78
|
+
if (container.Name) {
|
|
79
|
+
project.containers.push(container.Name.replace(/^\//, ""));
|
|
80
|
+
}
|
|
81
|
+
project.sources.add("container");
|
|
82
|
+
}
|
|
83
|
+
return projects;
|
|
84
|
+
}
|
|
85
|
+
function seed_projects_from_registry(projects, instance) {
|
|
86
|
+
for (const entry of list_registered_compose_projects(instance.registry_namespace)) {
|
|
87
|
+
ensure_project_entry(projects, entry.compose_project, entry.registry_namespace, entry.worktree_path);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function add_named_objects(projects, instance, kind, names, inspect_args) {
|
|
91
|
+
if (names.length === 0) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const label_keys = get_label_keys(instance.label_prefix);
|
|
95
|
+
const objects = run_json_command("docker", [...inspect_args, ...names]);
|
|
96
|
+
for (const object of objects) {
|
|
97
|
+
const labels = get_labels(object);
|
|
98
|
+
const project_name = labels["com.docker.compose.project"] ?? labels[label_keys.compose_project];
|
|
99
|
+
const registry_namespace = labels[label_keys.namespace] ?? null;
|
|
100
|
+
const worktree_path = labels[label_keys.worktree_path] ?? null;
|
|
101
|
+
if (!project_name) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if ((registry_namespace && registry_namespace !== instance.registry_namespace) ||
|
|
105
|
+
(!registry_namespace && !project_name.startsWith(instance.registry_namespace))) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const project = ensure_project_entry(projects, project_name, registry_namespace, worktree_path);
|
|
109
|
+
if (kind === "network" && object.Name) {
|
|
110
|
+
project.networks.push(object.Name);
|
|
111
|
+
}
|
|
112
|
+
if (kind === "volume" && object.Name) {
|
|
113
|
+
project.volumes.push(object.Name);
|
|
114
|
+
}
|
|
115
|
+
project.sources.add(kind);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function enrich_projects_with_volumes(projects, instance) {
|
|
119
|
+
const volume_names = run_command_capture("docker", ["volume", "ls", "-q"])
|
|
120
|
+
.stdout.split("\n")
|
|
121
|
+
.filter(Boolean);
|
|
122
|
+
add_named_objects(projects, instance, "volume", volume_names, ["volume", "inspect"]);
|
|
123
|
+
}
|
|
124
|
+
function enrich_projects_with_networks(projects, instance) {
|
|
125
|
+
const network_names = run_command_capture("docker", ["network", "ls", "-q"])
|
|
126
|
+
.stdout.split("\n")
|
|
127
|
+
.filter(Boolean);
|
|
128
|
+
add_named_objects(projects, instance, "network", network_names, ["network", "inspect"]);
|
|
129
|
+
}
|
|
130
|
+
function backfill_legacy_resource_names(projects) {
|
|
131
|
+
const container_names = new Set(run_command_capture("docker", ["ps", "-a", "--format", "{{.Names}}"])
|
|
132
|
+
.stdout.split("\n")
|
|
133
|
+
.filter(Boolean));
|
|
134
|
+
const network_names = new Set(run_command_capture("docker", ["network", "ls", "--format", "{{.Name}}"])
|
|
135
|
+
.stdout.split("\n")
|
|
136
|
+
.filter(Boolean));
|
|
137
|
+
const volume_names = new Set(run_command_capture("docker", ["volume", "ls", "--format", "{{.Name}}"])
|
|
138
|
+
.stdout.split("\n")
|
|
139
|
+
.filter(Boolean));
|
|
140
|
+
for (const project of projects.values()) {
|
|
141
|
+
const default_container = `${project.project_name}-db-1`;
|
|
142
|
+
const default_network = `${project.project_name}_default`;
|
|
143
|
+
const default_volume = `${project.project_name}_pgdata`;
|
|
144
|
+
if (project.containers.length === 0 && container_names.has(default_container)) {
|
|
145
|
+
project.containers.push(default_container);
|
|
146
|
+
}
|
|
147
|
+
if (project.networks.length === 0 && network_names.has(default_network)) {
|
|
148
|
+
project.networks.push(default_network);
|
|
149
|
+
}
|
|
150
|
+
if (project.volumes.length === 0 && volume_names.has(default_volume)) {
|
|
151
|
+
project.volumes.push(default_volume);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function is_active_worktree(project, active_worktrees) {
|
|
156
|
+
if (!project.worktree_path) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return active_worktrees.has(project.worktree_path) && existsSync(project.worktree_path);
|
|
160
|
+
}
|
|
161
|
+
function format_list(values) {
|
|
162
|
+
return values.length === 0 ? "none" : values.join(", ");
|
|
163
|
+
}
|
|
164
|
+
function print_project(project, state) {
|
|
165
|
+
const header = state === "active"
|
|
166
|
+
? `Active: ${project.project_name}`
|
|
167
|
+
: state === "orphan"
|
|
168
|
+
? `Orphan: ${project.project_name}`
|
|
169
|
+
: `Skipped: ${project.project_name}`;
|
|
170
|
+
console.log(header);
|
|
171
|
+
console.log(` worktree: ${project.worktree_path ?? "unknown"}`);
|
|
172
|
+
console.log(` containers: ${format_list(project.containers)}`);
|
|
173
|
+
console.log(` networks: ${format_list(project.networks)}`);
|
|
174
|
+
console.log(` volumes: ${format_list(project.volumes)}`);
|
|
175
|
+
}
|
|
176
|
+
function remove_named_objects(command_group, names) {
|
|
177
|
+
if (names.length === 0) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
run_command_inherit("docker", [command_group, "rm", ...names]);
|
|
181
|
+
}
|
|
182
|
+
function remove_containers(names) {
|
|
183
|
+
if (names.length === 0) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
run_command_inherit("docker", ["rm", "-f", ...names]);
|
|
187
|
+
}
|
|
188
|
+
export function classify_projects(projects, active_worktrees) {
|
|
189
|
+
return {
|
|
190
|
+
active_projects: projects.filter((project) => is_active_worktree(project, active_worktrees)),
|
|
191
|
+
orphan_projects: projects.filter((project) => project.worktree_path && !is_active_worktree(project, active_worktrees)),
|
|
192
|
+
unknown_projects: projects.filter((project) => !project.worktree_path),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
export function run_gc(loaded_config, instance, options) {
|
|
196
|
+
const active_worktrees = read_git_worktree_paths();
|
|
197
|
+
const projects = read_container_projects(instance);
|
|
198
|
+
seed_projects_from_registry(projects, instance);
|
|
199
|
+
enrich_projects_with_networks(projects, instance);
|
|
200
|
+
enrich_projects_with_volumes(projects, instance);
|
|
201
|
+
backfill_legacy_resource_names(projects);
|
|
202
|
+
const all_projects = [...projects.values()].sort((left, right) => left.project_name.localeCompare(right.project_name));
|
|
203
|
+
const classified_projects = classify_projects(all_projects, active_worktrees);
|
|
204
|
+
console.log("Devtree dependency garbage collection");
|
|
205
|
+
console.log(`Config: ${loaded_config.config_path}`);
|
|
206
|
+
console.log(`Active git worktrees: ${active_worktrees.size}`);
|
|
207
|
+
console.log(`Managed Docker projects: ${all_projects.length}`);
|
|
208
|
+
if (options.verbose && classified_projects.active_projects.length > 0) {
|
|
209
|
+
console.log("");
|
|
210
|
+
for (const project of classified_projects.active_projects) {
|
|
211
|
+
print_project(project, "active");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (classified_projects.unknown_projects.length > 0) {
|
|
215
|
+
console.log("");
|
|
216
|
+
console.log(`Skipping ${classified_projects.unknown_projects.length} project(s) without worktree metadata`);
|
|
217
|
+
for (const project of classified_projects.unknown_projects) {
|
|
218
|
+
print_project(project, "unknown");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (classified_projects.orphan_projects.length === 0) {
|
|
222
|
+
console.log("");
|
|
223
|
+
console.log("No orphaned dependency projects found.");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
console.log("");
|
|
227
|
+
console.log(`${options.dry_run ? "Would remove" : "Removing"} ${classified_projects.orphan_projects.length} orphaned project(s)`);
|
|
228
|
+
for (const project of classified_projects.orphan_projects) {
|
|
229
|
+
print_project(project, "orphan");
|
|
230
|
+
if (options.dry_run) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
remove_containers(project.containers);
|
|
234
|
+
remove_named_objects("network", project.networks);
|
|
235
|
+
remove_named_objects("volume", project.volumes);
|
|
236
|
+
unregister_compose_project(instance.registry_namespace, project.project_name);
|
|
237
|
+
}
|
|
238
|
+
console.log("");
|
|
239
|
+
console.log(options.dry_run
|
|
240
|
+
? "Dry run only. Re-run without `--dry-run` to remove the orphaned resources."
|
|
241
|
+
: "Dependency garbage collection complete.");
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=gc.js.map
|
package/dist/gc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gc.js","sourceRoot":"","sources":["../src/gc.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { define_devtree_config, load_devtree_config } from "./config.ts";
|
|
2
|
+
export type { Command_spec, Command_spec_context, Compose_dependency, Compose_dependency_context, Devtree_config, Devtree_dependency, Managed_env_entry, } from "./config.ts";
|
|
3
|
+
export { create_devtree_instance } from "./instance.ts";
|
|
4
|
+
export type { Devtree_instance } from "./instance.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAUzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Loaded_devtree_config } from "./config.ts";
|
|
2
|
+
export type Devtree_instance = {
|
|
3
|
+
app_name: string;
|
|
4
|
+
namespace: string;
|
|
5
|
+
repo_root: string;
|
|
6
|
+
worktree_path: string;
|
|
7
|
+
worktree_slug: string | null;
|
|
8
|
+
instance_id: string;
|
|
9
|
+
scoped_name: string;
|
|
10
|
+
env_file_path: string;
|
|
11
|
+
public_url: string;
|
|
12
|
+
label_prefix: string;
|
|
13
|
+
registry_namespace: string;
|
|
14
|
+
portless_enabled: boolean;
|
|
15
|
+
get_scoped_name: (suffix?: string) => string;
|
|
16
|
+
allocate_port: (name: string, base_port: number, span?: number) => number;
|
|
17
|
+
};
|
|
18
|
+
export declare function create_devtree_instance(loaded_config: Loaded_devtree_config): Devtree_instance;
|
package/dist/instance.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { existsSync, lstatSync, readFileSync } from "node:fs";
|
|
4
|
+
import { basename, dirname, resolve } from "node:path";
|
|
5
|
+
function slugify(value) {
|
|
6
|
+
return value
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
9
|
+
.replace(/^-+|-+$/g, "");
|
|
10
|
+
}
|
|
11
|
+
function get_parent_worktree_slug(repo_root, repo_slug) {
|
|
12
|
+
const parent_slug = slugify(basename(dirname(repo_root)));
|
|
13
|
+
if (!parent_slug || parent_slug === repo_slug) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return parent_slug;
|
|
17
|
+
}
|
|
18
|
+
function read_worktree_slug(repo_root, repo_slug) {
|
|
19
|
+
const git_path = resolve(repo_root, ".git");
|
|
20
|
+
if (!existsSync(git_path)) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
if (!lstatSync(git_path).isFile()) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const git_file_text = readFileSync(git_path, "utf8");
|
|
27
|
+
const worktree_match = git_file_text.match(/[\\/]+worktrees[\\/]+([^\\/ \n\r]+)/);
|
|
28
|
+
if (!worktree_match?.[1]) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const git_worktree_slug = slugify(worktree_match[1]);
|
|
32
|
+
if (!git_worktree_slug || git_worktree_slug === repo_slug) {
|
|
33
|
+
return get_parent_worktree_slug(repo_root, repo_slug);
|
|
34
|
+
}
|
|
35
|
+
return git_worktree_slug;
|
|
36
|
+
}
|
|
37
|
+
function get_hash_suffix(value) {
|
|
38
|
+
return createHash("sha1").update(value).digest("hex").slice(0, 8);
|
|
39
|
+
}
|
|
40
|
+
function read_branch_slug(repo_root) {
|
|
41
|
+
const branch_result = spawnSync("git", ["branch", "--show-current"], {
|
|
42
|
+
cwd: repo_root,
|
|
43
|
+
encoding: "utf8",
|
|
44
|
+
env: process.env,
|
|
45
|
+
});
|
|
46
|
+
if (branch_result.status !== 0) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const branch_name = branch_result.stdout.trim();
|
|
50
|
+
if (!branch_name) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return slugify(branch_name.split("/").at(-1) ?? branch_name);
|
|
54
|
+
}
|
|
55
|
+
function get_public_url(app_name, route_prefix) {
|
|
56
|
+
const protocol = process.env.PORTLESS_HTTPS === "1" ? "https" : "http";
|
|
57
|
+
const tld = process.env.PORTLESS_TLD?.trim() || "localhost";
|
|
58
|
+
const proxy_port = process.env.PORTLESS_PORT?.trim() || "1355";
|
|
59
|
+
const host = route_prefix ? `${route_prefix}.${app_name}` : app_name;
|
|
60
|
+
return `${protocol}://${host}.${tld}:${proxy_port}`;
|
|
61
|
+
}
|
|
62
|
+
function get_namespace(config) {
|
|
63
|
+
return slugify(config.namespace?.trim() || config.app_name);
|
|
64
|
+
}
|
|
65
|
+
export function create_devtree_instance(loaded_config) {
|
|
66
|
+
const app_name = slugify(loaded_config.config.app_name);
|
|
67
|
+
const namespace = get_namespace(loaded_config.config);
|
|
68
|
+
const worktree_path = loaded_config.repo_root;
|
|
69
|
+
const worktree_slug = read_worktree_slug(loaded_config.repo_root, namespace);
|
|
70
|
+
const branch_slug = worktree_slug ? read_branch_slug(loaded_config.repo_root) : null;
|
|
71
|
+
const instance_id = get_hash_suffix(worktree_path);
|
|
72
|
+
const scoped_name = `${namespace}-${instance_id}`;
|
|
73
|
+
const env_file_path = resolve(loaded_config.repo_root, loaded_config.config.env.file_path || ".env.local");
|
|
74
|
+
const label_prefix = loaded_config.config.garbage_collection?.docker_label_prefix?.trim() || "devtree";
|
|
75
|
+
const registry_namespace = loaded_config.config.garbage_collection?.registry_namespace?.trim() || namespace;
|
|
76
|
+
return {
|
|
77
|
+
app_name,
|
|
78
|
+
namespace,
|
|
79
|
+
repo_root: loaded_config.repo_root,
|
|
80
|
+
worktree_path,
|
|
81
|
+
worktree_slug,
|
|
82
|
+
instance_id,
|
|
83
|
+
scoped_name,
|
|
84
|
+
env_file_path,
|
|
85
|
+
public_url: get_public_url(app_name, branch_slug ?? worktree_slug),
|
|
86
|
+
label_prefix,
|
|
87
|
+
registry_namespace,
|
|
88
|
+
portless_enabled: loaded_config.config.portless?.enabled !== false && process.env.PORTLESS !== "0",
|
|
89
|
+
get_scoped_name(suffix) {
|
|
90
|
+
return suffix ? `${scoped_name}-${slugify(suffix)}` : scoped_name;
|
|
91
|
+
},
|
|
92
|
+
allocate_port(name, base_port, span = 1000) {
|
|
93
|
+
const hash_value = get_hash_suffix(`${worktree_path}:${slugify(name)}`);
|
|
94
|
+
return base_port + (parseInt(hash_value, 16) % span);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=instance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.js","sourceRoot":"","sources":["../src/instance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type Command_result = {
|
|
2
|
+
status: number;
|
|
3
|
+
stdout: string;
|
|
4
|
+
stderr: string;
|
|
5
|
+
};
|
|
6
|
+
export type Run_command_options = {
|
|
7
|
+
cwd?: string;
|
|
8
|
+
env?: Record<string, string | undefined>;
|
|
9
|
+
allow_failure?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function command_exists(command: string): boolean;
|
|
12
|
+
export declare function run_command_capture(command: string, args: string[], options?: Run_command_options): Command_result;
|
|
13
|
+
export declare function run_command_inherit(command: string, args: string[], options?: Run_command_options): number;
|
package/dist/process.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
export function command_exists(command) {
|
|
3
|
+
const result = spawnSync("which", [command], {
|
|
4
|
+
cwd: process.cwd(),
|
|
5
|
+
encoding: "utf8",
|
|
6
|
+
env: process.env,
|
|
7
|
+
});
|
|
8
|
+
return result.status === 0;
|
|
9
|
+
}
|
|
10
|
+
export function run_command_capture(command, args, options) {
|
|
11
|
+
const result = spawnSync(command, args, {
|
|
12
|
+
cwd: options?.cwd ?? process.cwd(),
|
|
13
|
+
encoding: "utf8",
|
|
14
|
+
env: { ...process.env, ...options?.env },
|
|
15
|
+
});
|
|
16
|
+
if (result.error) {
|
|
17
|
+
throw result.error;
|
|
18
|
+
}
|
|
19
|
+
const command_result = {
|
|
20
|
+
status: result.status ?? 1,
|
|
21
|
+
stdout: result.stdout?.trim() ?? "",
|
|
22
|
+
stderr: result.stderr?.trim() ?? "",
|
|
23
|
+
};
|
|
24
|
+
if (!options?.allow_failure && command_result.status !== 0) {
|
|
25
|
+
throw new Error(command_result.stderr || `${command} ${args.join(" ")} failed`);
|
|
26
|
+
}
|
|
27
|
+
return command_result;
|
|
28
|
+
}
|
|
29
|
+
export function run_command_inherit(command, args, options) {
|
|
30
|
+
const result = spawnSync(command, args, {
|
|
31
|
+
cwd: options?.cwd ?? process.cwd(),
|
|
32
|
+
env: { ...process.env, ...options?.env },
|
|
33
|
+
stdio: "inherit",
|
|
34
|
+
});
|
|
35
|
+
if (result.error) {
|
|
36
|
+
throw result.error;
|
|
37
|
+
}
|
|
38
|
+
if (!options?.allow_failure && result.status !== 0) {
|
|
39
|
+
process.exit(result.status ?? 1);
|
|
40
|
+
}
|
|
41
|
+
return result.status ?? 0;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAc/C,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAC3C,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,QAAQ,EAAE,MAAM;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,IAAc,EACd,OAA6B;IAE7B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;QACtC,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QAClC,QAAQ,EAAE,MAAM;QAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE;KACzC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,MAAM,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,cAAc,GAAG;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE;QACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE;KACpC,CAAC;IAEF,IAAI,CAAC,OAAO,EAAE,aAAa,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,IAAI,GAAG,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,IAAc,EACd,OAA6B;IAE7B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;QACtC,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QAClC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,EAAE;QACxC,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,MAAM,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,aAAa,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type Registered_compose_project = {
|
|
2
|
+
registry_namespace: string;
|
|
3
|
+
compose_project: string;
|
|
4
|
+
worktree_path: string;
|
|
5
|
+
dependency_name: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function register_compose_project(entry: Registered_compose_project): void;
|
|
8
|
+
export declare function unregister_compose_project(registry_namespace: string, compose_project: string): void;
|
|
9
|
+
export declare function list_registered_compose_projects(registry_namespace: string): Registered_compose_project[];
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
const registry_path = resolve(homedir(), ".devtree", "projects.json");
|
|
5
|
+
function read_registry() {
|
|
6
|
+
if (!existsSync(registry_path)) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
const file_text = readFileSync(registry_path, "utf8").trim();
|
|
10
|
+
if (!file_text) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
return JSON.parse(file_text);
|
|
14
|
+
}
|
|
15
|
+
function write_registry(entries) {
|
|
16
|
+
mkdirSync(dirname(registry_path), { recursive: true });
|
|
17
|
+
writeFileSync(registry_path, JSON.stringify(entries, null, 2) + "\n");
|
|
18
|
+
}
|
|
19
|
+
export function register_compose_project(entry) {
|
|
20
|
+
const next_entries = read_registry().filter((existing_entry) => !(existing_entry.registry_namespace === entry.registry_namespace &&
|
|
21
|
+
existing_entry.compose_project === entry.compose_project));
|
|
22
|
+
next_entries.push(entry);
|
|
23
|
+
next_entries.sort((left, right) => left.compose_project.localeCompare(right.compose_project));
|
|
24
|
+
write_registry(next_entries);
|
|
25
|
+
}
|
|
26
|
+
export function unregister_compose_project(registry_namespace, compose_project) {
|
|
27
|
+
const next_entries = read_registry().filter((existing_entry) => !(existing_entry.registry_namespace === registry_namespace &&
|
|
28
|
+
existing_entry.compose_project === compose_project));
|
|
29
|
+
write_registry(next_entries);
|
|
30
|
+
}
|
|
31
|
+
export function list_registered_compose_projects(registry_namespace) {
|
|
32
|
+
return read_registry().filter((entry) => entry.registry_namespace === registry_namespace);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAS7C,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;AAEtE,SAAS,aAAa;IACpB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAkC,CAAC;IAC5C,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAE7D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAkC,CAAC;IAC5C,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAiC,CAAC;AAC/D,CAAC;AAED,SAAS,cAAc,CAAC,OAAqC;IAC3D,SAAS,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,aAAa,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,KAAiC;IACxE,MAAM,YAAY,GAAG,aAAa,EAAE,CAAC,MAAM,CACzC,CAAC,cAAc,EAAE,EAAE,CACjB,CAAC,CACC,cAAc,CAAC,kBAAkB,KAAK,KAAK,CAAC,kBAAkB;QAC9D,cAAc,CAAC,eAAe,KAAK,KAAK,CAAC,eAAe,CACzD,CACJ,CAAC;IAEF,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;IAC9F,cAAc,CAAC,YAAY,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,kBAA0B,EAAE,eAAuB;IAC5F,MAAM,YAAY,GAAG,aAAa,EAAE,CAAC,MAAM,CACzC,CAAC,cAAc,EAAE,EAAE,CACjB,CAAC,CACC,cAAc,CAAC,kBAAkB,KAAK,kBAAkB;QACxD,cAAc,CAAC,eAAe,KAAK,eAAe,CACnD,CACJ,CAAC;IAEF,cAAc,CAAC,YAAY,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,kBAA0B;IACzE,OAAO,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,kBAAkB,KAAK,kBAAkB,CAAC,CAAC;AAC5F,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Devtree_config } from "./config.ts";
|
|
2
|
+
export type Resolved_tailscale = {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
cli_available: boolean;
|
|
5
|
+
host: string | null;
|
|
6
|
+
error: string | null;
|
|
7
|
+
};
|
|
8
|
+
export declare function tailscale_enabled(config: Devtree_config): boolean;
|
|
9
|
+
export declare function parse_tailscale_host(status_json: string): string | null;
|
|
10
|
+
export declare function resolve_tailscale(config: Devtree_config): Resolved_tailscale;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { command_exists, run_command_capture } from "./process.js";
|
|
2
|
+
export function tailscale_enabled(config) {
|
|
3
|
+
return config.tailscale?.enabled === true;
|
|
4
|
+
}
|
|
5
|
+
export function parse_tailscale_host(status_json) {
|
|
6
|
+
const parsed_status = JSON.parse(status_json);
|
|
7
|
+
const host = parsed_status.Self?.DNSName?.trim().replace(/\.$/, "");
|
|
8
|
+
return host || null;
|
|
9
|
+
}
|
|
10
|
+
export function resolve_tailscale(config) {
|
|
11
|
+
if (!tailscale_enabled(config)) {
|
|
12
|
+
return {
|
|
13
|
+
enabled: false,
|
|
14
|
+
cli_available: false,
|
|
15
|
+
host: null,
|
|
16
|
+
error: null,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (!command_exists("tailscale")) {
|
|
20
|
+
return {
|
|
21
|
+
enabled: true,
|
|
22
|
+
cli_available: false,
|
|
23
|
+
host: null,
|
|
24
|
+
error: "tailscale is enabled, but the `tailscale` command is not available on PATH",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const status_result = run_command_capture("tailscale", ["status", "--json"], {
|
|
28
|
+
allow_failure: true,
|
|
29
|
+
});
|
|
30
|
+
if (status_result.status !== 0) {
|
|
31
|
+
return {
|
|
32
|
+
enabled: true,
|
|
33
|
+
cli_available: true,
|
|
34
|
+
host: null,
|
|
35
|
+
error: status_result.stderr ||
|
|
36
|
+
"tailscale is enabled, but `tailscale status --json` did not return a usable host",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const host = parse_tailscale_host(status_result.stdout);
|
|
41
|
+
if (!host) {
|
|
42
|
+
return {
|
|
43
|
+
enabled: true,
|
|
44
|
+
cli_available: true,
|
|
45
|
+
host: null,
|
|
46
|
+
error: "tailscale is enabled, but `tailscale status --json` did not report a MagicDNS host",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
enabled: true,
|
|
51
|
+
cli_available: true,
|
|
52
|
+
host,
|
|
53
|
+
error: null,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return {
|
|
58
|
+
enabled: true,
|
|
59
|
+
cli_available: true,
|
|
60
|
+
host: null,
|
|
61
|
+
error: "tailscale is enabled, but `tailscale status --json` returned invalid JSON",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=tailscale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailscale.js","sourceRoot":"","sources":["../src/tailscale.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAenE,MAAM,UAAU,iBAAiB,CAAC,MAAsB;IACtD,OAAO,MAAM,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAqB,CAAC;IAClE,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEpE,OAAO,IAAI,IAAI,IAAI,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAsB;IACtD,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,OAAO,EAAE,KAAK;YACd,aAAa,EAAE,KAAK;YACpB,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,aAAa,EAAE,KAAK;YACpB,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,4EAA4E;SACpF,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,mBAAmB,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE;QAC3E,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;IAEH,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,aAAa,EAAE,IAAI;YACnB,IAAI,EAAE,IAAI;YACV,KAAK,EACH,aAAa,CAAC,MAAM;gBACpB,kFAAkF;SACrF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,oBAAoB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAExD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,aAAa,EAAE,IAAI;gBACnB,IAAI,EAAE,IAAI;gBACV,KAAK,EACH,oFAAoF;aACvF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,aAAa,EAAE,IAAI;YACnB,IAAI;YACJ,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,OAAO,EAAE,IAAI;YACb,aAAa,EAAE,IAAI;YACnB,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,2EAA2E;SACnF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/vite.d.ts
ADDED