HackerTrans
TopNewTrendsCommentsPastAskShowJobs

colinmcd

1,409 karmajoined 13 tahun yang lalu
Creator of Zod Formerly at EdgeDB and Bun Ride-or-die TypeScripter

Submissions

We built a 5x faster JavaScript package manager

nubjs.com
2 points·by colinmcd·6 hari yang lalu·0 comments

Node.js's phantom dependency problem and the path to a 5x faster package manager

nubjs.com
1 points·by colinmcd·8 hari yang lalu·0 comments

Show HN: Nub – A Bun-like all-in-one toolkit for Node.js

github.com
277 points·by colinmcd·22 hari yang lalu·81 comments

Nub – A Bun-like toolkit that extends Node.js instead of trying to replace it

github.com
3 points·by colinmcd·23 hari yang lalu·0 comments

Bolt Cloud

bolt.new
1 points·by colinmcd·11 bulan yang lalu·0 comments

An experiment in fixed-term open-source patronage

zod.dev
3 points·by colinmcd·2 tahun yang lalu·0 comments

Language Embedded Radiance Fields

lerf.io
7 points·by colinmcd·3 tahun yang lalu·0 comments

Bun v0.4

bun.sh
2 points·by colinmcd·4 tahun yang lalu·0 comments

Show HN: TypeScript query builder with full type inference

edgedb.com
4 points·by colinmcd·4 tahun yang lalu·0 comments

[untitled]

4 points·by colinmcd·4 tahun yang lalu·0 comments

Designing the ultimate TypeScript query builder

edgedb.com
5 points·by colinmcd·4 tahun yang lalu·0 comments

Designing the ultimate TypeScript query builder

edgedb.com
1 points·by colinmcd·4 tahun yang lalu·0 comments

Sharding our test suite for 10x faster runs on GitHub Actions

edgedb.com
4 points·by colinmcd·4 tahun yang lalu·0 comments

Everyone is wrong about ORMs

edgedb.com
6 points·by colinmcd·4 tahun yang lalu·4 comments

A solution to the SQL vs. ORM dilemma

edgedb.com
2 points·by colinmcd·4 tahun yang lalu·0 comments

Why ORMs are slow – and getting slower

edgedb.com
9 points·by colinmcd·4 tahun yang lalu·0 comments

How slow are ORMs, really?

edgedb.com
3 points·by colinmcd·4 tahun yang lalu·1 comments

Show HN: IMDBench – Benchmarking ORMs with realistic queries

github.com
4 points·by colinmcd·4 tahun yang lalu·0 comments

The graph-relational database, defined

edgedb.com
3 points·by colinmcd·4 tahun yang lalu·0 comments

The graph-relational database, defined

edgedb.com
19 points·by colinmcd·4 tahun yang lalu·8 comments

comments

colinmcd
·21 hari yang lalu·discuss
You can continue using pnpm if you want. Nub is a la carte. Nub's runtime or script runner functionality will work with any package manager that uses node_modules (actually Yarn PnP is also supported out of the box).

You can also move over to Nub from pnpm incrementally if you want the performance or security wins. It has complete pnpm compatibility: flag for flag identical CLI, reads and writes from your pnpm-lock.yaml, and respects your expecting configs completely. Nub and pnpm can be used simultaneously by different teammates without lockfile churn. This is a key design goal, and its what I mean by "incrementally adoptable". But yeah `nub install` will almost certainly work in your repo out of the box. (File an issue otherwise.)

https://nubjs.com/docs/install/pnpm

Same is true for npm, yarn, and bun as well. It detects your current package manager (based on package.json#packageManager or lockfile existence) and runs in "compatibility mode" for that specific package manager.

https://nubjs.com/docs/install#config-it-reads
colinmcd
·21 hari yang lalu·discuss
Exactly this. TypeScript also ended up being many users' entrypoint to JSX, decorators, etc as it became a catchall transpiler surface so respecting tsconfig is vital here (Node understandably has a policy against this). Plus there are extensionless imports, the "phantom" .js imports (pointing to .ts files), etc. List goes on. Type stripping ends up working out of the box for virtually no real world projects sadly.

https://nubjs.com/docs/runtime/typescript
colinmcd
·21 hari yang lalu·discuss
Indeed, Nub intentionally introduces no Nub-specific APIs: no Nub global, no nub: prefixed built-in modules, no Nub-named config file / lockfile, no "nub" field in package.json, not even any NUB_ environment variables. Most of the stuff Bun added is better as a proper dependency imo.
colinmcd
·21 hari yang lalu·discuss
Certainly. We're using subtrees now instead of submodules, lets avoids some tricky worktree/submodule interactions during local dev.

We've already pulled changes since that PR landed.

https://github.com/nubjs/nub/commit/b4abee87
colinmcd
·21 hari yang lalu·discuss
EDIT: Sorry, I understand you're talking about package.json. Would be fun to try to get the Node & package mgmt teams aligned to add support for comments in the package.json. Bun tried and failed to do this (requires ecosystem coordination).

Nub could absolutely support a config file and use it to set NODE_OPTIONS or flags in the node child process. There's no reason to throw out the baby with the bathwater due to DX concerns like this. That's a key part of the concept Nub is trying to prove. (To be clear I'm quite content to conform to Node's no-config-file policy at the moment.)
colinmcd
·21 hari yang lalu·discuss
I almost called it "oi" but I'm not sure anyone would have gotten the joke :P
colinmcd
·21 hari yang lalu·discuss
Right now, you should use Nub on the backend if you are relying on its augmentations. If you specifically want to disable Nub's augmentations (so you have a guarantee that your app/script will "just work" with regular Node, there's a couple ways to disable it.

  NODE_COMPAT=0 nub index.ts
  nub --node index.ts

I'll investigate a `nub build` that would do the transpilation upfront and properly chunk/bundle a prod build. It's a good idea. But yes, Nub's overhead (both time and space) is generally negligible relative to Node itself.

Re: added attack surface: the most obvious one is that Nub loads .env files (same as Bun/Next/Vite) so be aware of that. All of Node's permission flags are passed through as well. I won't claim there's no additional attack surface, but it doesn't have much surface area, just a Rust wrapper that spawns `node` ultimately.
colinmcd
·21 hari yang lalu·discuss
We use this to register our preload purely for performance reasons. In this and many other cases CommonJS is still faster than ESM. Using --require is about 0.5ms overhead vs 4.6ms for --import (on my M1 Macbook Pro).

Relatedly Node.js recently (2025) introduced a synchronous version of its resolver hook registration API (`module.registerHooks()`) specifically to improve performance over the old async `module.register()` API. It was a big unblocker for Nub. For the interested, the async API added 19ms fixed registration overhead + about 130us additional overhead per import.

Which flag Nub uses here doesn't impact userland at all, TLA is supported wherever it's supported by Node.js itself.
colinmcd
·21 hari yang lalu·discuss
It entered public beta last week, but just getting on HN now.
colinmcd
·21 hari yang lalu·discuss
Coming very soon!
colinmcd
·22 hari yang lalu·discuss
Thanks :) Highly recommend clicking the link too!
colinmcd
·22 hari yang lalu·discuss
Yep, full support on macOS, Linux, Windows. No official image yet (I'll start on this now) but you can get started with something like this.

  FROM node:26-slim
  RUN npm i -g @nubjs/nub
Works with any Node version down to 18.19 but recommend 22.15+ for best performance (that's when synchronous registerHooks was introduced[0])

[0] https://nodejs.org/api/module.html#moduleregisterhooksoption...
colinmcd
·22 hari yang lalu·discuss
Cloudflare Workers is a different runtime and has its own toolchain around it. Nub could theoretically support it when executing files (spawn `wrangler dev` instead of `node` if wrangler.toml is detected or something) but really I'm focused on making the Node.js experience as good as possible.

The other pieces of the toolkit could absolutely be used: package manager, script runner, package runner. Works with anything that implements the Node module resolution algorithm (actually Yarn PnP also works out of the box...).
colinmcd
·tahun lalu·discuss
As you allude to: your aliased "zod-next" dependency wouldn't be able to satisfy the requirements of any packages with a peer dep on Zod. But this approach has a more fundamental flaw. My goal is to let ecosystem libraries support Zod 3 and Zod 4 simultaneously. There's no reliable way to do that if they aren't in the same package.[0]

[0] https://github.com/colinhacks/zod/issues/4371
colinmcd
·tahun lalu·discuss
It won't typecheck, which is good in this case, because as you say that's a very bad idea :)
colinmcd
·tahun lalu·discuss
I understand this as a knee-jerk reaction. I didn't do this lightly.

> Perhaps publish a 4.x along with the 3.x stuff

You have some misconceptions about how npm works. Unfortunately it's less reasonable than you think. There's a single `latest` tag, and there's only one "latest" version at a time. It's expected that successive versions here will follow semver. Once I publish zod@4 I can no longer publish additional [email protected] versions. The workaround here is to publish v3 versions to a separate dist tag (zod@three) but anyone consuming that dist-tag (e.g. "zod": "three" in their package.json) loses the ability to specify a semver range.

I recommend reading the writeup[0]. I don't think you're appreciating the magnitude of the disruption a simple major version bump would have caused, or the reasons why this approach is necessary to unlock continuity for Zod's ecosystem libraries. They're quite subtle.

[0] https://github.com/colinhacks/zod/issues/4371
colinmcd
·tahun lalu·discuss
No, that kind of interop, especially static interop (assignability), would've been totally unworkable. Despite the length of the changelog, there are very few breaking changes to the user-facing API surface. It's mostly internal/structural changes and deprecations (most of which can be fixed with a find&replace).

Report back about that .d.ts issue. It should be far better. That kind of type explosion usually happens when TypeScript needs to infer function/method return types. Zod 4 uses isolatedDeclarations so this kind of thing shouldn't happen.
colinmcd
·tahun lalu·discuss
Yes! Zod now differentiates between `z.string().optional()` and `z.union([z.string(), z.undefined()])` (as in TypeScript itself). Details: https://x.com/colinhacks/status/1919291504587137496
colinmcd
·tahun lalu·discuss
Yep, at some indeterminate point when I gauge that there's sufficient support for Zod 4 in the ecosystem, I'll publish `[email protected]` to npm. This is detailed in the writeup[0]

[0] https://github.com/colinhacks/zod/issues/4371
colinmcd
·tahun lalu·discuss
This is not done for Zod's benefit. It's done for the benefit of libraries that depend on Zod, and the users of those libraries. If a library wants to add "incremental" support for Zod4 (that is, without dropping support for Zod 3 and publishing a new major), they need access to types (and possibly runtime code) from both libraries to do so in a sound way. I detail a number of other approaches for achieving this here[0] and why they ultimately fall short. Ultimately npm wasn't designed for this particular set of circumstances.

[0] https://github.com/colinhacks/zod/issues/4371