@nubjs/types 0.7.2 → 0.7.3

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
@@ -1,6 +1,6 @@
1
1
  # @nubjs/types
2
2
 
3
- TypeScript ambient declarations for code authored against the Nub runtime global `Worker`, `Temporal`, `reportError`, data-format wildcard imports (`*.yaml`, `*.toml`, etc.), and `import.meta.hot`.
3
+ TypeScript ambient declarations for code authored against the Nub runtime, including its global Worker, Temporal, proposal polyfills, data-format imports, and hot-reload metadata.
4
4
 
5
5
  ## Usage
6
6
 
@@ -14,4 +14,4 @@ Then in `tsconfig.json`:
14
14
  { "compilerOptions": { "types": ["node", "@nubjs/types"] } }
15
15
  ```
16
16
 
17
- **Recommended: `@types/node@26` (or at minimum `@types/node@25.9.3`).** This package requires `@types/node>=25` earlier versions lack the global `MessageEvent`, `ErrorEvent`, and `MessagePort` that the `Worker` declaration depends on. Upgrade once `@types/node@26` ships.
17
+ Use `@types/node@26`, or `@types/node@25.9.3` at minimum. TypeScript 6 and newer use the compiler's official Temporal declarations; TypeScript 5.9 uses the matching declarations bundled with this package.
package/common.d.ts ADDED
@@ -0,0 +1,243 @@
1
+ // @nubjs/types — ambient declarations for code authored against the Nub runtime.
2
+ //
3
+ // Nub augments Node with surfaces TypeScript doesn't know about. This package
4
+ // makes that nub-authored code typecheck so the parity bar holds: "if `tsc
5
+ // --noEmit` accepts your code, nub runs it."
6
+ //
7
+ // Declares Nub-only surfaces plus proposal APIs that are missing from a consumer's
8
+ // selected TypeScript lib. Proposal members augment the standard interfaces rather
9
+ // than redeclaring their global values: an older lib gains the methods, while a
10
+ // newer lib's declarations merge without TS2403/TS2717 conflicts. Runtime surfaces
11
+ // already covered by @types/node or the selected standard libraries remain absent.
12
+ // Add this package to a tsconfig with `types: ["node", "@nubjs/types"]`.
13
+ //
14
+ // MUST remain a global *script* file: NO top-level `import`/`export`. The wildcard
15
+ // `declare module "*.yaml"` declarations are only visible project-wide from a
16
+ // script file. (Adding `export {}` turns this into a module and silently breaks
17
+ // the data-import wildcards.) Globals are declared bare (`declare function …`,
18
+ // `declare var …`, `declare namespace …`) for the same reason.
19
+
20
+ // ── Data-format module imports (Nub load hook; wiki/runtime/data-loaders.md) ──
21
+ // Default export ONLY — data modules expose no named exports (a named import
22
+ // like `import { host } from "./c.yaml"` is a load-time error on nub, the same
23
+ // as Node's JSON modules). The object formats default to `Record<string,
24
+ // unknown>` so the default can be destructured with sound `unknown` keys —
25
+ // `import cfg from "./c.yaml"; const { host, port } = cfg;` gives `host`/`port:
26
+ // unknown`. This is the sound, typeable equivalent of named imports.
27
+ //
28
+ // CAVEAT: a top-level array or scalar (e.g. a YAML document whose root is a list
29
+ // or a bare string) is mistyped as a record by `Record<string, unknown>`; cast
30
+ // the default in that case (`import data from "./list.yaml"; const items = data
31
+ // as unknown as string[];`). `.txt` is always a `string`; `.json` is
32
+ // intentionally NOT declared — it's Node-native (resolveJsonModule).
33
+ declare module "*.yaml" {
34
+ const data: Record<string, unknown>;
35
+ export default data;
36
+ }
37
+ declare module "*.yml" {
38
+ const data: Record<string, unknown>;
39
+ export default data;
40
+ }
41
+ declare module "*.toml" {
42
+ const data: Record<string, unknown>;
43
+ export default data;
44
+ }
45
+ declare module "*.jsonc" {
46
+ const data: Record<string, unknown>;
47
+ export default data;
48
+ }
49
+ declare module "*.json5" {
50
+ const data: Record<string, unknown>;
51
+ export default data;
52
+ }
53
+ declare module "*.txt" {
54
+ const data: string;
55
+ export default data;
56
+ }
57
+
58
+ // ── reportError (WinterTC min-common-API; runtime/polyfills.cjs) ──
59
+ // In no Node version, in no @types/node. Nub installs it on every supported version.
60
+ declare function reportError(error: unknown): void;
61
+
62
+ // ── lib.dom step-aside helpers (idiom from bun-types: packages/bun-types/bun.d.ts) ──
63
+ // These two ambient *type* aliases let us declare DOM-overlapping globals (today
64
+ // just `Worker`) WITHOUT colliding (TS2403/TS2430) when the consumer ALSO has them
65
+ // globally — e.g. `lib: ["dom"]`, or any other lib that declares `Worker`. They
66
+ // are pure type-level helpers: a global *script* may declare ambient `type`s
67
+ // freely (only a top-level `import`/`export` would turn this into a module), so
68
+ // this does NOT break the wildcard `declare module "*.yaml"` decls above.
69
+ //
70
+ // `__NubLibDomIsLoaded` — lib.dom defines the global `onabort`; its presence is the
71
+ // signal that DOM is loaded, so the DOM owns these globals and we must step aside.
72
+ // `__NubUseLibDomIfAvailable<K, T>` — when DOM is loaded, adopt whatever type
73
+ // `globalThis` already has for key K; otherwise fall back to our own shape T. This
74
+ // is exactly Bun's `Bun.__internal.{LibDomIsLoaded,UseLibDomIfAvailable}`, recast
75
+ // as bare ambient globals (with a `__Nub` prefix) so the file stays a script.
76
+ type __NubLibDomIsLoaded = typeof globalThis extends { onabort: any } ? true : false;
77
+ type __NubUseLibDomIfAvailable<GlobalThisKeyName extends PropertyKey, Otherwise> =
78
+ __NubLibDomIsLoaded extends true
79
+ ? typeof globalThis extends { [K in GlobalThisKeyName]: infer T }
80
+ ? T
81
+ : Otherwise
82
+ : Otherwise;
83
+
84
+ // ── Browser-shape Worker global (runtime/worker-polyfill.mjs; wiki/runtime/web-worker.md) ──
85
+ // Nub ships the WHATWG/browser subset of `Worker` over node:worker_threads.Worker.
86
+ // @types/node has NO global `Worker` (only node:worker_threads' class), so this is
87
+ // the genuine gap. `MessageEvent`, `ErrorEvent`, and `MessagePort` are ALREADY
88
+ // global in @types/node>=25 (web-globals/fetch.d.ts + messaging.d.ts) — verified
89
+ // empirically — so they are referenced from there and intentionally NOT redeclared
90
+ // here (redeclaring them collides: TS2403).
91
+ //
92
+ // Step-aside: when `lib: ["dom"]` is in play, the DOM's own `Worker` wins — the
93
+ // interface body resolves to `{}` (via `__NubLibWorkerOrNubWorker`) and our `var`
94
+ // adopts the DOM type (via `__NubUseLibDomIfAvailable`), so the two coexist with
95
+ // NO TS2403/TS2430 collision. When DOM is absent (the normal Node case), our full
96
+ // browser-shape declaration applies unchanged.
97
+ interface WorkerOptions {
98
+ type?: "module" | "classic";
99
+ name?: string;
100
+ credentials?: "omit" | "same-origin" | "include";
101
+ // `eval: true` runs the constructor's first argument as the worker's source
102
+ // (Node's worker_threads inline form) instead of resolving it as a URL.
103
+ eval?: true;
104
+ }
105
+ interface __NubWorker extends EventTarget {
106
+ readonly name: string;
107
+ postMessage(message: any, transfer?: readonly (ArrayBuffer | MessagePort)[]): void;
108
+ // Returns the underlying worker_threads `Promise<exitCode>` (additive
109
+ // void→value widening; spec code that ignores the return is unaffected).
110
+ terminate(): Promise<number>;
111
+ onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
112
+ onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
113
+ onerror: ((this: Worker, ev: ErrorEvent) => any) | null;
114
+ // node:worker_threads EventEmitter surface, delegated to the underlying real
115
+ // Worker. The node channel carries Node's shapes — `message` the RAW posted
116
+ // value, `error` a bare `Error`, `exit` the numeric exit code, `online` no arg —
117
+ // distinct from the web channel above (`MessageEvent`/`ErrorEvent`). The adders
118
+ // return the handle for chaining.
119
+ on(event: "message", listener: (value: any) => void): this;
120
+ on(event: "messageerror", listener: (error: Error) => void): this;
121
+ on(event: "error", listener: (err: Error) => void): this;
122
+ on(event: "exit", listener: (exitCode: number) => void): this;
123
+ on(event: "online", listener: () => void): this;
124
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
125
+ once(event: "message", listener: (value: any) => void): this;
126
+ once(event: "messageerror", listener: (error: Error) => void): this;
127
+ once(event: "error", listener: (err: Error) => void): this;
128
+ once(event: "exit", listener: (exitCode: number) => void): this;
129
+ once(event: "online", listener: () => void): this;
130
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
131
+ addListener(event: "message", listener: (value: any) => void): this;
132
+ addListener(event: "messageerror", listener: (error: Error) => void): this;
133
+ addListener(event: "error", listener: (err: Error) => void): this;
134
+ addListener(event: "exit", listener: (exitCode: number) => void): this;
135
+ addListener(event: "online", listener: () => void): this;
136
+ addListener(event: string | symbol, listener: (...args: any[]) => void): this;
137
+ off(event: string | symbol, listener: (...args: any[]) => void): this;
138
+ removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
139
+ emit(event: string | symbol, ...args: any[]): boolean;
140
+ }
141
+ type __NubLibWorkerOrNubWorker = __NubLibDomIsLoaded extends true ? {} : __NubWorker;
142
+ interface Worker extends __NubLibWorkerOrNubWorker {}
143
+ declare var Worker: __NubUseLibDomIfAvailable<
144
+ "Worker",
145
+ {
146
+ prototype: Worker;
147
+ new (scriptURL: string | URL, options?: WorkerOptions): Worker;
148
+ }
149
+ >;
150
+
151
+ // ── import.meta.hot (Vite-compatible; wiki/runtime/hot-mode.md — v0.x, shape committed v0.1) ──
152
+ // Forward-compat commitment: ships now so framework authors can code against the
153
+ // shape. `import.meta.hot` is `undefined` unless `nub watch --hot` is active.
154
+ interface ImportMeta {
155
+ readonly hot?: {
156
+ readonly data: Record<string, any>;
157
+ accept(): void;
158
+ accept(cb: (mod: any) => void): void;
159
+ accept(dep: string, cb: (mod: any) => void): void;
160
+ accept(deps: readonly string[], cb: (mods: any[]) => void): void;
161
+ dispose(cb: (data: Record<string, any>) => void): void;
162
+ invalidate(): void;
163
+ on(event: string, cb: (data: any) => void): void;
164
+ send(event: string, data?: any): void;
165
+ };
166
+ }
167
+
168
+ // ── Recently polyfilled proposal APIs (runtime/polyfills.cjs) ──
169
+ // Use declaration merging for existing ECMAScript globals. This is the same shape
170
+ // TypeScript's `lib.esnext.*` files and Bun's runtime types use: never redeclare
171
+ // `var Promise`, `var Symbol`, etc. Method members safely become overloads when a
172
+ // future standard lib adds them. The one property member (`Symbol.metadata`) is
173
+ // byte-for-byte TypeScript's already-settled `lib.esnext.decorators` declaration.
174
+
175
+ // Iterator chunking/includes/join. `IteratorObject` is in lib.es2015.iterable even
176
+ // when the ES2025 Iterator constructor is not selected, so built-in iterators gain
177
+ // these methods at the ES2024 target too. The versioned package entry point loads
178
+ // TypeScript's own Iterator constructor and base-helper declarations.
179
+ interface IteratorObject<T, TReturn, TNext> {
180
+ chunks(chunkSize: number): IteratorObject<T[], undefined, unknown>;
181
+ windows(windowSize: number): IteratorObject<T[], undefined, unknown>;
182
+ includes(searchElement: T): boolean;
183
+ join(separator?: string): string;
184
+ }
185
+
186
+ interface Math {
187
+ sumPrecise(items: Iterable<number>): number;
188
+ }
189
+
190
+ interface SymbolConstructor {
191
+ readonly metadata: unique symbol;
192
+ }
193
+
194
+ interface Atomics {
195
+ pause(iterationNumber?: number): void;
196
+ }
197
+
198
+ // Promise.allKeyed / Promise.allSettledKeyed (TC39 await dictionary). The mapped
199
+ // types mirror the proposal README: the key set is preserved and each value is
200
+ // `Awaited`. Two runtime facts TypeScript cannot express — the result object has a
201
+ // null prototype, and only own enumerable keys appear at runtime.
202
+ interface PromiseConstructor {
203
+ allKeyed<T extends object>(promises: T): Promise<{ -readonly [K in keyof T]: Awaited<T[K]> }>;
204
+ allSettledKeyed<T extends object>(
205
+ promises: T,
206
+ ): Promise<{ -readonly [K in keyof T]: PromiseSettledResult<Awaited<T[K]>> }>;
207
+ }
208
+
209
+ // Uint8Array base64/hex. These signatures match TypeScript 6's
210
+ // lib.esnext.typedarrays exactly, so consumers on older TypeScript versions gain
211
+ // them and newer standard libraries merge the identical interface members.
212
+ interface Uint8Array<TArrayBuffer extends ArrayBufferLike> {
213
+ toBase64(options?: {
214
+ alphabet?: "base64" | "base64url" | undefined;
215
+ omitPadding?: boolean | undefined;
216
+ }): string;
217
+ setFromBase64(
218
+ string: string,
219
+ options?: {
220
+ alphabet?: "base64" | "base64url" | undefined;
221
+ lastChunkHandling?: "loose" | "strict" | "stop-before-partial" | undefined;
222
+ },
223
+ ): { read: number; written: number };
224
+ toHex(): string;
225
+ setFromHex(string: string): { read: number; written: number };
226
+ }
227
+ interface Uint8ArrayConstructor {
228
+ fromBase64(
229
+ string: string,
230
+ options?: {
231
+ alphabet?: "base64" | "base64url" | undefined;
232
+ lastChunkHandling?: "loose" | "strict" | "stop-before-partial" | undefined;
233
+ },
234
+ ): Uint8Array<ArrayBuffer>;
235
+ fromHex(string: string): Uint8Array<ArrayBuffer>;
236
+ }
237
+
238
+ // ── Date.prototype.toTemporalInstant (runtime/preload-common.cjs installs it) ──
239
+ // Nub assigns the polyfill's `toTemporalInstant` onto Date.prototype on the floor
240
+ // (matching native Node, which ships it once Temporal is native).
241
+ interface Date {
242
+ toTemporalInstant(): Temporal.Instant;
243
+ }