recker 1.0.26 → 1.0.27

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 (171) hide show
  1. package/dist/browser/browser/cache.d.ts +40 -0
  2. package/dist/browser/browser/cache.js +199 -0
  3. package/dist/browser/browser/crypto.d.ts +24 -0
  4. package/dist/browser/browser/crypto.js +80 -0
  5. package/dist/browser/browser/index.d.ts +31 -0
  6. package/dist/browser/browser/index.js +31 -0
  7. package/dist/browser/browser/recker.d.ts +26 -0
  8. package/dist/browser/browser/recker.js +61 -0
  9. package/dist/browser/cache/basic-file-storage.d.ts +12 -0
  10. package/dist/browser/cache/basic-file-storage.js +50 -0
  11. package/dist/browser/cache/memory-limits.d.ts +20 -0
  12. package/dist/browser/cache/memory-limits.js +96 -0
  13. package/dist/browser/cache/memory-storage.d.ts +132 -0
  14. package/dist/browser/cache/memory-storage.js +454 -0
  15. package/dist/browser/cache.d.ts +40 -0
  16. package/dist/browser/cache.js +199 -0
  17. package/dist/browser/constants/http-status.d.ts +73 -0
  18. package/dist/browser/constants/http-status.js +156 -0
  19. package/dist/browser/cookies/memory-cookie-jar.d.ts +30 -0
  20. package/dist/browser/cookies/memory-cookie-jar.js +210 -0
  21. package/dist/browser/core/client.d.ts +118 -0
  22. package/dist/browser/core/client.js +667 -0
  23. package/dist/browser/core/errors.d.ts +142 -0
  24. package/dist/browser/core/errors.js +308 -0
  25. package/dist/browser/core/index.d.ts +5 -0
  26. package/dist/browser/core/index.js +5 -0
  27. package/dist/browser/core/request-promise.d.ts +23 -0
  28. package/dist/browser/core/request-promise.js +82 -0
  29. package/dist/browser/core/request.d.ts +20 -0
  30. package/dist/browser/core/request.js +76 -0
  31. package/dist/browser/core/response.d.ts +34 -0
  32. package/dist/browser/core/response.js +178 -0
  33. package/dist/browser/crypto.d.ts +24 -0
  34. package/dist/browser/crypto.js +80 -0
  35. package/dist/browser/index.d.ts +31 -0
  36. package/dist/browser/index.js +31 -0
  37. package/dist/browser/plugins/auth/api-key.d.ts +8 -0
  38. package/dist/browser/plugins/auth/api-key.js +27 -0
  39. package/dist/browser/plugins/auth/auth0.d.ts +33 -0
  40. package/dist/browser/plugins/auth/auth0.js +94 -0
  41. package/dist/browser/plugins/auth/aws-sigv4.d.ts +10 -0
  42. package/dist/browser/plugins/auth/aws-sigv4.js +88 -0
  43. package/dist/browser/plugins/auth/azure-ad.d.ts +48 -0
  44. package/dist/browser/plugins/auth/azure-ad.js +152 -0
  45. package/dist/browser/plugins/auth/basic.d.ts +7 -0
  46. package/dist/browser/plugins/auth/basic.js +13 -0
  47. package/dist/browser/plugins/auth/bearer.d.ts +8 -0
  48. package/dist/browser/plugins/auth/bearer.js +17 -0
  49. package/dist/browser/plugins/auth/cognito.d.ts +45 -0
  50. package/dist/browser/plugins/auth/cognito.js +208 -0
  51. package/dist/browser/plugins/auth/digest.d.ts +8 -0
  52. package/dist/browser/plugins/auth/digest.js +100 -0
  53. package/dist/browser/plugins/auth/firebase.d.ts +32 -0
  54. package/dist/browser/plugins/auth/firebase.js +195 -0
  55. package/dist/browser/plugins/auth/github-app.d.ts +36 -0
  56. package/dist/browser/plugins/auth/github-app.js +170 -0
  57. package/dist/browser/plugins/auth/google-service-account.d.ts +49 -0
  58. package/dist/browser/plugins/auth/google-service-account.js +172 -0
  59. package/dist/browser/plugins/auth/index.d.ts +15 -0
  60. package/dist/browser/plugins/auth/index.js +15 -0
  61. package/dist/browser/plugins/auth/mtls.d.ts +37 -0
  62. package/dist/browser/plugins/auth/mtls.js +140 -0
  63. package/dist/browser/plugins/auth/oauth2.d.ts +8 -0
  64. package/dist/browser/plugins/auth/oauth2.js +26 -0
  65. package/dist/browser/plugins/auth/oidc.d.ts +55 -0
  66. package/dist/browser/plugins/auth/oidc.js +222 -0
  67. package/dist/browser/plugins/auth/okta.d.ts +47 -0
  68. package/dist/browser/plugins/auth/okta.js +157 -0
  69. package/dist/browser/plugins/auth.d.ts +1 -0
  70. package/dist/browser/plugins/auth.js +1 -0
  71. package/dist/browser/plugins/cache.d.ts +15 -0
  72. package/dist/browser/plugins/cache.js +486 -0
  73. package/dist/browser/plugins/circuit-breaker.d.ts +13 -0
  74. package/dist/browser/plugins/circuit-breaker.js +100 -0
  75. package/dist/browser/plugins/compression.d.ts +4 -0
  76. package/dist/browser/plugins/compression.js +130 -0
  77. package/dist/browser/plugins/cookie-jar.d.ts +5 -0
  78. package/dist/browser/plugins/cookie-jar.js +72 -0
  79. package/dist/browser/plugins/dedup.d.ts +5 -0
  80. package/dist/browser/plugins/dedup.js +35 -0
  81. package/dist/browser/plugins/graphql.d.ts +13 -0
  82. package/dist/browser/plugins/graphql.js +58 -0
  83. package/dist/browser/plugins/grpc-web.d.ts +79 -0
  84. package/dist/browser/plugins/grpc-web.js +261 -0
  85. package/dist/browser/plugins/hls.d.ts +105 -0
  86. package/dist/browser/plugins/hls.js +395 -0
  87. package/dist/browser/plugins/jsonrpc.d.ts +75 -0
  88. package/dist/browser/plugins/jsonrpc.js +143 -0
  89. package/dist/browser/plugins/logger.d.ts +13 -0
  90. package/dist/browser/plugins/logger.js +108 -0
  91. package/dist/browser/plugins/odata.d.ts +181 -0
  92. package/dist/browser/plugins/odata.js +564 -0
  93. package/dist/browser/plugins/pagination.d.ts +16 -0
  94. package/dist/browser/plugins/pagination.js +105 -0
  95. package/dist/browser/plugins/rate-limit.d.ts +15 -0
  96. package/dist/browser/plugins/rate-limit.js +162 -0
  97. package/dist/browser/plugins/retry.d.ts +14 -0
  98. package/dist/browser/plugins/retry.js +116 -0
  99. package/dist/browser/plugins/scrape.d.ts +21 -0
  100. package/dist/browser/plugins/scrape.js +82 -0
  101. package/dist/browser/plugins/server-timing.d.ts +7 -0
  102. package/dist/browser/plugins/server-timing.js +24 -0
  103. package/dist/browser/plugins/soap.d.ts +72 -0
  104. package/dist/browser/plugins/soap.js +347 -0
  105. package/dist/browser/plugins/xml.d.ts +9 -0
  106. package/dist/browser/plugins/xml.js +194 -0
  107. package/dist/browser/plugins/xsrf.d.ts +9 -0
  108. package/dist/browser/plugins/xsrf.js +48 -0
  109. package/dist/browser/recker.d.ts +26 -0
  110. package/dist/browser/recker.js +61 -0
  111. package/dist/browser/runner/request-runner.d.ts +46 -0
  112. package/dist/browser/runner/request-runner.js +89 -0
  113. package/dist/browser/scrape/document.d.ts +44 -0
  114. package/dist/browser/scrape/document.js +210 -0
  115. package/dist/browser/scrape/element.d.ts +49 -0
  116. package/dist/browser/scrape/element.js +176 -0
  117. package/dist/browser/scrape/extractors.d.ts +16 -0
  118. package/dist/browser/scrape/extractors.js +356 -0
  119. package/dist/browser/scrape/types.d.ts +107 -0
  120. package/dist/browser/scrape/types.js +1 -0
  121. package/dist/browser/transport/fetch.d.ts +11 -0
  122. package/dist/browser/transport/fetch.js +143 -0
  123. package/dist/browser/transport/undici.d.ts +38 -0
  124. package/dist/browser/transport/undici.js +897 -0
  125. package/dist/browser/types/ai.d.ts +267 -0
  126. package/dist/browser/types/ai.js +1 -0
  127. package/dist/browser/types/index.d.ts +351 -0
  128. package/dist/browser/types/index.js +1 -0
  129. package/dist/browser/types/logger.d.ts +16 -0
  130. package/dist/browser/types/logger.js +66 -0
  131. package/dist/browser/types/udp.d.ts +138 -0
  132. package/dist/browser/types/udp.js +1 -0
  133. package/dist/browser/utils/agent-manager.d.ts +29 -0
  134. package/dist/browser/utils/agent-manager.js +160 -0
  135. package/dist/browser/utils/body.d.ts +10 -0
  136. package/dist/browser/utils/body.js +148 -0
  137. package/dist/browser/utils/charset.d.ts +15 -0
  138. package/dist/browser/utils/charset.js +169 -0
  139. package/dist/browser/utils/concurrency.d.ts +20 -0
  140. package/dist/browser/utils/concurrency.js +120 -0
  141. package/dist/browser/utils/dns.d.ts +6 -0
  142. package/dist/browser/utils/dns.js +26 -0
  143. package/dist/browser/utils/header-parser.d.ts +94 -0
  144. package/dist/browser/utils/header-parser.js +617 -0
  145. package/dist/browser/utils/html-cleaner.d.ts +1 -0
  146. package/dist/browser/utils/html-cleaner.js +21 -0
  147. package/dist/browser/utils/link-header.d.ts +69 -0
  148. package/dist/browser/utils/link-header.js +190 -0
  149. package/dist/browser/utils/optional-require.d.ts +19 -0
  150. package/dist/browser/utils/optional-require.js +105 -0
  151. package/dist/browser/utils/progress.d.ts +8 -0
  152. package/dist/browser/utils/progress.js +82 -0
  153. package/dist/browser/utils/request-pool.d.ts +22 -0
  154. package/dist/browser/utils/request-pool.js +101 -0
  155. package/dist/browser/utils/sse.d.ts +7 -0
  156. package/dist/browser/utils/sse.js +67 -0
  157. package/dist/browser/utils/streaming.d.ts +17 -0
  158. package/dist/browser/utils/streaming.js +84 -0
  159. package/dist/browser/utils/try-fn.d.ts +3 -0
  160. package/dist/browser/utils/try-fn.js +59 -0
  161. package/dist/browser/utils/user-agent.d.ts +44 -0
  162. package/dist/browser/utils/user-agent.js +100 -0
  163. package/dist/browser/utils/whois.d.ts +32 -0
  164. package/dist/browser/utils/whois.js +246 -0
  165. package/dist/browser/websocket/client.d.ts +65 -0
  166. package/dist/browser/websocket/client.js +313 -0
  167. package/dist/cli/index.d.ts +1 -0
  168. package/dist/cli/index.js +1 -0
  169. package/dist/transport/fetch.d.ts +7 -1
  170. package/dist/transport/fetch.js +58 -76
  171. package/package.json +34 -2
@@ -0,0 +1,69 @@
1
+ export interface Link {
2
+ uri: string;
3
+ rel?: string;
4
+ anchor?: string;
5
+ type?: string;
6
+ media?: string;
7
+ title?: string;
8
+ hreflang?: string;
9
+ [key: string]: string | undefined;
10
+ }
11
+ export interface LinkCollection {
12
+ all: Link[];
13
+ [rel: string]: Link | Link[] | undefined;
14
+ }
15
+ export declare function parseLink(headerValue: string): LinkCollection;
16
+ export declare const LinkRel: {
17
+ readonly NEXT: "next";
18
+ readonly PREV: "prev";
19
+ readonly PREVIOUS: "previous";
20
+ readonly FIRST: "first";
21
+ readonly LAST: "last";
22
+ readonly ALTERNATE: "alternate";
23
+ readonly CANONICAL: "canonical";
24
+ readonly AUTHOR: "author";
25
+ readonly LICENSE: "license";
26
+ readonly STYLESHEET: "stylesheet";
27
+ readonly ICON: "icon";
28
+ readonly PRELOAD: "preload";
29
+ readonly PREFETCH: "prefetch";
30
+ readonly PRECONNECT: "preconnect";
31
+ readonly DNS_PREFETCH: "dns-prefetch";
32
+ readonly PRERENDER: "prerender";
33
+ readonly SELF: "self";
34
+ readonly EDIT: "edit";
35
+ readonly COLLECTION: "collection";
36
+ readonly ITEM: "item";
37
+ readonly HELP: "help";
38
+ readonly DESCRIBEDBY: "describedby";
39
+ readonly UP: "up";
40
+ readonly RELATED: "related";
41
+ readonly REPLIES: "replies";
42
+ readonly VIA: "via";
43
+ };
44
+ export declare class LinkHeaderParser {
45
+ private links;
46
+ constructor(headerValue: string);
47
+ getAll(): Link[];
48
+ getRel(rel: string): Link | Link[] | undefined;
49
+ getFirst(rel: string): Link | undefined;
50
+ has(rel: string): boolean;
51
+ getPagination(): {
52
+ next?: string;
53
+ prev?: string;
54
+ first?: string;
55
+ last?: string;
56
+ };
57
+ hasNext(): boolean;
58
+ hasPrev(): boolean;
59
+ getCanonical(): string | undefined;
60
+ getAlternates(): Link[];
61
+ getResourceHints(): {
62
+ preload: Link[];
63
+ prefetch: Link[];
64
+ preconnect: Link[];
65
+ dnsPrefetch: Link[];
66
+ };
67
+ toJSON(): LinkCollection;
68
+ }
69
+ export declare function parseLinkHeader(headers: Headers): LinkHeaderParser | null;
@@ -0,0 +1,190 @@
1
+ export function parseLink(headerValue) {
2
+ if (!headerValue || typeof headerValue !== 'string') {
3
+ return { all: [] };
4
+ }
5
+ const links = [];
6
+ const collection = { all: links };
7
+ const linkStrings = splitLinkHeader(headerValue);
8
+ for (const linkString of linkStrings) {
9
+ const link = parseSingleLink(linkString.trim());
10
+ if (link) {
11
+ links.push(link);
12
+ if (link.rel) {
13
+ const relTypes = link.rel.split(/\s+/);
14
+ for (const rel of relTypes) {
15
+ const existing = collection[rel];
16
+ if (existing) {
17
+ if (Array.isArray(existing)) {
18
+ existing.push(link);
19
+ }
20
+ else {
21
+ collection[rel] = [existing, link];
22
+ }
23
+ }
24
+ else {
25
+ collection[rel] = link;
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ return collection;
32
+ }
33
+ function splitLinkHeader(header) {
34
+ const result = [];
35
+ let current = '';
36
+ let inBrackets = false;
37
+ let inQuotes = false;
38
+ for (let i = 0; i < header.length; i++) {
39
+ const char = header[i];
40
+ const prevChar = i > 0 ? header[i - 1] : '';
41
+ if (char === '<' && !inQuotes) {
42
+ inBrackets = true;
43
+ }
44
+ else if (char === '>' && !inQuotes) {
45
+ inBrackets = false;
46
+ }
47
+ else if (char === '"' && prevChar !== '\\') {
48
+ inQuotes = !inQuotes;
49
+ }
50
+ else if (char === ',' && !inBrackets && !inQuotes) {
51
+ result.push(current.trim());
52
+ current = '';
53
+ continue;
54
+ }
55
+ current += char;
56
+ }
57
+ if (current.trim()) {
58
+ result.push(current.trim());
59
+ }
60
+ return result;
61
+ }
62
+ function parseSingleLink(linkString) {
63
+ const uriMatch = linkString.match(/^<([^>]+)>/);
64
+ if (!uriMatch) {
65
+ return null;
66
+ }
67
+ const uri = uriMatch[1];
68
+ const link = { uri };
69
+ const paramsString = linkString.slice(uriMatch[0].length);
70
+ const params = parseParameters(paramsString);
71
+ for (const [key, value] of Object.entries(params)) {
72
+ link[key] = value;
73
+ }
74
+ return link;
75
+ }
76
+ function parseParameters(paramsString) {
77
+ const params = {};
78
+ const paramStrings = paramsString.split(/;/).filter(s => s.trim());
79
+ for (const paramString of paramStrings) {
80
+ const equalIndex = paramString.indexOf('=');
81
+ if (equalIndex === -1)
82
+ continue;
83
+ const key = paramString.slice(0, equalIndex).trim();
84
+ let value = paramString.slice(equalIndex + 1).trim();
85
+ if (value.startsWith('"') && value.endsWith('"')) {
86
+ value = value.slice(1, -1);
87
+ }
88
+ else if (value.startsWith("'") && value.endsWith("'")) {
89
+ value = value.slice(1, -1);
90
+ }
91
+ value = value.replace(/\\(.)/g, '$1');
92
+ params[key] = value;
93
+ }
94
+ return params;
95
+ }
96
+ export const LinkRel = {
97
+ NEXT: 'next',
98
+ PREV: 'prev',
99
+ PREVIOUS: 'previous',
100
+ FIRST: 'first',
101
+ LAST: 'last',
102
+ ALTERNATE: 'alternate',
103
+ CANONICAL: 'canonical',
104
+ AUTHOR: 'author',
105
+ LICENSE: 'license',
106
+ STYLESHEET: 'stylesheet',
107
+ ICON: 'icon',
108
+ PRELOAD: 'preload',
109
+ PREFETCH: 'prefetch',
110
+ PRECONNECT: 'preconnect',
111
+ DNS_PREFETCH: 'dns-prefetch',
112
+ PRERENDER: 'prerender',
113
+ SELF: 'self',
114
+ EDIT: 'edit',
115
+ COLLECTION: 'collection',
116
+ ITEM: 'item',
117
+ HELP: 'help',
118
+ DESCRIBEDBY: 'describedby',
119
+ UP: 'up',
120
+ RELATED: 'related',
121
+ REPLIES: 'replies',
122
+ VIA: 'via',
123
+ };
124
+ export class LinkHeaderParser {
125
+ links;
126
+ constructor(headerValue) {
127
+ this.links = parseLink(headerValue);
128
+ }
129
+ getAll() {
130
+ return this.links.all;
131
+ }
132
+ getRel(rel) {
133
+ return this.links[rel];
134
+ }
135
+ getFirst(rel) {
136
+ const links = this.links[rel];
137
+ if (!links)
138
+ return undefined;
139
+ return Array.isArray(links) ? links[0] : links;
140
+ }
141
+ has(rel) {
142
+ return rel in this.links;
143
+ }
144
+ getPagination() {
145
+ return {
146
+ next: this.getFirst(LinkRel.NEXT)?.uri,
147
+ prev: this.getFirst(LinkRel.PREV)?.uri || this.getFirst(LinkRel.PREVIOUS)?.uri,
148
+ first: this.getFirst(LinkRel.FIRST)?.uri,
149
+ last: this.getFirst(LinkRel.LAST)?.uri,
150
+ };
151
+ }
152
+ hasNext() {
153
+ return this.has(LinkRel.NEXT);
154
+ }
155
+ hasPrev() {
156
+ return this.has(LinkRel.PREV) || this.has(LinkRel.PREVIOUS);
157
+ }
158
+ getCanonical() {
159
+ return this.getFirst(LinkRel.CANONICAL)?.uri;
160
+ }
161
+ getAlternates() {
162
+ const alts = this.getRel(LinkRel.ALTERNATE);
163
+ if (!alts)
164
+ return [];
165
+ return Array.isArray(alts) ? alts : [alts];
166
+ }
167
+ getResourceHints() {
168
+ const getLinks = (rel) => {
169
+ const links = this.getRel(rel);
170
+ if (!links)
171
+ return [];
172
+ return Array.isArray(links) ? links : [links];
173
+ };
174
+ return {
175
+ preload: getLinks(LinkRel.PRELOAD),
176
+ prefetch: getLinks(LinkRel.PREFETCH),
177
+ preconnect: getLinks(LinkRel.PRECONNECT),
178
+ dnsPrefetch: getLinks(LinkRel.DNS_PREFETCH),
179
+ };
180
+ }
181
+ toJSON() {
182
+ return this.links;
183
+ }
184
+ }
185
+ export function parseLinkHeader(headers) {
186
+ const linkHeader = headers.get('Link');
187
+ if (!linkHeader)
188
+ return null;
189
+ return new LinkHeaderParser(linkHeader);
190
+ }
@@ -0,0 +1,19 @@
1
+ interface DependencyInfo {
2
+ package: string;
3
+ submodule: string;
4
+ version?: string;
5
+ feature?: string;
6
+ }
7
+ export declare const OPTIONAL_DEPENDENCIES: Record<string, DependencyInfo>;
8
+ export declare class MissingDependencyError extends Error {
9
+ readonly packageName: string;
10
+ readonly submodule: string;
11
+ readonly installCommand: string;
12
+ constructor(packageName: string, submodule: string, installCommand: string);
13
+ }
14
+ export declare function clearModuleCache(): void;
15
+ export declare function requireOptional<T = unknown>(packageName: string, submodule?: string): Promise<T>;
16
+ export declare function isPackageAvailable(packageName: string): boolean;
17
+ export declare function getInstallCommand(packages: string[]): string;
18
+ export declare function requireOptionalMany<T extends Record<string, unknown>>(packages: string[], submodule: string): Promise<T>;
19
+ export {};
@@ -0,0 +1,105 @@
1
+ export const OPTIONAL_DEPENDENCIES = {
2
+ 'cardinal': {
3
+ package: 'cardinal',
4
+ submodule: 'recker/cli',
5
+ version: '^2.0.0',
6
+ feature: 'syntax highlighting',
7
+ },
8
+ 'ssh2-sftp-client': {
9
+ package: 'ssh2-sftp-client',
10
+ submodule: 'recker/protocols/sftp',
11
+ version: '^11.0.0',
12
+ feature: 'SFTP client',
13
+ },
14
+ 'cheerio': {
15
+ package: 'cheerio',
16
+ submodule: 'recker/scrape',
17
+ version: '^1.0.0',
18
+ feature: 'HTML parsing and scraping',
19
+ },
20
+ 'ioredis': {
21
+ package: 'ioredis',
22
+ submodule: 'recker/cache',
23
+ version: '^5.0.0',
24
+ feature: 'Redis cache storage',
25
+ },
26
+ };
27
+ export class MissingDependencyError extends Error {
28
+ packageName;
29
+ submodule;
30
+ installCommand;
31
+ constructor(packageName, submodule, installCommand) {
32
+ super(`Missing optional dependency: ${packageName}\n\n` +
33
+ `This dependency is required for ${submodule}.\n` +
34
+ `Install it with:\n\n ${installCommand}\n`);
35
+ this.packageName = packageName;
36
+ this.submodule = submodule;
37
+ this.installCommand = installCommand;
38
+ this.name = 'MissingDependencyError';
39
+ }
40
+ }
41
+ const moduleCache = new Map();
42
+ export function clearModuleCache() {
43
+ moduleCache.clear();
44
+ }
45
+ export async function requireOptional(packageName, submodule) {
46
+ if (moduleCache.has(packageName)) {
47
+ return moduleCache.get(packageName);
48
+ }
49
+ try {
50
+ const mod = await import(packageName);
51
+ moduleCache.set(packageName, mod);
52
+ return mod;
53
+ }
54
+ catch (error) {
55
+ const err = error;
56
+ const isModuleNotFound = err.code === 'ERR_MODULE_NOT_FOUND' ||
57
+ err.code === 'MODULE_NOT_FOUND' ||
58
+ (err.message?.includes('Cannot find module'));
59
+ if (isModuleNotFound) {
60
+ const info = OPTIONAL_DEPENDENCIES[packageName];
61
+ const sub = submodule || info?.submodule || 'this feature';
62
+ const version = info?.version || '';
63
+ const pkg = version ? `${packageName}@${version.replace('^', '')}` : packageName;
64
+ throw new MissingDependencyError(packageName, sub, `pnpm add ${pkg}`);
65
+ }
66
+ throw error;
67
+ }
68
+ }
69
+ export function isPackageAvailable(packageName) {
70
+ try {
71
+ require.resolve(packageName);
72
+ return true;
73
+ }
74
+ catch {
75
+ return false;
76
+ }
77
+ }
78
+ export function getInstallCommand(packages) {
79
+ const pkgsWithVersions = packages.map((pkg) => {
80
+ const info = OPTIONAL_DEPENDENCIES[pkg];
81
+ return info?.version ? `${pkg}@${info.version.replace('^', '')}` : pkg;
82
+ });
83
+ return `pnpm add ${pkgsWithVersions.join(' ')}`;
84
+ }
85
+ export async function requireOptionalMany(packages, submodule) {
86
+ const missing = [];
87
+ const results = {};
88
+ for (const pkg of packages) {
89
+ try {
90
+ results[pkg] = await requireOptional(pkg, submodule);
91
+ }
92
+ catch (error) {
93
+ if (error instanceof MissingDependencyError) {
94
+ missing.push(pkg);
95
+ }
96
+ else {
97
+ throw error;
98
+ }
99
+ }
100
+ }
101
+ if (missing.length > 0) {
102
+ throw new MissingDependencyError(missing.join(', '), submodule, getInstallCommand(missing));
103
+ }
104
+ return results;
105
+ }
@@ -0,0 +1,8 @@
1
+ import { ProgressEvent, ProgressCallback } from '../types/index.js';
2
+ export interface ProgressStreamOptions {
3
+ total?: number;
4
+ direction?: 'upload' | 'download';
5
+ throttleMs?: number;
6
+ }
7
+ export declare function createProgressStream(stream: ReadableStream<Uint8Array>, onProgress: ProgressCallback, optionsOrTotal?: number | ProgressStreamOptions): ReadableStream<Uint8Array>;
8
+ export declare function calculateProgress(loaded: number, total?: number, direction?: 'upload' | 'download'): ProgressEvent;
@@ -0,0 +1,82 @@
1
+ export function createProgressStream(stream, onProgress, optionsOrTotal) {
2
+ const options = typeof optionsOrTotal === 'number'
3
+ ? { total: optionsOrTotal }
4
+ : optionsOrTotal || {};
5
+ const { total, direction, throttleMs = 100 } = options;
6
+ let loaded = 0;
7
+ let startTime = Date.now();
8
+ let lastUpdate = 0;
9
+ let lastLoaded = 0;
10
+ let lastRateUpdate = startTime;
11
+ let smoothedRate = 0;
12
+ const rateSmoothingFactor = 0.3;
13
+ const emitProgress = (now, isFinal) => {
14
+ const elapsed = (now - startTime) / 1000;
15
+ const intervalMs = now - lastRateUpdate;
16
+ const bytesInInterval = loaded - lastLoaded;
17
+ if (intervalMs > 0) {
18
+ const instantRate = (bytesInInterval / intervalMs) * 1000;
19
+ smoothedRate = smoothedRate === 0
20
+ ? instantRate
21
+ : smoothedRate * (1 - rateSmoothingFactor) + instantRate * rateSmoothingFactor;
22
+ }
23
+ lastLoaded = loaded;
24
+ lastRateUpdate = now;
25
+ const rate = smoothedRate;
26
+ let percent;
27
+ if (total) {
28
+ percent = isFinal ? 100 : Math.min((loaded / total) * 100, 99.9);
29
+ }
30
+ const progress = {
31
+ loaded,
32
+ transferred: loaded,
33
+ total,
34
+ percent,
35
+ rate,
36
+ estimated: total && rate > 0 ? ((total - loaded) / rate) * 1000 : undefined,
37
+ direction,
38
+ };
39
+ onProgress(progress);
40
+ lastUpdate = now;
41
+ };
42
+ return new ReadableStream({
43
+ async start(controller) {
44
+ const reader = stream.getReader();
45
+ try {
46
+ emitProgress(Date.now(), false);
47
+ while (true) {
48
+ const { done, value } = await reader.read();
49
+ if (done) {
50
+ emitProgress(Date.now(), true);
51
+ controller.close();
52
+ break;
53
+ }
54
+ loaded += value.byteLength;
55
+ const now = Date.now();
56
+ const shouldUpdate = now - lastUpdate >= throttleMs ||
57
+ (total && loaded === total);
58
+ if (shouldUpdate) {
59
+ emitProgress(now, false);
60
+ }
61
+ controller.enqueue(value);
62
+ }
63
+ }
64
+ catch (error) {
65
+ controller.error(error);
66
+ throw error;
67
+ }
68
+ },
69
+ });
70
+ }
71
+ export function calculateProgress(loaded, total, direction) {
72
+ const progress = {
73
+ loaded,
74
+ transferred: loaded,
75
+ total,
76
+ direction,
77
+ };
78
+ if (total && total > 0) {
79
+ progress.percent = (loaded / total) * 100;
80
+ }
81
+ return progress;
82
+ }
@@ -0,0 +1,22 @@
1
+ import type { Middleware } from '../types/index.js';
2
+ export interface RequestPoolOptions {
3
+ concurrency?: number;
4
+ requestsPerInterval?: number;
5
+ interval?: number;
6
+ }
7
+ export declare class RequestPool {
8
+ private readonly concurrency;
9
+ private readonly requestsPerInterval?;
10
+ private readonly interval?;
11
+ private queue;
12
+ private active;
13
+ private windowStart;
14
+ private startedInWindow;
15
+ private waitingTimer?;
16
+ constructor(options?: RequestPoolOptions);
17
+ run<T>(fn: () => Promise<T>, signal?: AbortSignal): Promise<T>;
18
+ private _removeFromQueue;
19
+ private _canStart;
20
+ private _schedule;
21
+ asMiddleware(): Middleware;
22
+ }
@@ -0,0 +1,101 @@
1
+ import { ReckerError } from '../core/errors.js';
2
+ export class RequestPool {
3
+ concurrency;
4
+ requestsPerInterval;
5
+ interval;
6
+ queue = [];
7
+ active = 0;
8
+ windowStart = 0;
9
+ startedInWindow = 0;
10
+ waitingTimer;
11
+ constructor(options = {}) {
12
+ this.concurrency = options.concurrency ?? Number.POSITIVE_INFINITY;
13
+ this.requestsPerInterval = options.requestsPerInterval;
14
+ this.interval = options.interval;
15
+ }
16
+ run(fn, signal) {
17
+ if (signal?.aborted) {
18
+ return Promise.reject(signal.reason ?? new ReckerError('Request aborted before enqueue', undefined, undefined, ['Ensure the AbortSignal is not already aborted when calling the request.', 'Remove or reset the signal before enqueueing.']));
19
+ }
20
+ return new Promise((resolve, reject) => {
21
+ const request = { fn, resolve, reject, signal };
22
+ if (signal) {
23
+ const onAbort = () => {
24
+ this._removeFromQueue(request);
25
+ reject(signal.reason ?? new ReckerError('Request aborted while queued', undefined, undefined, ['Avoid aborting immediately after queuing.', 'Increase timeouts or adjust rate limits if cancellations are unintended.']));
26
+ this._schedule();
27
+ };
28
+ signal.addEventListener('abort', onAbort, { once: true });
29
+ request.abortCleanup = () => signal.removeEventListener('abort', onAbort);
30
+ }
31
+ this.queue.push(request);
32
+ this._schedule();
33
+ });
34
+ }
35
+ _removeFromQueue(request) {
36
+ const index = this.queue.indexOf(request);
37
+ if (index >= 0) {
38
+ this.queue.splice(index, 1);
39
+ }
40
+ }
41
+ _canStart(now) {
42
+ if (this.active >= this.concurrency) {
43
+ return false;
44
+ }
45
+ if (this.requestsPerInterval == null || this.interval == null) {
46
+ return true;
47
+ }
48
+ if (now - this.windowStart >= this.interval) {
49
+ this.windowStart = now;
50
+ this.startedInWindow = 0;
51
+ }
52
+ if (this.startedInWindow < this.requestsPerInterval) {
53
+ return true;
54
+ }
55
+ return false;
56
+ }
57
+ _schedule() {
58
+ if (this.waitingTimer) {
59
+ return;
60
+ }
61
+ const now = Date.now();
62
+ while (this.queue.length > 0 && this._canStart(Date.now())) {
63
+ const request = this.queue.shift();
64
+ if (request.signal?.aborted) {
65
+ request.abortCleanup?.();
66
+ request.reject(request.signal.reason ?? new ReckerError('Request aborted while queued', undefined, undefined, ['Avoid aborting immediately after queuing.', 'Increase timeouts or adjust rate limits if cancellations are unintended.']));
67
+ continue;
68
+ }
69
+ this.active++;
70
+ this.startedInWindow++;
71
+ const clearAbort = request.abortCleanup;
72
+ if (clearAbort) {
73
+ clearAbort();
74
+ request.abortCleanup = undefined;
75
+ }
76
+ Promise.resolve()
77
+ .then(() => request.fn())
78
+ .then((result) => request.resolve(result))
79
+ .catch((error) => request.reject(error))
80
+ .finally(() => {
81
+ this.active--;
82
+ this._schedule();
83
+ });
84
+ }
85
+ if (this.queue.length > 0 &&
86
+ this.requestsPerInterval != null &&
87
+ this.interval != null &&
88
+ !this._canStart(Date.now())) {
89
+ const wait = Math.max(0, this.windowStart + this.interval - Date.now());
90
+ this.waitingTimer = setTimeout(() => {
91
+ this.waitingTimer = undefined;
92
+ this._schedule();
93
+ }, wait);
94
+ }
95
+ }
96
+ asMiddleware() {
97
+ return async (req, next) => {
98
+ return this.run(() => next(req), req.signal);
99
+ };
100
+ }
101
+ }
@@ -0,0 +1,7 @@
1
+ export interface SSEEvent {
2
+ id?: string;
3
+ event?: string;
4
+ data: string;
5
+ retry?: number;
6
+ }
7
+ export declare function parseSSE(response: Response): AsyncGenerator<SSEEvent>;
@@ -0,0 +1,67 @@
1
+ import { StreamError } from '../core/errors.js';
2
+ export async function* parseSSE(response) {
3
+ if (!response.body) {
4
+ throw new StreamError('Response body is empty; cannot parse SSE stream.', {
5
+ streamType: 'sse',
6
+ retriable: true,
7
+ });
8
+ }
9
+ const reader = response.body.getReader();
10
+ const decoder = new TextDecoder();
11
+ let buffer = '';
12
+ let currentEvent = { data: '' };
13
+ try {
14
+ while (true) {
15
+ const { done, value } = await reader.read();
16
+ if (done)
17
+ break;
18
+ buffer += decoder.decode(value, { stream: true });
19
+ const lines = buffer.split(/\r\n|\r|\n/);
20
+ buffer = lines.pop() || '';
21
+ for (const line of lines) {
22
+ if (line.trim() === '') {
23
+ if (currentEvent.data || currentEvent.event || currentEvent.id) {
24
+ if (currentEvent.data.endsWith('\n')) {
25
+ currentEvent.data = currentEvent.data.slice(0, -1);
26
+ }
27
+ yield currentEvent;
28
+ currentEvent = { data: '' };
29
+ }
30
+ continue;
31
+ }
32
+ const colonIndex = line.indexOf(':');
33
+ let field = line;
34
+ let value = '';
35
+ if (colonIndex !== -1) {
36
+ field = line.slice(0, colonIndex);
37
+ value = line.slice(colonIndex + 1);
38
+ if (value.startsWith(' ')) {
39
+ value = value.slice(1);
40
+ }
41
+ }
42
+ switch (field) {
43
+ case 'data':
44
+ currentEvent.data += value + '\n';
45
+ break;
46
+ case 'event':
47
+ currentEvent.event = value;
48
+ break;
49
+ case 'id':
50
+ currentEvent.id = value;
51
+ break;
52
+ case 'retry':
53
+ const retry = parseInt(value, 10);
54
+ if (!isNaN(retry)) {
55
+ currentEvent.retry = retry;
56
+ }
57
+ break;
58
+ }
59
+ }
60
+ }
61
+ if (buffer.trim() !== '') {
62
+ }
63
+ }
64
+ finally {
65
+ reader.releaseLock();
66
+ }
67
+ }
@@ -0,0 +1,17 @@
1
+ import { Readable } from 'node:stream';
2
+ export declare function webToNodeStream(webStream: ReadableStream): Readable;
3
+ export declare function nodeToWebStream(nodeStream: Readable): ReadableStream<Uint8Array>;
4
+ export interface StreamProgressOptions {
5
+ onProgress?: (progress: {
6
+ loaded: number;
7
+ total?: number;
8
+ percent?: number;
9
+ }) => void;
10
+ total?: number;
11
+ }
12
+ export declare function trackStreamProgress(stream: Readable, options?: StreamProgressOptions): Readable;
13
+ export declare function pipeStream(source: Readable, destination: NodeJS.WritableStream, options?: StreamProgressOptions): Promise<void>;
14
+ export declare function createUploadStream(source: Readable): {
15
+ stream: ReadableStream<Uint8Array<ArrayBufferLike>>;
16
+ promise: Promise<void>;
17
+ };