@centralping/ergo 0.1.0-beta.1

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 (155) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +21 -0
  3. package/README.md +139 -0
  4. package/http/accepts.js +69 -0
  5. package/http/authorization.js +65 -0
  6. package/http/body.js +311 -0
  7. package/http/cache-control.js +123 -0
  8. package/http/compress.js +157 -0
  9. package/http/cookie.js +39 -0
  10. package/http/cors.js +79 -0
  11. package/http/csrf.js +76 -0
  12. package/http/handler.js +74 -0
  13. package/http/index.js +13 -0
  14. package/http/json-api-query.js +53 -0
  15. package/http/logger.js +167 -0
  16. package/http/main.js +140 -0
  17. package/http/precondition.js +53 -0
  18. package/http/prefer.js +36 -0
  19. package/http/rate-limit.js +66 -0
  20. package/http/security-headers.js +62 -0
  21. package/http/send.js +399 -0
  22. package/http/timeout.js +47 -0
  23. package/http/url.js +47 -0
  24. package/http/validate.js +84 -0
  25. package/lib/accepts.js +49 -0
  26. package/lib/attach-instance.js +23 -0
  27. package/lib/authorization.js +187 -0
  28. package/lib/body/multiparse.js +173 -0
  29. package/lib/body/multipart/headers.js +69 -0
  30. package/lib/body/writer.js +73 -0
  31. package/lib/cookie/cookie.js +192 -0
  32. package/lib/cookie/index.js +14 -0
  33. package/lib/cookie/jar.js +106 -0
  34. package/lib/cookie/parse.js +101 -0
  35. package/lib/cors.js +191 -0
  36. package/lib/csrf.js +96 -0
  37. package/lib/from-connect.js +69 -0
  38. package/lib/json-api-query/index.js +25 -0
  39. package/lib/json-api-query/schema.json +105 -0
  40. package/lib/json-api-query/validate.js +56 -0
  41. package/lib/link.js +96 -0
  42. package/lib/prefer.js +52 -0
  43. package/lib/query.js +113 -0
  44. package/lib/rate-limit.js +115 -0
  45. package/lib/sanitize-quoted-string.js +28 -0
  46. package/lib/security-headers.js +125 -0
  47. package/lib/validate.js +80 -0
  48. package/lib/vary.js +40 -0
  49. package/package.json +158 -0
  50. package/types/http/accepts.d.ts +8 -0
  51. package/types/http/authorization.d.ts +8 -0
  52. package/types/http/body.d.ts +20 -0
  53. package/types/http/cache-control.d.ts +16 -0
  54. package/types/http/compress.d.ts +5 -0
  55. package/types/http/cookie.d.ts +2 -0
  56. package/types/http/cors.d.ts +9 -0
  57. package/types/http/csrf.d.ts +9 -0
  58. package/types/http/handler.d.ts +2 -0
  59. package/types/http/index.d.ts +1 -0
  60. package/types/http/json-api-query.d.ts +2 -0
  61. package/types/http/logger.d.ts +9 -0
  62. package/types/http/main.d.ts +142 -0
  63. package/types/http/precondition.d.ts +44 -0
  64. package/types/http/prefer.d.ts +2 -0
  65. package/types/http/rate-limit.d.ts +17 -0
  66. package/types/http/security-headers.d.ts +10 -0
  67. package/types/http/send.d.ts +8 -0
  68. package/types/http/timeout.d.ts +5 -0
  69. package/types/http/url.d.ts +2 -0
  70. package/types/http/validate.d.ts +6 -0
  71. package/types/lib/accepts.d.ts +7 -0
  72. package/types/lib/attach-instance.d.ts +19 -0
  73. package/types/lib/authorization.d.ts +6 -0
  74. package/types/lib/body/multiparse.d.ts +9 -0
  75. package/types/lib/body/multipart/headers.d.ts +2 -0
  76. package/types/lib/body/writer.d.ts +2 -0
  77. package/types/lib/cookie/cookie.d.ts +32 -0
  78. package/types/lib/cookie/index.d.ts +2 -0
  79. package/types/lib/cookie/jar.d.ts +8 -0
  80. package/types/lib/cookie/parse.d.ts +19 -0
  81. package/types/lib/cors.d.ts +9 -0
  82. package/types/lib/csrf.d.ts +32 -0
  83. package/types/lib/from-connect.d.ts +47 -0
  84. package/types/lib/json-api-query/index.d.ts +123 -0
  85. package/types/lib/json-api-query/validate.d.ts +5 -0
  86. package/types/lib/link.d.ts +37 -0
  87. package/types/lib/prefer.d.ts +36 -0
  88. package/types/lib/query.d.ts +6 -0
  89. package/types/lib/rate-limit.d.ts +76 -0
  90. package/types/lib/sanitize-quoted-string.d.ts +19 -0
  91. package/types/lib/security-headers.d.ts +24 -0
  92. package/types/lib/validate.d.ts +16 -0
  93. package/types/lib/vary.d.ts +17 -0
  94. package/types/utils/attempt.d.ts +2 -0
  95. package/types/utils/buffers/index.d.ts +2 -0
  96. package/types/utils/buffers/match.d.ts +10 -0
  97. package/types/utils/buffers/split.d.ts +10 -0
  98. package/types/utils/compose-with.d.ts +40 -0
  99. package/types/utils/compose.d.ts +83 -0
  100. package/types/utils/flat-array.d.ts +2 -0
  101. package/types/utils/get.d.ts +5 -0
  102. package/types/utils/http-errors.d.ts +22 -0
  103. package/types/utils/iterables/buffer-split.d.ts +2 -0
  104. package/types/utils/iterables/chain.d.ts +2 -0
  105. package/types/utils/iterables/exec-all.d.ts +2 -0
  106. package/types/utils/iterables/filter.d.ts +2 -0
  107. package/types/utils/iterables/for-each.d.ts +2 -0
  108. package/types/utils/iterables/from-stream.d.ts +2 -0
  109. package/types/utils/iterables/index.d.ts +10 -0
  110. package/types/utils/iterables/map.d.ts +2 -0
  111. package/types/utils/iterables/range.d.ts +24 -0
  112. package/types/utils/iterables/reduce.d.ts +2 -0
  113. package/types/utils/iterables/take.d.ts +2 -0
  114. package/types/utils/observables/buffer-split.d.ts +2 -0
  115. package/types/utils/observables/chain.d.ts +2 -0
  116. package/types/utils/observables/index.d.ts +4 -0
  117. package/types/utils/observables/map.d.ts +2 -0
  118. package/types/utils/observables/take.d.ts +2 -0
  119. package/types/utils/pick.d.ts +2 -0
  120. package/types/utils/set.d.ts +2 -0
  121. package/types/utils/streams/index.d.ts +2 -0
  122. package/types/utils/streams/meter.d.ts +5 -0
  123. package/types/utils/streams/tee.d.ts +2 -0
  124. package/types/utils/type.d.ts +2 -0
  125. package/utils/attempt.js +37 -0
  126. package/utils/buffers/index.js +13 -0
  127. package/utils/buffers/match.js +96 -0
  128. package/utils/buffers/split.js +55 -0
  129. package/utils/compose-with.js +232 -0
  130. package/utils/compose.js +165 -0
  131. package/utils/flat-array.js +24 -0
  132. package/utils/get.js +39 -0
  133. package/utils/http-errors.js +113 -0
  134. package/utils/iterables/buffer-split.js +117 -0
  135. package/utils/iterables/chain.js +32 -0
  136. package/utils/iterables/exec-all.js +42 -0
  137. package/utils/iterables/filter.js +35 -0
  138. package/utils/iterables/for-each.js +33 -0
  139. package/utils/iterables/from-stream.js +29 -0
  140. package/utils/iterables/index.js +21 -0
  141. package/utils/iterables/map.js +47 -0
  142. package/utils/iterables/range.js +34 -0
  143. package/utils/iterables/reduce.js +43 -0
  144. package/utils/iterables/take.js +36 -0
  145. package/utils/observables/buffer-split.js +109 -0
  146. package/utils/observables/chain.js +33 -0
  147. package/utils/observables/index.js +19 -0
  148. package/utils/observables/map.js +34 -0
  149. package/utils/observables/take.js +40 -0
  150. package/utils/pick.js +41 -0
  151. package/utils/set.js +38 -0
  152. package/utils/streams/index.js +11 -0
  153. package/utils/streams/meter.js +98 -0
  154. package/utils/streams/tee.js +84 -0
  155. package/utils/type.js +47 -0
@@ -0,0 +1,83 @@
1
+ export default compose;
2
+ /**
3
+ * @fileoverview Async pipeline composition utility.
4
+ *
5
+ * Creates an async pipeline from a list of middleware functions. Each function receives
6
+ * the original arguments plus the accumulated state object from prior middleware.
7
+ *
8
+ * - `compose(...fns)` — runs functions sequentially (`serial`)
9
+ * - `compose.all(...fns)` — runs functions concurrently and merges all results
10
+ * - `compose.withOptions(options, ...fns)` — sequential with options (e.g. `breakWhen`)
11
+ * - `compose.all.withOptions(options, ...fns)` — concurrent with options
12
+ *
13
+ * State is accumulated into a null-prototype accumulator object with an
14
+ * `isAccumulator: true` flag and a `size` getter. If the last argument passed to the
15
+ * composed pipeline is already an accumulator object, it is reused for accumulation.
16
+ *
17
+ * Serial composition uses a sync fast-path: when a middleware returns a non-thenable
18
+ * value, the result is merged immediately without scheduling a microtask. This
19
+ * eliminates unnecessary `await` overhead for synchronous middleware (the majority
20
+ * of ergo's built-in middleware).
21
+ *
22
+ * @module utils/compose
23
+ * @version 0.2.0
24
+ * @since 0.1.0
25
+ *
26
+ * @example
27
+ * import compose from 'ergo/utils/compose';
28
+ *
29
+ * const pipeline = compose(
30
+ * async (req, res) => ({user: await getUser(req)}),
31
+ * async (req, res, {user}) => ({role: await getRole(user)})
32
+ * );
33
+ *
34
+ * const result = await pipeline(req, res);
35
+ * // result.user, result.role
36
+ *
37
+ * @example
38
+ * // Early termination with breakWhen
39
+ * const pipeline = compose.withOptions(
40
+ * {breakWhen: (acc) => acc.done},
41
+ * () => ({done: true, a: 1}),
42
+ * () => ({b: 2}) // never reached
43
+ * );
44
+ */
45
+ /**
46
+ * Composes middleware functions into an async pipeline with result accumulation.
47
+ *
48
+ * @param {...function} fns - Middleware functions to compose
49
+ * @returns {function} - Async composed pipeline
50
+ */
51
+ declare function compose(...fns: Function[]): Function;
52
+ declare namespace compose {
53
+ function all(...fns: any[]): Function;
54
+ namespace all {
55
+ /**
56
+ * Creates a concurrent pipeline with configuration options.
57
+ *
58
+ * @param {object} options - Pipeline options
59
+ * @param {...function} fns - Middleware functions to compose
60
+ * @returns {function} - Async composed pipeline
61
+ */
62
+ function withOptions(options: object, ...fns: Function[]): Function;
63
+ }
64
+ /**
65
+ * Creates a sequential pipeline with configuration options.
66
+ *
67
+ * @param {object} options - Pipeline options
68
+ * @param {function} [options.breakWhen] - Predicate `(acc) => boolean`; when truthy,
69
+ * serial iteration stops after the current step's result is merged
70
+ * @param {...function} fns - Middleware functions to compose
71
+ * @returns {function} - Async composed pipeline
72
+ */
73
+ function withOptions(options: {
74
+ breakWhen?: Function | undefined;
75
+ }, ...fns: Function[]): Function;
76
+ }
77
+ /**
78
+ * Creates a null-prototype accumulator object.
79
+ *
80
+ * @param {object} [defaults={}] - Initial properties to copy into the accumulator
81
+ * @returns {object} - Null-prototype accumulator with `isAccumulator: true` and `size` getter
82
+ */
83
+ export function accumulator(defaults?: object): object;
@@ -0,0 +1,2 @@
1
+ declare function _default(...items: any[]): any[];
2
+ export default _default;
@@ -0,0 +1,5 @@
1
+ declare function _default(obj?: object, path?: string, { safe, invoke }?: {
2
+ safe?: boolean | undefined;
3
+ invoke?: boolean | undefined;
4
+ }): any;
5
+ export default _default;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @param {number} [statusCode=500] - HTTP status code
3
+ * @param {object} [options] - RFC 9457 Problem Details fields
4
+ * @param {string} [options.type] - RFC 9457 `type` URI (defaults to MDN docs link)
5
+ * @param {string} [options.detail] - RFC 9457 `detail` (human-readable explanation)
6
+ * @param {string} [options.message] - Alias for `detail` (backward compat)
7
+ * @param {Array<[string, string]>} [options.headers] - Response headers to attach
8
+ * @param {string} [options.instance] - RFC 9457 `instance` URI identifying the specific occurrence
9
+ * @param {number|string} [options.retryAfter] - Retry-After value (seconds or HTTP-date).
10
+ * Auto-appended to `headers` as `['Retry-After', String(value)]` and included in toJSON().
11
+ * @param {Error} [options.originalError] - Underlying error
12
+ * @returns {Error} - Error with RFC 9457 properties and `toJSON()` method
13
+ */
14
+ export default function httpErrors(statusCode?: number, { type, message, detail: rawDetail, headers, instance, retryAfter, originalError, ...extra }?: {
15
+ type?: string | undefined;
16
+ detail?: string | undefined;
17
+ message?: string | undefined;
18
+ headers?: [string, string][] | undefined;
19
+ instance?: string | undefined;
20
+ retryAfter?: string | number | undefined;
21
+ originalError?: Error | undefined;
22
+ }): Error;
@@ -0,0 +1,2 @@
1
+ declare function _default(separator?: any | string, limit?: number): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(...generators: (Iterable<any> | Function)[]): any;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(re: RegExp): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(predicate: Function): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(cb: Function): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(stream: any): AsyncIterable<any>;
2
+ export default _default;
@@ -0,0 +1,10 @@
1
+ export { default as bufferSplit } from "./buffer-split.js";
2
+ export { default as chain } from "./chain.js";
3
+ export { default as execAll } from "./exec-all.js";
4
+ export { default as filter } from "./filter.js";
5
+ export { default as forEach } from "./for-each.js";
6
+ export { default as fromStream } from "./from-stream.js";
7
+ export { default as map } from "./map.js";
8
+ export { default as range } from "./range.js";
9
+ export { default as reduce } from "./reduce.js";
10
+ export { default as take } from "./take.js";
@@ -0,0 +1,2 @@
1
+ declare function _default(transform: Function): Function;
2
+ export default _default;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @fileoverview Integer range generator.
3
+ *
4
+ * Produces a sequence of integers from `start` (inclusive) to `stop` (exclusive)
5
+ * stepping by `step`. Mirrors Python's `range()` behaviour.
6
+ *
7
+ * @module utils/iterables/range
8
+ * @version 0.1.0
9
+ * @since 0.1.0
10
+ *
11
+ * @example
12
+ * import range from 'ergo/utils/iterables/range';
13
+ *
14
+ * [...range(5)] // => [0, 1, 2, 3, 4]
15
+ * [...range(1, 5)] // => [1, 2, 3, 4]
16
+ * [...range(0, 10, 2)] // => [0, 2, 4, 6, 8]
17
+ */
18
+ /**
19
+ * @param {number} start - Start value (or stop if only one arg)
20
+ * @param {number} [stop] - Exclusive upper bound
21
+ * @param {number} [step=1] - Step increment
22
+ * @returns {Generator<number>} - Sequence of integers
23
+ */
24
+ export default function _default(start: number, stop?: number, step?: number): Generator<number>;
@@ -0,0 +1,2 @@
1
+ declare function _default(reducer: Function, initialValue?: any): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(n?: number): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(separator?: any | string, limit?: number): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(...generators: (Function | Generator)[]): Generator;
2
+ export default _default;
@@ -0,0 +1,4 @@
1
+ export { default as bufferSplit } from "./buffer-split.js";
2
+ export { default as chain } from "./chain.js";
3
+ export { default as map } from "./map.js";
4
+ export { default as take } from "./take.js";
@@ -0,0 +1,2 @@
1
+ declare function _default(transform: Function): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(n?: number): Function;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(obj?: object, ...paths: (string | [string, string])[]): object;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(obj: object, path?: string, val: any): any;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ export { default as meter } from "./meter.js";
2
+ export { default as tee } from "./tee.js";
@@ -0,0 +1,5 @@
1
+ declare function _default({ expected, limit }?: {
2
+ expected?: number | undefined;
3
+ limit?: number | undefined;
4
+ }): any;
5
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(generator: Generator): any;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare function _default(o: any): string;
2
+ export default _default;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @fileoverview Try/catch wrapper for async functions.
3
+ *
4
+ * Wraps an async `fn` so that if it throws, the `fail` function is called with
5
+ * the original arguments plus the caught error appended. Both functions are awaited.
6
+ *
7
+ * Used by `http/handler.js` to wrap the try pipeline with an error handler pipeline.
8
+ *
9
+ * @module utils/attempt
10
+ * @version 0.1.0
11
+ * @since 0.1.0
12
+ *
13
+ * @example
14
+ * import attempt from 'ergo/utils/attempt';
15
+ *
16
+ * const safe = attempt(
17
+ * async (req, res) => { throw new Error('oops'); },
18
+ * async (req, res, err) => { res.writeHead(500); res.end(err.message); }
19
+ * );
20
+ *
21
+ * await safe(req, res); // calls the fail function with (req, res, err)
22
+ */
23
+
24
+ /**
25
+ * @param {function} fn - Primary async function to execute
26
+ * @param {function} fail - Error handler called with (...originalArgs, error)
27
+ * @returns {function} - Wrapped async function with try/catch behavior
28
+ */
29
+ export default (fn, fail) => {
30
+ return async (...args) => {
31
+ try {
32
+ return await fn(...args);
33
+ } catch (e) {
34
+ return await fail(...args, e);
35
+ }
36
+ };
37
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @fileoverview Buffer utilities barrel export.
3
+ *
4
+ * Provides `match` (KMP substring search in Buffers) and `split` (Buffer split by separator).
5
+ *
6
+ * @module utils/buffers
7
+ * @version 0.1.0
8
+ * @since 0.1.0
9
+ * @requires ./match.js
10
+ * @requires ./split.js
11
+ */
12
+ export {default as match} from './match.js';
13
+ export {default as split} from './split.js';
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @fileoverview KMP (Knuth-Morris-Pratt) substring search for Node.js Buffers.
3
+ *
4
+ * Finds all occurrences of a byte pattern in a Buffer using the KMP algorithm.
5
+ * Supports incremental/streaming search by accepting and returning a `partial` counter
6
+ * and pre-computed `lookup` table, enabling multi-chunk searches without re-scanning.
7
+ *
8
+ * Returns match start indices, the KMP failure function (`lookup`), and the unfinished
9
+ * match state (`partial`) for the next chunk.
10
+ *
11
+ * @module utils/buffers/match
12
+ * @version 0.1.0
13
+ * @since 0.1.0
14
+ *
15
+ * @example
16
+ * import bufferMatch from 'ergo/utils/buffers/match';
17
+ *
18
+ * const {matches} = bufferMatch(Buffer.from('hello world'), Buffer.from('l'));
19
+ * // matches => [2, 3, 9]
20
+ */
21
+ /**
22
+ * Searches for all occurrences of `searchBuffer` in `buffer` using KMP.
23
+ *
24
+ * @param {import('node:buffer').Buffer} [buffer=Buffer.from('')] - The buffer to search within
25
+ * @param {import('node:buffer').Buffer} [searchBuffer] - The byte pattern to search for
26
+ * @param {object} [options] - KMP search options
27
+ * @param {number} [options.limit=Infinity] - Maximum matches to return
28
+ * @param {number} [options.partial=0] - KMP partial match state from a prior chunk
29
+ * @param {number[]} [options.lookup] - Pre-computed KMP failure function table
30
+ * @returns {{matches: number[], partial: number, lookup: number[]}} - Match result with indices, partial state, and lookup table
31
+ */
32
+ export default (
33
+ buffer = Buffer.from(''),
34
+ searchBuffer,
35
+ {limit = Infinity, partial = 0, lookup} = {}
36
+ ) => {
37
+ /* eslint-disable no-param-reassign */
38
+ const matches = [];
39
+
40
+ if (lookup === undefined) {
41
+ lookup = makeLookup(searchBuffer);
42
+ }
43
+
44
+ if (lookup.length === 0) {
45
+ return {matches, partial, lookup};
46
+ }
47
+
48
+ for (let i = partial; i < buffer.length; i++) {
49
+ while (partial >= 0 && buffer[i] !== searchBuffer[partial]) {
50
+ if (partial > 0) {
51
+ partial = lookup[partial - 1];
52
+ } else {
53
+ partial = -1;
54
+ }
55
+ }
56
+
57
+ partial += 1;
58
+ if (partial === searchBuffer.length) {
59
+ matches.push(i - partial + 1);
60
+ partial = 0;
61
+
62
+ if (matches.length >= limit) {
63
+ break;
64
+ }
65
+ }
66
+ }
67
+
68
+ return {matches, partial, lookup};
69
+ /* eslint-enable no-param-reassign */
70
+ };
71
+
72
+ /**
73
+ * Builds the KMP failure function (partial match table) for a byte pattern.
74
+ *
75
+ * @param {import('node:buffer').Buffer|string} [searchBuffer=''] - The pattern to pre-process
76
+ * @returns {number[]} - The KMP failure function table
77
+ */
78
+ function makeLookup(searchBuffer = '') {
79
+ const lookup = [];
80
+ let pos = -1;
81
+
82
+ for (let i = 0; i < searchBuffer.length; i++) {
83
+ while (pos >= 0 && searchBuffer[i] !== searchBuffer[pos]) {
84
+ pos -= 1;
85
+
86
+ if (pos >= 0) {
87
+ pos = lookup[pos];
88
+ }
89
+ }
90
+
91
+ pos += 1;
92
+ lookup.push(pos);
93
+ }
94
+
95
+ return lookup;
96
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @fileoverview Buffer split utility using KMP-based pattern matching.
3
+ *
4
+ * Splits a Buffer by a separator pattern, analogous to `String.prototype.split()`.
5
+ * Supports incremental/streaming operation by threading `partial` and `lookup`
6
+ * state across chunks.
7
+ *
8
+ * Returns `{buffers, partial, lookup}` where `buffers` is the array of Buffer slices.
9
+ *
10
+ * @module utils/buffers/split
11
+ * @version 0.1.0
12
+ * @since 0.1.0
13
+ * @requires ./match.js
14
+ * @requires ../get.js
15
+ *
16
+ * @example
17
+ * import bufferSplit from 'ergo/utils/buffers/split';
18
+ *
19
+ * const {buffers} = bufferSplit(Buffer.from('a--b--c'), Buffer.from('--'));
20
+ * // buffers => [Buffer<'a'>, Buffer<'b'>, Buffer<'c'>]
21
+ */
22
+ import bufferMatch from './match.js';
23
+ import get from '../get.js';
24
+
25
+ /**
26
+ * Splits a Buffer by a separator pattern.
27
+ *
28
+ * @param {import('node:buffer').Buffer|string} buffer - Source buffer to split
29
+ * @param {import('node:buffer').Buffer} [separator] - Byte pattern to split on
30
+ * @param {object} [options] - KMP split options
31
+ * @param {number} [options.limit=Infinity] - Maximum splits to produce
32
+ * @param {number} [options.partial=0] - Partial KMP match state from prior chunk
33
+ * @param {number[]} [options.lookup] - Pre-computed KMP failure function table
34
+ * @returns {{buffers: import('node:buffer').Buffer[], partial: number, lookup: number[]}} - Split result with buffer slices, partial state, and lookup table
35
+ */
36
+ export default (buffer = Buffer.from(''), separator, {limit = Infinity, ...options} = {}) => {
37
+ const sepLen = get(separator, 'length', {safe: true}) ?? 0;
38
+ const {matches, ...rest} = bufferMatch(buffer, separator, {limit, ...options});
39
+
40
+ matches.push(buffer.length);
41
+
42
+ const splitsLength = Math.min(limit, matches.length);
43
+
44
+ let start = 0;
45
+ const buffers = Array.from({length: splitsLength}, (v, i) => {
46
+ const offset = matches[i];
47
+ const split = buffer.slice(start, offset);
48
+
49
+ start = offset + sepLen;
50
+
51
+ return split;
52
+ });
53
+
54
+ return {buffers, ...rest};
55
+ };