@lasso-ai/cli 1.4.1 → 1.4.3

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.
@@ -10,6 +10,8 @@ const node_fs_1 = __importDefault(require("node:fs"));
10
10
  const node_os_1 = __importDefault(require("node:os"));
11
11
  const node_path_1 = __importDefault(require("node:path"));
12
12
  const node_child_process_1 = require("node:child_process");
13
+ const node_https_1 = __importDefault(require("node:https"));
14
+ const node_http_1 = __importDefault(require("node:http"));
13
15
  const paths_1 = require("./paths");
14
16
  exports.TLS_KEY_FILE = node_path_1.default.join(paths_1.HOST_DIR, "host.key");
15
17
  exports.TLS_CERT_FILE = node_path_1.default.join(paths_1.HOST_DIR, "host.crt");
@@ -17,79 +19,213 @@ function hasCertificate() {
17
19
  return node_fs_1.default.existsSync(exports.TLS_KEY_FILE) && node_fs_1.default.existsSync(exports.TLS_CERT_FILE);
18
20
  }
19
21
  function isMkcertInstalled() {
22
+ // Check system PATH first
20
23
  try {
21
24
  (0, node_child_process_1.execFileSync)("mkcert", ["-version"], { stdio: "ignore" });
22
25
  return true;
23
26
  }
24
27
  catch {
28
+ // Check local installation
29
+ try {
30
+ const localMkcert = node_path_1.default.join(node_os_1.default.homedir(), ".lasso", "bin", "mkcert");
31
+ if (node_fs_1.default.existsSync(localMkcert)) {
32
+ (0, node_child_process_1.execFileSync)(localMkcert, ["-version"], { stdio: "ignore" });
33
+ return true;
34
+ }
35
+ }
36
+ catch { }
25
37
  return false;
26
38
  }
27
39
  }
28
- async function installMkcert() {
40
+ function getMkcertPath() {
41
+ // Check local installation first
42
+ const localMkcert = node_path_1.default.join(node_os_1.default.homedir(), ".lasso", "bin", "mkcert");
43
+ if (node_fs_1.default.existsSync(localMkcert)) {
44
+ return localMkcert;
45
+ }
46
+ return "mkcert";
47
+ }
48
+ async function downloadMkcert() {
49
+ const platform = node_os_1.default.platform();
50
+ const arch = node_os_1.default.arch();
51
+ let downloadUrl;
52
+ let binaryName;
53
+ // Determine the correct binary for the platform
54
+ if (platform === "darwin") {
55
+ if (arch === "x64") {
56
+ downloadUrl = "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-darwin-amd64";
57
+ binaryName = "mkcert-darwin-amd64";
58
+ }
59
+ else if (arch === "arm64") {
60
+ downloadUrl = "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-darwin-arm64";
61
+ binaryName = "mkcert-darwin-arm64";
62
+ }
63
+ else {
64
+ return { ok: false, error: `Unsupported architecture: ${arch}` };
65
+ }
66
+ }
67
+ else if (platform === "linux") {
68
+ if (arch === "x64") {
69
+ downloadUrl = "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64";
70
+ binaryName = "mkcert-linux-amd64";
71
+ }
72
+ else if (arch === "arm64") {
73
+ downloadUrl = "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-arm64";
74
+ binaryName = "mkcert-linux-arm64";
75
+ }
76
+ else {
77
+ return { ok: false, error: `Unsupported architecture: ${arch}` };
78
+ }
79
+ }
80
+ else {
81
+ return { ok: false, error: `Unsupported platform: ${platform}` };
82
+ }
29
83
  return new Promise((resolve) => {
30
- const platform = node_os_1.default.platform();
31
- let installCommand;
32
- let installArgs;
33
- if (platform === "darwin") {
34
- // macOS: Check if Homebrew is available
35
- try {
36
- (0, node_child_process_1.execFileSync)("brew", ["--version"], { stdio: "ignore" });
37
- installCommand = "brew";
38
- installArgs = ["install", "mkcert", "nss"];
84
+ const protocol = downloadUrl.startsWith("https") ? node_https_1.default : node_http_1.default;
85
+ const tempDir = node_os_1.default.tmpdir();
86
+ const tempPath = node_path_1.default.join(tempDir, binaryName);
87
+ console.log(`[Lasso] Downloading mkcert from ${downloadUrl}...`);
88
+ const file = node_fs_1.default.createWriteStream(tempPath);
89
+ protocol.get(downloadUrl, (response) => {
90
+ if (response.statusCode !== 200) {
91
+ node_fs_1.default.unlinkSync(tempPath);
92
+ return resolve({ ok: false, error: `Failed to download mkcert: ${response.statusCode}` });
39
93
  }
40
- catch {
41
- return resolve({ ok: false, error: "Homebrew not found. Please install Homebrew first: https://brew.sh/" });
94
+ response.pipe(file);
95
+ file.on("finish", () => {
96
+ file.close();
97
+ node_fs_1.default.chmodSync(tempPath, 0o755);
98
+ console.log(`[Lasso] ✓ mkcert downloaded to ${tempPath}`);
99
+ resolve({ ok: true, path: tempPath });
100
+ });
101
+ }).on("error", (error) => {
102
+ node_fs_1.default.unlinkSync(tempPath);
103
+ resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
104
+ });
105
+ });
106
+ }
107
+ async function installMkcert() {
108
+ const platform = node_os_1.default.platform();
109
+ // Try package manager first
110
+ if (platform === "darwin") {
111
+ try {
112
+ (0, node_child_process_1.execFileSync)("brew", ["--version"], { stdio: "ignore" });
113
+ console.log("[Lasso] Installing mkcert via Homebrew...");
114
+ const installResult = await new Promise((resolve) => {
115
+ const install = (0, node_child_process_1.spawn)("brew", ["install", "mkcert", "nss"], { stdio: "inherit" });
116
+ install.on("close", (code) => {
117
+ if (code === 0)
118
+ resolve({ ok: true });
119
+ else
120
+ resolve({ ok: false, error: `Homebrew install failed with code ${code}` });
121
+ });
122
+ install.on("error", (error) => {
123
+ resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
124
+ });
125
+ });
126
+ if (installResult.ok) {
127
+ (0, node_child_process_1.execFileSync)("mkcert", ["-install"], { stdio: "ignore" });
128
+ console.log("[Lasso] ✓ mkcert installed and CA configured");
129
+ return { ok: true };
42
130
  }
43
131
  }
44
- else if (platform === "linux") {
45
- // Linux: Try different package managers
46
- try {
47
- (0, node_child_process_1.execFileSync)("apt-get", ["--version"], { stdio: "ignore" });
48
- installCommand = "sudo";
49
- installArgs = ["apt-get", "install", "-y", "mkcert"];
50
- }
51
- catch {
52
- try {
53
- (0, node_child_process_1.execFileSync)("dnf", ["--version"], { stdio: "ignore" });
54
- installCommand = "sudo";
55
- installArgs = ["dnf", "install", "-y", "mkcert"];
56
- }
57
- catch {
58
- return resolve({ ok: false, error: "Could not detect package manager. Please install mkcert manually: https://mkcert.dev/" });
59
- }
132
+ catch {
133
+ console.log("[Lasso] Homebrew not available, trying direct download...");
134
+ }
135
+ }
136
+ else if (platform === "linux") {
137
+ try {
138
+ (0, node_child_process_1.execFileSync)("apt-get", ["--version"], { stdio: "ignore" });
139
+ console.log("[Lasso] Installing mkcert via apt-get...");
140
+ const installResult = await new Promise((resolve) => {
141
+ const install = (0, node_child_process_1.spawn)("sudo", ["apt-get", "install", "-y", "mkcert"], { stdio: "inherit" });
142
+ install.on("close", (code) => {
143
+ if (code === 0)
144
+ resolve({ ok: true });
145
+ else
146
+ resolve({ ok: false, error: `apt-get install failed with code ${code}` });
147
+ });
148
+ install.on("error", (error) => {
149
+ resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
150
+ });
151
+ });
152
+ if (installResult.ok) {
153
+ (0, node_child_process_1.execFileSync)("mkcert", ["-install"], { stdio: "ignore" });
154
+ console.log("[Lasso] ✓ mkcert installed and CA configured");
155
+ return { ok: true };
60
156
  }
61
157
  }
62
- else {
63
- return resolve({ ok: false, error: `Automatic mkcert installation not supported on ${platform}. Please install manually: https://mkcert.dev/` });
64
- }
65
- console.log(`[Lasso] Installing mkcert (this may require sudo password)...`);
66
- const install = (0, node_child_process_1.spawn)(installCommand, installArgs, { stdio: "inherit" });
67
- install.on("close", (code) => {
68
- if (code === 0) {
69
- // Install the local CA
70
- try {
158
+ catch {
159
+ try {
160
+ (0, node_child_process_1.execFileSync)("dnf", ["--version"], { stdio: "ignore" });
161
+ console.log("[Lasso] Installing mkcert via dnf...");
162
+ const installResult = await new Promise((resolve) => {
163
+ const install = (0, node_child_process_1.spawn)("sudo", ["dnf", "install", "-y", "mkcert"], { stdio: "inherit" });
164
+ install.on("close", (code) => {
165
+ if (code === 0)
166
+ resolve({ ok: true });
167
+ else
168
+ resolve({ ok: false, error: `dnf install failed with code ${code}` });
169
+ });
170
+ install.on("error", (error) => {
171
+ resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
172
+ });
173
+ });
174
+ if (installResult.ok) {
71
175
  (0, node_child_process_1.execFileSync)("mkcert", ["-install"], { stdio: "ignore" });
72
176
  console.log("[Lasso] ✓ mkcert installed and CA configured");
73
- resolve({ ok: true });
74
- }
75
- catch (error) {
76
- resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
177
+ return { ok: true };
77
178
  }
78
179
  }
79
- else {
80
- resolve({ ok: false, error: `mkcert installation failed with code ${code}` });
180
+ catch {
181
+ console.log("[Lasso] Package manager not available, trying direct download...");
81
182
  }
82
- });
83
- install.on("error", (error) => {
84
- resolve({ ok: false, error: error instanceof Error ? error.message : String(error) });
85
- });
86
- });
183
+ }
184
+ }
185
+ // Fallback: Download mkcert binary directly from GitHub
186
+ console.log("[Lasso] Downloading mkcert binary from GitHub...");
187
+ const downloadResult = await downloadMkcert();
188
+ if (!downloadResult.ok || !downloadResult.path) {
189
+ return { ok: false, error: downloadResult.error || "Failed to download mkcert binary" };
190
+ }
191
+ // Copy binary to a permanent location
192
+ const binDir = node_path_1.default.join(node_os_1.default.homedir(), ".lasso", "bin");
193
+ node_fs_1.default.mkdirSync(binDir, { recursive: true, mode: 0o755 });
194
+ const mkcertPath = node_path_1.default.join(binDir, "mkcert");
195
+ node_fs_1.default.copyFileSync(downloadResult.path, mkcertPath);
196
+ node_fs_1.default.chmodSync(mkcertPath, 0o755);
197
+ // Clean up temp file
198
+ try {
199
+ node_fs_1.default.unlinkSync(downloadResult.path);
200
+ }
201
+ catch { }
202
+ // Install the local CA using the downloaded binary
203
+ try {
204
+ (0, node_child_process_1.execFileSync)(mkcertPath, ["-install"], { stdio: "inherit" });
205
+ console.log("[Lasso] ✓ mkcert installed and CA configured");
206
+ return { ok: true };
207
+ }
208
+ catch (error) {
209
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
210
+ }
87
211
  }
88
212
  async function ensureHostCertificate(onProgress) {
89
213
  node_fs_1.default.mkdirSync(paths_1.HOST_DIR, { recursive: true, mode: 0o700 });
214
+ // Check if certificate exists and is trusted
90
215
  if (hasCertificate()) {
91
216
  const certStatus = hostCertificateStatus();
92
- return { ok: true, trusted: certStatus.trusted };
217
+ // If certificate exists but is not trusted and mkcert is available, regenerate it
218
+ if (!certStatus.trusted && isMkcertInstalled()) {
219
+ onProgress?.("Regenerating certificate with mkcert for trusted SSL...");
220
+ try {
221
+ node_fs_1.default.unlinkSync(exports.TLS_CERT_FILE);
222
+ node_fs_1.default.unlinkSync(exports.TLS_KEY_FILE);
223
+ }
224
+ catch { }
225
+ }
226
+ else {
227
+ return { ok: true, trusted: certStatus.trusted };
228
+ }
93
229
  }
94
230
  onProgress?.("Generating SSL certificate...");
95
231
  // Try mkcert first - it creates system-trusted certificates
@@ -104,7 +240,8 @@ async function ensureHostCertificate(onProgress) {
104
240
  if (isMkcertInstalled()) {
105
241
  try {
106
242
  onProgress?.("Creating trusted certificate with mkcert...");
107
- (0, node_child_process_1.execFileSync)("mkcert", ["-cert-file", exports.TLS_CERT_FILE, "-key-file", exports.TLS_KEY_FILE, "localhost", "127.0.0.1", "::1", "*.lasso"], { stdio: "ignore" });
243
+ const mkcertPath = getMkcertPath();
244
+ (0, node_child_process_1.execFileSync)(mkcertPath, ["-cert-file", exports.TLS_CERT_FILE, "-key-file", exports.TLS_KEY_FILE, "localhost", "127.0.0.1", "::1", "*.lasso"], { stdio: "ignore" });
108
245
  node_fs_1.default.chmodSync(exports.TLS_KEY_FILE, 0o600);
109
246
  onProgress?.("✓ SSL certificate ready (trusted)");
110
247
  return { ok: true, trusted: true };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lasso-ai/cli",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "Select any part of your running app, describe a change, and let AI edit the real source code.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/cli/index.js",