@visulima/ono 1.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## @visulima/ono 1.0.0 (2025-09-12)
2
+
3
+ ### Features
4
+
5
+ * **ono:** initialize flare package with error handling utilities a… ([#515](https://github.com/visulima/visulima/issues/515)) ([9eaf418](https://github.com/visulima/visulima/commit/9eaf41878717a4d34c07f5513a60ca3e09bceda6))
package/LICENSE.md ADDED
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 visulima
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ <!-- DEPENDENCIES -->
24
+ <!-- /DEPENDENCIES -->
25
+
26
+ <!-- TYPE_DEPENDENCIES -->
27
+ <!-- /TYPE_DEPENDENCIES -->
package/README.md ADDED
@@ -0,0 +1,617 @@
1
+ <div align="center">
2
+ <h3>Visulima ono (Oh No!)</h3>
3
+ <p>
4
+ A modern, delightful error overlay and inspector for Node.js servers and dev tooling.
5
+ </p>
6
+ </div>
7
+
8
+ <br />
9
+
10
+ <div align="center">
11
+
12
+ [![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url]
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ <div align="center">
19
+ <p>
20
+ <sup>
21
+ Daniel Bannert's open source work is supported by the community on <a href="https://github.com/sponsors/prisis">GitHub Sponsors</a>
22
+ </sup>
23
+ </p>
24
+ </div>
25
+
26
+ ---
27
+
28
+ | Light Mode | Dark Mode |
29
+ | -------------------------------- | ------------------------------ |
30
+ | ![light](./__assets__/light.jpg) | ![dark](./__assets__/dark.jpg) |
31
+
32
+ ## Install
33
+
34
+ ```sh
35
+ pnpm add @visulima/ono
36
+ ```
37
+
38
+ ```sh
39
+ npm i @visulima/ono
40
+ ```
41
+
42
+ ```sh
43
+ yarn add @visulima/ono
44
+ ```
45
+
46
+ ## Features
47
+
48
+ - Pretty, theme‑aware error page
49
+ - Sticky header (shows error name/message while scrolling)
50
+ - One‑click copy for error title (icon feedback)
51
+ - Stack trace viewer
52
+ - Shiki‑powered syntax highlighting (singleton highlighter)
53
+ - Tabs for frames; grouping for internal/node_modules/application frames
54
+ - Tooltips and labels to guide usage
55
+ - Optional "Open in editor" button per frame
56
+ - Error causes viewer (nested causes, each with its own viewer)
57
+ - Solutions panel
58
+ - Default open; smooth expand/collapse without layout jump
59
+ - Animated height/opacity; icon toggles open/close
60
+ - Built-in rule-based Markdown hints for common issues (ESM/CJS interop, export mismatch, port in use, missing files/case, TS path mapping, DNS/connection, React hydration mismatch, undefined property access)
61
+ - Custom solution finders support
62
+ - Raw stack trace panel
63
+ - Theme toggle (auto/dark/light) with persistence
64
+ - **Copy to Clipboard** - One-click copying for all data sections
65
+ - **Responsive Design** - Sticky sidebar navigation with smooth scrolling
66
+ - Consistent tooltips (one global script; components only output HTML)
67
+
68
+ **New in latest version:**
69
+
70
+ - **Tabbed Interface** - Switch between Stack and Context views
71
+ - **Request Context Panel** - Detailed HTTP request debugging information
72
+ - cURL command with proper formatting and copy functionality
73
+ - Headers, cookies, body, and session data
74
+ - App routing, client info, Git status, and version details
75
+ - Smart data sanitization and masking for sensitive information
76
+ - **Flexible Context API** - Add any custom context data via `createRequestContextPage()`
77
+ - **Modern Ono Class API** - Simple, consistent interface for both HTML and ANSI rendering
78
+ - **Solution Finders** - Extensible system for custom error solutions
79
+
80
+ Accessibility and keyboard UX
81
+
82
+ - ARIA-correct tabs and panels for stack frames; improved labeling
83
+ - Focus trap within the overlay; restores focus on close
84
+ - Keyboard shortcuts help dialog (press Shift+/ or “?” button)
85
+ - Buttons/controls are keyboard-activatable (Enter/Space)
86
+
87
+ Editor integration
88
+
89
+ - Editor selector is always visible; selection persists (localStorage)
90
+ - Uses server endpoint when configured; otherwise opens via editor URL scheme (defaults to VS Code)
91
+
92
+ ### Using the Ono class (recommended)
93
+
94
+ The new Ono class provides a simple, consistent API for both HTML and ANSI error rendering:
95
+
96
+ ```ts
97
+ import { Ono } from "@visulima/ono";
98
+
99
+ const ono = new Ono();
100
+
101
+ // HTML error page
102
+ const html = await ono.toHTML(error, {
103
+ cspNonce: "your-nonce",
104
+ theme: "dark",
105
+ solutionFinders: [
106
+ /* custom finders */
107
+ ],
108
+ });
109
+
110
+ // ANSI terminal output
111
+ const { errorAnsi, solutionBox } = await ono.toANSI(error, {
112
+ solutionFinders: [
113
+ /* custom finders */
114
+ ],
115
+ });
116
+ ```
117
+
118
+ ### Node.js HTTP Server Example
119
+
120
+ ```ts
121
+ import { createServer } from "node:http";
122
+ import { Ono } from "@visulima/ono";
123
+ import { createRequestContextPage } from "@visulima/ono/page/context";
124
+ import { createNodeHttpHandler } from "@visulima/ono/server/open-in-editor";
125
+
126
+ const ono = new Ono();
127
+ const openInEditorHandler = createNodeHttpHandler();
128
+
129
+ const server = createServer(async (request, response) => {
130
+ const url = new URL(request.url || "/", `http://localhost:3000`);
131
+
132
+ // Open-in-editor endpoint
133
+ if (url.pathname === "/__open-in-editor") {
134
+ return openInEditorHandler(request, response);
135
+ }
136
+
137
+ try {
138
+ // Your app logic here
139
+ throw new Error("Something went wrong!");
140
+ } catch (error) {
141
+ // Create context page with request information
142
+ const contextPage = await createRequestContextPage(request, {
143
+ context: {
144
+ request: {
145
+ method: request.method,
146
+ url: request.url,
147
+ headers: request.headers,
148
+ },
149
+ user: {
150
+ client: {
151
+ ip: request.socket?.remoteAddress,
152
+ userAgent: request.headers["user-agent"],
153
+ },
154
+ },
155
+ },
156
+ });
157
+
158
+ // Generate HTML error page
159
+ const html = await ono.toHTML(error, {
160
+ content: [contextPage],
161
+ openInEditorUrl: "__open-in-editor",
162
+ cspNonce: "nonce-" + Date.now(),
163
+ theme: "auto",
164
+ });
165
+
166
+ response.writeHead(500, {
167
+ "Content-Type": "text/html",
168
+ "Content-Length": Buffer.byteLength(html, "utf8"),
169
+ });
170
+ response.end(html);
171
+ }
172
+ });
173
+
174
+ server.listen(3000);
175
+ ```
176
+
177
+ ### Hono Framework Example
178
+
179
+ ```ts
180
+ import { serve } from "@hono/node-server";
181
+ import { Hono } from "hono";
182
+ import { Ono } from "@visulima/ono";
183
+ import { createRequestContextPage } from "@visulima/ono/page/context";
184
+
185
+ const app = new Hono();
186
+ const ono = new Ono();
187
+
188
+ app.get("/", (c) => c.text("OK"));
189
+
190
+ app.get("/error", () => {
191
+ throw new Error("Boom from Hono");
192
+ });
193
+
194
+ app.onError(async (err, c) => {
195
+ const contextPage = await createRequestContextPage(c.req.raw, {
196
+ context: {
197
+ request: {
198
+ method: c.req.method,
199
+ url: c.req.url,
200
+ headers: Object.fromEntries(c.req.raw.headers.entries()),
201
+ },
202
+ },
203
+ });
204
+
205
+ const html = await ono.toHTML(err, {
206
+ content: [contextPage],
207
+ cspNonce: "hono-nonce-" + Date.now(),
208
+ theme: "dark",
209
+ });
210
+
211
+ return c.html(html, 500);
212
+ });
213
+
214
+ serve({ fetch: app.fetch, port: 3000 });
215
+ ```
216
+
217
+ ## API
218
+
219
+ ### Ono Class
220
+
221
+ The main API for rendering errors in both HTML and ANSI formats.
222
+
223
+ #### Constructor
224
+
225
+ ```ts
226
+ const ono = new Ono();
227
+ ```
228
+
229
+ #### Methods
230
+
231
+ ##### `toHTML(error, options?)` => `Promise<string>`
232
+
233
+ Renders an error as an HTML page.
234
+
235
+ - **error**: `unknown` - The error to render
236
+ - **options**: `TemplateOptions` (optional)
237
+ - `content?: ContentPage[]` - Additional pages to display as tabs
238
+ - `cspNonce?: string` - CSP nonce for inline scripts/styles
239
+ - `editor?: Editors` - Default editor for "Open in editor" functionality
240
+ - `openInEditorUrl?: string` - Server endpoint for opening files in editor
241
+ - `solutionFinders?: SolutionFinder[]` - Custom solution finders
242
+ - `theme?: 'dark' | 'light' | 'auto'` - Theme preference
243
+
244
+ Returns the complete HTML string for the error page.
245
+
246
+ ##### `toANSI(error, options?)` => `Promise<{ errorAnsi: string; solutionBox?: string }>`
247
+
248
+ Renders an error as ANSI terminal output.
249
+
250
+ - **error**: `unknown` - The error to render
251
+ - **options**: `CliOptions` (optional)
252
+ - `solutionFinders?: SolutionFinder[]` - Custom solution finders
253
+ - All other options from `@visulima/error` renderError options
254
+
255
+ Returns an object with `errorAnsi` (the formatted error) and optional `solutionBox` (suggested solutions).
256
+
257
+ ### createRequestContextPage(request, options) => `Promise<ContentPage | undefined>`
258
+
259
+ Creates a context page with detailed request debugging information.
260
+
261
+ - **request**: `Request` - The HTTP request object
262
+ - **options**: `ContextContentOptions`
263
+ - `context?: Record<string, unknown>` - Additional context data
264
+ - `headerAllowlist?: string[]` - Headers to include (default: all)
265
+ - `headerDenylist?: string[]` - Headers to exclude
266
+ - `maskValue?: string` - Mask for sensitive values (default: "[masked]")
267
+
268
+ ### createNodeHttpHandler(options) => `(req, res) => void`
269
+
270
+ Creates an HTTP handler for opening files in editors.
271
+
272
+ - **options**: `OpenInEditorOptions` (optional)
273
+ - `projectRoot?: string` - Project root directory
274
+ - `allowOutsideProject?: boolean` - Allow opening files outside project
275
+
276
+ Returns an Express/Node.js compatible request handler.
277
+
278
+ ### CLI Example
279
+
280
+ ```ts
281
+ import { Ono } from "@visulima/ono";
282
+
283
+ const ono = new Ono();
284
+
285
+ try {
286
+ throw new Error("Something went wrong!");
287
+ } catch (error) {
288
+ // Basic ANSI output
289
+ const result = await ono.toANSI(error);
290
+ console.log(result.errorAnsi);
291
+
292
+ if (result.solutionBox) {
293
+ console.log("\n" + result.solutionBox);
294
+ }
295
+
296
+ // With custom solution finder
297
+ const resultWithCustom = await ono.toANSI(error, {
298
+ solutionFinders: [
299
+ {
300
+ name: "custom-finder",
301
+ priority: 100,
302
+ handle: async (err, context) => ({
303
+ header: "Custom Solution",
304
+ body: "Try checking your configuration.",
305
+ }),
306
+ },
307
+ ],
308
+ });
309
+ }
310
+ ```
311
+
312
+ ### Request Context Panel
313
+
314
+ Use `createRequestContextPage()` to create a "Context" tab with comprehensive debugging information:
315
+
316
+ - **Request Overview** - cURL command with proper formatting and copy functionality
317
+ - **Headers** - HTTP headers with smart masking for sensitive data
318
+ - **Body** - Request body content with proper formatting
319
+ - **Session** - Session data in organized key-value tables
320
+ - **Cookies** - Cookie information in readable format
321
+ - **Dynamic Context Sections** - Any additional context keys you provide are automatically rendered as sections with:
322
+ - Proper titles (capitalized)
323
+ - Copy buttons for JSON data
324
+ - Organized key-value tables
325
+ - Sticky sidebar navigation
326
+
327
+ **Built-in sections** (when data is provided):
328
+
329
+ - `app` - Application routing details (route, params, query)
330
+ - `user` - Client information (IP, User-Agent, geo)
331
+ - `git` - Repository status (branch, commit, tag, dirty state)
332
+ - `versions` - Package versions and dependencies
333
+
334
+ **Custom sections** - Add any context data you want:
335
+
336
+ - `database` - Database connection info, queries, etc.
337
+ - `cache` - Cache status and keys
338
+ - `environment` - Environment variables
339
+ - `performance` - Performance metrics
340
+ - And more!
341
+
342
+ **Deep Object & Array Support** - The context panel intelligently renders:
343
+
344
+ - Nested objects with proper indentation and visual hierarchy
345
+ - Arrays with indexed items and collapsible structure
346
+ - Complex data types (strings, numbers, booleans, null, undefined)
347
+ - Performance-optimized rendering with depth limits (max 3 levels)
348
+ - Smart truncation for large datasets (shows first 10 items/keys)
349
+
350
+ All sections include copy buttons for easy data extraction and debugging.
351
+
352
+ ### Custom Solution Finders
353
+
354
+ Create custom solution finders to provide specific guidance for your application's errors:
355
+
356
+ ```ts
357
+ import { Ono } from "@visulima/ono";
358
+
359
+ const customFinder = {
360
+ name: "my-app-finder",
361
+ priority: 100, // Higher priority = checked first
362
+ handle: async (error, context) => {
363
+ if (error.message.includes("database connection")) {
364
+ return {
365
+ header: "Database Connection Issue",
366
+ body: "Check your database configuration and ensure the server is running.",
367
+ };
368
+ }
369
+
370
+ if (error.message.includes("authentication")) {
371
+ return {
372
+ header: "Authentication Error",
373
+ body: "Verify your API keys and authentication tokens are valid.",
374
+ };
375
+ }
376
+
377
+ return undefined; // No solution found
378
+ },
379
+ };
380
+
381
+ const ono = new Ono();
382
+ const html = await ono.toHTML(error, {
383
+ solutionFinders: [customFinder],
384
+ });
385
+ ```
386
+
387
+ ### Copy to Clipboard
388
+
389
+ All data sections in the Request Context Panel include copy buttons that:
390
+
391
+ - Copy data in JSON format for easy debugging
392
+ - Provide visual feedback (button changes to "Copied!" with green styling)
393
+ - Support both modern `navigator.clipboard` API and fallback methods
394
+ - Work across all browsers and environments
395
+
396
+ ### Adding custom pages/tabs via `options.content`
397
+
398
+ You can add any number of custom pages using the `content` option:
399
+
400
+ ```ts
401
+ import { Ono } from "@visulima/ono";
402
+ import { createRequestContextPage } from "@visulima/ono/page/context";
403
+
404
+ const ono = new Ono();
405
+
406
+ // Create a context page with request information
407
+ const contextPage = await createRequestContextPage(request, {
408
+ context: {
409
+ request: request,
410
+ app: { routing: { route: "/api/users", params: {}, query: {} } },
411
+ user: { client: { ip: "127.0.0.1", userAgent: "Mozilla/5.0..." } },
412
+ database: { connection: "active", queries: ["SELECT * FROM users"] },
413
+ },
414
+ });
415
+
416
+ // Add custom pages
417
+ const customPages = [
418
+ contextPage, // Context page with request info
419
+ {
420
+ id: "performance",
421
+ name: "Performance",
422
+ code: {
423
+ html: "<div><h3>Performance Metrics</h3><p>Custom performance data here...</p></div>",
424
+ },
425
+ },
426
+ {
427
+ id: "debug",
428
+ name: "Debug Info",
429
+ code: {
430
+ html: "<div><h3>Debug Information</h3><pre>" + JSON.stringify(debugData, null, 2) + "</pre></div>",
431
+ },
432
+ },
433
+ ];
434
+
435
+ const html = await ono.toHTML(error, {
436
+ content: customPages,
437
+ cspNonce: "your-nonce",
438
+ });
439
+ ```
440
+
441
+ ## Examples
442
+
443
+ The `examples/` directory contains working examples for different use cases:
444
+
445
+ ### CLI Example (`examples/cli/`)
446
+
447
+ Demonstrates basic ANSI output and custom solution finders:
448
+
449
+ ```bash
450
+ cd examples/cli
451
+ node index.js
452
+ ```
453
+
454
+ ### Node.js HTTP Server (`examples/node/`)
455
+
456
+ Complete HTTP server example with rich context pages:
457
+
458
+ ```bash
459
+ cd examples/node
460
+ node index.js
461
+ ```
462
+
463
+ Try these routes:
464
+
465
+ - `/error` - Basic error with context
466
+ - `/esm-cjs` - ESM/CJS interop error
467
+ - `/export-mismatch` - Export mismatch error
468
+ - `/custom-solution` - Custom solution finder demo
469
+
470
+ ### Hono Framework (`examples/hono/`)
471
+
472
+ Hono framework integration example:
473
+
474
+ ```bash
475
+ cd examples/hono
476
+ node index.js
477
+ ```
478
+
479
+ Try these routes:
480
+
481
+ - `/error` - Basic error handling
482
+ - `/error-html` - HTML error page
483
+ - `/api/error-json` - JSON error response
484
+
485
+ ### Server helpers
486
+
487
+ From `@visulima/ono/server/open-in-editor`:
488
+
489
+ - `openInEditor(request, options)` — core function (uses `open-editor` under the hood)
490
+ - `createNodeHttpHandler(options)` — returns `(req, res) => void` for Node http servers
491
+ - `createExpressHandler(options)` — returns `(req, res) => void` for Express/Connect
492
+
493
+ Options:
494
+
495
+ - `projectRoot?: string` — defaults to `process.cwd()`
496
+ - `allowOutsideProject?: boolean` — defaults to `false`
497
+
498
+ ### Editor selector
499
+
500
+ - Always visible
501
+ - Persists user choice in `localStorage` (`ono:editor`)
502
+ - Used for both the server opener (sent as `editor` in the POST body) and the client-side fallback
503
+
504
+ ### Client-side fallback editor links
505
+
506
+ - If `openInEditorUrl` is not set, clicking “Open in editor” uses editor URL schemes on the client. The default editor is VS Code. The selected editor in the header is respected.
507
+ - Supported editors and templates (placeholders: `%f` = file, `%l` = line, `%c` = column when supported):
508
+ - textmate: `txmt://open?url=file://%f&line=%l`
509
+ - macvim: `mvim://open?url=file://%f&line=%l`
510
+ - emacs: `emacs://open?url=file://%f&line=%l`
511
+ - sublime: `subl://open?url=file://%f&line=%l`
512
+ - phpstorm: `phpstorm://open?file=%f&line=%l`
513
+ - atom: `atom://core/open/file?filename=%f&line=%l`
514
+ - atom-beta: `atom-beta://core/open/file?filename=%f&line=%l`
515
+ - brackets: `brackets://open?url=file://%f&line=%l`
516
+ - clion: `clion://open?file=%f&line=%l`
517
+ - code (VS Code): `vscode://file/%f:%l:%c`
518
+ - code-insiders: `vscode-insiders://file/%f:%l:%c`
519
+ - codium (VSCodium): `vscodium://file/%f:%l:%c`
520
+ - cursor: `cursor://file/%f:%l:%c`
521
+ - emacs: `emacs://open?url=file://%f&line=%l`
522
+ - idea: `idea://open?file=%f&line=%l`
523
+ - intellij: `idea://open?file=%f&line=%l`
524
+ - macvim: `mvim://open?url=file://%f&line=%l`
525
+ - notepad++: `notepad-plus-plus://open?file=%f&line=%l`
526
+ - phpstorm: `phpstorm://open?file=%f&line=%l`
527
+ - pycharm: `pycharm://open?file=%f&line=%l`
528
+ - rider: `rider://open?file=%f&line=%l`
529
+ - rubymine: `rubymine://open?file=%f&line=%l`
530
+ - sublime: `subl://open?url=file://%f&line=%l`
531
+ - textmate: `txmt://open?url=file://%f&line=%l`
532
+ - vim: `vim://open?url=file://%f&line=%l`
533
+ - visualstudio: `visualstudio://open?file=%f&line=%l`
534
+ - vscode: `vscode://file/%f:%l:%c`
535
+ - vscodium: `vscodium://file/%f:%l:%c`
536
+ - webstorm: `webstorm://open?file=%f&line=%l`
537
+ - xcode: `xcode://open?file=%f&line=%l`
538
+ - zed: `zed://open?file=%f&line=%l&column=%c`
539
+ - android-studio: `idea://open?file=%f&line=%l`
540
+
541
+ ### Keyboard Shortcuts
542
+
543
+ - **Shift+/ (or ?)** — Open shortcuts help dialog
544
+ - **Esc** — Close dialogs
545
+ - **Enter/Space** — Activate focused control (e.g., toggles, tabs)
546
+
547
+ ### Tooltips
548
+
549
+ Components emit HTML with `data-tooltip-trigger`; a single script exported by the tooltip module is imported once by the layout (so there's no duplication).
550
+
551
+ ### Extend the VisulimaError
552
+
553
+ ```ts
554
+ import { VisulimaError } from "@visulima/error";
555
+
556
+ class MyError extends VisulimaError {
557
+ constructor(message: string) {
558
+ super({
559
+ name: "MyError",
560
+ message,
561
+ });
562
+ }
563
+ }
564
+
565
+ throw new MyError("My error message");
566
+
567
+ // or
568
+
569
+ const error = new MyError("My error message");
570
+
571
+ error.hint = "My error hint";
572
+
573
+ throw error;
574
+ ```
575
+
576
+ ### Pretty code frame
577
+
578
+ ```ts
579
+ import { codeFrame } from "@visulima/error";
580
+
581
+ const source = "const x = 10;\nconst error = x.y;\n";
582
+ const loc = { column: 16, line: 2 };
583
+
584
+ const frame = codeFrame(source, loc);
585
+
586
+ console.log(frame);
587
+ // 1 | const x = 10;
588
+ // > 2 | const error = x.y;
589
+ // | ^
590
+ ```
591
+
592
+ ## Supported Node.js Versions
593
+
594
+ Libraries in this ecosystem make the best effort to track [Node.js’ release schedule](https://github.com/nodejs/release#release-schedule).
595
+ Here’s [a post on why we think this is important](https://medium.com/the-node-js-collection/maintainers-should-consider-following-node-js-release-schedule-ab08ed4de71a).
596
+
597
+ ## Contributing
598
+
599
+ If you would like to help take a look at the [list of issues](https://github.com/visulima/visulima/issues) and check our [Contributing](.github/CONTRIBUTING.md) guild.
600
+
601
+ > **Note:** please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
602
+
603
+ ## Credits
604
+
605
+ - [Daniel Bannert](https://github.com/prisis)
606
+ - [All Contributors](https://github.com/visulima/visulima/graphs/contributors)
607
+
608
+ ## License
609
+
610
+ The visulima error is open-sourced software licensed under the [MIT][license-url]
611
+
612
+ [typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
613
+ [typescript-url]: "typescript"
614
+ [license-image]: https://img.shields.io/npm/l/@visulima/ono?color=blueviolet&style=for-the-badge
615
+ [license-url]: LICENSE.md "license"
616
+ [npm-image]: https://img.shields.io/npm/v/@visulima/ono/latest.svg?style=for-the-badge&logo=npm
617
+ [npm-url]: https://www.npmjs.com/package/@visulima/ono/v/latest "npm"
@@ -0,0 +1,45 @@
1
+ import { C as ContentPage } from '../../packem_shared/types-B8vYgwmD.js';
2
+ import { IncomingMessage } from 'node:http';
3
+
4
+ type NativeRequest = typeof globalThis.Request;
5
+ type NativeHeaders = typeof globalThis.Headers;
6
+ interface CustomHeaders {
7
+ entries: () => IterableIterator<[string, string]>;
8
+ forEach: (callback: (value: string, key: string) => void) => void;
9
+ get: (name: string) => string | null;
10
+ }
11
+ interface CustomRequest {
12
+ clone?: () => CustomRequest;
13
+ headers?: Record<string, string | string[]> | CustomHeaders;
14
+ json?: () => Promise<unknown>;
15
+ method?: string;
16
+ text?: () => Promise<string>;
17
+ url?: string;
18
+ }
19
+ type HeadersLike = NativeHeaders | CustomHeaders;
20
+ type RequestLike = NativeRequest | (IncomingMessage & {
21
+ body?: unknown;
22
+ clone?: () => RequestLike;
23
+ json?: () => Promise<unknown>;
24
+ text?: () => Promise<string>;
25
+ }) | CustomRequest | {
26
+ body?: unknown;
27
+ headers?: Record<string, string | string[]> | HeadersLike;
28
+ method?: string;
29
+ off?: (event: string, handler: (chunk: unknown) => void) => void;
30
+ on?: (event: string, handler: (chunk: unknown) => void) => void;
31
+ setEncoding?: (encoding: string) => void;
32
+ url?: string;
33
+ };
34
+ type ContextContentOptions = {
35
+ context?: Record<string, unknown>;
36
+ headerAllowlist?: string[];
37
+ headerDenylist?: string[];
38
+ maskValue?: string;
39
+ previewBytes?: number;
40
+ totalCapBytes?: number;
41
+ };
42
+
43
+ declare const createRequestContext: (request: RequestLike, options: ContextContentOptions) => Promise<ContentPage | undefined>;
44
+
45
+ export { createRequestContext as default };