mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-30 21:09:29 +00:00
* fix: navigate back to list after delete/remove errors instead of exiting
Previously, choosing "Delete this server" or "Remove from history" from
the action menu would always exit the picker — even if the operation
failed. Now handleRecordAction returns "back" for delete/remove actions,
and activeServerPicker refreshes the remaining list and loops back to
the picker. Cancel on the action menu also returns to the list.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add ValueOf<T> type helper and GritQL enum ban rule
- Add shared ValueOf<T> type that extracts value unions from const objects
and readonly tuples
- Update RecordActionOutcome to use ValueOf<typeof RecordActionOutcome>
- Add lint/no-ts-enum.grit GritQL rule that bans TypeScript enum keyword
- Register new rule in biome.json plugins
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: sort type export before value exports in shared index
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add biome config for shared package, fix export sort order
Add biome.json to packages/shared so lint + format + import organization
is enforced on the shared library. Fix ValueOf export position to match
biome's organizeImports sort order (type specifiers after value exports).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: hoist type re-exports to top of shared index
Split inline `type Result` and `type ValueOf` out of mixed export
statements into separate `export type { ... }` re-exports, hoisted
to the top per biome's organizeImports group config.
biome's useExportType rule doesn't flag re-exports (only locally
defined types), so these must be manually separated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: consolidate biome config to single root biome.json
Remove per-package biome.json files (packages/cli, packages/shared,
.claude/scripts, .claude/skills/setup-spa) and consolidate into a
single root config with includes glob covering packages/**/*.ts.
Update GritQL rule exclusions to also match shared/src/ paths now
that the shared package is covered by the root config. Fix build-clouds.ts
lint issues (node: protocol, block statements, import sort) that were
newly caught.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: replace grit filename exclusions with biome-ignore comments
Remove all $filename exclusion logic from GritQL rules and instead add
biome-ignore-all comments at the top of files that legitimately need
the banned patterns (result.ts, parse.ts, type-guards.ts).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
78 lines
1.9 KiB
TypeScript
78 lines
1.9 KiB
TypeScript
#!/usr/bin/env bun
|
|
|
|
// Build bundled JS files for cloud providers that use TypeScript.
|
|
// Each cloud with a cli/src/{cloud}/main.ts gets bundled into {cloud}.js.
|
|
// These bundles are uploaded to GitHub releases for curl|bash execution.
|
|
//
|
|
// Usage:
|
|
// bun run cli/build-clouds.ts # build all clouds
|
|
// bun run cli/build-clouds.ts aws # build specific cloud
|
|
|
|
import { existsSync, readdirSync } from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const cliDir = path.dirname(new URL(import.meta.url).pathname);
|
|
const srcDir = path.join(cliDir, "src");
|
|
|
|
async function buildCloud(cloud: string): Promise<boolean> {
|
|
const entry = path.join(srcDir, cloud, "main.ts");
|
|
const outfile = path.join(cliDir, `${cloud}.js`);
|
|
|
|
if (!existsSync(entry)) {
|
|
console.log(`skip: ${entry} not found`);
|
|
return false;
|
|
}
|
|
|
|
console.log(`build: src/${cloud}/main.ts -> ${cloud}.js`);
|
|
const result = await Bun.build({
|
|
entrypoints: [
|
|
entry,
|
|
],
|
|
outdir: cliDir,
|
|
naming: `${cloud}.js`,
|
|
target: "bun",
|
|
minify: true,
|
|
packages: "bundle",
|
|
});
|
|
|
|
if (!result.success) {
|
|
console.error(`FAIL: ${cloud}`);
|
|
for (const log of result.logs) {
|
|
console.error(" ", log);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const stat = Bun.file(outfile);
|
|
console.log(` ${cloud}.js ${(stat.size / 1024).toFixed(1)} KB`);
|
|
return true;
|
|
}
|
|
|
|
const filter = process.argv[2];
|
|
let built = 0;
|
|
let failed = 0;
|
|
|
|
if (filter) {
|
|
(await buildCloud(filter)) ? built++ : failed++;
|
|
} else {
|
|
// Auto-discover: any directory under src/ with a main.ts
|
|
for (const entry of readdirSync(srcDir, {
|
|
withFileTypes: true,
|
|
})) {
|
|
if (!entry.isDirectory()) {
|
|
continue;
|
|
}
|
|
if (entry.name.startsWith("__")) {
|
|
continue;
|
|
}
|
|
if (!existsSync(path.join(srcDir, entry.name, "main.ts"))) {
|
|
continue;
|
|
}
|
|
(await buildCloud(entry.name)) ? built++ : failed++;
|
|
}
|
|
}
|
|
|
|
console.log(`\n${built} built, ${failed} failed`);
|
|
if (failed > 0) {
|
|
process.exit(1);
|
|
}
|