@keystrokehq/cli 0.0.160 → 0.0.162
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/discovery-DV7FkTRA-JYiC_9cY.mjs +71 -0
- package/dist/discovery-DV7FkTRA-JYiC_9cY.mjs.map +1 -0
- package/dist/{dist-Bux5mRKJ.mjs → dist-DaxU7U68.mjs} +4 -4
- package/dist/{dist-Bux5mRKJ.mjs.map → dist-DaxU7U68.mjs.map} +1 -1
- package/dist/{dist-D4vZsmLQ.mjs → dist-DlKPt1x2.mjs} +4 -3
- package/dist/{dist-D4vZsmLQ.mjs.map → dist-DlKPt1x2.mjs.map} +1 -1
- package/dist/{dist-Dk0phE6_.mjs → dist-VxvEaDUL.mjs} +4 -2
- package/dist/dist-VxvEaDUL.mjs.map +1 -0
- package/dist/index.mjs +10 -87
- package/dist/index.mjs.map +1 -1
- package/dist/maybe-auto-update-0abXnfw7.mjs +408 -0
- package/dist/maybe-auto-update-0abXnfw7.mjs.map +1 -0
- package/dist/{discovery-DV7FkTRA-BFmtZG9u.mjs → schemas-Bq8SXmZk.mjs} +2 -69
- package/dist/schemas-Bq8SXmZk.mjs.map +1 -0
- package/dist/{version-DESgLEkE.mjs → version-MB0r46Z4.mjs} +81 -2
- package/dist/version-MB0r46Z4.mjs.map +1 -0
- package/dist/{walk-project-171B4cvO-DJy3qZKd.mjs → walk-project-171B4cvO-DKtupJ6Z.mjs} +2 -2
- package/dist/{walk-project-171B4cvO-DJy3qZKd.mjs.map → walk-project-171B4cvO-DKtupJ6Z.mjs.map} +1 -1
- package/package.json +1 -1
- package/dist/discovery-DV7FkTRA-BFmtZG9u.mjs.map +0 -1
- package/dist/dist-Dk0phE6_.mjs.map +0 -1
- package/dist/maybe-auto-update-DCsPT080.mjs +0 -247
- package/dist/maybe-auto-update-DCsPT080.mjs.map +0 -1
- package/dist/version-DESgLEkE.mjs.map +0 -1
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { l as getCliConfigDir, r as detectPackageManager, s as resolveCliRoot, t as readCliVersion } from "./version-MB0r46Z4.mjs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
//#region src/update/compare-version.ts
|
|
7
|
+
function parseVersion(version) {
|
|
8
|
+
const [major = 0, minor = 0, patch = 0] = (version.trim().replace(/^v/, "").split("-")[0] ?? "").split(".").map((part) => {
|
|
9
|
+
const value = Number.parseInt(part, 10);
|
|
10
|
+
return Number.isFinite(value) ? value : 0;
|
|
11
|
+
});
|
|
12
|
+
return [
|
|
13
|
+
major,
|
|
14
|
+
minor,
|
|
15
|
+
patch
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
function isNewerVersion(latest, current) {
|
|
19
|
+
const [latestMajor, latestMinor, latestPatch] = parseVersion(latest);
|
|
20
|
+
const [currentMajor, currentMinor, currentPatch] = parseVersion(current);
|
|
21
|
+
if (latestMajor !== currentMajor) return latestMajor > currentMajor;
|
|
22
|
+
if (latestMinor !== currentMinor) return latestMinor > currentMinor;
|
|
23
|
+
return latestPatch > currentPatch;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/update/detect-cli-install.ts
|
|
27
|
+
function realpathSafe(path) {
|
|
28
|
+
try {
|
|
29
|
+
return realpathSync(path);
|
|
30
|
+
} catch {
|
|
31
|
+
return path;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function detectManagerFromLockfile(dir) {
|
|
35
|
+
if (existsSync(join(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
36
|
+
if (existsSync(join(dir, "bun.lockb")) || existsSync(join(dir, "bun.lock"))) return "bun";
|
|
37
|
+
if (existsSync(join(dir, "yarn.lock"))) return "yarn";
|
|
38
|
+
if (existsSync(join(dir, "package-lock.json"))) return "npm";
|
|
39
|
+
}
|
|
40
|
+
function findLocalProjectRoot(packageRoot) {
|
|
41
|
+
const normalizedRoot = realpathSafe(packageRoot);
|
|
42
|
+
let dir = dirname(packageRoot);
|
|
43
|
+
while (dir !== dirname(dir)) {
|
|
44
|
+
const installedCliPath = join(dir, "node_modules", "@keystrokehq", "cli");
|
|
45
|
+
if (existsSync(join(dir, "package.json")) && realpathSafe(installedCliPath) === normalizedRoot) return dir;
|
|
46
|
+
dir = dirname(dir);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function globalRootForManager(manager) {
|
|
50
|
+
const { command, args } = {
|
|
51
|
+
pnpm: {
|
|
52
|
+
command: "pnpm",
|
|
53
|
+
args: ["root", "-g"]
|
|
54
|
+
},
|
|
55
|
+
npm: {
|
|
56
|
+
command: "npm",
|
|
57
|
+
args: ["root", "-g"]
|
|
58
|
+
},
|
|
59
|
+
yarn: {
|
|
60
|
+
command: "yarn",
|
|
61
|
+
args: ["global", "dir"]
|
|
62
|
+
},
|
|
63
|
+
bun: {
|
|
64
|
+
command: "bun",
|
|
65
|
+
args: ["pm", "bin"]
|
|
66
|
+
}
|
|
67
|
+
}[manager];
|
|
68
|
+
const result = spawnSync(command, args, { encoding: "utf8" });
|
|
69
|
+
if (result.status !== 0) return;
|
|
70
|
+
const root = result.stdout.trim();
|
|
71
|
+
return root ? realpathSafe(root) : void 0;
|
|
72
|
+
}
|
|
73
|
+
function detectGlobalManager(packageRoot) {
|
|
74
|
+
const normalizedRoot = realpathSafe(packageRoot);
|
|
75
|
+
if (normalizedRoot.includes(`${join("", ".pnpm")}`)) return "pnpm";
|
|
76
|
+
for (const manager of [
|
|
77
|
+
"pnpm",
|
|
78
|
+
"npm",
|
|
79
|
+
"yarn",
|
|
80
|
+
"bun"
|
|
81
|
+
]) {
|
|
82
|
+
const globalRoot = globalRootForManager(manager);
|
|
83
|
+
if (globalRoot && normalizedRoot.startsWith(globalRoot)) return manager;
|
|
84
|
+
}
|
|
85
|
+
if (process.env.PNPM_HOME) return "pnpm";
|
|
86
|
+
return detectPackageManager();
|
|
87
|
+
}
|
|
88
|
+
function detectCliInstall(packageRoot) {
|
|
89
|
+
const normalizedRoot = realpathSafe(packageRoot);
|
|
90
|
+
const projectRoot = findLocalProjectRoot(normalizedRoot);
|
|
91
|
+
if (projectRoot) return {
|
|
92
|
+
kind: "local",
|
|
93
|
+
packageManager: detectManagerFromLockfile(projectRoot) ?? detectPackageManager(),
|
|
94
|
+
packageRoot: normalizedRoot,
|
|
95
|
+
projectRoot
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
kind: "global",
|
|
99
|
+
packageManager: detectGlobalManager(normalizedRoot),
|
|
100
|
+
packageRoot: normalizedRoot
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/update/detect-release-age-block.ts
|
|
105
|
+
const RELEASE_AGE_PATTERNS = [
|
|
106
|
+
/minimumReleaseAge/i,
|
|
107
|
+
/minimum-release-age/i,
|
|
108
|
+
/ERR_PNPM_NO_MATURE_MATCHING_VERSION/,
|
|
109
|
+
/ERR_PNPM_MINIMUM_RELEASE_AGE/,
|
|
110
|
+
/does not meet the minimumReleaseAge constraint/
|
|
111
|
+
];
|
|
112
|
+
function isReleaseAgeBlock(output) {
|
|
113
|
+
return RELEASE_AGE_PATTERNS.some((pattern) => pattern.test(output));
|
|
114
|
+
}
|
|
115
|
+
function formatReleaseAgeBlockMessage(options) {
|
|
116
|
+
const retry = options.retryAfter !== void 0 ? ` Retry after ${options.retryAfter.toLocaleString()}.` : "";
|
|
117
|
+
return `@keystrokehq/cli ${options.availableVersion} is available but blocked by your minimum-release-age setting. You're on ${options.currentVersion}.${retry} Add @keystrokehq/cli to minimumReleaseAgeExclude to install immediately.`;
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
//#region src/update/fetch-latest-version.ts
|
|
121
|
+
const REGISTRY_URL = "https://registry.npmjs.org/@keystrokehq%2Fcli";
|
|
122
|
+
const REQUEST_TIMEOUT_MS = 3e3;
|
|
123
|
+
async function fetchLatestCliRelease() {
|
|
124
|
+
const controller = new AbortController();
|
|
125
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
126
|
+
try {
|
|
127
|
+
const response = await fetch(REGISTRY_URL, {
|
|
128
|
+
signal: controller.signal,
|
|
129
|
+
headers: { Accept: "application/json" }
|
|
130
|
+
});
|
|
131
|
+
if (!response.ok) return;
|
|
132
|
+
const payload = await response.json();
|
|
133
|
+
const version = payload["dist-tags"]?.latest?.trim();
|
|
134
|
+
if (!version) return;
|
|
135
|
+
return {
|
|
136
|
+
version,
|
|
137
|
+
publishedAt: payload.time?.[version]
|
|
138
|
+
};
|
|
139
|
+
} catch {
|
|
140
|
+
return;
|
|
141
|
+
} finally {
|
|
142
|
+
clearTimeout(timeout);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/update/read-pnpm-release-age-minutes.ts
|
|
147
|
+
function readPnpmMinimumReleaseAgeMinutes() {
|
|
148
|
+
const result = spawnSync("pnpm", [
|
|
149
|
+
"config",
|
|
150
|
+
"get",
|
|
151
|
+
"minimum-release-age"
|
|
152
|
+
], { encoding: "utf8" });
|
|
153
|
+
if (result.status !== 0) return;
|
|
154
|
+
const value = result.stdout.trim();
|
|
155
|
+
if (!value || value === "undefined" || value === "0") return;
|
|
156
|
+
const minutes = Number.parseInt(value, 10);
|
|
157
|
+
return Number.isFinite(minutes) && minutes > 0 ? minutes : void 0;
|
|
158
|
+
}
|
|
159
|
+
function computeReleaseAgeRetryAfter(publishedAt, minimumReleaseAgeMinutes) {
|
|
160
|
+
if (!publishedAt || !minimumReleaseAgeMinutes) return;
|
|
161
|
+
const publishedMs = Date.parse(publishedAt);
|
|
162
|
+
if (!Number.isFinite(publishedMs)) return;
|
|
163
|
+
return new Date(publishedMs + minimumReleaseAgeMinutes * 6e4);
|
|
164
|
+
}
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/update/resolve-global-pnpm-root.ts
|
|
167
|
+
/** pnpm global installs live in `<pnpm-home>/global/<major>/`. */
|
|
168
|
+
function resolveGlobalPnpmRoot(packageRoot) {
|
|
169
|
+
return packageRoot.replace(/\\/g, "/").match(/^(.*\/global\/\d+)\//)?.[1];
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/update/build-update-command.ts
|
|
173
|
+
const PACKAGE_NAME = "@keystrokehq/cli@latest";
|
|
174
|
+
function buildUpdateCommand(install) {
|
|
175
|
+
const { kind, packageManager } = install;
|
|
176
|
+
if (kind === "global") switch (packageManager) {
|
|
177
|
+
case "pnpm": return {
|
|
178
|
+
command: "pnpm",
|
|
179
|
+
args: [
|
|
180
|
+
"add",
|
|
181
|
+
"-g",
|
|
182
|
+
PACKAGE_NAME
|
|
183
|
+
],
|
|
184
|
+
cwd: resolveGlobalPnpmRoot(install.packageRoot)
|
|
185
|
+
};
|
|
186
|
+
case "yarn": return {
|
|
187
|
+
command: "yarn",
|
|
188
|
+
args: [
|
|
189
|
+
"global",
|
|
190
|
+
"add",
|
|
191
|
+
PACKAGE_NAME
|
|
192
|
+
]
|
|
193
|
+
};
|
|
194
|
+
case "bun": return {
|
|
195
|
+
command: "bun",
|
|
196
|
+
args: [
|
|
197
|
+
"add",
|
|
198
|
+
"-g",
|
|
199
|
+
PACKAGE_NAME
|
|
200
|
+
]
|
|
201
|
+
};
|
|
202
|
+
default: return {
|
|
203
|
+
command: "npm",
|
|
204
|
+
args: [
|
|
205
|
+
"install",
|
|
206
|
+
"-g",
|
|
207
|
+
PACKAGE_NAME
|
|
208
|
+
]
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const cwd = install.projectRoot;
|
|
212
|
+
switch (packageManager) {
|
|
213
|
+
case "pnpm": return {
|
|
214
|
+
command: "pnpm",
|
|
215
|
+
args: [
|
|
216
|
+
"add",
|
|
217
|
+
"-D",
|
|
218
|
+
PACKAGE_NAME
|
|
219
|
+
],
|
|
220
|
+
cwd
|
|
221
|
+
};
|
|
222
|
+
case "yarn": return {
|
|
223
|
+
command: "yarn",
|
|
224
|
+
args: [
|
|
225
|
+
"add",
|
|
226
|
+
"-D",
|
|
227
|
+
PACKAGE_NAME
|
|
228
|
+
],
|
|
229
|
+
cwd
|
|
230
|
+
};
|
|
231
|
+
case "bun": return {
|
|
232
|
+
command: "bun",
|
|
233
|
+
args: [
|
|
234
|
+
"add",
|
|
235
|
+
"-D",
|
|
236
|
+
PACKAGE_NAME
|
|
237
|
+
],
|
|
238
|
+
cwd
|
|
239
|
+
};
|
|
240
|
+
default: return {
|
|
241
|
+
command: "npm",
|
|
242
|
+
args: [
|
|
243
|
+
"install",
|
|
244
|
+
"-D",
|
|
245
|
+
PACKAGE_NAME
|
|
246
|
+
],
|
|
247
|
+
cwd
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//#endregion
|
|
252
|
+
//#region src/update/run-package-manager-update.ts
|
|
253
|
+
function updateSpawnEnv() {
|
|
254
|
+
const env = { ...process.env };
|
|
255
|
+
const pnpmHome = env.PNPM_HOME;
|
|
256
|
+
if (!pnpmHome) return env;
|
|
257
|
+
const pathKey = process.platform === "win32" ? "Path" : "PATH";
|
|
258
|
+
const path = env[pathKey] ?? "";
|
|
259
|
+
const segments = path.split(process.platform === "win32" ? ";" : ":");
|
|
260
|
+
const prefix = [`${pnpmHome}/bin`, pnpmHome].filter((dir) => !segments.includes(dir));
|
|
261
|
+
if (prefix.length > 0) env[pathKey] = [...prefix, path].filter(Boolean).join(process.platform === "win32" ? ";" : ":");
|
|
262
|
+
return env;
|
|
263
|
+
}
|
|
264
|
+
function runPackageManager(command, args, cwd) {
|
|
265
|
+
const result = spawnSync(command, args, {
|
|
266
|
+
cwd,
|
|
267
|
+
encoding: "utf8",
|
|
268
|
+
env: updateSpawnEnv()
|
|
269
|
+
});
|
|
270
|
+
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
271
|
+
return {
|
|
272
|
+
ok: result.status === 0,
|
|
273
|
+
output
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function migratePnpmGlobal(cwd) {
|
|
277
|
+
return spawnSync("pnpm", ["install"], {
|
|
278
|
+
cwd,
|
|
279
|
+
encoding: "utf8",
|
|
280
|
+
env: {
|
|
281
|
+
...updateSpawnEnv(),
|
|
282
|
+
CI: "true"
|
|
283
|
+
}
|
|
284
|
+
}).status === 0;
|
|
285
|
+
}
|
|
286
|
+
function runPackageManagerUpdate(install) {
|
|
287
|
+
const { command, args, cwd } = buildUpdateCommand(install);
|
|
288
|
+
const firstAttempt = runPackageManager(command, args, cwd);
|
|
289
|
+
if (firstAttempt.ok) return firstAttempt;
|
|
290
|
+
if (install.kind === "global" && install.packageManager === "pnpm" && cwd) {
|
|
291
|
+
if (migratePnpmGlobal(cwd)) return runPackageManager(command, args, cwd);
|
|
292
|
+
}
|
|
293
|
+
return firstAttempt;
|
|
294
|
+
}
|
|
295
|
+
//#endregion
|
|
296
|
+
//#region src/update/update-block-cache.ts
|
|
297
|
+
const CACHE_FILE = "update-check.json";
|
|
298
|
+
const GENERIC_RETRY_MS = 1440 * 60 * 1e3;
|
|
299
|
+
function cachePath(configDir = getCliConfigDir()) {
|
|
300
|
+
return join(configDir, CACHE_FILE);
|
|
301
|
+
}
|
|
302
|
+
function readUpdateBlockCache(configDir) {
|
|
303
|
+
const path = cachePath(configDir);
|
|
304
|
+
if (!existsSync(path)) return {};
|
|
305
|
+
try {
|
|
306
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
307
|
+
} catch {
|
|
308
|
+
return {};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function writeUpdateBlockCache(cache, configDir) {
|
|
312
|
+
const dir = configDir ?? getCliConfigDir();
|
|
313
|
+
mkdirSync(dir, { recursive: true });
|
|
314
|
+
writeFileSync(cachePath(dir), `${JSON.stringify(cache, null, 2)}\n`, "utf8");
|
|
315
|
+
}
|
|
316
|
+
function shouldSkipCachedUpdate(cache, registryLatest, now = Date.now()) {
|
|
317
|
+
if (cache.registryLatest !== registryLatest) return false;
|
|
318
|
+
if (cache.blockedUntil) {
|
|
319
|
+
const blockedUntilMs = Date.parse(cache.blockedUntil);
|
|
320
|
+
if (Number.isFinite(blockedUntilMs) && blockedUntilMs > now) return true;
|
|
321
|
+
}
|
|
322
|
+
if (cache.lastFailedAt) {
|
|
323
|
+
const lastFailedMs = Date.parse(cache.lastFailedAt);
|
|
324
|
+
if (Number.isFinite(lastFailedMs) && now - lastFailedMs < GENERIC_RETRY_MS) return true;
|
|
325
|
+
}
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
function clearUpdateBlockCache(configDir) {
|
|
329
|
+
writeUpdateBlockCache({}, configDir);
|
|
330
|
+
}
|
|
331
|
+
function recordReleaseAgeBlock(options) {
|
|
332
|
+
writeUpdateBlockCache({
|
|
333
|
+
registryLatest: options.registryLatest,
|
|
334
|
+
blockedUntil: options.retryAfter?.toISOString()
|
|
335
|
+
}, options.configDir);
|
|
336
|
+
}
|
|
337
|
+
function recordGenericUpdateFailure(registryLatest, configDir) {
|
|
338
|
+
writeUpdateBlockCache({
|
|
339
|
+
registryLatest,
|
|
340
|
+
lastFailedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
341
|
+
}, configDir);
|
|
342
|
+
}
|
|
343
|
+
//#endregion
|
|
344
|
+
//#region src/update/maybe-auto-update.ts
|
|
345
|
+
function shouldSkipAutoUpdate(argv) {
|
|
346
|
+
if (process.env.KEYSTROKE_DEV || process.env.KEYSTROKE_SKIP_UPDATE || process.env.KEYSTROKE_UPDATING) return true;
|
|
347
|
+
if (process.env.CI === "true" || process.env.CI === "1") return true;
|
|
348
|
+
const args = argv.slice(2);
|
|
349
|
+
if (args.length === 0) return false;
|
|
350
|
+
return args.every((arg) => arg === "-V" || arg === "--version" || arg === "-h" || arg === "--help" || arg.startsWith("-V"));
|
|
351
|
+
}
|
|
352
|
+
function reexecCli(argv) {
|
|
353
|
+
const result = spawnSync(process.execPath, argv.slice(1), {
|
|
354
|
+
stdio: "inherit",
|
|
355
|
+
env: {
|
|
356
|
+
...process.env,
|
|
357
|
+
KEYSTROKE_UPDATING: "1"
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
process.exit(result.status ?? 1);
|
|
361
|
+
}
|
|
362
|
+
function releaseAgeRetryAfter(install, publishedAt) {
|
|
363
|
+
if (install.packageManager !== "pnpm") return;
|
|
364
|
+
return computeReleaseAgeRetryAfter(publishedAt, readPnpmMinimumReleaseAgeMinutes());
|
|
365
|
+
}
|
|
366
|
+
async function maybeAutoUpdate(argv) {
|
|
367
|
+
if (shouldSkipAutoUpdate(argv)) return;
|
|
368
|
+
const install = detectCliInstall(resolveCliRoot(import.meta.url));
|
|
369
|
+
if (!install || install.kind === "local" && !install.projectRoot) return;
|
|
370
|
+
const currentVersion = readCliVersion();
|
|
371
|
+
const release = await fetchLatestCliRelease();
|
|
372
|
+
if (!release || !isNewerVersion(release.version, currentVersion)) {
|
|
373
|
+
clearUpdateBlockCache();
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (shouldSkipCachedUpdate(readUpdateBlockCache(), release.version)) return;
|
|
377
|
+
process.stderr.write(`Updating @keystrokehq/cli ${currentVersion} -> ${release.version} via ${install.packageManager}...\n`);
|
|
378
|
+
const result = runPackageManagerUpdate(install);
|
|
379
|
+
const installedVersion = readCliVersion();
|
|
380
|
+
if (isNewerVersion(installedVersion, currentVersion)) {
|
|
381
|
+
clearUpdateBlockCache();
|
|
382
|
+
process.stderr.write(`Updated @keystrokehq/cli ${currentVersion} -> ${installedVersion}.\n`);
|
|
383
|
+
reexecCli(argv);
|
|
384
|
+
}
|
|
385
|
+
if (result.ok) {
|
|
386
|
+
clearUpdateBlockCache();
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (isReleaseAgeBlock(result.output)) {
|
|
390
|
+
const retryAfter = releaseAgeRetryAfter(install, release.publishedAt);
|
|
391
|
+
recordReleaseAgeBlock({
|
|
392
|
+
registryLatest: release.version,
|
|
393
|
+
retryAfter
|
|
394
|
+
});
|
|
395
|
+
process.stderr.write(`${formatReleaseAgeBlockMessage({
|
|
396
|
+
currentVersion,
|
|
397
|
+
availableVersion: release.version,
|
|
398
|
+
retryAfter
|
|
399
|
+
})}\n`);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
recordGenericUpdateFailure(release.version);
|
|
403
|
+
process.stderr.write("Auto-update failed; continuing with the current version.\n");
|
|
404
|
+
}
|
|
405
|
+
//#endregion
|
|
406
|
+
export { maybeAutoUpdate };
|
|
407
|
+
|
|
408
|
+
//# sourceMappingURL=maybe-auto-update-0abXnfw7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maybe-auto-update-0abXnfw7.mjs","names":[],"sources":["../src/update/compare-version.ts","../src/update/detect-cli-install.ts","../src/update/detect-release-age-block.ts","../src/update/fetch-latest-version.ts","../src/update/read-pnpm-release-age-minutes.ts","../src/update/resolve-global-pnpm-root.ts","../src/update/build-update-command.ts","../src/update/run-package-manager-update.ts","../src/update/update-block-cache.ts","../src/update/maybe-auto-update.ts"],"sourcesContent":["function parseVersion(version: string): [number, number, number] {\n const normalized = version.trim().replace(/^v/, \"\").split(\"-\")[0] ?? \"\";\n const [major = 0, minor = 0, patch = 0] = normalized.split(\".\").map((part) => {\n const value = Number.parseInt(part, 10);\n return Number.isFinite(value) ? value : 0;\n });\n\n return [major, minor, patch];\n}\n\nexport function isNewerVersion(latest: string, current: string): boolean {\n const [latestMajor, latestMinor, latestPatch] = parseVersion(latest);\n const [currentMajor, currentMinor, currentPatch] = parseVersion(current);\n\n if (latestMajor !== currentMajor) {\n return latestMajor > currentMajor;\n }\n\n if (latestMinor !== currentMinor) {\n return latestMinor > currentMinor;\n }\n\n return latestPatch > currentPatch;\n}\n","import { existsSync, realpathSync } from \"node:fs\";\nimport { spawnSync } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\n\nimport { detectPackageManager, type PackageManager } from \"../init/package-manager\";\n\nexport type CliInstallKind = \"global\" | \"local\";\n\nexport type CliInstallInfo = {\n kind: CliInstallKind;\n packageManager: PackageManager;\n packageRoot: string;\n projectRoot?: string;\n};\n\nfunction realpathSafe(path: string): string {\n try {\n return realpathSync(path);\n } catch {\n return path;\n }\n}\n\nfunction detectManagerFromLockfile(dir: string): PackageManager | undefined {\n if (existsSync(join(dir, \"pnpm-lock.yaml\"))) {\n return \"pnpm\";\n }\n\n if (existsSync(join(dir, \"bun.lockb\")) || existsSync(join(dir, \"bun.lock\"))) {\n return \"bun\";\n }\n\n if (existsSync(join(dir, \"yarn.lock\"))) {\n return \"yarn\";\n }\n\n if (existsSync(join(dir, \"package-lock.json\"))) {\n return \"npm\";\n }\n\n return undefined;\n}\n\nfunction findLocalProjectRoot(packageRoot: string): string | undefined {\n const normalizedRoot = realpathSafe(packageRoot);\n let dir = dirname(packageRoot);\n\n while (dir !== dirname(dir)) {\n const installedCliPath = join(dir, \"node_modules\", \"@keystrokehq\", \"cli\");\n if (\n existsSync(join(dir, \"package.json\")) &&\n realpathSafe(installedCliPath) === normalizedRoot\n ) {\n return dir;\n }\n\n dir = dirname(dir);\n }\n\n return undefined;\n}\n\nfunction globalRootForManager(manager: PackageManager): string | undefined {\n const commands: Record<PackageManager, { command: string; args: string[] }> = {\n pnpm: { command: \"pnpm\", args: [\"root\", \"-g\"] },\n npm: { command: \"npm\", args: [\"root\", \"-g\"] },\n yarn: { command: \"yarn\", args: [\"global\", \"dir\"] },\n bun: { command: \"bun\", args: [\"pm\", \"bin\"] },\n };\n\n const { command, args } = commands[manager];\n const result = spawnSync(command, args, { encoding: \"utf8\" });\n\n if (result.status !== 0) {\n return undefined;\n }\n\n const root = result.stdout.trim();\n return root ? realpathSafe(root) : undefined;\n}\n\nfunction detectGlobalManager(packageRoot: string): PackageManager {\n const normalizedRoot = realpathSafe(packageRoot);\n\n if (normalizedRoot.includes(`${join(\"\", \".pnpm\")}`)) {\n return \"pnpm\";\n }\n\n for (const manager of [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const) {\n const globalRoot = globalRootForManager(manager);\n if (globalRoot && normalizedRoot.startsWith(globalRoot)) {\n return manager;\n }\n }\n\n if (process.env.PNPM_HOME) {\n return \"pnpm\";\n }\n\n return detectPackageManager();\n}\n\nexport function detectCliInstall(packageRoot: string): CliInstallInfo | undefined {\n const normalizedRoot = realpathSafe(packageRoot);\n const projectRoot = findLocalProjectRoot(normalizedRoot);\n\n if (projectRoot) {\n const packageManager = detectManagerFromLockfile(projectRoot) ?? detectPackageManager();\n\n return {\n kind: \"local\",\n packageManager,\n packageRoot: normalizedRoot,\n projectRoot,\n };\n }\n\n return {\n kind: \"global\",\n packageManager: detectGlobalManager(normalizedRoot),\n packageRoot: normalizedRoot,\n };\n}\n","const RELEASE_AGE_PATTERNS = [\n /minimumReleaseAge/i,\n /minimum-release-age/i,\n /ERR_PNPM_NO_MATURE_MATCHING_VERSION/,\n /ERR_PNPM_MINIMUM_RELEASE_AGE/,\n /does not meet the minimumReleaseAge constraint/,\n];\n\nexport function isReleaseAgeBlock(output: string): boolean {\n return RELEASE_AGE_PATTERNS.some((pattern) => pattern.test(output));\n}\n\nexport function formatReleaseAgeBlockMessage(options: {\n currentVersion: string;\n availableVersion: string;\n retryAfter?: Date;\n}): string {\n const retry =\n options.retryAfter !== undefined ? ` Retry after ${options.retryAfter.toLocaleString()}.` : \"\";\n\n return (\n `@keystrokehq/cli ${options.availableVersion} is available but blocked by your ` +\n `minimum-release-age setting. You're on ${options.currentVersion}.${retry} ` +\n `Add @keystrokehq/cli to minimumReleaseAgeExclude to install immediately.`\n );\n}\n","const REGISTRY_URL = \"https://registry.npmjs.org/@keystrokehq%2Fcli\";\nconst REQUEST_TIMEOUT_MS = 3_000;\n\ntype RegistryPackage = {\n \"dist-tags\"?: {\n latest?: string;\n };\n time?: Record<string, string>;\n};\n\nexport type CliRegistryRelease = {\n version: string;\n publishedAt?: string;\n};\n\nexport async function fetchLatestCliRelease(): Promise<CliRegistryRelease | undefined> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(REGISTRY_URL, {\n signal: controller.signal,\n headers: {\n Accept: \"application/json\",\n },\n });\n\n if (!response.ok) {\n return undefined;\n }\n\n const payload = (await response.json()) as RegistryPackage;\n const version = payload[\"dist-tags\"]?.latest?.trim();\n if (!version) {\n return undefined;\n }\n\n return {\n version,\n publishedAt: payload.time?.[version],\n };\n } catch {\n return undefined;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport async function fetchLatestCliVersion(): Promise<string | undefined> {\n const release = await fetchLatestCliRelease();\n return release?.version;\n}\n","import { spawnSync } from \"node:child_process\";\n\nexport function readPnpmMinimumReleaseAgeMinutes(): number | undefined {\n const result = spawnSync(\"pnpm\", [\"config\", \"get\", \"minimum-release-age\"], {\n encoding: \"utf8\",\n });\n\n if (result.status !== 0) {\n return undefined;\n }\n\n const value = result.stdout.trim();\n if (!value || value === \"undefined\" || value === \"0\") {\n return undefined;\n }\n\n const minutes = Number.parseInt(value, 10);\n return Number.isFinite(minutes) && minutes > 0 ? minutes : undefined;\n}\n\nexport function computeReleaseAgeRetryAfter(\n publishedAt: string | undefined,\n minimumReleaseAgeMinutes: number | undefined,\n): Date | undefined {\n if (!publishedAt || !minimumReleaseAgeMinutes) {\n return undefined;\n }\n\n const publishedMs = Date.parse(publishedAt);\n if (!Number.isFinite(publishedMs)) {\n return undefined;\n }\n\n return new Date(publishedMs + minimumReleaseAgeMinutes * 60_000);\n}\n","/** pnpm global installs live in `<pnpm-home>/global/<major>/`. */\nexport function resolveGlobalPnpmRoot(packageRoot: string): string | undefined {\n const normalized = packageRoot.replace(/\\\\/g, \"/\");\n const match = normalized.match(/^(.*\\/global\\/\\d+)\\//);\n return match?.[1];\n}\n","import type { CliInstallInfo } from \"./detect-cli-install\";\nimport { resolveGlobalPnpmRoot } from \"./resolve-global-pnpm-root\";\n\nconst PACKAGE_NAME = \"@keystrokehq/cli@latest\";\n\nexport function buildUpdateCommand(install: CliInstallInfo): {\n command: string;\n args: string[];\n cwd?: string;\n} {\n const { kind, packageManager } = install;\n\n if (kind === \"global\") {\n switch (packageManager) {\n case \"pnpm\":\n return {\n command: \"pnpm\",\n args: [\"add\", \"-g\", PACKAGE_NAME],\n cwd: resolveGlobalPnpmRoot(install.packageRoot),\n };\n case \"yarn\":\n return { command: \"yarn\", args: [\"global\", \"add\", PACKAGE_NAME] };\n case \"bun\":\n return { command: \"bun\", args: [\"add\", \"-g\", PACKAGE_NAME] };\n case \"npm\":\n default:\n return { command: \"npm\", args: [\"install\", \"-g\", PACKAGE_NAME] };\n }\n }\n\n const cwd = install.projectRoot;\n switch (packageManager) {\n case \"pnpm\":\n return { command: \"pnpm\", args: [\"add\", \"-D\", PACKAGE_NAME], cwd };\n case \"yarn\":\n return { command: \"yarn\", args: [\"add\", \"-D\", PACKAGE_NAME], cwd };\n case \"bun\":\n return { command: \"bun\", args: [\"add\", \"-D\", PACKAGE_NAME], cwd };\n case \"npm\":\n default:\n return { command: \"npm\", args: [\"install\", \"-D\", PACKAGE_NAME], cwd };\n }\n}\n","import { spawnSync } from \"node:child_process\";\n\nimport { buildUpdateCommand } from \"./build-update-command\";\nimport type { CliInstallInfo } from \"./detect-cli-install\";\n\nexport function updateSpawnEnv(): NodeJS.ProcessEnv {\n const env = { ...process.env };\n const pnpmHome = env.PNPM_HOME;\n\n if (!pnpmHome) {\n return env;\n }\n\n const pathKey = process.platform === \"win32\" ? \"Path\" : \"PATH\";\n const path = env[pathKey] ?? \"\";\n const segments = path.split(process.platform === \"win32\" ? \";\" : \":\");\n const binDir = `${pnpmHome}/bin`;\n const prefix = [binDir, pnpmHome].filter((dir) => !segments.includes(dir));\n\n if (prefix.length > 0) {\n env[pathKey] = [...prefix, path].filter(Boolean).join(process.platform === \"win32\" ? \";\" : \":\");\n }\n\n return env;\n}\n\nexport type PackageManagerRunResult = {\n ok: boolean;\n output: string;\n};\n\nfunction runPackageManager(command: string, args: string[], cwd?: string): PackageManagerRunResult {\n const result = spawnSync(command, args, {\n cwd,\n encoding: \"utf8\",\n env: updateSpawnEnv(),\n });\n\n const output = `${result.stdout ?? \"\"}${result.stderr ?? \"\"}`;\n\n return {\n ok: result.status === 0,\n output,\n };\n}\n\nfunction migratePnpmGlobal(cwd: string): boolean {\n const result = spawnSync(\"pnpm\", [\"install\"], {\n cwd,\n encoding: \"utf8\",\n env: {\n ...updateSpawnEnv(),\n CI: \"true\",\n },\n });\n\n return result.status === 0;\n}\n\nexport function runPackageManagerUpdate(install: CliInstallInfo): PackageManagerRunResult {\n const { command, args, cwd } = buildUpdateCommand(install);\n const firstAttempt = runPackageManager(command, args, cwd);\n\n if (firstAttempt.ok) {\n return firstAttempt;\n }\n\n if (install.kind === \"global\" && install.packageManager === \"pnpm\" && cwd) {\n if (migratePnpmGlobal(cwd)) {\n return runPackageManager(command, args, cwd);\n }\n }\n\n return firstAttempt;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { getCliConfigDir } from \"../config\";\n\nexport type UpdateBlockCache = {\n registryLatest?: string;\n blockedUntil?: string;\n lastFailedAt?: string;\n};\n\nconst CACHE_FILE = \"update-check.json\";\nconst GENERIC_RETRY_MS = 24 * 60 * 60 * 1000;\n\nfunction cachePath(configDir = getCliConfigDir()): string {\n return join(configDir, CACHE_FILE);\n}\n\nexport function readUpdateBlockCache(configDir?: string): UpdateBlockCache {\n const path = cachePath(configDir);\n if (!existsSync(path)) {\n return {};\n }\n\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as UpdateBlockCache;\n } catch {\n return {};\n }\n}\n\nexport function writeUpdateBlockCache(cache: UpdateBlockCache, configDir?: string): void {\n const dir = configDir ?? getCliConfigDir();\n mkdirSync(dir, { recursive: true });\n writeFileSync(cachePath(dir), `${JSON.stringify(cache, null, 2)}\\n`, \"utf8\");\n}\n\nexport function shouldSkipCachedUpdate(\n cache: UpdateBlockCache,\n registryLatest: string,\n now = Date.now(),\n): boolean {\n if (cache.registryLatest !== registryLatest) {\n return false;\n }\n\n if (cache.blockedUntil) {\n const blockedUntilMs = Date.parse(cache.blockedUntil);\n if (Number.isFinite(blockedUntilMs) && blockedUntilMs > now) {\n return true;\n }\n }\n\n if (cache.lastFailedAt) {\n const lastFailedMs = Date.parse(cache.lastFailedAt);\n if (Number.isFinite(lastFailedMs) && now - lastFailedMs < GENERIC_RETRY_MS) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function clearUpdateBlockCache(configDir?: string): void {\n writeUpdateBlockCache({}, configDir);\n}\n\nexport function recordReleaseAgeBlock(options: {\n registryLatest: string;\n retryAfter?: Date;\n configDir?: string;\n}): void {\n writeUpdateBlockCache(\n {\n registryLatest: options.registryLatest,\n blockedUntil: options.retryAfter?.toISOString(),\n },\n options.configDir,\n );\n}\n\nexport function recordGenericUpdateFailure(registryLatest: string, configDir?: string): void {\n writeUpdateBlockCache(\n {\n registryLatest,\n lastFailedAt: new Date().toISOString(),\n },\n configDir,\n );\n}\n","import { spawnSync } from \"node:child_process\";\n\nimport { resolveCliRoot } from \"../project/resolve-cli-root\";\nimport { readCliVersion } from \"../version\";\nimport { isNewerVersion } from \"./compare-version\";\nimport { detectCliInstall } from \"./detect-cli-install\";\nimport { formatReleaseAgeBlockMessage, isReleaseAgeBlock } from \"./detect-release-age-block\";\nimport { fetchLatestCliRelease } from \"./fetch-latest-version\";\nimport {\n computeReleaseAgeRetryAfter,\n readPnpmMinimumReleaseAgeMinutes,\n} from \"./read-pnpm-release-age-minutes\";\nimport { runPackageManagerUpdate } from \"./run-package-manager-update\";\nimport {\n clearUpdateBlockCache,\n readUpdateBlockCache,\n recordGenericUpdateFailure,\n recordReleaseAgeBlock,\n shouldSkipCachedUpdate,\n} from \"./update-block-cache\";\n\nfunction shouldSkipAutoUpdate(argv: string[]): boolean {\n if (\n process.env.KEYSTROKE_DEV ||\n process.env.KEYSTROKE_SKIP_UPDATE ||\n process.env.KEYSTROKE_UPDATING\n ) {\n return true;\n }\n\n if (process.env.CI === \"true\" || process.env.CI === \"1\") {\n return true;\n }\n\n const args = argv.slice(2);\n if (args.length === 0) {\n return false;\n }\n\n return args.every(\n (arg) =>\n arg === \"-V\" ||\n arg === \"--version\" ||\n arg === \"-h\" ||\n arg === \"--help\" ||\n arg.startsWith(\"-V\"),\n );\n}\n\nfunction reexecCli(argv: string[]): never {\n const result = spawnSync(process.execPath, argv.slice(1), {\n stdio: \"inherit\",\n env: {\n ...process.env,\n KEYSTROKE_UPDATING: \"1\",\n },\n });\n\n process.exit(result.status ?? 1);\n}\n\nfunction releaseAgeRetryAfter(\n install: NonNullable<ReturnType<typeof detectCliInstall>>,\n publishedAt: string | undefined,\n): Date | undefined {\n if (install.packageManager !== \"pnpm\") {\n return undefined;\n }\n\n return computeReleaseAgeRetryAfter(publishedAt, readPnpmMinimumReleaseAgeMinutes());\n}\n\nexport async function maybeAutoUpdate(argv: string[]): Promise<void> {\n if (shouldSkipAutoUpdate(argv)) {\n return;\n }\n\n const install = detectCliInstall(resolveCliRoot(import.meta.url));\n if (!install || (install.kind === \"local\" && !install.projectRoot)) {\n return;\n }\n\n const currentVersion = readCliVersion();\n const release = await fetchLatestCliRelease();\n\n if (!release || !isNewerVersion(release.version, currentVersion)) {\n clearUpdateBlockCache();\n return;\n }\n\n const cache = readUpdateBlockCache();\n if (shouldSkipCachedUpdate(cache, release.version)) {\n return;\n }\n\n process.stderr.write(\n `Updating @keystrokehq/cli ${currentVersion} -> ${release.version} via ${install.packageManager}...\\n`,\n );\n\n const result = runPackageManagerUpdate(install);\n const installedVersion = readCliVersion();\n\n if (isNewerVersion(installedVersion, currentVersion)) {\n clearUpdateBlockCache();\n process.stderr.write(`Updated @keystrokehq/cli ${currentVersion} -> ${installedVersion}.\\n`);\n reexecCli(argv);\n }\n\n if (result.ok) {\n clearUpdateBlockCache();\n return;\n }\n\n if (isReleaseAgeBlock(result.output)) {\n const retryAfter = releaseAgeRetryAfter(install, release.publishedAt);\n recordReleaseAgeBlock({\n registryLatest: release.version,\n retryAfter,\n });\n process.stderr.write(\n `${formatReleaseAgeBlockMessage({\n currentVersion,\n availableVersion: release.version,\n retryAfter,\n })}\\n`,\n );\n return;\n }\n\n recordGenericUpdateFailure(release.version);\n process.stderr.write(\"Auto-update failed; continuing with the current version.\\n\");\n}\n"],"mappings":";;;;;;AAAA,SAAS,aAAa,SAA2C;CAE/D,MAAM,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ,MADlB,QAAQ,KAAK,EAAE,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,EAAE,MAAM,IAChB,MAAM,GAAG,EAAE,KAAK,SAAS;EAC5E,MAAM,QAAQ,OAAO,SAAS,MAAM,EAAE;EACtC,OAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;CAC1C,CAAC;CAED,OAAO;EAAC;EAAO;EAAO;CAAK;AAC7B;AAEA,SAAgB,eAAe,QAAgB,SAA0B;CACvE,MAAM,CAAC,aAAa,aAAa,eAAe,aAAa,MAAM;CACnE,MAAM,CAAC,cAAc,cAAc,gBAAgB,aAAa,OAAO;CAEvE,IAAI,gBAAgB,cAClB,OAAO,cAAc;CAGvB,IAAI,gBAAgB,cAClB,OAAO,cAAc;CAGvB,OAAO,cAAc;AACvB;;;ACRA,SAAS,aAAa,MAAsB;CAC1C,IAAI;EACF,OAAO,aAAa,IAAI;CAC1B,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,0BAA0B,KAAyC;CAC1E,IAAI,WAAW,KAAK,KAAK,gBAAgB,CAAC,GACxC,OAAO;CAGT,IAAI,WAAW,KAAK,KAAK,WAAW,CAAC,KAAK,WAAW,KAAK,KAAK,UAAU,CAAC,GACxE,OAAO;CAGT,IAAI,WAAW,KAAK,KAAK,WAAW,CAAC,GACnC,OAAO;CAGT,IAAI,WAAW,KAAK,KAAK,mBAAmB,CAAC,GAC3C,OAAO;AAIX;AAEA,SAAS,qBAAqB,aAAyC;CACrE,MAAM,iBAAiB,aAAa,WAAW;CAC/C,IAAI,MAAM,QAAQ,WAAW;CAE7B,OAAO,QAAQ,QAAQ,GAAG,GAAG;EAC3B,MAAM,mBAAmB,KAAK,KAAK,gBAAgB,gBAAgB,KAAK;EACxE,IACE,WAAW,KAAK,KAAK,cAAc,CAAC,KACpC,aAAa,gBAAgB,MAAM,gBAEnC,OAAO;EAGT,MAAM,QAAQ,GAAG;CACnB;AAGF;AAEA,SAAS,qBAAqB,SAA6C;CAQzE,MAAM,EAAE,SAAS,SAAS;EANxB,MAAM;GAAE,SAAS;GAAQ,MAAM,CAAC,QAAQ,IAAI;EAAE;EAC9C,KAAK;GAAE,SAAS;GAAO,MAAM,CAAC,QAAQ,IAAI;EAAE;EAC5C,MAAM;GAAE,SAAS;GAAQ,MAAM,CAAC,UAAU,KAAK;EAAE;EACjD,KAAK;GAAE,SAAS;GAAO,MAAM,CAAC,MAAM,KAAK;EAAE;CAGZ,EAAE;CACnC,MAAM,SAAS,UAAU,SAAS,MAAM,EAAE,UAAU,OAAO,CAAC;CAE5D,IAAI,OAAO,WAAW,GACpB;CAGF,MAAM,OAAO,OAAO,OAAO,KAAK;CAChC,OAAO,OAAO,aAAa,IAAI,IAAI,KAAA;AACrC;AAEA,SAAS,oBAAoB,aAAqC;CAChE,MAAM,iBAAiB,aAAa,WAAW;CAE/C,IAAI,eAAe,SAAS,GAAG,KAAK,IAAI,OAAO,GAAG,GAChD,OAAO;CAGT,KAAK,MAAM,WAAW;EAAC;EAAQ;EAAO;EAAQ;CAAK,GAAY;EAC7D,MAAM,aAAa,qBAAqB,OAAO;EAC/C,IAAI,cAAc,eAAe,WAAW,UAAU,GACpD,OAAO;CAEX;CAEA,IAAI,QAAQ,IAAI,WACd,OAAO;CAGT,OAAO,qBAAqB;AAC9B;AAEA,SAAgB,iBAAiB,aAAiD;CAChF,MAAM,iBAAiB,aAAa,WAAW;CAC/C,MAAM,cAAc,qBAAqB,cAAc;CAEvD,IAAI,aAGF,OAAO;EACL,MAAM;EACN,gBAJqB,0BAA0B,WAAW,KAAK,qBAAqB;EAKpF,aAAa;EACb;CACF;CAGF,OAAO;EACL,MAAM;EACN,gBAAgB,oBAAoB,cAAc;EAClD,aAAa;CACf;AACF;;;AC1HA,MAAM,uBAAuB;CAC3B;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgB,kBAAkB,QAAyB;CACzD,OAAO,qBAAqB,MAAM,YAAY,QAAQ,KAAK,MAAM,CAAC;AACpE;AAEA,SAAgB,6BAA6B,SAIlC;CACT,MAAM,QACJ,QAAQ,eAAe,KAAA,IAAY,gBAAgB,QAAQ,WAAW,eAAe,EAAE,KAAK;CAE9F,OACE,oBAAoB,QAAQ,iBAAiB,2EACH,QAAQ,eAAe,GAAG,MAAM;AAG9E;;;ACzBA,MAAM,eAAe;AACrB,MAAM,qBAAqB;AAc3B,eAAsB,wBAAiE;CACrF,MAAM,aAAa,IAAI,gBAAgB;CACvC,MAAM,UAAU,iBAAiB,WAAW,MAAM,GAAG,kBAAkB;CAEvE,IAAI;EACF,MAAM,WAAW,MAAM,MAAM,cAAc;GACzC,QAAQ,WAAW;GACnB,SAAS,EACP,QAAQ,mBACV;EACF,CAAC;EAED,IAAI,CAAC,SAAS,IACZ;EAGF,MAAM,UAAW,MAAM,SAAS,KAAK;EACrC,MAAM,UAAU,QAAQ,cAAc,QAAQ,KAAK;EACnD,IAAI,CAAC,SACH;EAGF,OAAO;GACL;GACA,aAAa,QAAQ,OAAO;EAC9B;CACF,QAAQ;EACN;CACF,UAAU;EACR,aAAa,OAAO;CACtB;AACF;;;AC5CA,SAAgB,mCAAuD;CACrE,MAAM,SAAS,UAAU,QAAQ;EAAC;EAAU;EAAO;CAAqB,GAAG,EACzE,UAAU,OACZ,CAAC;CAED,IAAI,OAAO,WAAW,GACpB;CAGF,MAAM,QAAQ,OAAO,OAAO,KAAK;CACjC,IAAI,CAAC,SAAS,UAAU,eAAe,UAAU,KAC/C;CAGF,MAAM,UAAU,OAAO,SAAS,OAAO,EAAE;CACzC,OAAO,OAAO,SAAS,OAAO,KAAK,UAAU,IAAI,UAAU,KAAA;AAC7D;AAEA,SAAgB,4BACd,aACA,0BACkB;CAClB,IAAI,CAAC,eAAe,CAAC,0BACnB;CAGF,MAAM,cAAc,KAAK,MAAM,WAAW;CAC1C,IAAI,CAAC,OAAO,SAAS,WAAW,GAC9B;CAGF,OAAO,IAAI,KAAK,cAAc,2BAA2B,GAAM;AACjE;;;;ACjCA,SAAgB,sBAAsB,aAAyC;CAG7E,OAFmB,YAAY,QAAQ,OAAO,GACvB,EAAE,MAAM,sBACpB,IAAI;AACjB;;;ACFA,MAAM,eAAe;AAErB,SAAgB,mBAAmB,SAIjC;CACA,MAAM,EAAE,MAAM,mBAAmB;CAEjC,IAAI,SAAS,UACX,QAAQ,gBAAR;EACE,KAAK,QACH,OAAO;GACL,SAAS;GACT,MAAM;IAAC;IAAO;IAAM;GAAY;GAChC,KAAK,sBAAsB,QAAQ,WAAW;EAChD;EACF,KAAK,QACH,OAAO;GAAE,SAAS;GAAQ,MAAM;IAAC;IAAU;IAAO;GAAY;EAAE;EAClE,KAAK,OACH,OAAO;GAAE,SAAS;GAAO,MAAM;IAAC;IAAO;IAAM;GAAY;EAAE;EAE7D,SACE,OAAO;GAAE,SAAS;GAAO,MAAM;IAAC;IAAW;IAAM;GAAY;EAAE;CACnE;CAGF,MAAM,MAAM,QAAQ;CACpB,QAAQ,gBAAR;EACE,KAAK,QACH,OAAO;GAAE,SAAS;GAAQ,MAAM;IAAC;IAAO;IAAM;GAAY;GAAG;EAAI;EACnE,KAAK,QACH,OAAO;GAAE,SAAS;GAAQ,MAAM;IAAC;IAAO;IAAM;GAAY;GAAG;EAAI;EACnE,KAAK,OACH,OAAO;GAAE,SAAS;GAAO,MAAM;IAAC;IAAO;IAAM;GAAY;GAAG;EAAI;EAElE,SACE,OAAO;GAAE,SAAS;GAAO,MAAM;IAAC;IAAW;IAAM;GAAY;GAAG;EAAI;CACxE;AACF;;;ACrCA,SAAgB,iBAAoC;CAClD,MAAM,MAAM,EAAE,GAAG,QAAQ,IAAI;CAC7B,MAAM,WAAW,IAAI;CAErB,IAAI,CAAC,UACH,OAAO;CAGT,MAAM,UAAU,QAAQ,aAAa,UAAU,SAAS;CACxD,MAAM,OAAO,IAAI,YAAY;CAC7B,MAAM,WAAW,KAAK,MAAM,QAAQ,aAAa,UAAU,MAAM,GAAG;CAEpE,MAAM,SAAS,CAAC,GADE,SAAS,OACH,QAAQ,EAAE,QAAQ,QAAQ,CAAC,SAAS,SAAS,GAAG,CAAC;CAEzE,IAAI,OAAO,SAAS,GAClB,IAAI,WAAW,CAAC,GAAG,QAAQ,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,QAAQ,aAAa,UAAU,MAAM,GAAG;CAGhG,OAAO;AACT;AAOA,SAAS,kBAAkB,SAAiB,MAAgB,KAAuC;CACjG,MAAM,SAAS,UAAU,SAAS,MAAM;EACtC;EACA,UAAU;EACV,KAAK,eAAe;CACtB,CAAC;CAED,MAAM,SAAS,GAAG,OAAO,UAAU,KAAK,OAAO,UAAU;CAEzD,OAAO;EACL,IAAI,OAAO,WAAW;EACtB;CACF;AACF;AAEA,SAAS,kBAAkB,KAAsB;CAU/C,OATe,UAAU,QAAQ,CAAC,SAAS,GAAG;EAC5C;EACA,UAAU;EACV,KAAK;GACH,GAAG,eAAe;GAClB,IAAI;EACN;CACF,CAEY,EAAE,WAAW;AAC3B;AAEA,SAAgB,wBAAwB,SAAkD;CACxF,MAAM,EAAE,SAAS,MAAM,QAAQ,mBAAmB,OAAO;CACzD,MAAM,eAAe,kBAAkB,SAAS,MAAM,GAAG;CAEzD,IAAI,aAAa,IACf,OAAO;CAGT,IAAI,QAAQ,SAAS,YAAY,QAAQ,mBAAmB,UAAU;MAChE,kBAAkB,GAAG,GACvB,OAAO,kBAAkB,SAAS,MAAM,GAAG;CAAA;CAI/C,OAAO;AACT;;;AC/DA,MAAM,aAAa;AACnB,MAAM,mBAAmB,OAAU,KAAK;AAExC,SAAS,UAAU,YAAY,gBAAgB,GAAW;CACxD,OAAO,KAAK,WAAW,UAAU;AACnC;AAEA,SAAgB,qBAAqB,WAAsC;CACzE,MAAM,OAAO,UAAU,SAAS;CAChC,IAAI,CAAC,WAAW,IAAI,GAClB,OAAO,CAAC;CAGV,IAAI;EACF,OAAO,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC;CAC9C,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAgB,sBAAsB,OAAyB,WAA0B;CACvF,MAAM,MAAM,aAAa,gBAAgB;CACzC,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;CAClC,cAAc,UAAU,GAAG,GAAG,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,KAAK,MAAM;AAC7E;AAEA,SAAgB,uBACd,OACA,gBACA,MAAM,KAAK,IAAI,GACN;CACT,IAAI,MAAM,mBAAmB,gBAC3B,OAAO;CAGT,IAAI,MAAM,cAAc;EACtB,MAAM,iBAAiB,KAAK,MAAM,MAAM,YAAY;EACpD,IAAI,OAAO,SAAS,cAAc,KAAK,iBAAiB,KACtD,OAAO;CAEX;CAEA,IAAI,MAAM,cAAc;EACtB,MAAM,eAAe,KAAK,MAAM,MAAM,YAAY;EAClD,IAAI,OAAO,SAAS,YAAY,KAAK,MAAM,eAAe,kBACxD,OAAO;CAEX;CAEA,OAAO;AACT;AAEA,SAAgB,sBAAsB,WAA0B;CAC9D,sBAAsB,CAAC,GAAG,SAAS;AACrC;AAEA,SAAgB,sBAAsB,SAI7B;CACP,sBACE;EACE,gBAAgB,QAAQ;EACxB,cAAc,QAAQ,YAAY,YAAY;CAChD,GACA,QAAQ,SACV;AACF;AAEA,SAAgB,2BAA2B,gBAAwB,WAA0B;CAC3F,sBACE;EACE;EACA,+BAAc,IAAI,KAAK,GAAE,YAAY;CACvC,GACA,SACF;AACF;;;ACpEA,SAAS,qBAAqB,MAAyB;CACrD,IACE,QAAQ,IAAI,iBACZ,QAAQ,IAAI,yBACZ,QAAQ,IAAI,oBAEZ,OAAO;CAGT,IAAI,QAAQ,IAAI,OAAO,UAAU,QAAQ,IAAI,OAAO,KAClD,OAAO;CAGT,MAAM,OAAO,KAAK,MAAM,CAAC;CACzB,IAAI,KAAK,WAAW,GAClB,OAAO;CAGT,OAAO,KAAK,OACT,QACC,QAAQ,QACR,QAAQ,eACR,QAAQ,QACR,QAAQ,YACR,IAAI,WAAW,IAAI,CACvB;AACF;AAEA,SAAS,UAAU,MAAuB;CACxC,MAAM,SAAS,UAAU,QAAQ,UAAU,KAAK,MAAM,CAAC,GAAG;EACxD,OAAO;EACP,KAAK;GACH,GAAG,QAAQ;GACX,oBAAoB;EACtB;CACF,CAAC;CAED,QAAQ,KAAK,OAAO,UAAU,CAAC;AACjC;AAEA,SAAS,qBACP,SACA,aACkB;CAClB,IAAI,QAAQ,mBAAmB,QAC7B;CAGF,OAAO,4BAA4B,aAAa,iCAAiC,CAAC;AACpF;AAEA,eAAsB,gBAAgB,MAA+B;CACnE,IAAI,qBAAqB,IAAI,GAC3B;CAGF,MAAM,UAAU,iBAAiB,eAAe,OAAO,KAAK,GAAG,CAAC;CAChE,IAAI,CAAC,WAAY,QAAQ,SAAS,WAAW,CAAC,QAAQ,aACpD;CAGF,MAAM,iBAAiB,eAAe;CACtC,MAAM,UAAU,MAAM,sBAAsB;CAE5C,IAAI,CAAC,WAAW,CAAC,eAAe,QAAQ,SAAS,cAAc,GAAG;EAChE,sBAAsB;EACtB;CACF;CAGA,IAAI,uBADU,qBACiB,GAAG,QAAQ,OAAO,GAC/C;CAGF,QAAQ,OAAO,MACb,6BAA6B,eAAe,MAAM,QAAQ,QAAQ,OAAO,QAAQ,eAAe,MAClG;CAEA,MAAM,SAAS,wBAAwB,OAAO;CAC9C,MAAM,mBAAmB,eAAe;CAExC,IAAI,eAAe,kBAAkB,cAAc,GAAG;EACpD,sBAAsB;EACtB,QAAQ,OAAO,MAAM,4BAA4B,eAAe,MAAM,iBAAiB,IAAI;EAC3F,UAAU,IAAI;CAChB;CAEA,IAAI,OAAO,IAAI;EACb,sBAAsB;EACtB;CACF;CAEA,IAAI,kBAAkB,OAAO,MAAM,GAAG;EACpC,MAAM,aAAa,qBAAqB,SAAS,QAAQ,WAAW;EACpE,sBAAsB;GACpB,gBAAgB,QAAQ;GACxB;EACF,CAAC;EACD,QAAQ,OAAO,MACb,GAAG,6BAA6B;GAC9B;GACA,kBAAkB,QAAQ;GAC1B;EACF,CAAC,EAAE,GACL;EACA;CACF;CAEA,2BAA2B,QAAQ,OAAO;CAC1C,QAAQ,OAAO,MAAM,4DAA4D;AACnF"}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { join, relative, sep } from "node:path";
|
|
3
|
-
import { readdir, stat } from "node:fs/promises";
|
|
4
2
|
//#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
|
|
5
3
|
var _a$1;
|
|
6
4
|
function $constructor(name, initializer, params) {
|
|
@@ -4673,71 +4671,6 @@ function superRefine(fn, params) {
|
|
|
4673
4671
|
return /* @__PURE__ */ _superRefine(fn, params);
|
|
4674
4672
|
}
|
|
4675
4673
|
//#endregion
|
|
4676
|
-
|
|
4677
|
-
const SOURCE_EXT = /\.(ts|mts|mjs|js)$/;
|
|
4678
|
-
const DECLARATION_FILE$1 = /\.d\.(ts|mts|cts)$/;
|
|
4679
|
-
function entryIdFromFile(rootDir, filePath, options) {
|
|
4680
|
-
if (DECLARATION_FILE$1.test(filePath)) return null;
|
|
4681
|
-
const baseName = filePath.split(sep).at(-1) ?? "";
|
|
4682
|
-
if (/\.(int\.)?test\.(ts|mts)$/.test(baseName)) return null;
|
|
4683
|
-
const segments = relative(rootDir, filePath).replace(SOURCE_EXT, "").split(sep).filter((segment) => segment.length > 0);
|
|
4684
|
-
if (segments.length === 1) return segments[0] ?? null;
|
|
4685
|
-
const last = segments.at(-1);
|
|
4686
|
-
const entryNames = new Set([options.nestedEntry]);
|
|
4687
|
-
if (options.allowIndex !== false) entryNames.add("index");
|
|
4688
|
-
if (!last || !entryNames.has(last)) return null;
|
|
4689
|
-
const id = segments.slice(0, -1).join("/");
|
|
4690
|
-
return id.length > 0 ? id : null;
|
|
4691
|
-
}
|
|
4692
|
-
const SOURCE_FILE = /\.(ts|mts|mjs|js)$/;
|
|
4693
|
-
const TEST_FILE = /\.(int\.)?test\.(ts|mts)$/;
|
|
4694
|
-
const DECLARATION_FILE = /\.d\.(ts|mts|cts)$/;
|
|
4695
|
-
const JUNK_FILE = /^\._|\.DS_Store$/;
|
|
4696
|
-
async function walkTypeScriptFiles(dir) {
|
|
4697
|
-
let names;
|
|
4698
|
-
try {
|
|
4699
|
-
names = await readdir(dir);
|
|
4700
|
-
} catch (error) {
|
|
4701
|
-
if (error.code === "ENOENT") return [];
|
|
4702
|
-
throw error;
|
|
4703
|
-
}
|
|
4704
|
-
const files = [];
|
|
4705
|
-
for (const name of names) {
|
|
4706
|
-
const path = join(dir, name);
|
|
4707
|
-
if ((await stat(path)).isDirectory()) files.push(...await walkTypeScriptFiles(path));
|
|
4708
|
-
else if (!JUNK_FILE.test(name) && SOURCE_FILE.test(name) && !DECLARATION_FILE.test(name) && !TEST_FILE.test(name)) files.push(path);
|
|
4709
|
-
}
|
|
4710
|
-
return files;
|
|
4711
|
-
}
|
|
4712
|
-
async function discoverEntries(rootDir, options) {
|
|
4713
|
-
const files = await walkTypeScriptFiles(rootDir);
|
|
4714
|
-
const byKey = /* @__PURE__ */ new Map();
|
|
4715
|
-
for (const filePath of files) {
|
|
4716
|
-
const id = entryIdFromFile(rootDir, filePath, options);
|
|
4717
|
-
if (!id) continue;
|
|
4718
|
-
const key = options.formatKey(id);
|
|
4719
|
-
const moduleFile = relative(rootDir, filePath);
|
|
4720
|
-
const existing = byKey.get(key);
|
|
4721
|
-
if (existing) throw new Error(`Duplicate ${options.duplicateLabel} ${key}: ${existing.filePath} and ${filePath}`);
|
|
4722
|
-
byKey.set(key, {
|
|
4723
|
-
key,
|
|
4724
|
-
filePath,
|
|
4725
|
-
moduleFile
|
|
4726
|
-
});
|
|
4727
|
-
}
|
|
4728
|
-
return [...byKey.values()];
|
|
4729
|
-
}
|
|
4730
|
-
async function discoverModuleFileEntries(rootDir, options) {
|
|
4731
|
-
return (await discoverEntries(rootDir, {
|
|
4732
|
-
nestedEntry: options.nestedEntry,
|
|
4733
|
-
formatKey: (id) => id,
|
|
4734
|
-
duplicateLabel: options.duplicateLabel
|
|
4735
|
-
})).filter((entry) => options.shouldDiscoverFile?.(entry.filePath) ?? true).map(({ filePath, moduleFile }) => ({
|
|
4736
|
-
filePath,
|
|
4737
|
-
moduleFile
|
|
4738
|
-
}));
|
|
4739
|
-
}
|
|
4740
|
-
//#endregion
|
|
4741
|
-
export { _coercedNumber as S, string as _, ZodNumber as a, url as b, _function as c, custom as d, discriminatedUnion as f, record as g, object as h, walkTypeScriptFiles as i, array as l, number as m, discoverModuleFileEntries as n, ZodType as o, literal as p, entryIdFromFile as r, _enum as s, discoverEntries as t, boolean as u, union as v, toJSONSchema as x, unknown as y };
|
|
4674
|
+
export { toJSONSchema as _, array as a, discriminatedUnion as c, object as d, record as f, url as g, unknown as h, _function as i, literal as l, union as m, ZodType as n, boolean as o, string as p, _enum as r, custom as s, ZodNumber as t, number as u, _coercedNumber as v };
|
|
4742
4675
|
|
|
4743
|
-
//# sourceMappingURL=
|
|
4676
|
+
//# sourceMappingURL=schemas-Bq8SXmZk.mjs.map
|