Skip to content

feat: add Node.js entry point and build script#18324

Merged
thdxr merged 1 commit intodevfrom
feat/node-entry
Mar 20, 2026
Merged

feat: add Node.js entry point and build script#18324
thdxr merged 1 commit intodevfrom
feat/node-entry

Conversation

@thdxr
Copy link
Copy Markdown
Member

@thdxr thdxr commented Mar 20, 2026

Summary

  • Add src/node.ts as a Node.js entry point that starts the server on port 1338
  • Add script/build-node.ts that bundles the entry point with DB migrations embedded at build time via Bun.build

Depends on the Hono/node-server server refactoring in opencode-2-0 for Server.listen() to work under Node.js.

thdxr added a commit that referenced this pull request Mar 20, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 20, 2026

Greptile Summary

This PR adds two new files to support a Node.js distribution of opencode: a thin entry point (src/node.ts) that starts the Hono server on port 1338, and a Bun-driven build script (script/build-node.ts) that embeds DB migrations at bundle time using Bun.build({ target: "node" }). Both files fit naturally into the existing build infrastructure, but there are a few issues to address before merging.

  • Silent build failure (script/build-node.ts): Bun.build() (non-compile mode) resolves rather than throws on failure; the result is not inspected, so a broken bundle will always print "Build complete" — masking errors in CI.
  • Duplicated migration loading (script/build-node.ts): The entire migration-reading block (lines 12–57) is a verbatim copy of the same block in script/build.ts. Extracting a shared helper would prevent drift if the migration layout ever changes.
  • Hardcoded bind address (src/node.ts): The entry point unconditionally binds to 0.0.0.0:1338 with no environment variable or CLI override, which may be too permissive for some deployment contexts.
  • Node.js runtime compatibility (src/node.ts): As acknowledged in the PR description, Server.listen() currently delegates to Bun.serve() and imports from hono/bun, so the built artifact will fail at runtime under Node.js until the referenced Hono/node-server refactoring lands. This PR is intentionally incomplete pending that work, but it is worth making the dependency explicit (e.g. a TODO comment or // depends on opencode-2-0).

Confidence Score: 2/5

  • Not safe to merge as-is: the build script silently swallows build failures and the runtime entry point is non-functional in Node.js pending a separate PR.
  • The critical P1 issue (unchecked Bun.build result) means CI could ship a broken bundle with no signal of failure. The entry point itself is intentionally a stub pending the Hono/node-server refactor, which is acceptable as a draft but should be clearly marked. Naming/duplication style issues are minor but add up given the AGENTS.md conventions in this repo.
  • packages/opencode/script/build-node.ts requires the most attention — the unchecked Bun.build() result is the highest-priority fix.

Important Files Changed

Filename Overview
packages/opencode/script/build-node.ts New Bun build script for the Node.js target; duplicates the full migration-loading block from build.ts verbatim, and critically does not check the Bun.build() result, meaning build failures are silently ignored and "Build complete" is always printed.
packages/opencode/src/node.ts Thin Node.js entry point that calls Server.listen() on a hardcoded port 1338 / 0.0.0.0; safe as a placeholder but currently calls Bun.serve() internally (acknowledged as depending on a future refactoring PR) and offers no runtime override for hostname or port.

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant BN as build-node.ts (Bun)
    participant FS as migration/ directory
    participant Bundler as Bun.build()
    participant Dist as dist/node.js
    participant Node as Node.js process

    Dev->>BN: bun run script/build-node.ts
    BN->>FS: readdir migration/ (filter timestamp dirs)
    FS-->>BN: sorted migration dir names
    BN->>FS: read each migration.sql
    FS-->>BN: SQL content per migration
    BN->>BN: parse timestamp from dir name (Date.UTC)
    BN->>Bundler: Bun.build({ target:"node", entrypoints:["src/node.ts"], define:{OPENCODE_MIGRATIONS} })
    Bundler-->>BN: BuildOutput (success/failure — currently unchecked)
    BN->>Dist: writes dist/node.js (ESM bundle)
    Note over BN: Prints "Build complete" regardless of success

    Dev->>Node: node dist/node.js
    Node->>Dist: execute entry point
    Dist->>Dist: import Server from ./server/server
    Dist->>Dist: Server.listen({ port:1338, hostname:"0.0.0.0" })
    Note over Dist: Currently calls Bun.serve() internally<br/>(requires future Hono/node-server refactor)
    Dist-->>Node: server object logged to stdout
Loading

Comments Outside Diff (1)

  1. packages/opencode/script/build-node.ts, line 12-57 (link)

    P2 Duplicated migration loading block from build.ts

    Lines 12–57 are a verbatim copy of the migration loading code that already exists in script/build.ts (lines 29–57). Any future change to migration format, timestamp parsing, or directory structure must now be made in both places. Consider extracting this shared logic into a small helper (e.g. script/migrations.ts) and importing it in both build scripts to keep things DRY.

Last reviewed commit: "feat: add Node.js en..."

Comment on lines +44 to +53
target: "node",
entrypoints: ["./src/node.ts"],
outdir: "./dist",
format: "esm",
external: ["jsonc-parser"],
define: {
OPENCODE_MIGRATIONS: JSON.stringify(migrations),
},
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Bun.build() result unchecked — build failures will be silently swallowed

Bun.build() (without the compile option) does not throw on failure — it resolves with { success: false, logs: [...] }. As written, the script will always print "Build complete" regardless of whether the bundle actually succeeded, making build errors invisible in CI or local runs.

Suggested change
target: "node",
entrypoints: ["./src/node.ts"],
outdir: "./dist",
format: "esm",
external: ["jsonc-parser"],
define: {
OPENCODE_MIGRATIONS: JSON.stringify(migrations),
},
})
const result = await Bun.build({
target: "node",
entrypoints: ["./src/node.ts"],
outdir: "./dist",
format: "esm",
external: ["jsonc-parser"],
define: {
OPENCODE_MIGRATIONS: JSON.stringify(migrations),
},
})
if (!result.success) {
for (const log of result.logs) console.error(log)
process.exit(1)
}

Comment on lines +15 to +17
await fs.promises.readdir(path.join(dir, "migration"), {
withFileTypes: true,
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Multi-word variable and single-use variable — AGENTS.md naming rules

Per the repo's style guide, multi-word camelCase names should be avoided in favour of single-word alternatives, and variables used only once should be inlined to reduce total variable count.

  • migrationDirsdirs
  • __filename is used exactly once (to produce __dirname); __dirname is also used exactly once (to produce dir). Both can be collapsed:
Suggested change
await fs.promises.readdir(path.join(dir, "migration"), {
withFileTypes: true,
})
const dir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +3 to +6
const result = await Server.listen({
port: 1338,
hostname: "0.0.0.0",
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Hardcoded 0.0.0.0 with no override path

Binding to 0.0.0.0 exposes the server on every network interface (including external/public ones). Unlike the existing Bun entry point (src/index.ts) which accepts runtime flags, this Node.js entry point offers no way to restrict the bind address without recompiling. Consider reading the hostname (and port) from an environment variable or CLI argument so operators can restrict to 127.0.0.1 in production-adjacent deployments.

Adds src/node.ts as a Node.js entry point that starts the server on
port 1338, and script/build-node.ts that bundles it with DB migrations
embedded at build time via Bun.build.

Note: depends on the Hono/node-server server refactoring (opencode-2-0)
for Server.listen() to return a proper async listener.
@thdxr thdxr force-pushed the feat/node-entry branch from 608a77a to 7817faa Compare March 20, 2026 01:34
@thdxr thdxr merged commit 92cd908 into dev Mar 20, 2026
4 checks passed
@thdxr thdxr deleted the feat/node-entry branch March 20, 2026 01:35
demostanis pushed a commit to demostanis/opencode that referenced this pull request Mar 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant