Skip to content

feat: add opt-in strictPrefix option - #41

Merged
suhailopensource merged 3 commits into
suhailopensource:mainfrom
NspxMiguel:feat/strict-prefix
Oct 11, 2026
Merged

suhailopensource merged 3 commits into
suhailopensource:mainfrom
NspxMiguel:feat/strict-prefix

Conversation

@NspxMiguel

Copy link
Copy Markdown
Contributor

Closes #35

Adds strictPrefix?: boolean to createId and createSortableId. When true, the prefix must match /^[A-Za-z0-9]{1,63}$/, otherwise a TypeError names the first offending character, e.g. prefid: prefix "us er" contains an invalid character " " at index 2.

  • Check lives in assertValidPrefix (src/internal/prefix.ts)
  • Tests: space, punctuation, non-ASCII, 63 chars allowed, 64 rejected, default mode unchanged; both generators
  • README section and CHANGELOG entry under Unreleased
  • npm run verify passes; default behavior is unchanged

@suhailopensource

Copy link
Copy Markdown
Owner

Thanks @NspxMiguel, this is a really clean PR. It's small, focused, and follows the issue closely.

What I checked:

  • npm run verify passes (128 tests, coverage gate green), and the branch is up to date with main.
  • The error text matches the issue exactly: prefid: prefix "us er" contains an invalid character " " at index 2.
  • Emoji are handled well. "ab😀" reports "😀" at index 2, not half a character. Nice use of codePointAt.
  • Default mode really is unchanged. I generated the same seeded IDs on main and on this branch and got byte-identical output.
  • The option is on both IdOptions and SortableIdOptions in the built types. It also works on Node 14 to 24, Bun and Deno.
  • Your tests caught the mutations I tried: 63 changed to 64, the strict check removed, and the default flipped to strict.

A few small changes before I merge:

  1. Make strict a required parameter in src/internal/prefix.ts. Use

    strict: boolean,

    instead of strict = false,. Both callers already pass it, so nothing else changes. The reason: the two open batch PRs (feat: add batch ID generation #44, feat: add many() for batch ID generation #45) add a .many() method that calls assertValidPrefix(prefix, separator) with only two arguments. With the default value that still compiles, and createId({ strictPrefix: true }).many("us er", 3) would quietly return IDs instead of throwing. With a required parameter, TypeScript flags those calls straight away.

  2. Add a test for an emoji prefix. The code already handles this correctly, but no test covers it. If I swap the String.fromCodePoint(prefix.codePointAt(...)) line for prefix[bad.index], every test still passes, and the message would print half an emoji. This test in test/generate.test.ts, right after the non-ASCII test, locks it in:

    it("names a whole emoji, not half of it", () => {
      expect(() => strict("ab😀")).toThrow(/invalid character "😀" at index 2/);
    });
  3. README: show the real error text. The example comment leaves out the prefid: part, so people searching for the message won't find it. Suggested line:

    id("us er"); // throws TypeError: prefid: prefix "us er" contains an invalid character " " at index 2.

Optional, happy either way: the 64-character error says prefid: prefix must be at most 63 characters in strict mode. It would help a little more if it said how long the prefix was, for example prefid: prefix is 64 characters long; strict mode allows at most 63. The 64-character test could then check that exact message instead of only TypeError.

Thanks again, this is very close!

createId and createSortableId accept strictPrefix. When true, the prefix
must be 1-63 ASCII letters or digits; otherwise a TypeError names the first
offending character. Default behavior is unchanged.
Make strict a required parameter so callers that forget it fail to
compile instead of silently skipping the check. Cover an emoji prefix,
show the full error text in the README, and report the prefix length in
the 64-character error.
@NspxMiguel

Copy link
Copy Markdown
Contributor Author

Thanks for the careful review. Pushed: strict is now a required parameter of assertValidPrefix; the emoji test (ab😀); the README line shows the full TypeError: prefid: … text; and the 64-character error now says prefid: prefix is 64 characters long; strict mode allows at most 63., with the test checking that exact message. Rebased on current main. npm run verify passes (129 tests).

For #45 I'll pass strictPrefix into the many() prefix checks and add a test once this one lands.

@suhailopensource
suhailopensource merged commit 7da02af into suhailopensource:main Oct 11, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] : opt-in strict prefix validation

2 participants