@centralping/ergo 0.1.0-beta.1 → 0.1.0-beta.2

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.
Files changed (87) hide show
  1. package/README.md +14 -15
  2. package/http/accepts.js +1 -2
  3. package/http/authorization.js +1 -2
  4. package/http/body.js +1 -2
  5. package/http/cache-control.js +1 -2
  6. package/http/compress.js +1 -2
  7. package/http/cookie.js +1 -2
  8. package/http/cors.js +1 -2
  9. package/http/csrf.js +1 -2
  10. package/http/handler.js +1 -2
  11. package/http/index.js +37 -4
  12. package/http/json-api-query.js +1 -2
  13. package/http/logger.js +1 -2
  14. package/http/main.js +2 -3
  15. package/http/precondition.js +1 -2
  16. package/http/prefer.js +1 -2
  17. package/http/rate-limit.js +1 -2
  18. package/http/security-headers.js +1 -2
  19. package/http/send.js +1 -2
  20. package/http/timeout.js +1 -2
  21. package/http/url.js +1 -2
  22. package/http/validate.js +1 -2
  23. package/lib/accepts.js +1 -2
  24. package/lib/attach-instance.js +0 -1
  25. package/lib/authorization.js +1 -2
  26. package/lib/body/multiparse.js +1 -2
  27. package/lib/body/multipart/headers.js +1 -2
  28. package/lib/body/writer.js +1 -2
  29. package/lib/cookie/cookie.js +1 -2
  30. package/lib/cookie/index.js +0 -1
  31. package/lib/cookie/jar.js +16 -12
  32. package/lib/cookie/parse.js +1 -2
  33. package/lib/cors.js +1 -2
  34. package/lib/csrf.js +1 -2
  35. package/lib/from-connect.js +2 -3
  36. package/lib/json-api-query/index.js +0 -1
  37. package/lib/json-api-query/validate.js +1 -2
  38. package/lib/link.js +1 -2
  39. package/lib/prefer.js +1 -2
  40. package/lib/query.js +1 -2
  41. package/lib/rate-limit.js +1 -2
  42. package/lib/sanitize-quoted-string.js +0 -1
  43. package/lib/security-headers.js +1 -2
  44. package/lib/validate.js +1 -2
  45. package/lib/vary.js +0 -1
  46. package/package.json +2 -2
  47. package/types/http/precondition.d.ts +1 -2
  48. package/types/lib/attach-instance.d.ts +0 -1
  49. package/types/lib/cookie/jar.d.ts +4 -0
  50. package/types/lib/from-connect.d.ts +2 -3
  51. package/types/lib/prefer.d.ts +1 -2
  52. package/types/lib/rate-limit.d.ts +1 -2
  53. package/types/lib/sanitize-quoted-string.d.ts +0 -1
  54. package/types/lib/vary.d.ts +0 -1
  55. package/types/utils/compose.d.ts +1 -2
  56. package/types/utils/iterables/range.d.ts +1 -2
  57. package/utils/attempt.js +1 -2
  58. package/utils/buffers/index.js +0 -1
  59. package/utils/buffers/match.js +1 -2
  60. package/utils/buffers/split.js +1 -2
  61. package/utils/compose-with.js +1 -2
  62. package/utils/compose.js +1 -2
  63. package/utils/flat-array.js +1 -2
  64. package/utils/get.js +1 -2
  65. package/utils/http-errors.js +1 -2
  66. package/utils/iterables/buffer-split.js +1 -2
  67. package/utils/iterables/chain.js +1 -2
  68. package/utils/iterables/exec-all.js +1 -2
  69. package/utils/iterables/filter.js +1 -2
  70. package/utils/iterables/for-each.js +1 -2
  71. package/utils/iterables/from-stream.js +1 -2
  72. package/utils/iterables/index.js +0 -1
  73. package/utils/iterables/map.js +1 -2
  74. package/utils/iterables/range.js +1 -2
  75. package/utils/iterables/reduce.js +1 -2
  76. package/utils/iterables/take.js +1 -2
  77. package/utils/observables/buffer-split.js +0 -1
  78. package/utils/observables/chain.js +0 -1
  79. package/utils/observables/index.js +0 -1
  80. package/utils/observables/map.js +0 -1
  81. package/utils/observables/take.js +0 -1
  82. package/utils/pick.js +1 -2
  83. package/utils/set.js +1 -2
  84. package/utils/streams/index.js +0 -1
  85. package/utils/streams/meter.js +1 -2
  86. package/utils/streams/tee.js +1 -2
  87. package/utils/type.js +1 -2
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  <p align="center">
2
2
  <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="assets/logo-wordmark-dark.svg">
4
- <source media="(prefers-color-scheme: light)" srcset="assets/logo-wordmark-light.svg">
5
- <img alt="ergo" src="assets/logo-wordmark-light.svg" width="240">
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/CentralPing/ergo/main/assets/logo-wordmark-dark.svg">
4
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/CentralPing/ergo/main/assets/logo-wordmark-light.svg">
5
+ <img alt="ergo" src="https://raw.githubusercontent.com/CentralPing/ergo/main/assets/logo-wordmark-light.svg" width="240">
6
6
  </picture>
7
7
  </p>
8
8
 
@@ -11,7 +11,7 @@
11
11
  [![npm version](https://img.shields.io/npm/v/@centralping/ergo.svg)](https://www.npmjs.com/package/@centralping/ergo)
12
12
  [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/CentralPing/ergo/badge)](https://scorecard.dev/viewer/?uri=github.com/CentralPing/ergo)
13
13
  [![Node.js >=22](https://img.shields.io/badge/node-%3E%3D22-brightgreen)](https://nodejs.org)
14
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/CentralPing/ergo/blob/main/LICENSE)
15
15
 
16
16
  A **Fast Fail** REST API toolkit for Node.js. _ergo_ (error or go) provides composable, stream-native middleware organized around the principle that a server should fail as early as possible -- before doing any expensive work -- through four ordered stages: **Negotiation, Authorization, Validation, and Execution**. Every behavior is backed by an IETF RFC or industry standard, not invented conventions.
17
17
 
@@ -57,20 +57,19 @@ Requires **Node.js >= 22**.
57
57
 
58
58
  ```js
59
59
  import {createServer} from 'node:http';
60
- import {compose, handler, logger, cors, authorization, body, send} from '@centralping/ergo';
60
+ import {compose, handler, logger, cors, authorization, body} from '@centralping/ergo';
61
61
 
62
62
  const pipeline = compose(
63
- [logger(), [], 'log'],
64
- [cors(), [], 'cors'],
63
+ [logger(), 'log'],
64
+ [cors(), 'cors'],
65
65
  [authorization({strategies: [{type: 'Bearer', authorizer: (_, token) =>
66
66
  token === 'my-token' ? {authorized: true, info: {uid: 1}} : {}
67
- }]}), [], 'auth'],
68
- [body(), [], 'body'],
69
- (req, res, {auth, body}) => ({body: {user: auth, data: body.parsed}}),
70
- send()
67
+ }]}), 'auth'],
68
+ [body(), 'body'],
69
+ (req, res, acc) => ({response: {body: {user: acc.auth, data: acc.body.parsed}}})
71
70
  );
72
71
 
73
- createServer(handler(pipeline, send())).listen(3000);
72
+ createServer(handler(pipeline)).listen(3000);
74
73
  ```
75
74
 
76
75
  ## Middleware Overview
@@ -96,7 +95,7 @@ createServer(handler(pipeline, send())).listen(3000);
96
95
  | `cacheControl()` | Cache-Control header management | [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) |
97
96
  | `jsonApiQuery()` | JSON:API query parameter validation | [JSON:API](https://jsonapi.org/) |
98
97
 
99
- See the [full API reference](https://centralping.github.io/api/ergo/) for detailed options and examples.
98
+ See the [full API reference](https://centralping.github.io/packages/ergo/) for detailed options and examples.
100
99
 
101
100
  ## Standards Compliance
102
101
 
@@ -120,8 +119,8 @@ See the [full API reference](https://centralping.github.io/api/ergo/) for detail
120
119
  ## Documentation
121
120
 
122
121
  - [Getting Started](https://centralping.github.io/getting-started/)
123
- - [API Reference](https://centralping.github.io/api/ergo/)
124
- - [Architecture & Design](https://centralping.github.io/architecture/)
122
+ - [API Reference](https://centralping.github.io/packages/ergo/)
123
+ - [Fast Fail Pipeline](https://centralping.github.io/concepts/fast-fail/)
125
124
  - [Benchmarks](https://centralping.github.io/benchmarks/)
126
125
 
127
126
  ## Development
package/http/accepts.js CHANGED
@@ -10,13 +10,12 @@
10
10
  * Fast Fail pipeline.
11
11
  *
12
12
  * @module http/accepts
13
- * @version 0.1.0
14
13
  * @since 0.1.0
15
14
  * @requires ../lib/accepts.js
16
15
  * @requires ../utils/http-errors.js
17
16
  *
18
17
  * @example
19
- * import {compose, accepts} from 'ergo';
18
+ * import {compose, accepts} from '@centralping/ergo';
20
19
  *
21
20
  * const pipeline = compose(
22
21
  * [accepts({types: ['application/json']}), 'accepts'],
@@ -10,13 +10,12 @@
10
10
  * response header (RFC 7235).
11
11
  *
12
12
  * @module http/authorization
13
- * @version 0.1.0
14
13
  * @since 0.1.0
15
14
  * @requires ../lib/authorization.js
16
15
  * @requires ../utils/http-errors.js
17
16
  *
18
17
  * @example
19
- * import {compose, authorization} from 'ergo';
18
+ * import {compose, authorization} from '@centralping/ergo';
20
19
  *
21
20
  * const pipeline = compose(
22
21
  * [authorization({
package/http/body.js CHANGED
@@ -17,7 +17,6 @@
17
17
  * 3-stream pipeline for reduced per-request overhead.
18
18
  *
19
19
  * @module http/body
20
- * @version 0.1.0
21
20
  * @since 0.1.0
22
21
  * @requires node:stream
23
22
  * @requires node:zlib
@@ -29,7 +28,7 @@
29
28
  * @requires ../utils/http-errors.js
30
29
  *
31
30
  * @example
32
- * import {compose, body} from 'ergo';
31
+ * import {compose, body} from '@centralping/ergo';
33
32
  *
34
33
  * const pipeline = compose(
35
34
  * [body({limit: 2 * 1024 * 1024}), 'body'],
@@ -6,11 +6,10 @@
6
6
  * a raw directive string or structured options that are assembled into a directive.
7
7
  *
8
8
  * @module http/cache-control
9
- * @version 0.1.0
10
9
  * @since 0.1.0
11
10
  *
12
11
  * @example
13
- * import {compose, cacheControl} from 'ergo';
12
+ * import {compose, cacheControl} from '@centralping/ergo';
14
13
  *
15
14
  * // String shorthand
16
15
  * const pipeline = compose(
package/http/compress.js CHANGED
@@ -13,13 +13,12 @@
13
13
  * - Bodies below the configurable `threshold` byte count (default 1 KiB)
14
14
  *
15
15
  * @module http/compress
16
- * @version 0.1.0
17
16
  * @since 0.1.0
18
17
  * @requires node:zlib
19
18
  * @requires negotiator
20
19
  *
21
20
  * @example
22
- * import {compose, compress} from 'ergo';
21
+ * import {compose, compress} from '@centralping/ergo';
23
22
  *
24
23
  * const pipeline = compose(
25
24
  * compress({threshold: 1024, encodings: ['br', 'gzip', 'deflate']}),
package/http/cookie.js CHANGED
@@ -12,12 +12,11 @@
12
12
  * and other cookie-based workflows.
13
13
  *
14
14
  * @module http/cookie
15
- * @version 0.1.0
16
15
  * @since 0.1.0
17
16
  * @requires ../lib/cookie/index.js
18
17
  *
19
18
  * @example
20
- * import {compose, cookie} from 'ergo';
19
+ * import {compose, cookie} from '@centralping/ergo';
21
20
  *
22
21
  * const pipeline = compose(
23
22
  * [cookie(), 'cookies'],
package/http/cors.js CHANGED
@@ -10,13 +10,12 @@
10
10
  * Pre-flight `OPTIONS` requests should be handled at the router level using `ergo-router`.
11
11
  *
12
12
  * @module http/cors
13
- * @version 0.1.0
14
13
  * @since 0.1.0
15
14
  * @requires ../lib/cors.js
16
15
  * @requires ../utils/http-errors.js
17
16
  *
18
17
  * @example
19
- * import {compose, cors} from 'ergo';
18
+ * import {compose, cors} from '@centralping/ergo';
20
19
  *
21
20
  * const pipeline = compose(
22
21
  * [cors({
package/http/csrf.js CHANGED
@@ -11,13 +11,12 @@
11
11
  * The CSRF UUID is stored in a separate cookie so the token can be regenerated independently.
12
12
  *
13
13
  * @module http/csrf
14
- * @version 0.1.0
15
14
  * @since 0.1.0
16
15
  * @requires ../lib/csrf.js
17
16
  * @requires ../utils/http-errors.js
18
17
  *
19
18
  * @example
20
- * import {compose, cookie, csrf} from 'ergo';
19
+ * import {compose, cookie, csrf} from '@centralping/ergo';
21
20
  *
22
21
  * const csrfMiddleware = csrf({secret: process.env.CSRF_SECRET});
23
22
  *
package/http/handler.js CHANGED
@@ -13,11 +13,10 @@
13
13
  * compose middleware directly without the router.
14
14
  *
15
15
  * @module http/handler
16
- * @version 0.2.0
17
16
  * @since 0.1.0
18
17
  *
19
18
  * @example
20
- * import {handler, compose, send, logger, authorization, body} from 'ergo';
19
+ * import {handler, compose, logger, authorization, body} from '@centralping/ergo';
21
20
  *
22
21
  * const pipeline = compose(
23
22
  * [logger(), 'log'],
package/http/index.js CHANGED
@@ -1,13 +1,46 @@
1
1
  /**
2
- * @fileoverview Entry point for the @centralping/ergo package.
2
+ * @fileoverview Fast Fail REST API toolkit for Node.js.
3
3
  *
4
- * Re-exports the main module for ESM consumers:
5
- * `import { handler, send } from '@centralping/ergo'`
4
+ * Composable middleware organized into four ordered pipeline stages — a failure
5
+ * at any stage immediately returns a standards-compliant error response so no
6
+ * downstream work is wasted:
7
+ *
8
+ * | Stage | Middleware | Purpose |
9
+ * | --- | --- | --- |
10
+ * | **Negotiation** | {@link logger}, {@link cors}, {@link accepts}, {@link cookie}, {@link url} | Parse/inspect request headers and URL |
11
+ * | **Authorization** | {@link authorization}, {@link csrf} | Authenticate and verify request integrity |
12
+ * | **Validation** | {@link body}, {@link jsonApiQuery}, {@link validate} | Parse and validate the request body |
13
+ * | **Execution** | {@link timeout}, {@link compress}, {@link handler}, {@link send} | Run the handler and serialize the response |
14
+ *
15
+ * Cross-cutting middleware available at any stage:
16
+ * {@link cacheControl}, {@link prefer}, {@link precondition},
17
+ * {@link rateLimit}, {@link securityHeaders}
18
+ *
19
+ * **Composition utilities:** {@link compose}, {@link createResponseAcc},
20
+ * {@link mergeResponse}, {@link httpErrors}, {@link fromConnect}
6
21
  *
7
22
  * @module @centralping/ergo
8
- * @version 0.1.0-beta.1
9
23
  * @since 0.1.0
10
24
  * @requires ./main.js
25
+ *
26
+ * @example
27
+ * import {compose, handler, logger, cors, accepts, authorization,
28
+ * body, send} from '@centralping/ergo';
29
+ *
30
+ * const pipeline = compose(
31
+ * [logger(), 'log'],
32
+ * [cors(), 'cors'],
33
+ * [accepts({types: ['application/json']}), 'accepts'],
34
+ * [authorization({strategies: [...]}), 'auth'],
35
+ * [body(), 'body'],
36
+ * (req, res, acc) => ({response: {body: acc.body.parsed}}),
37
+ * );
38
+ *
39
+ * const server = http.createServer(handler(pipeline));
40
+ *
41
+ * @see {@link https://centralping.github.io/concepts/fast-fail/ Fast Fail Pipeline}
42
+ * @see {@link https://centralping.github.io/concepts/security/ Security}
43
+ * @see {@link https://centralping.github.io/concepts/standards/ Standards Compliance}
11
44
  */
12
45
 
13
46
  export * from './main.js';
@@ -11,13 +11,12 @@
11
11
  * Must be placed after `url()` in the pipeline so that `acc.url` is populated.
12
12
  *
13
13
  * @module http/json-api-query
14
- * @version 0.1.0
15
14
  * @since 0.1.0
16
15
  * @requires ../lib/json-api-query/index.js
17
16
  * @requires ../utils/http-errors.js
18
17
  *
19
18
  * @example
20
- * import {compose, url, jsonApiQuery} from 'ergo';
19
+ * import {compose, url, jsonApiQuery} from '@centralping/ergo';
21
20
  *
22
21
  * const pipeline = compose(
23
22
  * [url(), 'url'],
package/http/logger.js CHANGED
@@ -23,13 +23,12 @@
23
23
  * accidental secret leakage.
24
24
  *
25
25
  * @module http/logger
26
- * @version 0.1.0
27
26
  * @since 0.1.0
28
27
  * @requires node:os
29
28
  * @requires node:crypto
30
29
  *
31
30
  * @example
32
- * import {compose, logger} from 'ergo';
31
+ * import {compose, logger} from '@centralping/ergo';
33
32
  *
34
33
  * const pipeline = compose(
35
34
  * [logger(), 'log'],
package/http/main.js CHANGED
@@ -14,8 +14,7 @@
14
14
  * accumulated under named keys in `domainAcc`; response properties merge
15
15
  * into `responseAcc`. `send()` is called post-pipeline by `handler()`.
16
16
  *
17
- * @module ergo
18
- * @version 0.1.0
17
+ * @module @centralping/ergo
19
18
  * @since 0.1.0
20
19
  * @requires ./handler.js
21
20
  * @requires ./accepts.js
@@ -42,7 +41,7 @@
42
41
  *
43
42
  * @example
44
43
  * import {compose, handler, logger, cors, authorization, accepts,
45
- * cookie, url, body} from 'ergo';
44
+ * cookie, url, body} from '@centralping/ergo';
46
45
  *
47
46
  * const pipeline = compose(
48
47
  * // Stage 1: Negotiation
@@ -10,11 +10,10 @@
10
10
  * inspection that short-circuits before authorization, body parsing, or execution.
11
11
  *
12
12
  * @module http/precondition
13
- * @version 0.1.0
14
13
  * @since 0.1.0
15
14
  *
16
15
  * @example
17
- * import {compose, precondition} from 'ergo';
16
+ * import {compose, precondition} from '@centralping/ergo';
18
17
  *
19
18
  * // Enforce on all requests (method scoping handled by pipeline builder)
20
19
  * const pipeline = compose(
package/http/prefer.js CHANGED
@@ -8,12 +8,11 @@
8
8
  * Placed in Stage 1 (Negotiation) — cheap header parse with no I/O.
9
9
  *
10
10
  * @module http/prefer
11
- * @version 0.1.0
12
11
  * @since 0.1.0
13
12
  * @requires ../lib/prefer.js
14
13
  *
15
14
  * @example
16
- * import {compose, prefer} from 'ergo';
15
+ * import {compose, prefer} from '@centralping/ergo';
17
16
  *
18
17
  * const pipeline = compose(
19
18
  * [prefer(), 'prefer'],
@@ -10,12 +10,11 @@
10
10
  * or execution.
11
11
  *
12
12
  * @module http/rate-limit
13
- * @version 0.1.0
14
13
  * @since 0.1.0
15
14
  * @requires ../lib/rate-limit.js
16
15
  *
17
16
  * @example
18
- * import {compose, rateLimit} from 'ergo';
17
+ * import {compose, rateLimit} from '@centralping/ergo';
19
18
  *
20
19
  * const pipeline = compose(
21
20
  * [rateLimit({max: 100, windowMs: 60000}), 'rateLimit'],
@@ -8,12 +8,11 @@
8
8
  * Delegates tuple construction to `lib/security-headers.js` (the shared primitive).
9
9
  *
10
10
  * @module http/security-headers
11
- * @version 0.1.0
12
11
  * @since 0.1.0
13
12
  * @requires ../lib/security-headers.js
14
13
  *
15
14
  * @example
16
- * import {compose, securityHeaders} from 'ergo';
15
+ * import {compose, securityHeaders} from '@centralping/ergo';
17
16
  *
18
17
  * // Use defaults
19
18
  * const pipeline = compose(
package/http/send.js CHANGED
@@ -29,7 +29,6 @@
29
29
  * - Optional response envelope for 2xx Object bodies
30
30
  *
31
31
  * @module http/send
32
- * @version 0.2.0
33
32
  * @since 0.1.0
34
33
  * @requires node:stream
35
34
  * @requires node:http
@@ -38,7 +37,7 @@
38
37
  * @requires ../lib/vary.js
39
38
  *
40
39
  * @example
41
- * import {send, createResponseAcc} from 'ergo';
40
+ * import {send, createResponseAcc} from '@centralping/ergo';
42
41
  *
43
42
  * const writer = send({etag: true});
44
43
  * // After pipeline completes:
package/http/timeout.js CHANGED
@@ -12,11 +12,10 @@
12
12
  * can be GC'd.
13
13
  *
14
14
  * @module http/timeout
15
- * @version 0.2.0
16
15
  * @since 0.1.0
17
16
  *
18
17
  * @example
19
- * import {compose, timeout} from 'ergo';
18
+ * import {compose, timeout} from '@centralping/ergo';
20
19
  *
21
20
  * const pipeline = compose(
22
21
  * [timeout({ms: 10000, statusCode: 504}), 'timeout'],
package/http/url.js CHANGED
@@ -11,12 +11,11 @@
11
11
  * - `search` is the raw query string including the `?` prefix, or `undefined`
12
12
  *
13
13
  * @module http/url
14
- * @version 0.1.0
15
14
  * @since 0.1.0
16
15
  * @requires ../lib/query.js
17
16
  *
18
17
  * @example
19
- * import {compose, url} from 'ergo';
18
+ * import {compose, url} from '@centralping/ergo';
20
19
  *
21
20
  * const pipeline = compose(
22
21
  * [url(), 'url'],
package/http/validate.js CHANGED
@@ -9,12 +9,11 @@
9
9
  * are populated before validation runs.
10
10
  *
11
11
  * @module http/validate
12
- * @version 0.1.0
13
12
  * @since 0.1.0
14
13
  * @requires ../lib/validate.js
15
14
  *
16
15
  * @example
17
- * import {compose, body, url, validate} from 'ergo';
16
+ * import {compose, body, url, validate} from '@centralping/ergo';
18
17
  *
19
18
  * const pipeline = compose(
20
19
  * [body(), 'body'],
package/lib/accepts.js CHANGED
@@ -6,13 +6,12 @@
6
6
  * as the pure-logic backing implementation.
7
7
  *
8
8
  * @module lib/accepts
9
- * @version 0.1.0
10
9
  * @since 0.1.0
11
10
  * @requires negotiator
12
11
  * @requires ../utils/flat-array.js
13
12
  *
14
13
  * @example
15
- * import accepts from 'ergo/lib/accepts';
14
+ * import accepts from '@centralping/ergo/lib/accepts';
16
15
  *
17
16
  * const negotiate = accepts({types: ['application/json', 'text/html']});
18
17
  * const result = negotiate({'accept': 'text/html,application/json;q=0.9'});
@@ -5,7 +5,6 @@
5
5
  * `x-request-id` header, formatted as a `urn:uuid:` URI.
6
6
  *
7
7
  * @module lib/attach-instance
8
- * @version 0.1.0
9
8
  * @since 0.1.0
10
9
  */
11
10
 
@@ -11,11 +11,10 @@
11
11
  * 401 for known schemes (with a `WWW-Authenticate` challenge) or 403 for unrecognized schemes.
12
12
  *
13
13
  * @module lib/authorization
14
- * @version 0.1.0
15
14
  * @since 0.1.0
16
15
  *
17
16
  * @example
18
- * import authorize from 'ergo/lib/authorization';
17
+ * import authorize from '@centralping/ergo/lib/authorization';
19
18
  *
20
19
  * const authorizer = authorize([{
21
20
  * type: 'Bearer',
@@ -12,7 +12,6 @@
12
12
  * `Content-Disposition`, `Content-Type`, `Content-Transfer-Encoding`.
13
13
  *
14
14
  * @module lib/body/multiparse
15
- * @version 0.1.0
16
15
  * @since 0.1.0
17
16
  * @requires ./multipart/headers.js
18
17
  * @requires ../../utils/iterables/buffer-split.js
@@ -21,7 +20,7 @@
21
20
  * @see {@link https://www.rfc-editor.org/rfc/rfc7578}
22
21
  *
23
22
  * @example
24
- * import multiparse from 'ergo/lib/body/multiparse';
23
+ * import multiparse from '@centralping/ergo/lib/body/multiparse';
25
24
  *
26
25
  * const parts = multiparse(rawBodyBuffer, 'boundary-string');
27
26
  * // parts => [{headers: {...}, name: 'file', filename: 'upload.txt', body: Buffer}]
@@ -11,14 +11,13 @@
11
11
  * - `content-transfer-encoding` (deprecated but present in legacy clients)
12
12
  *
13
13
  * @module lib/body/multipart/headers
14
- * @version 0.1.0
15
14
  * @since 0.1.0
16
15
  * @requires ../../../utils/iterables/exec-all.js
17
16
  *
18
17
  * @see {@link https://www.rfc-editor.org/rfc/rfc7578 RFC 7578 - Returning Values from Forms: multipart/form-data}
19
18
  *
20
19
  * @example
21
- * import parseHeaders from 'ergo/lib/body/multipart/headers';
20
+ * import parseHeaders from '@centralping/ergo/lib/body/multipart/headers';
22
21
  *
23
22
  * parseHeaders(['Content-Disposition: form-data; name="field1"']);
24
23
  * // => {'content-disposition': {type: 'form-data', parameters: {name: 'field1'}}}
@@ -8,13 +8,12 @@
8
8
  * `pipeline(req, meter, decompressor, writer())`
9
9
  *
10
10
  * @module lib/body/writer
11
- * @version 0.1.0
12
11
  * @since 0.1.0
13
12
  * @requires node:stream
14
13
  *
15
14
  * @example
16
15
  * import {pipeline} from 'node:stream';
17
- * import writer from 'ergo/lib/body/writer';
16
+ * import writer from '@centralping/ergo/lib/body/writer';
18
17
  *
19
18
  * const w = writer();
20
19
  * pipeline(readable, w, err => {
@@ -9,11 +9,10 @@
9
9
  * immediately by defaulting `maxAge` to 0.
10
10
  *
11
11
  * @module lib/cookie/cookie
12
- * @version 0.1.0
13
12
  * @since 0.1.0
14
13
  *
15
14
  * @example
16
- * import bake from 'ergo/lib/cookie/cookie';
15
+ * import bake from '@centralping/ergo/lib/cookie/cookie';
17
16
  *
18
17
  * const c = bake('session', 'abc123', {maxAge: 3600, sameSite: 'Lax'});
19
18
  * c.toHeader(); // 'session=abc123; Path=/; Max-Age=3600; SameSite=Lax; Secure; HttpOnly'
@@ -5,7 +5,6 @@
5
5
  * and `jar` for creating a cookie jar instance that manages cookie state for a request.
6
6
  *
7
7
  * @module lib/cookie
8
- * @version 0.1.0
9
8
  * @since 0.1.0
10
9
  * @requires ./parse.js
11
10
  * @requires ./jar.js
package/lib/cookie/jar.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Creates a cookie jar with dual-storage semantics for per-request cookie management.
5
5
  *
6
6
  * **Incoming cookies** (from the `Cookie` header) are parsed as raw `name: value` strings
7
- * and stored as own properties via `Object.assign()`. Per RFC 6265 §5.4, the browser sends
7
+ * and stored as own properties. Per RFC 6265 §5.4, the browser sends
8
8
  * only `name=value` pairs — no directives. Access them directly: `jar.session`.
9
9
  *
10
10
  * **Outgoing cookies** (created via `set()`) are full cookie objects with directives,
@@ -19,14 +19,13 @@
19
19
  * - `toHeader()` — serializes outgoing cookies to `Set-Cookie` header strings
20
20
  *
21
21
  * @module lib/cookie/jar
22
- * @version 0.1.0
23
22
  * @since 0.1.0
24
23
  * @requires ./cookie.js
25
24
  * @requires ../../utils/iterables/index.js
26
25
  *
27
26
  * @example
28
- * import jar from 'ergo/lib/cookie/jar';
29
- * import parse from 'ergo/lib/cookie/parse';
27
+ * import jar from '@centralping/ergo/lib/cookie/jar';
28
+ * import parse from '@centralping/ergo/lib/cookie/parse';
30
29
  *
31
30
  * const cookies = jar(parse('session=abc123; lang=en'));
32
31
  * cookies.session; // => 'abc123' (incoming, own property)
@@ -91,16 +90,21 @@ const clay = Object.create(
91
90
  /**
92
91
  * Creates a cookie jar pre-populated from a parsed cookie object.
93
92
  *
93
+ * Incoming cookie names that collide with jar prototype methods or own properties
94
+ * (`set`, `get`, `clear`, `toHeader`, `isJar`, `size`, `jar`) are silently dropped
95
+ * to prevent `TypeError` from strict-mode assignment to non-writable properties.
96
+ *
94
97
  * @param {object} [cookies={}] - Initial cookie values (from `parse()`)
95
98
  * @returns {object} - Cookie jar with `get`, `set`, `clear`, `toHeader`, `size` members
96
99
  */
97
100
  function jar(cookies = {}) {
98
- return Object.assign(
99
- Object.create(clay, {
100
- jar: {
101
- value: new Map()
102
- }
103
- }),
104
- cookies
105
- );
101
+ const instance = Object.create(clay, {jar: {value: new Map()}});
102
+
103
+ for (const key of Object.keys(cookies)) {
104
+ if (!(key in instance)) {
105
+ instance[key] = cookies[key];
106
+ }
107
+ }
108
+
109
+ return instance;
106
110
  }
@@ -10,7 +10,6 @@
10
10
  * to protect against header-stuffing attacks.
11
11
  *
12
12
  * @module lib/cookie/parse
13
- * @version 0.1.0
14
13
  * @since 0.1.0
15
14
  * @requires ../../utils/iterables/index.js
16
15
  *
@@ -18,7 +17,7 @@
18
17
  * @see {@link https://www.rfc-editor.org/rfc/rfc2109 RFC 2109 - HTTP State Management Mechanism (obsoleted)}
19
18
  *
20
19
  * @example
21
- * import parse from 'ergo/lib/cookie/parse';
20
+ * import parse from '@centralping/ergo/lib/cookie/parse';
22
21
  *
23
22
  * parse('session=abc123; user=alice');
24
23
  * // => {session: 'abc123', user: 'alice'}
package/lib/cors.js CHANGED
@@ -15,13 +15,12 @@
15
15
  * @see {@link https://www.w3.org/TR/2014/REC-cors-20140116/}
16
16
  *
17
17
  * @module lib/cors
18
- * @version 0.1.0
19
18
  * @since 0.1.0
20
19
  * @requires ../utils/type.js
21
20
  * @requires ../utils/flat-array.js
22
21
  *
23
22
  * @example
24
- * import cors from 'ergo/lib/cors';
23
+ * import cors from '@centralping/ergo/lib/cors';
25
24
  *
26
25
  * const corsValidator = cors({
27
26
  * origins: ['https://app.example.com'],
package/lib/csrf.js CHANGED
@@ -9,13 +9,12 @@
9
9
  * can be reissued without changing the UUID.
10
10
  *
11
11
  * @module lib/csrf
12
- * @version 0.1.0
13
12
  * @since 0.1.0
14
13
  * @requires node:crypto
15
14
  * @requires ../utils/type.js
16
15
  *
17
16
  * @example
18
- * import {issue, verify} from 'ergo/lib/csrf';
17
+ * import {issue, verify} from '@centralping/ergo/lib/csrf';
19
18
  *
20
19
  * const {token, uuid} = issue('my-secret');
21
20
  * // token => 'base64-encoded-hmac'