-
Notifications
You must be signed in to change notification settings - Fork 20
chore(pgvector-embedded): rebuild prebuilt artifacts (v0.8.1) #977
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a8f4e81
ac57527
d685d72
cafe28a
8acdd5e
3168fea
203b82f
06e8fed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| /** | ||
| * Ensure a connector project's npm dependencies are installed before the CLI | ||
| * compiles its connectors. esbuild bundles a connector's imports relative to | ||
| * the connector file's directory, so the project's own `node_modules` (next to | ||
| * `package.json`) must exist. We run `bun install --ignore-scripts` when stale: | ||
| * `--ignore-scripts` keeps install-time supply-chain surface off the user's | ||
| * machine — packages that need build scripts (native bindings) belong in | ||
| * `runtime.nix.packages`, not bundled npm. | ||
| */ | ||
|
|
||
| import { execFileSync } from "node:child_process"; | ||
| import { existsSync, statSync } from "node:fs"; | ||
| import { dirname, join } from "node:path"; | ||
|
|
||
| // Per-process memo so `lobu apply` installs each project root at most once. | ||
| const ensuredRoots = new Set<string>(); | ||
|
|
||
| /** | ||
| * Find the connector's project root — the nearest ancestor with `lobu.toml`. | ||
| * Anchoring on `lobu.toml` (not any ancestor `package.json`) is what stops a | ||
| * connector inside a monorepo from resolving to the monorepo's root | ||
| * package.json and triggering a wrong-directory install. | ||
| */ | ||
| export function findProjectRoot(fromFile: string): string | null { | ||
| let dir = dirname(fromFile); | ||
| for (let i = 0; i < 40; i++) { | ||
| if (existsSync(join(dir, "lobu.toml"))) return dir; | ||
| const parent = dirname(dir); | ||
| if (parent === dir) break; | ||
| dir = parent; | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| function installIsStale(root: string): boolean { | ||
| const nodeModules = join(root, "node_modules"); | ||
| if (!existsSync(nodeModules)) return true; | ||
| const lock = join(root, "bun.lock"); | ||
| if (!existsSync(lock)) return false; // deps present, no lockfile to compare against | ||
| try { | ||
| return statSync(lock).mtimeMs > statSync(nodeModules).mtimeMs; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| function hasBun(): boolean { | ||
| try { | ||
| execFileSync("bun", ["--version"], { stdio: "ignore" }); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Install the connector project's deps if missing/stale. No-op when the | ||
| * connector has no `package.json` (no declared npm deps to bundle). | ||
| */ | ||
| export function ensureProjectDepsInstalled( | ||
| connectorFilePath: string, | ||
| log: (message: string) => void | ||
| ): void { | ||
| const root = findProjectRoot(connectorFilePath); | ||
| if (!root || ensuredRoots.has(root)) return; | ||
| // No package.json at the project root → the connector declares no npm deps | ||
| // (the SDK is runtime-provided/externalized), so there's nothing to install. | ||
| if (!existsSync(join(root, "package.json"))) { | ||
| ensuredRoots.add(root); | ||
| return; | ||
| } | ||
| if (!installIsStale(root)) { | ||
| ensuredRoots.add(root); | ||
| return; | ||
| } | ||
| if (!hasBun()) { | ||
| throw new Error( | ||
| `Connector dependencies in ${root} need installing, but \`bun\` is not on PATH. ` + | ||
| `Run \`bun install\` in ${root}, or install bun (https://bun.sh).` | ||
| ); | ||
| } | ||
| log(`Installing connector dependencies in ${root}...`); | ||
| execFileSync("bun", ["install", "--ignore-scripts"], { | ||
| cwd: root, | ||
| stdio: "inherit", | ||
| }); | ||
| ensuredRoots.add(root); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -705,6 +705,64 @@ export async function initCommand( | |
| await mkdir(join(projectDir, "skills"), { recursive: true }); | ||
| await writeFile(join(projectDir, "skills", ".gitkeep"), ""); | ||
|
|
||
| // Connector authoring surface: package.json declares the connector SDK | ||
| // (provided by the runtime — externalized at compile, here for editor | ||
| // types) plus any npm deps the user adds; tsconfig gives the editor | ||
| // resolution; the connectors/ dir holds `*.connector.ts`. `lobu apply` | ||
| // runs `bun install --ignore-scripts` here and bundles each connector's | ||
| // own deps. | ||
| // | ||
| // `--here` can target a directory that already has a package.json / | ||
| // tsconfig.json — merge into package.json (preserve the user's fields, just | ||
| // add the SDK devDependency) and never overwrite an existing tsconfig. | ||
| const pkgJsonPath = join(projectDir, "package.json"); | ||
| let pkgJson: Record<string, unknown>; | ||
| try { | ||
| pkgJson = JSON.parse(await readFile(pkgJsonPath, "utf-8")) as Record< | ||
| string, | ||
| unknown | ||
| >; | ||
| } catch { | ||
| pkgJson = { | ||
|
Comment on lines
+720
to
+726
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Restrict fallback behavior to missing-file errors only At Line 720 and Line 741, the broad Proposed fix- try {
- pkgJson = JSON.parse(await readFile(pkgJsonPath, "utf-8")) as Record<
- string,
- unknown
- >;
- } catch {
+ try {
+ const raw = await readFile(pkgJsonPath, "utf-8");
+ pkgJson = JSON.parse(raw) as Record<string, unknown>;
+ } catch (err) {
+ const code = (err as NodeJS.ErrnoException).code;
+ if (code !== "ENOENT") throw err;
pkgJson = {
name: projectName,
version: "0.0.0",
private: true,
type: "module",
};
}
@@
- try {
- await readFile(tsconfigPath, "utf-8"); // exists — leave the user's config untouched
- } catch {
+ try {
+ await readFile(tsconfigPath, "utf-8"); // exists — leave the user's config untouched
+ } catch (err) {
+ const code = (err as NodeJS.ErrnoException).code;
+ if (code !== "ENOENT") throw err;
await writeFile(
tsconfigPath,
`${JSON.stringify(Also applies to: 741-744 🤖 Prompt for AI Agents |
||
| name: projectName, | ||
| version: "0.0.0", | ||
| private: true, | ||
| type: "module", | ||
| }; | ||
| } | ||
| pkgJson.devDependencies = { | ||
| ...((pkgJson.devDependencies as Record<string, string> | undefined) ?? | ||
| {}), | ||
| "@lobu/connector-sdk": `^${cliVersion}`, | ||
| }; | ||
| await writeFile(pkgJsonPath, `${JSON.stringify(pkgJson, null, 2)}\n`); | ||
|
|
||
| const tsconfigPath = join(projectDir, "tsconfig.json"); | ||
| try { | ||
| await readFile(tsconfigPath, "utf-8"); // exists — leave the user's config untouched | ||
| } catch { | ||
| await writeFile( | ||
| tsconfigPath, | ||
| `${JSON.stringify( | ||
| { | ||
| compilerOptions: { | ||
| target: "ES2022", | ||
| module: "Preserve", | ||
| moduleResolution: "bundler", | ||
| strict: true, | ||
| skipLibCheck: true, | ||
| noEmit: true, | ||
| }, | ||
| include: ["connectors/**/*.ts"], | ||
| }, | ||
| null, | ||
| 2 | ||
| )}\n` | ||
| ); | ||
| } | ||
| await mkdir(join(projectDir, "connectors"), { recursive: true }); | ||
| await writeFile(join(projectDir, "connectors", ".gitkeep"), ""); | ||
|
|
||
| await renderTemplate( | ||
| "AGENTS.md.tmpl", | ||
| variables, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Staleness check should include
package.jsonchangesLine 35-42 only compares
bun.lockvsnode_modules. Ifpackage.jsonchanged but the lockfile wasn’t updated yet, this returns non-stale and skips install, causing downstream module-resolution failures during compile.Proposed fix
function installIsStale(root: string): boolean { const nodeModules = join(root, "node_modules"); if (!existsSync(nodeModules)) return true; + const packageJson = join(root, "package.json"); const lock = join(root, "bun.lock"); - if (!existsSync(lock)) return false; // deps present, no lockfile to compare against try { - return statSync(lock).mtimeMs > statSync(nodeModules).mtimeMs; + const nodeModulesMtime = statSync(nodeModules).mtimeMs; + const packageMtime = existsSync(packageJson) + ? statSync(packageJson).mtimeMs + : 0; + const lockMtime = existsSync(lock) ? statSync(lock).mtimeMs : 0; + return Math.max(packageMtime, lockMtime) > nodeModulesMtime; } catch { return false; } }📝 Committable suggestion
🤖 Prompt for AI Agents