driggsby 0.1.41 → 0.2.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.
Files changed (50) hide show
  1. package/README.md +59 -0
  2. package/bin/driggsby.js +2 -0
  3. package/dist/api/base-url.js +31 -0
  4. package/dist/api/network-error.js +55 -0
  5. package/dist/args-deploy.js +94 -0
  6. package/dist/args-init.js +29 -0
  7. package/dist/args-mcp-setup.js +258 -0
  8. package/dist/args-shared.js +28 -0
  9. package/dist/args.js +177 -0
  10. package/dist/clap-suggestions.js +66 -0
  11. package/dist/cli-error.js +12 -0
  12. package/dist/credentials/clear-outcome.js +1 -0
  13. package/dist/credentials/file-store.js +77 -0
  14. package/dist/credentials/keychain.js +54 -0
  15. package/dist/credentials/secret-tool.js +48 -0
  16. package/dist/credentials/store.js +164 -0
  17. package/dist/credentials/tool-runner.js +55 -0
  18. package/dist/deploy/api-session.js +85 -0
  19. package/dist/deploy/deploy-command.js +126 -0
  20. package/dist/deploy/rollback-command.js +100 -0
  21. package/dist/deploy/versions-command.js +97 -0
  22. package/dist/dev/dev-command.js +106 -0
  23. package/dist/dev/dev-servers.js +274 -0
  24. package/dist/dev/host-page.js +147 -0
  25. package/dist/dev/mcp-broker.js +149 -0
  26. package/dist/dev/static-files.js +104 -0
  27. package/dist/dev/tool-allowlist.js +18 -0
  28. package/dist/dev/watcher.js +76 -0
  29. package/dist/help.js +180 -0
  30. package/dist/init/init-command.js +114 -0
  31. package/dist/init/templates.js +271 -0
  32. package/dist/login/claim-client.js +151 -0
  33. package/dist/login/login.js +146 -0
  34. package/dist/login/logout.js +37 -0
  35. package/dist/login/open-url.js +79 -0
  36. package/dist/main.js +57 -0
  37. package/dist/mcp-setup/classify.js +37 -0
  38. package/dist/mcp-setup/client-command.js +133 -0
  39. package/dist/mcp-setup/commands.js +53 -0
  40. package/dist/mcp-setup/known-client.js +38 -0
  41. package/dist/mcp-setup/setup.js +137 -0
  42. package/dist/mcp-setup/spawn-plan.js +91 -0
  43. package/dist/mcp-setup/text.js +83 -0
  44. package/dist/terminal-text.js +19 -0
  45. package/dist/version.js +6 -0
  46. package/package.json +22 -41
  47. package/bin/driggsby +0 -10
  48. package/install.js +0 -159
  49. package/lib/artifacts.js +0 -49
  50. package/lib/process.js +0 -65
package/install.js DELETED
@@ -1,159 +0,0 @@
1
- #!/usr/bin/env node
2
- import { createHash, randomUUID } from "node:crypto";
3
- import { chmodSync, createWriteStream, existsSync, lstatSync, mkdtempSync, mkdirSync, renameSync, rmSync, } from "node:fs";
4
- import { tmpdir } from "node:os";
5
- import { basename, join } from "node:path";
6
- import { Transform } from "node:stream";
7
- import { pipeline } from "node:stream/promises";
8
- import { packageBinDirectory, packageBinPath, readPackageJson, resolvePlatform, unsupportedPlatformMessage, } from "./lib/artifacts.js";
9
- import { readCommandOutput, writeCommandOutputToFile } from "./lib/process.js";
10
- const maxArtifactBytes = 64 * 1024 * 1024;
11
- const packageJson = readPackageJson();
12
- try {
13
- await install();
14
- }
15
- catch (error) {
16
- console.error(publicInstallErrorMessage(error));
17
- process.exit(1);
18
- }
19
- function publicInstallErrorMessage(error) {
20
- if (error instanceof Error && error.message.startsWith("Driggsby ")) {
21
- return error.message;
22
- }
23
- return "Driggsby native binary could not be installed. Check your network connection and reinstall with npm scripts enabled.";
24
- }
25
- async function install() {
26
- const resolution = resolvePlatform(packageJson);
27
- const platform = resolution.platform;
28
- if (!platform) {
29
- console.warn(unsupportedPlatformMessage(resolution));
30
- return;
31
- }
32
- validatePlatformConfig(platform);
33
- ensurePackageBinDirectory();
34
- const binaryPath = packageBinPath;
35
- const tempBinaryPath = join(packageBinDirectory, `.${platform.binaryPath}.${randomUUID()}.tmp`);
36
- const artifactUrl = `${packageJson.driggsbyArtifacts.baseUrl}/${platform.artifactName}`;
37
- const tempDirectory = mkdtempSync(join(tmpdir(), "driggsby-install-"));
38
- chmodSync(tempDirectory, 0o700);
39
- const tempArtifact = join(tempDirectory, platform.artifactName);
40
- try {
41
- const expectedChecksum = packageJson.driggsbyArtifacts.checksums[platform.artifactName];
42
- if (!expectedChecksum) {
43
- throw new Error(`Driggsby package is missing a checksum for ${platform.artifactName}.`);
44
- }
45
- await downloadAndVerifyFile(artifactUrl, tempArtifact, expectedChecksum);
46
- extractTarball(tempArtifact, tempBinaryPath, platform.binaryPath);
47
- chmodSync(tempBinaryPath, 0o755);
48
- renameSync(tempBinaryPath, binaryPath);
49
- }
50
- catch (error) {
51
- rmSync(tempBinaryPath, { force: true });
52
- throw error;
53
- }
54
- finally {
55
- rmSync(tempDirectory, { force: true, recursive: true });
56
- }
57
- }
58
- function validatePlatformConfig(platform) {
59
- if (platform.binaryPath !== "driggsby") {
60
- throw new Error("Driggsby package contains unsupported binary metadata.");
61
- }
62
- if (!/^driggsby-[A-Za-z0-9_-]+\.tar\.xz$/.test(platform.artifactName)) {
63
- throw new Error("Driggsby package contains unsupported artifact metadata.");
64
- }
65
- }
66
- function ensurePackageBinDirectory() {
67
- if (!existsSync(packageBinDirectory)) {
68
- mkdirSync(packageBinDirectory, { recursive: true });
69
- }
70
- const stats = lstatSync(packageBinDirectory);
71
- if (!stats.isDirectory() || stats.isSymbolicLink()) {
72
- throw new Error("Driggsby package bin directory is not a regular directory.");
73
- }
74
- }
75
- async function downloadAndVerifyFile(url, destination, expectedChecksum) {
76
- const response = await fetch(url);
77
- if (!response.ok || response.body === null) {
78
- throw new Error(`Could not download Driggsby binary ${url}: HTTP ${response.status}.`);
79
- }
80
- const contentLength = response.headers.get("content-length");
81
- if (contentLength && Number(contentLength) > maxArtifactBytes) {
82
- throw new Error(`Driggsby binary download is unexpectedly large: ${contentLength} bytes.`);
83
- }
84
- const hash = createHash("sha256");
85
- let bytesRead = 0;
86
- const verifier = new Transform({
87
- transform(chunk, _encoding, callback) {
88
- bytesRead += chunk.byteLength;
89
- if (bytesRead > maxArtifactBytes) {
90
- callback(new Error(`Driggsby binary download exceeded ${maxArtifactBytes} bytes.`));
91
- return;
92
- }
93
- hash.update(chunk);
94
- callback(null, chunk);
95
- },
96
- });
97
- await pipeline(response.body, verifier, createWriteStream(destination, { flags: "wx", mode: 0o600 }));
98
- const actualChecksum = hash.digest("hex");
99
- if (actualChecksum !== expectedChecksum) {
100
- throw new Error(`Driggsby binary checksum mismatch for ${basename(destination)}. Expected ${expectedChecksum}, got ${actualChecksum}.`);
101
- }
102
- }
103
- function extractTarball(artifactPath, destination, binaryPath) {
104
- const tarPath = trustedTarPath();
105
- const entry = findBinaryTarEntry(tarPath, artifactPath, binaryPath);
106
- assertRegularTarEntry(tarPath, artifactPath, entry, binaryPath);
107
- writeCommandOutputToFile(tarPath, ["-xOf", artifactPath, "--", entry], destination, maxArtifactBytes);
108
- if (!existsSync(destination)) {
109
- throw new Error(`Driggsby archive did not contain expected binary ${binaryPath}.`);
110
- }
111
- const installedBinaryStats = lstatSync(destination);
112
- if (!installedBinaryStats.isFile() || installedBinaryStats.isSymbolicLink()) {
113
- throw new Error(`Driggsby archive entry ${binaryPath} was not a regular file.`);
114
- }
115
- }
116
- function assertRegularTarEntry(tarPath, artifactPath, entry, binaryPath) {
117
- const listings = readCommandOutput(tarPath, ["-tvf", artifactPath, "--", entry])
118
- .split("\n")
119
- .filter((line) => line.trim().length > 0);
120
- if (listings.length !== 1 || !listings[0]?.startsWith("-")) {
121
- throw new Error(`Driggsby archive entry ${binaryPath} was not a regular file.`);
122
- }
123
- }
124
- function trustedTarPath() {
125
- for (const candidate of ["/usr/bin/tar", "/bin/tar"]) {
126
- if (existsSync(candidate)) {
127
- return candidate;
128
- }
129
- }
130
- throw new Error("Could not find the system tar executable required to unpack Driggsby.");
131
- }
132
- function findBinaryTarEntry(tarPath, artifactPath, binaryPath) {
133
- const entries = readCommandOutput(tarPath, ["-tf", artifactPath])
134
- .split("\n")
135
- .map((entry) => entry.trim())
136
- .filter((entry) => entry.length > 0);
137
- const binaryEntries = [];
138
- for (const entry of entries) {
139
- const normalizedEntry = entry.replace(/\\/g, "/");
140
- const segments = normalizedEntry.split("/").filter((segment) => segment.length > 0);
141
- if (normalizedEntry.startsWith("/") ||
142
- /^[A-Za-z]:/.test(normalizedEntry) ||
143
- segments.includes("..") ||
144
- segments.some((segment) => segment.startsWith("-"))) {
145
- throw new Error(`Driggsby archive contains unsafe path ${entry}.`);
146
- }
147
- if (segments.length === 2 && segments[1] === binaryPath) {
148
- binaryEntries.push(entry);
149
- }
150
- }
151
- if (binaryEntries.length !== 1) {
152
- throw new Error(`Driggsby archive did not contain exactly one ${binaryPath} binary.`);
153
- }
154
- const [binaryEntry] = binaryEntries;
155
- if (!binaryEntry) {
156
- throw new Error(`Driggsby archive did not contain expected binary ${binaryPath}.`);
157
- }
158
- return binaryEntry;
159
- }
package/lib/artifacts.js DELETED
@@ -1,49 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- export const packageDirectory = dirname(dirname(fileURLToPath(import.meta.url)));
5
- export const packageBinDirectory = join(packageDirectory, "bin");
6
- export const packageBinPath = join(packageBinDirectory, "driggsby");
7
- export function readPackageJson() {
8
- return JSON.parse(readFileSync(join(packageDirectory, "package.json"), "utf8"));
9
- }
10
- export function resolvePlatform(packageJson) {
11
- const triple = targetTriple();
12
- return {
13
- platform: packageJson.driggsbyArtifacts.supportedPlatforms[triple],
14
- supportedTargets: Object.keys(packageJson.driggsbyArtifacts.supportedPlatforms).sort(),
15
- triple,
16
- };
17
- }
18
- export function unsupportedPlatformMessage(resolution) {
19
- const supported = resolution.supportedTargets.length > 0
20
- ? resolution.supportedTargets.join(", ")
21
- : "none";
22
- return `Driggsby does not currently publish a native binary for ${process.platform}/${process.arch} (${resolution.triple}). Supported targets: ${supported}.`;
23
- }
24
- function targetTriple() {
25
- const architecture = mapArchitecture(process.arch);
26
- const operatingSystem = mapOperatingSystem(process.platform);
27
- return `${architecture}-${operatingSystem}`;
28
- }
29
- function mapArchitecture(architecture) {
30
- if (architecture === "arm64") {
31
- return "aarch64";
32
- }
33
- if (architecture === "x64") {
34
- return "x86_64";
35
- }
36
- return architecture;
37
- }
38
- function mapOperatingSystem(platform) {
39
- if (platform === "darwin") {
40
- return "apple-darwin";
41
- }
42
- if (platform === "linux") {
43
- return "unknown-linux-gnu";
44
- }
45
- if (platform === "win32") {
46
- return "pc-windows-msvc";
47
- }
48
- return platform;
49
- }
package/lib/process.js DELETED
@@ -1,65 +0,0 @@
1
- import { spawnSync } from "node:child_process";
2
- import { writeFileSync } from "node:fs";
3
- export function runFile(command, args) {
4
- const result = spawnSync(command, args, {
5
- cwd: process.cwd(),
6
- stdio: "inherit",
7
- });
8
- if (result.error) {
9
- throw result.error;
10
- }
11
- return { status: result.status ?? 1 };
12
- }
13
- export function spawnFile(command, args) {
14
- const result = runFile(command, args);
15
- if (result.status !== 0) {
16
- throw new Error(`${command} exited with status ${result.status}.`);
17
- }
18
- }
19
- export function readCommandOutput(command, args) {
20
- const result = spawnSync(command, args, {
21
- cwd: process.cwd(),
22
- encoding: "utf8",
23
- maxBuffer: 1024 * 1024,
24
- });
25
- if (result.error) {
26
- throw result.error;
27
- }
28
- if (result.status !== 0) {
29
- const stderr = result.stderr.trim();
30
- const detail = stderr.length > 0 ? `: ${stderr}` : "";
31
- throw new Error(`${command} exited with status ${result.status ?? 1}${detail}.`);
32
- }
33
- return result.stdout;
34
- }
35
- export function writeCommandOutputToFile(command, args, destination, maxBytes) {
36
- const result = spawnSync(command, args, {
37
- cwd: process.cwd(),
38
- encoding: "buffer",
39
- maxBuffer: maxBytes,
40
- });
41
- if (result.error) {
42
- throw result.error;
43
- }
44
- if (result.status !== 0) {
45
- const stderr = result.stderr.toString("utf8").trim();
46
- const detail = stderr.length > 0 ? `: ${stderr}` : "";
47
- throw new Error(`${command} exited with status ${result.status ?? 1}${detail}.`);
48
- }
49
- writeFileSync(destination, result.stdout, { flag: "wx", mode: 0o700 });
50
- }
51
- export function spawnFileAndExit(command, args) {
52
- try {
53
- const result = runFile(command, args);
54
- process.exit(result.status);
55
- }
56
- catch (error) {
57
- if (error instanceof Error) {
58
- console.error(error.message);
59
- }
60
- else {
61
- console.error(error);
62
- }
63
- process.exit(1);
64
- }
65
- }