@mistweaverco/kulala-core 0.18.0 → 0.18.2

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/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { spawnSync } from "node:child_process";
4
+ import { spawn } from "node:child_process";
5
5
 
6
6
  // src/lib/downloader/index.ts
7
7
  import fs from "node:fs";
@@ -11,7 +11,7 @@ import { chmodSync, createWriteStream } from "node:fs";
11
11
  import { pipeline } from "node:stream/promises";
12
12
 
13
13
  // src/versions/backend.ts
14
- var KULALA_CORE_VERSION = "0.18.0";
14
+ var KULALA_CORE_VERSION = "0.18.2";
15
15
 
16
16
  // src/lib/downloader/index.ts
17
17
  var PACKAGE_ROOT = path.dirname(fileURLToPath(import.meta.url));
@@ -185,7 +185,7 @@ async function tryInstallBackend() {
185
185
  console.error("@mistweaverco/kulala-core will attempt to download it on first use instead.");
186
186
  }
187
187
  }
188
- async function ensureInstalled() {
188
+ function resolveExecutableSync() {
189
189
  const fromEnv = process.env.KULALA_CORE_PATH;
190
190
  if (fromEnv && fromEnv.length > 0) {
191
191
  if (!fs.existsSync(fromEnv)) {
@@ -200,6 +200,13 @@ async function ensureInstalled() {
200
200
  if (binaryExists() && versionMatches()) {
201
201
  return getBinPath();
202
202
  }
203
+ return null;
204
+ }
205
+ async function ensureInstalled() {
206
+ const cached = resolveExecutableSync();
207
+ if (cached) {
208
+ return cached;
209
+ }
203
210
  if (binaryExists()) {
204
211
  removeStaleBinary();
205
212
  }
@@ -208,6 +215,7 @@ async function ensureInstalled() {
208
215
  }
209
216
  var downloader = {
210
217
  ensureInstalled,
218
+ resolveExecutableSync,
211
219
  getBinPath,
212
220
  installBackend,
213
221
  tryInstallBackend
@@ -215,15 +223,21 @@ var downloader = {
215
223
 
216
224
  // src/cli.ts
217
225
  async function main() {
218
- const executable = await downloader.ensureInstalled();
219
- const result = spawnSync(executable, process.argv.slice(2), {
220
- stdio: "inherit",
226
+ const executable = downloader.resolveExecutableSync() ?? await downloader.ensureInstalled();
227
+ const child = spawn(executable, process.argv.slice(2), {
228
+ stdio: [process.stdin, process.stdout, process.stderr],
221
229
  env: process.env
222
230
  });
223
- if (result.error) {
224
- throw result.error;
225
- }
226
- process.exit(result.status ?? 1);
231
+ await new Promise((resolve, reject) => {
232
+ child.on("error", reject);
233
+ child.on("close", (code, signal) => {
234
+ if (signal) {
235
+ process.kill(process.pid, signal);
236
+ return;
237
+ }
238
+ process.exit(code ?? 1);
239
+ });
240
+ });
227
241
  }
228
242
  main().catch((error) => {
229
243
  const message = error instanceof Error ? error.message : String(error);
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { chmodSync, createWriteStream } from "node:fs";
9
9
  import { pipeline } from "node:stream/promises";
10
10
 
11
11
  // src/versions/backend.ts
12
- var KULALA_CORE_VERSION = "0.18.0";
12
+ var KULALA_CORE_VERSION = "0.18.2";
13
13
 
14
14
  // src/lib/downloader/index.ts
15
15
  var PACKAGE_ROOT = path.dirname(fileURLToPath(import.meta.url));
@@ -183,7 +183,7 @@ async function tryInstallBackend() {
183
183
  console.error("@mistweaverco/kulala-core will attempt to download it on first use instead.");
184
184
  }
185
185
  }
186
- async function ensureInstalled() {
186
+ function resolveExecutableSync() {
187
187
  const fromEnv = process.env.KULALA_CORE_PATH;
188
188
  if (fromEnv && fromEnv.length > 0) {
189
189
  if (!fs.existsSync(fromEnv)) {
@@ -198,6 +198,13 @@ async function ensureInstalled() {
198
198
  if (binaryExists() && versionMatches()) {
199
199
  return getBinPath();
200
200
  }
201
+ return null;
202
+ }
203
+ async function ensureInstalled() {
204
+ const cached = resolveExecutableSync();
205
+ if (cached) {
206
+ return cached;
207
+ }
201
208
  if (binaryExists()) {
202
209
  removeStaleBinary();
203
210
  }
@@ -206,6 +213,7 @@ async function ensureInstalled() {
206
213
  }
207
214
  var downloader = {
208
215
  ensureInstalled,
216
+ resolveExecutableSync,
209
217
  getBinPath,
210
218
  installBackend,
211
219
  tryInstallBackend
@@ -0,0 +1,202 @@
1
+ // src/postinstall.ts
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
5
+
6
+ // src/lib/downloader/index.ts
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { chmodSync, createWriteStream } from "node:fs";
11
+ import { pipeline } from "node:stream/promises";
12
+
13
+ // src/versions/backend.ts
14
+ var KULALA_CORE_VERSION = "0.18.2";
15
+
16
+ // src/lib/downloader/index.ts
17
+ var PACKAGE_ROOT = path.dirname(fileURLToPath(import.meta.url));
18
+ var BINARY_NAME = "kulala-core";
19
+ var DOWNLOAD_URL = "https://github.com/mistweaverco/kulala-core/releases/download/v%s/%s";
20
+ function platform() {
21
+ const os = process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "windows" : "linux";
22
+ const arch = process.arch;
23
+ let archName = arch;
24
+ if (arch === "x64") {
25
+ archName = "x86_64";
26
+ } else if (arch === "arm64") {
27
+ archName = os === "darwin" ? "arm64" : "aarch64";
28
+ }
29
+ return `${os}-${archName}`;
30
+ }
31
+ function getBinDir() {
32
+ return path.join(PACKAGE_ROOT, "bin");
33
+ }
34
+ function getReleaseBinName() {
35
+ const name = `${BINARY_NAME}-${platform()}`;
36
+ return process.platform === "win32" ? `${name}.exe` : name;
37
+ }
38
+ function getBinName() {
39
+ return process.platform === "win32" ? `${BINARY_NAME}.exe` : BINARY_NAME;
40
+ }
41
+ function getBinPath() {
42
+ return path.join(getBinDir(), getBinName());
43
+ }
44
+ function getVersionPath() {
45
+ return path.join(getBinDir(), "version.txt");
46
+ }
47
+ function getLocalDevBinaryPath() {
48
+ const candidates = [
49
+ path.join(PACKAGE_ROOT, "..", "core", "dist", "kulala-core"),
50
+ path.join(PACKAGE_ROOT, "..", "..", "core", "dist", "kulala-core")
51
+ ];
52
+ for (const candidate of candidates) {
53
+ if (fs.existsSync(candidate)) {
54
+ return candidate;
55
+ }
56
+ }
57
+ return null;
58
+ }
59
+ function binaryExists() {
60
+ return fs.existsSync(getBinPath());
61
+ }
62
+ function getInstalledVersion() {
63
+ const versionPath = getVersionPath();
64
+ if (!fs.existsSync(versionPath)) {
65
+ return null;
66
+ }
67
+ return fs.readFileSync(versionPath, "utf-8").trim();
68
+ }
69
+ function versionMatches() {
70
+ const installed = getInstalledVersion();
71
+ return installed === KULALA_CORE_VERSION;
72
+ }
73
+ function makeExecutable(filePath) {
74
+ if (process.platform !== "win32") {
75
+ chmodSync(filePath, 493);
76
+ }
77
+ }
78
+ var SPINNER_FRAMES = [
79
+ "⠋",
80
+ "⠙",
81
+ "⠹",
82
+ "⠸",
83
+ "⠼",
84
+ "⠴",
85
+ "⠦",
86
+ "⠧",
87
+ "⠇",
88
+ "⠏"
89
+ ];
90
+ function isInteractiveTerminal() {
91
+ return process.stderr.isTTY === true;
92
+ }
93
+ function createDownloadProgress() {
94
+ let timer;
95
+ let frame = 0;
96
+ let message = "";
97
+ const clearLine = () => {
98
+ if (timer) {
99
+ clearInterval(timer);
100
+ timer = undefined;
101
+ }
102
+ if (isInteractiveTerminal()) {
103
+ process.stderr.write("\r\x1B[K");
104
+ }
105
+ };
106
+ return {
107
+ start(msg) {
108
+ message = msg;
109
+ if (!isInteractiveTerminal()) {
110
+ console.error(message);
111
+ return;
112
+ }
113
+ const render = () => {
114
+ process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${message}`);
115
+ frame = (frame + 1) % SPINNER_FRAMES.length;
116
+ };
117
+ render();
118
+ timer = setInterval(render, 80);
119
+ },
120
+ succeed(msg) {
121
+ clearLine();
122
+ console.error(msg);
123
+ },
124
+ fail() {
125
+ clearLine();
126
+ }
127
+ };
128
+ }
129
+ async function downloadFile(url, outputPath) {
130
+ const response = await fetch(url);
131
+ if (!response.ok || !response.body) {
132
+ throw new Error(`Failed to download kulala-core from ${url}: ${response.status} ${response.statusText}`);
133
+ }
134
+ await pipeline(response.body, createWriteStream(outputPath));
135
+ }
136
+ function removeStaleBinary() {
137
+ if (!binaryExists()) {
138
+ return;
139
+ }
140
+ fs.unlinkSync(getBinPath());
141
+ const versionPath = getVersionPath();
142
+ if (fs.existsSync(versionPath)) {
143
+ fs.unlinkSync(versionPath);
144
+ }
145
+ }
146
+ async function installBackend() {
147
+ const binDir = getBinDir();
148
+ fs.mkdirSync(binDir, { recursive: true });
149
+ const releaseName = getReleaseBinName();
150
+ const url = DOWNLOAD_URL.replace("%s", KULALA_CORE_VERSION).replace("%s", releaseName);
151
+ const downloadPath = path.join(binDir, `${releaseName}.download`);
152
+ const binPath = getBinPath();
153
+ const progress = createDownloadProgress();
154
+ progress.start(`Downloading kulala-core v${KULALA_CORE_VERSION}...`);
155
+ try {
156
+ await downloadFile(url, downloadPath);
157
+ makeExecutable(downloadPath);
158
+ fs.renameSync(downloadPath, binPath);
159
+ fs.writeFileSync(getVersionPath(), KULALA_CORE_VERSION, "utf-8");
160
+ progress.succeed(`Installed kulala-core to ${binPath}`);
161
+ } catch (error) {
162
+ progress.fail();
163
+ throw error;
164
+ }
165
+ }
166
+ async function tryInstallBackend() {
167
+ const fromEnv = process.env.KULALA_CORE_PATH;
168
+ if (fromEnv && fromEnv.length > 0) {
169
+ return;
170
+ }
171
+ if (getLocalDevBinaryPath()) {
172
+ return;
173
+ }
174
+ if (binaryExists() && versionMatches()) {
175
+ return;
176
+ }
177
+ if (binaryExists()) {
178
+ removeStaleBinary();
179
+ }
180
+ try {
181
+ await installBackend();
182
+ } catch (error) {
183
+ const message = error instanceof Error ? error.message : String(error);
184
+ console.error(`Warning: failed to download kulala-core during install: ${message}`);
185
+ console.error("@mistweaverco/kulala-core will attempt to download it on first use instead.");
186
+ }
187
+ }
188
+
189
+ // src/postinstall.ts
190
+ var packageRoot = join(dirname(fileURLToPath2(import.meta.url)), "..");
191
+ if (existsSync(join(packageRoot, "scripts", "build.ts"))) {
192
+ process.exit(0);
193
+ }
194
+ try {
195
+ await tryInstallBackend();
196
+ } catch (error) {
197
+ const message = error instanceof Error ? error.message : String(error);
198
+ process.stderr.write(`Warning: kulala-core postinstall failed: ${message}
199
+ `);
200
+ process.stderr.write(`@mistweaverco/kulala-core will attempt to download it on first use instead.
201
+ `);
202
+ }
@@ -5,9 +5,11 @@ export declare function installBackend(): Promise<void>;
5
5
  * Never throws; logs a warning when download fails so first-use fallback can run.
6
6
  */
7
7
  export declare function tryInstallBackend(): Promise<void>;
8
+ export declare function resolveExecutableSync(): string | null;
8
9
  export declare function ensureInstalled(): Promise<string>;
9
10
  export declare const downloader: {
10
11
  ensureInstalled: typeof ensureInstalled;
12
+ resolveExecutableSync: typeof resolveExecutableSync;
11
13
  getBinPath: typeof getBinPath;
12
14
  installBackend: typeof installBackend;
13
15
  tryInstallBackend: typeof tryInstallBackend;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mistweaverco/kulala-core",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {