@apiquest/fracture 1.0.2 → 1.0.4

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 (168) hide show
  1. package/README.md +119 -0
  2. package/bin/cli.js +2 -2
  3. package/dist/CollectionRunner.js +3 -3
  4. package/dist/ScriptEngine.js +4 -4
  5. package/dist/cli/plugin-commands.d.ts.map +1 -1
  6. package/dist/cli/plugin-commands.js +2 -1
  7. package/dist/cli/plugin-commands.js.map +1 -1
  8. package/package.json +55 -50
  9. package/src/CollectionAnalyzer.ts +102 -102
  10. package/src/CollectionRunner.ts +1423 -1423
  11. package/src/CollectionRunner.types.ts +9 -9
  12. package/src/CollectionValidator.ts +289 -289
  13. package/src/ConsoleReporter.ts +143 -143
  14. package/src/CookieJar.ts +258 -258
  15. package/src/DagScheduler.ts +439 -439
  16. package/src/Logger.ts +85 -85
  17. package/src/PluginLoader.ts +126 -126
  18. package/src/PluginManager.ts +208 -208
  19. package/src/PluginResolver.ts +154 -154
  20. package/src/QuestAPI.ts +764 -764
  21. package/src/QuestAPI.types.ts +33 -33
  22. package/src/QuestTestAPI.ts +164 -164
  23. package/src/RequestFilter.ts +224 -224
  24. package/src/ScriptEngine.ts +219 -219
  25. package/src/ScriptValidator.ts +428 -428
  26. package/src/TaskGraph.ts +598 -598
  27. package/src/TestCounter.ts +109 -109
  28. package/src/VariableResolver.ts +114 -114
  29. package/src/cli/index.ts +480 -480
  30. package/src/cli/plugin-commands.ts +342 -341
  31. package/src/cli/plugin-discovery.ts +44 -44
  32. package/src/index.ts +24 -24
  33. package/src/utils.ts +52 -52
  34. package/tsconfig.json +20 -20
  35. package/tsconfig.test.json +5 -5
  36. package/vitest.config.ts +22 -22
  37. package/dist/ExecutionTree.d.ts +0 -77
  38. package/dist/ExecutionTree.d.ts.map +0 -1
  39. package/dist/ExecutionTree.js +0 -265
  40. package/dist/ExecutionTree.js.map +0 -1
  41. package/dist/fracture/src/CollectionAnalyzer.d.ts +0 -17
  42. package/dist/fracture/src/CollectionAnalyzer.d.ts.map +0 -1
  43. package/dist/fracture/src/CollectionAnalyzer.js +0 -70
  44. package/dist/fracture/src/CollectionAnalyzer.js.map +0 -1
  45. package/dist/fracture/src/CollectionRunner.d.ts +0 -39
  46. package/dist/fracture/src/CollectionRunner.d.ts.map +0 -1
  47. package/dist/fracture/src/CollectionRunner.js +0 -802
  48. package/dist/fracture/src/CollectionRunner.js.map +0 -1
  49. package/dist/fracture/src/CollectionRunner.types.d.ts +0 -8
  50. package/dist/fracture/src/CollectionRunner.types.d.ts.map +0 -1
  51. package/dist/fracture/src/CollectionRunner.types.js +0 -2
  52. package/dist/fracture/src/CollectionRunner.types.js.map +0 -1
  53. package/dist/fracture/src/CollectionValidator.d.ts +0 -14
  54. package/dist/fracture/src/CollectionValidator.d.ts.map +0 -1
  55. package/dist/fracture/src/CollectionValidator.js +0 -145
  56. package/dist/fracture/src/CollectionValidator.js.map +0 -1
  57. package/dist/fracture/src/ConsoleReporter.d.ts +0 -24
  58. package/dist/fracture/src/ConsoleReporter.d.ts.map +0 -1
  59. package/dist/fracture/src/ConsoleReporter.js +0 -123
  60. package/dist/fracture/src/ConsoleReporter.js.map +0 -1
  61. package/dist/fracture/src/CookieJar.d.ts +0 -70
  62. package/dist/fracture/src/CookieJar.d.ts.map +0 -1
  63. package/dist/fracture/src/CookieJar.js +0 -233
  64. package/dist/fracture/src/CookieJar.js.map +0 -1
  65. package/dist/fracture/src/ExecutionTree.d.ts +0 -77
  66. package/dist/fracture/src/ExecutionTree.d.ts.map +0 -1
  67. package/dist/fracture/src/ExecutionTree.js +0 -258
  68. package/dist/fracture/src/ExecutionTree.js.map +0 -1
  69. package/dist/fracture/src/Logger.d.ts +0 -25
  70. package/dist/fracture/src/Logger.d.ts.map +0 -1
  71. package/dist/fracture/src/Logger.js +0 -78
  72. package/dist/fracture/src/Logger.js.map +0 -1
  73. package/dist/fracture/src/PluginLoader.d.ts +0 -23
  74. package/dist/fracture/src/PluginLoader.d.ts.map +0 -1
  75. package/dist/fracture/src/PluginLoader.js +0 -102
  76. package/dist/fracture/src/PluginLoader.js.map +0 -1
  77. package/dist/fracture/src/PluginManager.d.ts +0 -64
  78. package/dist/fracture/src/PluginManager.d.ts.map +0 -1
  79. package/dist/fracture/src/PluginManager.js +0 -162
  80. package/dist/fracture/src/PluginManager.js.map +0 -1
  81. package/dist/fracture/src/PluginResolver.d.ts +0 -35
  82. package/dist/fracture/src/PluginResolver.d.ts.map +0 -1
  83. package/dist/fracture/src/PluginResolver.js +0 -128
  84. package/dist/fracture/src/PluginResolver.js.map +0 -1
  85. package/dist/fracture/src/QuestAPI.d.ts +0 -9
  86. package/dist/fracture/src/QuestAPI.d.ts.map +0 -1
  87. package/dist/fracture/src/QuestAPI.js +0 -679
  88. package/dist/fracture/src/QuestAPI.js.map +0 -1
  89. package/dist/fracture/src/QuestAPI.types.d.ts +0 -35
  90. package/dist/fracture/src/QuestAPI.types.d.ts.map +0 -1
  91. package/dist/fracture/src/QuestAPI.types.js +0 -3
  92. package/dist/fracture/src/QuestAPI.types.js.map +0 -1
  93. package/dist/fracture/src/QuestTestAPI.d.ts +0 -12
  94. package/dist/fracture/src/QuestTestAPI.d.ts.map +0 -1
  95. package/dist/fracture/src/QuestTestAPI.js +0 -133
  96. package/dist/fracture/src/QuestTestAPI.js.map +0 -1
  97. package/dist/fracture/src/ScriptEngine.d.ts +0 -21
  98. package/dist/fracture/src/ScriptEngine.d.ts.map +0 -1
  99. package/dist/fracture/src/ScriptEngine.js +0 -183
  100. package/dist/fracture/src/ScriptEngine.js.map +0 -1
  101. package/dist/fracture/src/ScriptValidator.d.ts +0 -68
  102. package/dist/fracture/src/ScriptValidator.d.ts.map +0 -1
  103. package/dist/fracture/src/ScriptValidator.js +0 -351
  104. package/dist/fracture/src/ScriptValidator.js.map +0 -1
  105. package/dist/fracture/src/TestCounter.d.ts +0 -18
  106. package/dist/fracture/src/TestCounter.d.ts.map +0 -1
  107. package/dist/fracture/src/TestCounter.js +0 -82
  108. package/dist/fracture/src/TestCounter.js.map +0 -1
  109. package/dist/fracture/src/VariableResolver.d.ts +0 -20
  110. package/dist/fracture/src/VariableResolver.d.ts.map +0 -1
  111. package/dist/fracture/src/VariableResolver.js +0 -100
  112. package/dist/fracture/src/VariableResolver.js.map +0 -1
  113. package/dist/fracture/src/cli/index.d.ts +0 -3
  114. package/dist/fracture/src/cli/index.d.ts.map +0 -1
  115. package/dist/fracture/src/cli/index.js +0 -347
  116. package/dist/fracture/src/cli/index.js.map +0 -1
  117. package/dist/fracture/src/cli/plugin-commands.d.ts +0 -6
  118. package/dist/fracture/src/cli/plugin-commands.d.ts.map +0 -1
  119. package/dist/fracture/src/cli/plugin-commands.js +0 -263
  120. package/dist/fracture/src/cli/plugin-commands.js.map +0 -1
  121. package/dist/fracture/src/cli/plugin-discovery.d.ts +0 -11
  122. package/dist/fracture/src/cli/plugin-discovery.d.ts.map +0 -1
  123. package/dist/fracture/src/cli/plugin-discovery.js +0 -64
  124. package/dist/fracture/src/cli/plugin-discovery.js.map +0 -1
  125. package/dist/fracture/src/index.d.ts +0 -13
  126. package/dist/fracture/src/index.d.ts.map +0 -1
  127. package/dist/fracture/src/index.js +0 -17
  128. package/dist/fracture/src/index.js.map +0 -1
  129. package/dist/fracture/src/utils.d.ts +0 -28
  130. package/dist/fracture/src/utils.d.ts.map +0 -1
  131. package/dist/fracture/src/utils.js +0 -48
  132. package/dist/fracture/src/utils.js.map +0 -1
  133. package/dist/plugin-auth/src/apikey-auth.d.ts +0 -3
  134. package/dist/plugin-auth/src/apikey-auth.d.ts.map +0 -1
  135. package/dist/plugin-auth/src/apikey-auth.js +0 -73
  136. package/dist/plugin-auth/src/apikey-auth.js.map +0 -1
  137. package/dist/plugin-auth/src/basic-auth.d.ts +0 -3
  138. package/dist/plugin-auth/src/basic-auth.d.ts.map +0 -1
  139. package/dist/plugin-auth/src/basic-auth.js +0 -61
  140. package/dist/plugin-auth/src/basic-auth.js.map +0 -1
  141. package/dist/plugin-auth/src/bearer-auth.d.ts +0 -3
  142. package/dist/plugin-auth/src/bearer-auth.d.ts.map +0 -1
  143. package/dist/plugin-auth/src/bearer-auth.js +0 -49
  144. package/dist/plugin-auth/src/bearer-auth.js.map +0 -1
  145. package/dist/plugin-auth/src/helpers.d.ts +0 -3
  146. package/dist/plugin-auth/src/helpers.d.ts.map +0 -1
  147. package/dist/plugin-auth/src/helpers.js +0 -8
  148. package/dist/plugin-auth/src/helpers.js.map +0 -1
  149. package/dist/plugin-auth/src/index.d.ts +0 -10
  150. package/dist/plugin-auth/src/index.d.ts.map +0 -1
  151. package/dist/plugin-auth/src/index.js +0 -25
  152. package/dist/plugin-auth/src/index.js.map +0 -1
  153. package/dist/plugin-auth/src/oauth2-auth.d.ts +0 -35
  154. package/dist/plugin-auth/src/oauth2-auth.d.ts.map +0 -1
  155. package/dist/plugin-auth/src/oauth2-auth.js +0 -266
  156. package/dist/plugin-auth/src/oauth2-auth.js.map +0 -1
  157. package/dist/plugin-http/src/index.d.ts +0 -4
  158. package/dist/plugin-http/src/index.d.ts.map +0 -1
  159. package/dist/plugin-http/src/index.js +0 -266
  160. package/dist/plugin-http/src/index.js.map +0 -1
  161. package/dist/plugin-vault-file/src/index.d.ts +0 -67
  162. package/dist/plugin-vault-file/src/index.d.ts.map +0 -1
  163. package/dist/plugin-vault-file/src/index.js +0 -171
  164. package/dist/plugin-vault-file/src/index.js.map +0 -1
  165. package/dist/types.d.ts +0 -374
  166. package/dist/types.d.ts.map +0 -1
  167. package/dist/types.js +0 -13
  168. package/dist/types.js.map +0 -1
package/src/CookieJar.ts CHANGED
@@ -1,258 +1,258 @@
1
- import { CookieJar as ToughCookieJar, Cookie } from 'tough-cookie';
2
- import type { ICookieJar, CookieJarOptions, Cookie as ICookie, CookieSetOptions } from '@apiquest/types';
3
-
4
- /**
5
- * CookieJar implementation using tough-cookie for production-quality cookie management.
6
- * Wraps tough-cookie's CookieJar to provide ICookieJar interface.
7
- */
8
- export class CookieJar implements ICookieJar {
9
- private jar: ToughCookieJar;
10
- private options: CookieJarOptions;
11
-
12
- constructor(options?: CookieJarOptions) {
13
- this.options = options ?? { persist: false };
14
- this.jar = new ToughCookieJar();
15
- }
16
-
17
- /**
18
- * Store cookies from Set-Cookie headers
19
- * @param setCookieHeaders - Single header string or array of header strings
20
- * @param requestUrl - URL the cookies came from (REQUIRED for domain/path matching)
21
- */
22
- store(setCookieHeaders: string | string[] | null | undefined, requestUrl: string): void {
23
- if (setCookieHeaders === null || setCookieHeaders === undefined) {
24
- return;
25
- }
26
-
27
- const headers = Array.isArray(setCookieHeaders) ? setCookieHeaders : [setCookieHeaders];
28
-
29
- for (const header of headers) {
30
- try {
31
- this.jar.setCookieSync(header, requestUrl);
32
- } catch (error) {
33
- // Ignore invalid cookies (tough-cookie throws on malformed cookies)
34
- // Silent failure is fine here
35
- }
36
- }
37
- }
38
-
39
- /**
40
- * Get cookie value by name
41
- * When called without domain, searches ALL cookies (across all domains)
42
- *
43
- * @param name - Cookie name
44
- * @param domain - Optional domain to filter (not commonly used)
45
- * @param path - Optional path to filter (not commonly used)
46
- * @returns Cookie value or null if not found
47
- */
48
- get(name: string, domain?: string, path?: string): string | null {
49
- // Use toJSON to get ALL cookies, then manually filter for expiration only
50
- const allCookiesJson = this.jar.toJSON();
51
- if (allCookiesJson?.cookies === undefined) {
52
- return null;
53
- }
54
-
55
- // Search for cookie by name
56
- for (const cookieData of allCookiesJson.cookies) {
57
- // Use Cookie.fromJSON for proper typing
58
- const cookie = Cookie.fromJSON(cookieData);
59
- if (cookie === null || cookie === undefined) {
60
- continue;
61
- }
62
-
63
- if (cookie.key !== name) {
64
- continue;
65
- }
66
-
67
- // Check expiration
68
- const expiryTime = cookie.expiryTime();
69
- if (expiryTime !== null && expiryTime !== undefined && expiryTime < Date.now()) {
70
- continue; // Skip expired cookies
71
- }
72
-
73
- // If domain filter specified, check it
74
- if (domain !== null && domain !== undefined && domain !== '') {
75
- if (cookie.domain === null) {
76
- continue;
77
- }
78
- if (cookie.domain !== domain && !cookie.domain.endsWith(domain)) {
79
- continue;
80
- }
81
- }
82
-
83
- // If path filter specified, check it
84
- if (path !== null && path !== undefined && path !== '') {
85
- if (cookie.path === null || cookie.path !== path) {
86
- continue;
87
- }
88
- }
89
-
90
- return cookie.value;
91
- }
92
-
93
- return null;
94
- }
95
-
96
- /**
97
- * Check if cookie exists
98
- * @param name - Cookie name
99
- * @param domain - Optional domain filter
100
- * @param path - Optional path filter
101
- * @returns true if cookie exists
102
- */
103
- has(name: string, domain?: string, path?: string): boolean {
104
- return this.get(name, domain, path) !== null;
105
- }
106
-
107
- /**
108
- * Remove a cookie by name
109
- * @param name - Cookie name
110
- * @param domain - Optional domain
111
- * @param path - Optional path
112
- */
113
- remove(name: string, domain?: string, path?: string): void {
114
- const allCookiesJson = this.jar.toJSON();
115
- if (allCookiesJson?.cookies === undefined) {
116
- return;
117
- }
118
-
119
- // Find matching cookies using Cookie.fromJSON for proper typing
120
- const cookiesToRemove: Cookie[] = [];
121
- for (const cookieData of allCookiesJson.cookies) {
122
- const cookie = Cookie.fromJSON(cookieData);
123
- if (cookie === null || cookie === undefined) {
124
- continue;
125
- }
126
-
127
- if (cookie.key !== name) {
128
- continue;
129
- }
130
-
131
- // Check domain filter
132
- if (domain !== null && domain !== undefined && domain !== '') {
133
- if (cookie.domain === null) {
134
- continue;
135
- }
136
- if (cookie.domain !== domain && !cookie.domain.endsWith(domain)) {
137
- continue;
138
- }
139
- }
140
-
141
- // Check path filter
142
- if (path !== null && path !== undefined && path !== '') {
143
- if (cookie.path === null || cookie.path !== path) {
144
- continue;
145
- }
146
- }
147
-
148
- cookiesToRemove.push(cookie);
149
- }
150
-
151
- // Remove each matching cookie
152
- for (const cookie of cookiesToRemove) {
153
- // Domain should always be present in cookies from tough-cookie
154
- const cookieDomain = cookie.domain;
155
- if (cookieDomain === null || cookieDomain === undefined) {
156
- continue; // Skip cookies without domain
157
- }
158
- const cookiePath = cookie.path ?? '/';
159
- try {
160
- this.jar.store.removeCookie(cookieDomain, cookiePath, cookie.key, () => {
161
- // Callback required by tough-cookie API
162
- });
163
- } catch {
164
- // Ignore errors
165
- }
166
- }
167
- }
168
-
169
- /**
170
- * Set a cookie manually
171
- * Constructs URL from cookie's domain for RFC 6265 validation
172
- * @param name - Cookie name
173
- * @param value - Cookie value
174
- * @param options - Cookie options
175
- */
176
- set(name: string, value: string, options: CookieSetOptions): void {
177
- let cookieStr = `${name}=${value}; Domain=${options.domain}; Path=${options.path ?? '/'}`;
178
-
179
- if (options.expires !== null && options.expires !== undefined) {
180
- cookieStr += `; Expires=${options.expires}`;
181
- }
182
- if (options.httpOnly === true) {
183
- cookieStr += '; HttpOnly';
184
- }
185
- if (options.secure === true) {
186
- cookieStr += '; Secure';
187
- }
188
- if (options.sameSite !== null && options.sameSite !== undefined) {
189
- cookieStr += `; SameSite=${options.sameSite}`;
190
- }
191
-
192
- const protocol = options.secure === true ? 'https' : 'http';
193
- const url = `${protocol}://${options.domain}${options.path ?? '/'}`;
194
-
195
- this.jar.setCookieSync(cookieStr, url);
196
- }
197
-
198
- /**
199
- * Clear all cookies
200
- */
201
- clear(): void {
202
- this.jar.removeAllCookiesSync();
203
- }
204
-
205
- /**
206
- * Get all cookies as an object
207
- * Returns non-expired cookies from ALL domains
208
- * @returns Object with cookie names as keys and values
209
- */
210
- toObject(): Record<string, string> {
211
- const result: Record<string, string> = {};
212
-
213
- // Use toJSON to get all cookies, filter expired manually
214
- const allCookiesJson = this.jar.toJSON();
215
- if (allCookiesJson?.cookies === undefined) {
216
- return result;
217
- }
218
-
219
- // Add all non-expired cookies
220
- for (const cookieData of allCookiesJson.cookies) {
221
- try {
222
- const cookie = Cookie.fromJSON(cookieData);
223
- if (cookie === null || cookie === undefined) {
224
- continue;
225
- }
226
-
227
- const expiryTime = cookie.expiryTime();
228
- // Not expired if: no expiry time OR expiry time is in the future
229
- const isExpired = expiryTime !== null && expiryTime !== undefined && expiryTime < Date.now();
230
- if (!isExpired) {
231
- result[cookie.key] = cookie.value;
232
- }
233
- } catch {
234
- // Skip cookies that can't be parsed
235
- }
236
- }
237
-
238
- return result;
239
- }
240
-
241
- /**
242
- * Get Cookie header string for a URL
243
- * This is the main method used by HTTP plugin to send cookies with requests
244
- * @param url - URL to get cookies for
245
- * @returns Cookie header string in "name1=value1; name2=value2" format, or null if no cookies
246
- */
247
- getCookieHeader(url: string): string | null {
248
- try {
249
- const cookieString = this.jar.getCookieStringSync(url);
250
- if (cookieString === null || cookieString === undefined || cookieString === '') {
251
- return null;
252
- }
253
- return cookieString;
254
- } catch {
255
- return null;
256
- }
257
- }
258
- }
1
+ import { CookieJar as ToughCookieJar, Cookie } from 'tough-cookie';
2
+ import type { ICookieJar, CookieJarOptions, Cookie as ICookie, CookieSetOptions } from '@apiquest/types';
3
+
4
+ /**
5
+ * CookieJar implementation using tough-cookie for production-quality cookie management.
6
+ * Wraps tough-cookie's CookieJar to provide ICookieJar interface.
7
+ */
8
+ export class CookieJar implements ICookieJar {
9
+ private jar: ToughCookieJar;
10
+ private options: CookieJarOptions;
11
+
12
+ constructor(options?: CookieJarOptions) {
13
+ this.options = options ?? { persist: false };
14
+ this.jar = new ToughCookieJar();
15
+ }
16
+
17
+ /**
18
+ * Store cookies from Set-Cookie headers
19
+ * @param setCookieHeaders - Single header string or array of header strings
20
+ * @param requestUrl - URL the cookies came from (REQUIRED for domain/path matching)
21
+ */
22
+ store(setCookieHeaders: string | string[] | null | undefined, requestUrl: string): void {
23
+ if (setCookieHeaders === null || setCookieHeaders === undefined) {
24
+ return;
25
+ }
26
+
27
+ const headers = Array.isArray(setCookieHeaders) ? setCookieHeaders : [setCookieHeaders];
28
+
29
+ for (const header of headers) {
30
+ try {
31
+ this.jar.setCookieSync(header, requestUrl);
32
+ } catch (error) {
33
+ // Ignore invalid cookies (tough-cookie throws on malformed cookies)
34
+ // Silent failure is fine here
35
+ }
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Get cookie value by name
41
+ * When called without domain, searches ALL cookies (across all domains)
42
+ *
43
+ * @param name - Cookie name
44
+ * @param domain - Optional domain to filter (not commonly used)
45
+ * @param path - Optional path to filter (not commonly used)
46
+ * @returns Cookie value or null if not found
47
+ */
48
+ get(name: string, domain?: string, path?: string): string | null {
49
+ // Use toJSON to get ALL cookies, then manually filter for expiration only
50
+ const allCookiesJson = this.jar.toJSON();
51
+ if (allCookiesJson?.cookies === undefined) {
52
+ return null;
53
+ }
54
+
55
+ // Search for cookie by name
56
+ for (const cookieData of allCookiesJson.cookies) {
57
+ // Use Cookie.fromJSON for proper typing
58
+ const cookie = Cookie.fromJSON(cookieData);
59
+ if (cookie === null || cookie === undefined) {
60
+ continue;
61
+ }
62
+
63
+ if (cookie.key !== name) {
64
+ continue;
65
+ }
66
+
67
+ // Check expiration
68
+ const expiryTime = cookie.expiryTime();
69
+ if (expiryTime !== null && expiryTime !== undefined && expiryTime < Date.now()) {
70
+ continue; // Skip expired cookies
71
+ }
72
+
73
+ // If domain filter specified, check it
74
+ if (domain !== null && domain !== undefined && domain !== '') {
75
+ if (cookie.domain === null) {
76
+ continue;
77
+ }
78
+ if (cookie.domain !== domain && !cookie.domain.endsWith(domain)) {
79
+ continue;
80
+ }
81
+ }
82
+
83
+ // If path filter specified, check it
84
+ if (path !== null && path !== undefined && path !== '') {
85
+ if (cookie.path === null || cookie.path !== path) {
86
+ continue;
87
+ }
88
+ }
89
+
90
+ return cookie.value;
91
+ }
92
+
93
+ return null;
94
+ }
95
+
96
+ /**
97
+ * Check if cookie exists
98
+ * @param name - Cookie name
99
+ * @param domain - Optional domain filter
100
+ * @param path - Optional path filter
101
+ * @returns true if cookie exists
102
+ */
103
+ has(name: string, domain?: string, path?: string): boolean {
104
+ return this.get(name, domain, path) !== null;
105
+ }
106
+
107
+ /**
108
+ * Remove a cookie by name
109
+ * @param name - Cookie name
110
+ * @param domain - Optional domain
111
+ * @param path - Optional path
112
+ */
113
+ remove(name: string, domain?: string, path?: string): void {
114
+ const allCookiesJson = this.jar.toJSON();
115
+ if (allCookiesJson?.cookies === undefined) {
116
+ return;
117
+ }
118
+
119
+ // Find matching cookies using Cookie.fromJSON for proper typing
120
+ const cookiesToRemove: Cookie[] = [];
121
+ for (const cookieData of allCookiesJson.cookies) {
122
+ const cookie = Cookie.fromJSON(cookieData);
123
+ if (cookie === null || cookie === undefined) {
124
+ continue;
125
+ }
126
+
127
+ if (cookie.key !== name) {
128
+ continue;
129
+ }
130
+
131
+ // Check domain filter
132
+ if (domain !== null && domain !== undefined && domain !== '') {
133
+ if (cookie.domain === null) {
134
+ continue;
135
+ }
136
+ if (cookie.domain !== domain && !cookie.domain.endsWith(domain)) {
137
+ continue;
138
+ }
139
+ }
140
+
141
+ // Check path filter
142
+ if (path !== null && path !== undefined && path !== '') {
143
+ if (cookie.path === null || cookie.path !== path) {
144
+ continue;
145
+ }
146
+ }
147
+
148
+ cookiesToRemove.push(cookie);
149
+ }
150
+
151
+ // Remove each matching cookie
152
+ for (const cookie of cookiesToRemove) {
153
+ // Domain should always be present in cookies from tough-cookie
154
+ const cookieDomain = cookie.domain;
155
+ if (cookieDomain === null || cookieDomain === undefined) {
156
+ continue; // Skip cookies without domain
157
+ }
158
+ const cookiePath = cookie.path ?? '/';
159
+ try {
160
+ this.jar.store.removeCookie(cookieDomain, cookiePath, cookie.key, () => {
161
+ // Callback required by tough-cookie API
162
+ });
163
+ } catch {
164
+ // Ignore errors
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Set a cookie manually
171
+ * Constructs URL from cookie's domain for RFC 6265 validation
172
+ * @param name - Cookie name
173
+ * @param value - Cookie value
174
+ * @param options - Cookie options
175
+ */
176
+ set(name: string, value: string, options: CookieSetOptions): void {
177
+ let cookieStr = `${name}=${value}; Domain=${options.domain}; Path=${options.path ?? '/'}`;
178
+
179
+ if (options.expires !== null && options.expires !== undefined) {
180
+ cookieStr += `; Expires=${options.expires}`;
181
+ }
182
+ if (options.httpOnly === true) {
183
+ cookieStr += '; HttpOnly';
184
+ }
185
+ if (options.secure === true) {
186
+ cookieStr += '; Secure';
187
+ }
188
+ if (options.sameSite !== null && options.sameSite !== undefined) {
189
+ cookieStr += `; SameSite=${options.sameSite}`;
190
+ }
191
+
192
+ const protocol = options.secure === true ? 'https' : 'http';
193
+ const url = `${protocol}://${options.domain}${options.path ?? '/'}`;
194
+
195
+ this.jar.setCookieSync(cookieStr, url);
196
+ }
197
+
198
+ /**
199
+ * Clear all cookies
200
+ */
201
+ clear(): void {
202
+ this.jar.removeAllCookiesSync();
203
+ }
204
+
205
+ /**
206
+ * Get all cookies as an object
207
+ * Returns non-expired cookies from ALL domains
208
+ * @returns Object with cookie names as keys and values
209
+ */
210
+ toObject(): Record<string, string> {
211
+ const result: Record<string, string> = {};
212
+
213
+ // Use toJSON to get all cookies, filter expired manually
214
+ const allCookiesJson = this.jar.toJSON();
215
+ if (allCookiesJson?.cookies === undefined) {
216
+ return result;
217
+ }
218
+
219
+ // Add all non-expired cookies
220
+ for (const cookieData of allCookiesJson.cookies) {
221
+ try {
222
+ const cookie = Cookie.fromJSON(cookieData);
223
+ if (cookie === null || cookie === undefined) {
224
+ continue;
225
+ }
226
+
227
+ const expiryTime = cookie.expiryTime();
228
+ // Not expired if: no expiry time OR expiry time is in the future
229
+ const isExpired = expiryTime !== null && expiryTime !== undefined && expiryTime < Date.now();
230
+ if (!isExpired) {
231
+ result[cookie.key] = cookie.value;
232
+ }
233
+ } catch {
234
+ // Skip cookies that can't be parsed
235
+ }
236
+ }
237
+
238
+ return result;
239
+ }
240
+
241
+ /**
242
+ * Get Cookie header string for a URL
243
+ * This is the main method used by HTTP plugin to send cookies with requests
244
+ * @param url - URL to get cookies for
245
+ * @returns Cookie header string in "name1=value1; name2=value2" format, or null if no cookies
246
+ */
247
+ getCookieHeader(url: string): string | null {
248
+ try {
249
+ const cookieString = this.jar.getCookieStringSync(url);
250
+ if (cookieString === null || cookieString === undefined || cookieString === '') {
251
+ return null;
252
+ }
253
+ return cookieString;
254
+ } catch {
255
+ return null;
256
+ }
257
+ }
258
+ }