sigilid 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,10 +24,12 @@ const id = generateId(); // "K7gkJ_q3vR2nL8xH5eM0w"
24
24
  - **URL-safe by default** — 64-character alphabet: `A-Z a-z 0-9 _ -`
25
25
  - **Tree-shakeable** — subpath exports mean your bundle only includes what you import
26
26
  - **Zero runtime dependencies** — no third-party code in production output
27
+ - **Optional Node native fast path** — `sigilid/native` for Node-only throughput tuning
27
28
  - **ESM-only** — works in modern Node, edge runtimes, and all major bundlers
28
29
  - **Strong TypeScript support** — strict types, branded ID types, precise inference
29
30
  - **Predictable behavior** — explicit errors on invalid input, no silent failures
30
- - **One package, six entrypoints** — `install sigilid`, then import only what you need
31
+ - **One package, seven entrypoints** — `install sigilid`, then import only what you need
32
+ - **Companion native addon package** — only needed when using `sigilid/native`
31
33
 
32
34
  ---
33
35
 
@@ -38,10 +40,10 @@ one never pulls in the others.
38
40
 
39
41
  | Import | Size |
40
42
  | -------------------- | ------ |
41
- | `sigilid` | ~234 B |
43
+ | `sigilid` | ~297 B |
42
44
  | `sigilid/non-secure` | ~214 B |
43
- | `sigilid/prefix` | ~348 B |
44
- | `sigilid/typed` | ~382 B |
45
+ | `sigilid/prefix` | ~385 B |
46
+ | `sigilid/typed` | ~398 B |
45
47
  | `sigilid/validate` | ~360 B |
46
48
  | `sigilid/alphabet` | ~380 B |
47
49
 
@@ -65,6 +67,14 @@ yarn add sigilid
65
67
 
66
68
  Node 20+ required. Works in all modern runtimes that expose the Web Crypto API (`globalThis.crypto`).
67
69
 
70
+ Optional native path:
71
+
72
+ ```bash
73
+ npm install sigilid @sigilid/native-addon
74
+ ```
75
+
76
+ Use `@sigilid/native-addon` only if you plan to import `sigilid/native`.
77
+
68
78
  ---
69
79
 
70
80
  ## Quick start
@@ -133,6 +143,30 @@ generateNonSecureId(8); // 8-character ID
133
143
 
134
144
  ---
135
145
 
146
+ ### `sigilid/native` — optional Node-only fast path
147
+
148
+ ```ts
149
+ import { generateDefault, generateId } from "sigilid/native";
150
+
151
+ generateDefault(); // 21-character secure ID
152
+ generateDefault(32); // 32-character secure ID
153
+
154
+ // Alias that mirrors the root naming
155
+ generateId(21);
156
+ ```
157
+
158
+ - Node-only entrypoint.
159
+ - Requires the companion addon package: `@sigilid/native-addon`.
160
+ - Uses secure randomness and the same default alphabet as `sigilid`.
161
+ - Throws a clear error if the addon is missing or the runtime is unsupported.
162
+ - Addon install tries prebuilt binaries first, then falls back to local `node-gyp` build.
163
+ - Publishing note: `sigilid` and `@sigilid/native-addon` are versioned/published separately.
164
+
165
+ If you want the broadest compatibility (browser, edge, and Node) stick to the root
166
+ `sigilid` import.
167
+
168
+ ---
169
+
136
170
  ### `sigilid/prefix` — prefixed IDs
137
171
 
138
172
  ```ts
@@ -333,6 +367,34 @@ similar. The subpath ecosystem is where `sigilid` earns its place.
333
367
  If you are targeting an environment without Web Crypto, use `sigilid/non-secure`
334
368
  with the understanding that `Math.random` is not cryptographically safe.
335
369
 
370
+ `sigilid/native` is a separate Node-only path. It depends on the companion addon
371
+ package and is not intended for browsers or edge runtimes.
372
+
373
+ ---
374
+
375
+ ## Benchmarking
376
+
377
+ For local performance checks, run:
378
+
379
+ ```bash
380
+ npm ci
381
+ npm run build
382
+ npm run bench
383
+ ```
384
+
385
+ Native vs JS benchmark:
386
+
387
+ ```bash
388
+ npm run build:native-addon
389
+ npm run bench:native
390
+ ```
391
+
392
+ Build prebuilt binaries for publishing the addon:
393
+
394
+ ```bash
395
+ npm run prebuild:native-addon
396
+ ```
397
+
336
398
  ---
337
399
 
338
400
  ## Package exports
@@ -340,6 +402,7 @@ with the understanding that `Math.random` is not cryptographically safe.
340
402
  | Import | Entry file | Description |
341
403
  | -------------------- | -------------------- | ---------------------------------- |
342
404
  | `sigilid` | `dist/index.js` | Secure root generator |
405
+ | `sigilid/native` | `dist/native.js` | Optional Node-only native fast path |
343
406
  | `sigilid/non-secure` | `dist/non-secure.js` | Math.random-based generator |
344
407
  | `sigilid/prefix` | `dist/prefix.js` | Prefixed ID helpers |
345
408
  | `sigilid/typed` | `dist/typed.js` | Branded types and typed generators |
@@ -0,0 +1,7 @@
1
+ /**
2
+ * URL-safe alphabet used by default. 64 characters: A-Z, a-z, 0-9, _, -.
3
+ * Chosen to be safe in URLs, filenames, and most log formats without encoding.
4
+ */
5
+ declare const DEFAULT_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
6
+
7
+ export { DEFAULT_ALPHABET as D };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,4 @@
1
- /**
2
- * URL-safe alphabet used by default. 64 characters: A-Z, a-z, 0-9, _, -.
3
- * Chosen to be safe in URLs, filenames, and most log formats without encoding.
4
- */
5
- declare const DEFAULT_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
1
+ export { D as DEFAULT_ALPHABET } from './constants-CFnCjbhy.js';
6
2
 
7
3
  /**
8
4
  * Generates a cryptographically secure random ID.
@@ -16,4 +12,4 @@ declare const DEFAULT_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst
16
12
  */
17
13
  declare function generateId(length?: number): string;
18
14
 
19
- export { DEFAULT_ALPHABET, generateId };
15
+ export { generateId };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- function e(r){if(!Number.isInteger(r)||r<1||r>255)throw new RangeError(`length must be 1\u2013255, got ${r}`)}var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";function n(r){return Array.from(crypto.getRandomValues(new Uint8Array(r)),o=>t[o&63]).join("")}function g(r=21){return e(r),n(r)}export{t as DEFAULT_ALPHABET,g as generateId};
1
+ function s(t){if(!Number.isInteger(t)||t<1||t>255)throw new RangeError(`length must be 1\u2013255, got ${t}`)}var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";var n=1024,i=new Uint8Array(n),m=e,r=n;function a(t){r+t>n&&(crypto.getRandomValues(i),r=0);let o="",f=r+t;for(;r<f;)o+=m[i[r++]&63];return o}function w(t=21){return s(t),a(t)}export{e as DEFAULT_ALPHABET,w as generateId};
@@ -0,0 +1,6 @@
1
+ export { D as DEFAULT_ALPHABET } from './constants-CFnCjbhy.js';
2
+
3
+ declare function generateDefault(length?: number): string;
4
+ declare function generateId(length?: number): string;
5
+
6
+ export { generateDefault, generateId };
package/dist/native.js ADDED
@@ -0,0 +1 @@
1
+ import {createRequire}from'module';function n(e){if(!Number.isInteger(e)||e<1||e>255)throw new RangeError(`length must be 1\u2013255, got ${e}`)}var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";var d=createRequire(import.meta.url),u="@sigilid/native-addon";function f(){return typeof process<"u"&&typeof process.versions?.node=="string"}function o(e=u){if(!f())throw new Error("sigilid/native is only supported in Node.js.");try{let t=d(e);if(typeof t.generateDefault!="function")throw new TypeError(`${e} does not export generateDefault(length).`);return t}catch(t){let i=`sigilid/native failed to load ${e}. Install it with "npm install ${e}" and ensure native builds are available.`,r=new Error(i);throw t instanceof Error&&Object.defineProperty(r,"cause",{value:t,enumerable:false,configurable:true,writable:true}),r}}var l=o();function p(e=21){return n(e),l.generateDefault(e)}function h(e=21){return p(e)}export{a as DEFAULT_ALPHABET,p as generateDefault,h as generateId};
package/dist/prefix.js CHANGED
@@ -1 +1 @@
1
- function e(r){if(!Number.isInteger(r)||r<1||r>255)throw new RangeError(`length must be 1\u2013255, got ${r}`)}function n(r){if(typeof r!="string"||r.length===0)throw new TypeError("prefix must be a non-empty string");if(!/^[a-z][a-z\d]*$/i.test(r))throw new TypeError("prefix must start with a letter and contain only alphanumeric characters")}var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";function o(r){return Array.from(crypto.getRandomValues(new Uint8Array(r)),t=>i[t&63]).join("")}function p(r,t=21){return n(r),e(t),`${r}_${o(t)}`}function c(r,t=21){return n(r),e(t),()=>`${r}_${o(t)}`}export{c as createPrefixedGenerator,p as generatePrefixedId};
1
+ function n(r){if(!Number.isInteger(r)||r<1||r>255)throw new RangeError(`length must be 1\u2013255, got ${r}`)}function o(r){if(typeof r!="string"||r.length===0)throw new TypeError("prefix must be a non-empty string");if(!/^[a-z][a-z\d]*$/i.test(r))throw new TypeError("prefix must start with a letter and contain only alphanumeric characters")}var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";var s=1024,u=new Uint8Array(s),c=a,e=s;function i(r){e+r>s&&(crypto.getRandomValues(u),e=0);let t="",f=e+r;for(;e<f;)t+=c[u[e++]&63];return t}function x(r,t=21){return o(r),n(t),`${r}_${i(t)}`}function E(r,t=21){return o(r),n(t),()=>`${r}_${i(t)}`}export{E as createPrefixedGenerator,x as generatePrefixedId};
package/dist/typed.js CHANGED
@@ -1 +1 @@
1
- function n(r){if(!Number.isInteger(r)||r<1||r>255)throw new RangeError(`length must be 1\u2013255, got ${r}`)}function o(r){if(typeof r!="string"||r.length===0)throw new TypeError("prefix must be a non-empty string");if(!/^[a-z][a-z\d]*$/i.test(r))throw new TypeError("prefix must start with a letter and contain only alphanumeric characters")}var s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";function a(r){return Array.from(crypto.getRandomValues(new Uint8Array(r)),t=>s[t&63]).join("")}function p(r){return r}function m(r,t=21){return r!==void 0&&o(r),n(t),()=>{let e=a(t);return r!==void 0?`${r}_${e}`:e}}export{p as castId,m as createTypedGenerator};
1
+ function s(t){if(!Number.isInteger(t)||t<1||t>255)throw new RangeError(`length must be 1\u2013255, got ${t}`)}function a(t){if(typeof t!="string"||t.length===0)throw new TypeError("prefix must be a non-empty string");if(!/^[a-z][a-z\d]*$/i.test(t))throw new TypeError("prefix must start with a letter and contain only alphanumeric characters")}var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";var o=1024,d=new Uint8Array(o),u=i,e=o;function f(t){e+t>o&&(crypto.getRandomValues(d),e=0);let r="",n=e+t;for(;e<n;)r+=u[d[e++]&63];return r}function l(t){return t}function w(t,r=21){return t!==void 0&&a(t),s(r),()=>{let n=f(r);return t!==void 0?`${t}_${n}`:n}}export{l as castId,w as createTypedGenerator};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sigilid",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "A tiny, tree-shakeable ID toolkit for TypeScript apps. Secure core with optional subpath exports for prefixed IDs, typed IDs, validation, and custom alphabets.",
5
5
  "license": "MIT",
6
6
  "author": "moritzmyrz",
@@ -38,6 +38,10 @@
38
38
  "types": "./dist/index.d.ts",
39
39
  "import": "./dist/index.js"
40
40
  },
41
+ "./native": {
42
+ "types": "./dist/native.d.ts",
43
+ "node": "./dist/native.js"
44
+ },
41
45
  "./non-secure": {
42
46
  "types": "./dist/non-secure.d.ts",
43
47
  "import": "./dist/non-secure.js"
@@ -67,6 +71,10 @@
67
71
  ],
68
72
  "scripts": {
69
73
  "build": "tsup",
74
+ "build:native-addon": "npm --prefix packages/native-addon run build",
75
+ "prebuild:native-addon": "npm --prefix packages/native-addon run prebuild",
76
+ "release:check": "npm run lint && npm run typecheck && npm run test && npm run build",
77
+ "release:pack": "npm pack && npm pack ./packages/native-addon",
70
78
  "test": "vitest run",
71
79
  "test:watch": "vitest",
72
80
  "test:coverage": "vitest run --coverage",
@@ -77,7 +85,8 @@
77
85
  "clean": "rm -rf dist *.tsbuildinfo",
78
86
  "verify": "npm run lint && npm run typecheck && npm run test && npm run build",
79
87
  "playground": "tsx tools/playground.ts",
80
- "bench": "tsx tools/benchmark.ts"
88
+ "bench": "tsx tools/benchmark.ts",
89
+ "bench:native": "tsx tools/benchmark-native.ts"
81
90
  },
82
91
  "size-limit": [
83
92
  {
@@ -112,6 +121,8 @@
112
121
  }
113
122
  ],
114
123
  "devDependencies": {
124
+ "@sigilid/native-addon": "file:packages/native-addon",
125
+ "@types/node": "^24.5.2",
115
126
  "@biomejs/biome": "^1.9.4",
116
127
  "@size-limit/preset-small-lib": "^12.0.1",
117
128
  "@vitest/coverage-v8": "^3.0.7",