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.
- package/dist/browser/browser/cache.d.ts +40 -0
- package/dist/browser/browser/cache.js +199 -0
- package/dist/browser/browser/crypto.d.ts +24 -0
- package/dist/browser/browser/crypto.js +80 -0
- package/dist/browser/browser/index.d.ts +31 -0
- package/dist/browser/browser/index.js +31 -0
- package/dist/browser/browser/recker.d.ts +26 -0
- package/dist/browser/browser/recker.js +61 -0
- package/dist/browser/cache/basic-file-storage.d.ts +12 -0
- package/dist/browser/cache/basic-file-storage.js +50 -0
- package/dist/browser/cache/memory-limits.d.ts +20 -0
- package/dist/browser/cache/memory-limits.js +96 -0
- package/dist/browser/cache/memory-storage.d.ts +132 -0
- package/dist/browser/cache/memory-storage.js +454 -0
- package/dist/browser/cache.d.ts +40 -0
- package/dist/browser/cache.js +199 -0
- package/dist/browser/constants/http-status.d.ts +73 -0
- package/dist/browser/constants/http-status.js +156 -0
- package/dist/browser/cookies/memory-cookie-jar.d.ts +30 -0
- package/dist/browser/cookies/memory-cookie-jar.js +210 -0
- package/dist/browser/core/client.d.ts +118 -0
- package/dist/browser/core/client.js +667 -0
- package/dist/browser/core/errors.d.ts +142 -0
- package/dist/browser/core/errors.js +308 -0
- package/dist/browser/core/index.d.ts +5 -0
- package/dist/browser/core/index.js +5 -0
- package/dist/browser/core/request-promise.d.ts +23 -0
- package/dist/browser/core/request-promise.js +82 -0
- package/dist/browser/core/request.d.ts +20 -0
- package/dist/browser/core/request.js +76 -0
- package/dist/browser/core/response.d.ts +34 -0
- package/dist/browser/core/response.js +178 -0
- package/dist/browser/crypto.d.ts +24 -0
- package/dist/browser/crypto.js +80 -0
- package/dist/browser/index.d.ts +31 -0
- package/dist/browser/index.js +31 -0
- package/dist/browser/plugins/auth/api-key.d.ts +8 -0
- package/dist/browser/plugins/auth/api-key.js +27 -0
- package/dist/browser/plugins/auth/auth0.d.ts +33 -0
- package/dist/browser/plugins/auth/auth0.js +94 -0
- package/dist/browser/plugins/auth/aws-sigv4.d.ts +10 -0
- package/dist/browser/plugins/auth/aws-sigv4.js +88 -0
- package/dist/browser/plugins/auth/azure-ad.d.ts +48 -0
- package/dist/browser/plugins/auth/azure-ad.js +152 -0
- package/dist/browser/plugins/auth/basic.d.ts +7 -0
- package/dist/browser/plugins/auth/basic.js +13 -0
- package/dist/browser/plugins/auth/bearer.d.ts +8 -0
- package/dist/browser/plugins/auth/bearer.js +17 -0
- package/dist/browser/plugins/auth/cognito.d.ts +45 -0
- package/dist/browser/plugins/auth/cognito.js +208 -0
- package/dist/browser/plugins/auth/digest.d.ts +8 -0
- package/dist/browser/plugins/auth/digest.js +100 -0
- package/dist/browser/plugins/auth/firebase.d.ts +32 -0
- package/dist/browser/plugins/auth/firebase.js +195 -0
- package/dist/browser/plugins/auth/github-app.d.ts +36 -0
- package/dist/browser/plugins/auth/github-app.js +170 -0
- package/dist/browser/plugins/auth/google-service-account.d.ts +49 -0
- package/dist/browser/plugins/auth/google-service-account.js +172 -0
- package/dist/browser/plugins/auth/index.d.ts +15 -0
- package/dist/browser/plugins/auth/index.js +15 -0
- package/dist/browser/plugins/auth/mtls.d.ts +37 -0
- package/dist/browser/plugins/auth/mtls.js +140 -0
- package/dist/browser/plugins/auth/oauth2.d.ts +8 -0
- package/dist/browser/plugins/auth/oauth2.js +26 -0
- package/dist/browser/plugins/auth/oidc.d.ts +55 -0
- package/dist/browser/plugins/auth/oidc.js +222 -0
- package/dist/browser/plugins/auth/okta.d.ts +47 -0
- package/dist/browser/plugins/auth/okta.js +157 -0
- package/dist/browser/plugins/auth.d.ts +1 -0
- package/dist/browser/plugins/auth.js +1 -0
- package/dist/browser/plugins/cache.d.ts +15 -0
- package/dist/browser/plugins/cache.js +486 -0
- package/dist/browser/plugins/circuit-breaker.d.ts +13 -0
- package/dist/browser/plugins/circuit-breaker.js +100 -0
- package/dist/browser/plugins/compression.d.ts +4 -0
- package/dist/browser/plugins/compression.js +130 -0
- package/dist/browser/plugins/cookie-jar.d.ts +5 -0
- package/dist/browser/plugins/cookie-jar.js +72 -0
- package/dist/browser/plugins/dedup.d.ts +5 -0
- package/dist/browser/plugins/dedup.js +35 -0
- package/dist/browser/plugins/graphql.d.ts +13 -0
- package/dist/browser/plugins/graphql.js +58 -0
- package/dist/browser/plugins/grpc-web.d.ts +79 -0
- package/dist/browser/plugins/grpc-web.js +261 -0
- package/dist/browser/plugins/hls.d.ts +105 -0
- package/dist/browser/plugins/hls.js +395 -0
- package/dist/browser/plugins/jsonrpc.d.ts +75 -0
- package/dist/browser/plugins/jsonrpc.js +143 -0
- package/dist/browser/plugins/logger.d.ts +13 -0
- package/dist/browser/plugins/logger.js +108 -0
- package/dist/browser/plugins/odata.d.ts +181 -0
- package/dist/browser/plugins/odata.js +564 -0
- package/dist/browser/plugins/pagination.d.ts +16 -0
- package/dist/browser/plugins/pagination.js +105 -0
- package/dist/browser/plugins/rate-limit.d.ts +15 -0
- package/dist/browser/plugins/rate-limit.js +162 -0
- package/dist/browser/plugins/retry.d.ts +14 -0
- package/dist/browser/plugins/retry.js +116 -0
- package/dist/browser/plugins/scrape.d.ts +21 -0
- package/dist/browser/plugins/scrape.js +82 -0
- package/dist/browser/plugins/server-timing.d.ts +7 -0
- package/dist/browser/plugins/server-timing.js +24 -0
- package/dist/browser/plugins/soap.d.ts +72 -0
- package/dist/browser/plugins/soap.js +347 -0
- package/dist/browser/plugins/xml.d.ts +9 -0
- package/dist/browser/plugins/xml.js +194 -0
- package/dist/browser/plugins/xsrf.d.ts +9 -0
- package/dist/browser/plugins/xsrf.js +48 -0
- package/dist/browser/recker.d.ts +26 -0
- package/dist/browser/recker.js +61 -0
- package/dist/browser/runner/request-runner.d.ts +46 -0
- package/dist/browser/runner/request-runner.js +89 -0
- package/dist/browser/scrape/document.d.ts +44 -0
- package/dist/browser/scrape/document.js +210 -0
- package/dist/browser/scrape/element.d.ts +49 -0
- package/dist/browser/scrape/element.js +176 -0
- package/dist/browser/scrape/extractors.d.ts +16 -0
- package/dist/browser/scrape/extractors.js +356 -0
- package/dist/browser/scrape/types.d.ts +107 -0
- package/dist/browser/scrape/types.js +1 -0
- package/dist/browser/transport/fetch.d.ts +11 -0
- package/dist/browser/transport/fetch.js +143 -0
- package/dist/browser/transport/undici.d.ts +38 -0
- package/dist/browser/transport/undici.js +897 -0
- package/dist/browser/types/ai.d.ts +267 -0
- package/dist/browser/types/ai.js +1 -0
- package/dist/browser/types/index.d.ts +351 -0
- package/dist/browser/types/index.js +1 -0
- package/dist/browser/types/logger.d.ts +16 -0
- package/dist/browser/types/logger.js +66 -0
- package/dist/browser/types/udp.d.ts +138 -0
- package/dist/browser/types/udp.js +1 -0
- package/dist/browser/utils/agent-manager.d.ts +29 -0
- package/dist/browser/utils/agent-manager.js +160 -0
- package/dist/browser/utils/body.d.ts +10 -0
- package/dist/browser/utils/body.js +148 -0
- package/dist/browser/utils/charset.d.ts +15 -0
- package/dist/browser/utils/charset.js +169 -0
- package/dist/browser/utils/concurrency.d.ts +20 -0
- package/dist/browser/utils/concurrency.js +120 -0
- package/dist/browser/utils/dns.d.ts +6 -0
- package/dist/browser/utils/dns.js +26 -0
- package/dist/browser/utils/header-parser.d.ts +94 -0
- package/dist/browser/utils/header-parser.js +617 -0
- package/dist/browser/utils/html-cleaner.d.ts +1 -0
- package/dist/browser/utils/html-cleaner.js +21 -0
- package/dist/browser/utils/link-header.d.ts +69 -0
- package/dist/browser/utils/link-header.js +190 -0
- package/dist/browser/utils/optional-require.d.ts +19 -0
- package/dist/browser/utils/optional-require.js +105 -0
- package/dist/browser/utils/progress.d.ts +8 -0
- package/dist/browser/utils/progress.js +82 -0
- package/dist/browser/utils/request-pool.d.ts +22 -0
- package/dist/browser/utils/request-pool.js +101 -0
- package/dist/browser/utils/sse.d.ts +7 -0
- package/dist/browser/utils/sse.js +67 -0
- package/dist/browser/utils/streaming.d.ts +17 -0
- package/dist/browser/utils/streaming.js +84 -0
- package/dist/browser/utils/try-fn.d.ts +3 -0
- package/dist/browser/utils/try-fn.js +59 -0
- package/dist/browser/utils/user-agent.d.ts +44 -0
- package/dist/browser/utils/user-agent.js +100 -0
- package/dist/browser/utils/whois.d.ts +32 -0
- package/dist/browser/utils/whois.js +246 -0
- package/dist/browser/websocket/client.d.ts +65 -0
- package/dist/browser/websocket/client.js +313 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +1 -0
- package/dist/transport/fetch.d.ts +7 -1
- package/dist/transport/fetch.js +58 -76
- package/package.json +34 -2
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
function jsToXmlRpcValue(value) {
|
|
2
|
+
if (value === null || value === undefined) {
|
|
3
|
+
return '<nil/>';
|
|
4
|
+
}
|
|
5
|
+
if (typeof value === 'boolean') {
|
|
6
|
+
return `<boolean>${value ? '1' : '0'}</boolean>`;
|
|
7
|
+
}
|
|
8
|
+
if (typeof value === 'number') {
|
|
9
|
+
if (Number.isInteger(value)) {
|
|
10
|
+
return `<int>${value}</int>`;
|
|
11
|
+
}
|
|
12
|
+
return `<double>${value}</double>`;
|
|
13
|
+
}
|
|
14
|
+
if (typeof value === 'string') {
|
|
15
|
+
return `<string>${escapeXml(value)}</string>`;
|
|
16
|
+
}
|
|
17
|
+
if (value instanceof Date) {
|
|
18
|
+
return `<dateTime.iso8601>${value.toISOString()}</dateTime.iso8601>`;
|
|
19
|
+
}
|
|
20
|
+
if (value instanceof Uint8Array || Buffer.isBuffer(value)) {
|
|
21
|
+
const base64 = Buffer.from(value).toString('base64');
|
|
22
|
+
return `<base64>${base64}</base64>`;
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
const items = value.map((item) => `<value>${jsToXmlRpcValue(item)}</value>`).join('');
|
|
26
|
+
return `<array><data>${items}</data></array>`;
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === 'object') {
|
|
29
|
+
const members = Object.entries(value)
|
|
30
|
+
.map(([name, val]) => `<member><name>${escapeXml(name)}</name><value>${jsToXmlRpcValue(val)}</value></member>`)
|
|
31
|
+
.join('');
|
|
32
|
+
return `<struct>${members}</struct>`;
|
|
33
|
+
}
|
|
34
|
+
return `<string>${String(value)}</string>`;
|
|
35
|
+
}
|
|
36
|
+
function parseXmlRpcValue(xml) {
|
|
37
|
+
const trimmed = xml.trim();
|
|
38
|
+
if (trimmed.includes('<nil/>') || trimmed.includes('<nil></nil>')) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (trimmed.startsWith('<array>') || trimmed.includes('<array>')) {
|
|
42
|
+
const dataMatch = trimmed.match(/<array>\s*<data>([\s\S]*)<\/data>\s*<\/array>/);
|
|
43
|
+
if (dataMatch) {
|
|
44
|
+
const values = [];
|
|
45
|
+
const dataContent = dataMatch[1];
|
|
46
|
+
const valueParts = dataContent.split(/<\/value>/);
|
|
47
|
+
for (const part of valueParts) {
|
|
48
|
+
const valueStart = part.indexOf('<value>');
|
|
49
|
+
if (valueStart !== -1) {
|
|
50
|
+
const content = part.slice(valueStart + 7);
|
|
51
|
+
values.push(parseXmlRpcValue(content.trim()));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return values;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (trimmed.startsWith('<struct>') || trimmed.includes('<struct>')) {
|
|
58
|
+
const structContent = trimmed.match(/<struct>([\s\S]*)<\/struct>/);
|
|
59
|
+
if (structContent) {
|
|
60
|
+
const obj = {};
|
|
61
|
+
const memberParts = structContent[1].split(/<\/member>/);
|
|
62
|
+
for (const part of memberParts) {
|
|
63
|
+
const memberStart = part.indexOf('<member>');
|
|
64
|
+
if (memberStart !== -1) {
|
|
65
|
+
const memberContent = part.slice(memberStart + 8);
|
|
66
|
+
const nameMatch = memberContent.match(/<name>([\s\S]*?)<\/name>/);
|
|
67
|
+
const valueMatch = memberContent.match(/<value>([\s\S]*)<\/value>/s);
|
|
68
|
+
if (nameMatch && valueMatch) {
|
|
69
|
+
obj[unescapeXml(nameMatch[1].trim())] = parseXmlRpcValue(valueMatch[1].trim());
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return obj;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const intMatch = trimmed.match(/^<(?:int|i4|i8)>(-?\d+)<\/(?:int|i4|i8)>$/);
|
|
77
|
+
if (intMatch) {
|
|
78
|
+
return parseInt(intMatch[1], 10);
|
|
79
|
+
}
|
|
80
|
+
const boolMatch = trimmed.match(/^<boolean>([01])<\/boolean>$/);
|
|
81
|
+
if (boolMatch) {
|
|
82
|
+
return boolMatch[1] === '1';
|
|
83
|
+
}
|
|
84
|
+
const doubleMatch = trimmed.match(/^<double>(-?[\d.]+(?:[eE][+-]?\d+)?)<\/double>$/);
|
|
85
|
+
if (doubleMatch) {
|
|
86
|
+
return parseFloat(doubleMatch[1]);
|
|
87
|
+
}
|
|
88
|
+
const stringMatch = trimmed.match(/^<string>([\s\S]*?)<\/string>$/);
|
|
89
|
+
if (stringMatch) {
|
|
90
|
+
return unescapeXml(stringMatch[1]);
|
|
91
|
+
}
|
|
92
|
+
const dateMatch = trimmed.match(/^<dateTime\.iso8601>([\s\S]*?)<\/dateTime\.iso8601>$/);
|
|
93
|
+
if (dateMatch) {
|
|
94
|
+
return new Date(dateMatch[1]);
|
|
95
|
+
}
|
|
96
|
+
const base64Match = trimmed.match(/^<base64>([\s\S]*?)<\/base64>$/);
|
|
97
|
+
if (base64Match) {
|
|
98
|
+
return Buffer.from(base64Match[1], 'base64');
|
|
99
|
+
}
|
|
100
|
+
return trimmed;
|
|
101
|
+
}
|
|
102
|
+
export class XmlRpcClient {
|
|
103
|
+
client;
|
|
104
|
+
endpoint;
|
|
105
|
+
requestOptions;
|
|
106
|
+
constructor(client, options) {
|
|
107
|
+
this.client = client;
|
|
108
|
+
this.endpoint = options.endpoint;
|
|
109
|
+
this.requestOptions = options.requestOptions ?? {};
|
|
110
|
+
}
|
|
111
|
+
async call(method, params = []) {
|
|
112
|
+
const paramsXml = params.map((p) => `<param><value>${jsToXmlRpcValue(p)}</value></param>`).join('');
|
|
113
|
+
const xml = `<?xml version="1.0"?>
|
|
114
|
+
<methodCall>
|
|
115
|
+
<methodName>${escapeXml(method)}</methodName>
|
|
116
|
+
<params>${paramsXml}</params>
|
|
117
|
+
</methodCall>`;
|
|
118
|
+
const response = await this.client.post(this.endpoint, xml, {
|
|
119
|
+
...this.requestOptions,
|
|
120
|
+
headers: {
|
|
121
|
+
'Content-Type': 'text/xml',
|
|
122
|
+
...this.requestOptions.headers,
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
const responseXml = await response.text();
|
|
126
|
+
return this.parseResponse(responseXml);
|
|
127
|
+
}
|
|
128
|
+
parseResponse(xml) {
|
|
129
|
+
const faultMatch = xml.match(/<fault>\s*<value>([\s\S]+)<\/value>\s*<\/fault>/);
|
|
130
|
+
if (faultMatch) {
|
|
131
|
+
const fault = parseXmlRpcValue(faultMatch[1]);
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
fault: {
|
|
135
|
+
faultCode: fault.faultCode ?? 0,
|
|
136
|
+
faultString: fault.faultString ?? 'Unknown error',
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const paramsMatch = xml.match(/<params>\s*<param>\s*<value>([\s\S]+)<\/value>\s*<\/param>\s*<\/params>/);
|
|
141
|
+
if (paramsMatch) {
|
|
142
|
+
return {
|
|
143
|
+
success: true,
|
|
144
|
+
result: parseXmlRpcValue(paramsMatch[1]),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return { success: true };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const SOAP_NAMESPACES = {
|
|
151
|
+
'1.1': {
|
|
152
|
+
envelope: 'http://schemas.xmlsoap.org/soap/envelope/',
|
|
153
|
+
contentType: 'text/xml; charset=utf-8',
|
|
154
|
+
},
|
|
155
|
+
'1.2': {
|
|
156
|
+
envelope: 'http://www.w3.org/2003/05/soap-envelope',
|
|
157
|
+
contentType: 'application/soap+xml; charset=utf-8',
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
export class SoapClient {
|
|
161
|
+
client;
|
|
162
|
+
options;
|
|
163
|
+
constructor(client, options) {
|
|
164
|
+
this.client = client;
|
|
165
|
+
this.options = {
|
|
166
|
+
endpoint: options.endpoint,
|
|
167
|
+
version: options.version ?? '1.2',
|
|
168
|
+
namespace: options.namespace ?? '',
|
|
169
|
+
namespacePrefix: options.namespacePrefix ?? 'ns',
|
|
170
|
+
wsdl: options.wsdl,
|
|
171
|
+
soapHeaders: options.soapHeaders ?? {},
|
|
172
|
+
requestOptions: options.requestOptions ?? {},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async call(method, params = {}, options) {
|
|
176
|
+
const soapNs = SOAP_NAMESPACES[this.options.version];
|
|
177
|
+
const prefix = this.options.namespacePrefix;
|
|
178
|
+
const ns = this.options.namespace;
|
|
179
|
+
const soapHeaders = { ...this.options.soapHeaders, ...options?.soapHeaders };
|
|
180
|
+
let soapHeaderXml = '';
|
|
181
|
+
if (Object.keys(soapHeaders).length > 0) {
|
|
182
|
+
const headerContent = this.objectToXml(soapHeaders, prefix);
|
|
183
|
+
soapHeaderXml = `<soap:Header>${headerContent}</soap:Header>`;
|
|
184
|
+
}
|
|
185
|
+
const paramsXml = this.objectToXml(params, prefix);
|
|
186
|
+
const methodXml = ns
|
|
187
|
+
? `<${prefix}:${method} xmlns:${prefix}="${ns}">${paramsXml}</${prefix}:${method}>`
|
|
188
|
+
: `<${method}>${paramsXml}</${method}>`;
|
|
189
|
+
const envelope = `<?xml version="1.0" encoding="utf-8"?>
|
|
190
|
+
<soap:Envelope xmlns:soap="${soapNs.envelope}">
|
|
191
|
+
${soapHeaderXml}
|
|
192
|
+
<soap:Body>
|
|
193
|
+
${methodXml}
|
|
194
|
+
</soap:Body>
|
|
195
|
+
</soap:Envelope>`;
|
|
196
|
+
const headers = {
|
|
197
|
+
'Content-Type': soapNs.contentType,
|
|
198
|
+
};
|
|
199
|
+
if (this.options.version === '1.1') {
|
|
200
|
+
const action = options?.soapAction ?? `${ns}/${method}`;
|
|
201
|
+
headers['SOAPAction'] = `"${action}"`;
|
|
202
|
+
}
|
|
203
|
+
const response = await this.client.post(this.options.endpoint, envelope, {
|
|
204
|
+
...this.options.requestOptions,
|
|
205
|
+
headers: {
|
|
206
|
+
...headers,
|
|
207
|
+
...this.options.requestOptions.headers,
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
const responseXml = await response.text();
|
|
211
|
+
return this.parseResponse(responseXml, method);
|
|
212
|
+
}
|
|
213
|
+
async getWsdl() {
|
|
214
|
+
if (!this.options.wsdl)
|
|
215
|
+
return null;
|
|
216
|
+
const response = await this.client.get(this.options.wsdl);
|
|
217
|
+
return response.text();
|
|
218
|
+
}
|
|
219
|
+
objectToXml(obj, prefix) {
|
|
220
|
+
return Object.entries(obj)
|
|
221
|
+
.map(([key, value]) => {
|
|
222
|
+
const tagName = prefix ? `${prefix}:${key}` : key;
|
|
223
|
+
if (value === null || value === undefined) {
|
|
224
|
+
return `<${tagName} xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>`;
|
|
225
|
+
}
|
|
226
|
+
if (typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {
|
|
227
|
+
return `<${tagName}>${this.objectToXml(value)}</${tagName}>`;
|
|
228
|
+
}
|
|
229
|
+
if (Array.isArray(value)) {
|
|
230
|
+
return value.map((item) => {
|
|
231
|
+
if (typeof item === 'object') {
|
|
232
|
+
return `<${tagName}>${this.objectToXml(item)}</${tagName}>`;
|
|
233
|
+
}
|
|
234
|
+
return `<${tagName}>${escapeXml(String(item))}</${tagName}>`;
|
|
235
|
+
}).join('');
|
|
236
|
+
}
|
|
237
|
+
if (value instanceof Date) {
|
|
238
|
+
return `<${tagName}>${value.toISOString()}</${tagName}>`;
|
|
239
|
+
}
|
|
240
|
+
return `<${tagName}>${escapeXml(String(value))}</${tagName}>`;
|
|
241
|
+
})
|
|
242
|
+
.join('');
|
|
243
|
+
}
|
|
244
|
+
parseResponse(xml, method) {
|
|
245
|
+
const faultMatch = xml.match(/<(?:soap:|SOAP-ENV:|)[Ff]ault[^>]*>([\s\S]*?)<\/(?:soap:|SOAP-ENV:|)[Ff]ault>/i);
|
|
246
|
+
if (faultMatch) {
|
|
247
|
+
const faultXml = faultMatch[1];
|
|
248
|
+
const codeMatch = faultXml.match(/<faultcode[^>]*>([\s\S]*?)<\/faultcode>/i);
|
|
249
|
+
const stringMatch = faultXml.match(/<faultstring[^>]*>([\s\S]*?)<\/faultstring>/i);
|
|
250
|
+
const actorMatch = faultXml.match(/<faultactor[^>]*>([\s\S]*?)<\/faultactor>/i);
|
|
251
|
+
const detailMatch = faultXml.match(/<detail[^>]*>([\s\S]*?)<\/detail>/i);
|
|
252
|
+
const codeMatch12 = faultXml.match(/<(?:\w+:)?Code[^>]*>[\s\S]*?<(?:\w+:)?Value[^>]*>([\s\S]*?)<\/(?:\w+:)?Value>/i);
|
|
253
|
+
const reasonMatch12 = faultXml.match(/<(?:\w+:)?Reason[^>]*>[\s\S]*?<(?:\w+:)?Text[^>]*>([\s\S]*?)<\/(?:\w+:)?Text>/i);
|
|
254
|
+
return {
|
|
255
|
+
success: false,
|
|
256
|
+
fault: {
|
|
257
|
+
code: unescapeXml(codeMatch?.[1] ?? codeMatch12?.[1] ?? 'Unknown'),
|
|
258
|
+
string: unescapeXml(stringMatch?.[1] ?? reasonMatch12?.[1] ?? 'Unknown error'),
|
|
259
|
+
actor: actorMatch ? unescapeXml(actorMatch[1]) : undefined,
|
|
260
|
+
detail: detailMatch ? detailMatch[1] : undefined,
|
|
261
|
+
},
|
|
262
|
+
rawXml: xml,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const bodyMatch = xml.match(/<(?:soap:|SOAP-ENV:|)[Bb]ody[^>]*>([\s\S]*?)<\/(?:soap:|SOAP-ENV:|)[Bb]ody>/i);
|
|
266
|
+
if (!bodyMatch) {
|
|
267
|
+
return {
|
|
268
|
+
success: false,
|
|
269
|
+
fault: { code: 'ParseError', string: 'Could not parse SOAP response body' },
|
|
270
|
+
rawXml: xml,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
const bodyContent = bodyMatch[1].trim();
|
|
274
|
+
const responseRegex = new RegExp(`<(?:\\w+:)?${method}(?:Response|Result)[^>]*>([\\s\\S]*?)<\\/(?:\\w+:)?${method}(?:Response|Result)>`, 'i');
|
|
275
|
+
const responseMatch = bodyContent.match(responseRegex);
|
|
276
|
+
const resultXml = responseMatch ? responseMatch[1] : bodyContent;
|
|
277
|
+
const result = this.parseXmlToObject(resultXml);
|
|
278
|
+
return {
|
|
279
|
+
success: true,
|
|
280
|
+
result: result,
|
|
281
|
+
rawXml: xml,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
parseXmlToObject(xml) {
|
|
285
|
+
const trimmed = xml.trim();
|
|
286
|
+
if (!trimmed.startsWith('<')) {
|
|
287
|
+
return unescapeXml(trimmed);
|
|
288
|
+
}
|
|
289
|
+
const obj = {};
|
|
290
|
+
const elementRegex = /<([^\/][^>\s]*)[^>]*>([\s\S]*?)<\/\1>/g;
|
|
291
|
+
let match;
|
|
292
|
+
let hasElements = false;
|
|
293
|
+
while ((match = elementRegex.exec(trimmed)) !== null) {
|
|
294
|
+
hasElements = true;
|
|
295
|
+
const [, tagName, content] = match;
|
|
296
|
+
const key = tagName.includes(':') ? tagName.split(':')[1] : tagName;
|
|
297
|
+
const value = this.parseXmlToObject(content);
|
|
298
|
+
if (key in obj) {
|
|
299
|
+
if (Array.isArray(obj[key])) {
|
|
300
|
+
obj[key].push(value);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
obj[key] = [obj[key], value];
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
obj[key] = value;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (!hasElements) {
|
|
311
|
+
return unescapeXml(trimmed);
|
|
312
|
+
}
|
|
313
|
+
return obj;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function escapeXml(str) {
|
|
317
|
+
return str
|
|
318
|
+
.replace(/&/g, '&')
|
|
319
|
+
.replace(/</g, '<')
|
|
320
|
+
.replace(/>/g, '>')
|
|
321
|
+
.replace(/"/g, '"')
|
|
322
|
+
.replace(/'/g, ''');
|
|
323
|
+
}
|
|
324
|
+
function unescapeXml(str) {
|
|
325
|
+
return str
|
|
326
|
+
.replace(/'/g, "'")
|
|
327
|
+
.replace(/"/g, '"')
|
|
328
|
+
.replace(/>/g, '>')
|
|
329
|
+
.replace(/</g, '<')
|
|
330
|
+
.replace(/&/g, '&');
|
|
331
|
+
}
|
|
332
|
+
export function createXmlRpcClient(client, options) {
|
|
333
|
+
return new XmlRpcClient(client, options);
|
|
334
|
+
}
|
|
335
|
+
export function createSoapClient(client, options) {
|
|
336
|
+
return new SoapClient(client, options);
|
|
337
|
+
}
|
|
338
|
+
export function soap() {
|
|
339
|
+
return (client) => {
|
|
340
|
+
client.soap = (options) => {
|
|
341
|
+
return createSoapClient(client, options);
|
|
342
|
+
};
|
|
343
|
+
client.xmlrpc = (endpoint, requestOptions) => {
|
|
344
|
+
return createXmlRpcClient(client, { endpoint, requestOptions });
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReckerResponse } from '../types/index.js';
|
|
2
|
+
export interface XMLPluginOptions {
|
|
3
|
+
parser?: (xml: string) => any;
|
|
4
|
+
serializer?: (obj: any) => string;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseXML(xml: string): any;
|
|
7
|
+
export declare function serializeXML(obj: any, rootName?: string): string;
|
|
8
|
+
export declare function xmlResponse<T = any>(promise: Promise<ReckerResponse>, parser?: (xml: string) => any): Promise<T>;
|
|
9
|
+
export { parseXML as parse, serializeXML as serialize };
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
export function parseXML(xml) {
|
|
2
|
+
const cleanXml = xml
|
|
3
|
+
.replace(/<\?xml[^?]*\?>/gi, '')
|
|
4
|
+
.replace(/<!--[\s\S]*?-->/g, '')
|
|
5
|
+
.trim();
|
|
6
|
+
return parseElement(cleanXml);
|
|
7
|
+
}
|
|
8
|
+
function parseElement(xml) {
|
|
9
|
+
const rootMatch = xml.match(/^<(\w+)([^>]*)>([\s\S]*)<\/\1>$/);
|
|
10
|
+
if (!rootMatch) {
|
|
11
|
+
const selfClosingMatch = xml.match(/^<(\w+)([^/>]*)\/>$/);
|
|
12
|
+
if (selfClosingMatch) {
|
|
13
|
+
const [, tagName, attrs] = selfClosingMatch;
|
|
14
|
+
const attributes = parseAttributes(attrs);
|
|
15
|
+
return Object.keys(attributes).length > 0 ? { [tagName]: attributes } : { [tagName]: null };
|
|
16
|
+
}
|
|
17
|
+
return decodeXMLEntities(xml.trim());
|
|
18
|
+
}
|
|
19
|
+
const [, tagName, attrs, content] = rootMatch;
|
|
20
|
+
const attributes = parseAttributes(attrs);
|
|
21
|
+
const children = parseChildren(content);
|
|
22
|
+
const result = {};
|
|
23
|
+
if (Object.keys(attributes).length > 0) {
|
|
24
|
+
result['@attributes'] = attributes;
|
|
25
|
+
}
|
|
26
|
+
if (typeof children === 'string') {
|
|
27
|
+
if (Object.keys(attributes).length > 0) {
|
|
28
|
+
result['#text'] = children;
|
|
29
|
+
return { [tagName]: result };
|
|
30
|
+
}
|
|
31
|
+
return { [tagName]: children };
|
|
32
|
+
}
|
|
33
|
+
if (Array.isArray(children)) {
|
|
34
|
+
for (const child of children) {
|
|
35
|
+
for (const [key, value] of Object.entries(child)) {
|
|
36
|
+
if (result[key] !== undefined) {
|
|
37
|
+
if (!Array.isArray(result[key])) {
|
|
38
|
+
result[key] = [result[key]];
|
|
39
|
+
}
|
|
40
|
+
result[key].push(value);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
result[key] = value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return { [tagName]: Object.keys(result).length > 0 ? result : null };
|
|
49
|
+
}
|
|
50
|
+
function parseAttributes(attrs) {
|
|
51
|
+
const result = {};
|
|
52
|
+
const attrRegex = /(\w+)=["']([^"']*)["']/g;
|
|
53
|
+
let match;
|
|
54
|
+
while ((match = attrRegex.exec(attrs)) !== null) {
|
|
55
|
+
result[match[1]] = decodeXMLEntities(match[2]);
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
function parseChildren(content) {
|
|
60
|
+
const trimmed = content.trim();
|
|
61
|
+
if (!trimmed)
|
|
62
|
+
return '';
|
|
63
|
+
if (!trimmed.startsWith('<')) {
|
|
64
|
+
return decodeXMLEntities(trimmed);
|
|
65
|
+
}
|
|
66
|
+
const children = [];
|
|
67
|
+
let remaining = trimmed;
|
|
68
|
+
while (remaining.length > 0) {
|
|
69
|
+
remaining = remaining.trim();
|
|
70
|
+
if (!remaining)
|
|
71
|
+
break;
|
|
72
|
+
const tagMatch = remaining.match(/^<(\w+)([^>]*)>/);
|
|
73
|
+
if (!tagMatch) {
|
|
74
|
+
const textEnd = remaining.indexOf('<');
|
|
75
|
+
if (textEnd > 0) {
|
|
76
|
+
const text = remaining.substring(0, textEnd).trim();
|
|
77
|
+
if (text) {
|
|
78
|
+
children.push({ '#text': decodeXMLEntities(text) });
|
|
79
|
+
}
|
|
80
|
+
remaining = remaining.substring(textEnd);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
const [fullMatch, tagName, attrs] = tagMatch;
|
|
86
|
+
if (attrs.endsWith('/') || remaining.substring(fullMatch.length - 1, fullMatch.length + 1) === '/>') {
|
|
87
|
+
const selfMatch = remaining.match(/^<(\w+)([^/>]*)\/?>/);
|
|
88
|
+
if (selfMatch) {
|
|
89
|
+
const selfAttrs = parseAttributes(selfMatch[2]);
|
|
90
|
+
children.push({ [tagName]: Object.keys(selfAttrs).length > 0 ? { '@attributes': selfAttrs } : null });
|
|
91
|
+
remaining = remaining.substring(selfMatch[0].length);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const closingTag = `</${tagName}>`;
|
|
96
|
+
let depth = 1;
|
|
97
|
+
let pos = fullMatch.length;
|
|
98
|
+
while (depth > 0 && pos < remaining.length) {
|
|
99
|
+
const nextOpen = remaining.indexOf(`<${tagName}`, pos);
|
|
100
|
+
const nextClose = remaining.indexOf(closingTag, pos);
|
|
101
|
+
if (nextClose === -1)
|
|
102
|
+
break;
|
|
103
|
+
if (nextOpen !== -1 && nextOpen < nextClose) {
|
|
104
|
+
const afterOpen = remaining.substring(nextOpen);
|
|
105
|
+
const selfCloseMatch = afterOpen.match(/^<\w+[^>]*\/>/);
|
|
106
|
+
if (!selfCloseMatch) {
|
|
107
|
+
depth++;
|
|
108
|
+
}
|
|
109
|
+
pos = nextOpen + 1;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
depth--;
|
|
113
|
+
if (depth === 0) {
|
|
114
|
+
const elementXml = remaining.substring(0, nextClose + closingTag.length);
|
|
115
|
+
children.push(parseElement(elementXml));
|
|
116
|
+
remaining = remaining.substring(nextClose + closingTag.length);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
pos = nextClose + 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (depth > 0) {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return children;
|
|
128
|
+
}
|
|
129
|
+
function decodeXMLEntities(str) {
|
|
130
|
+
return str
|
|
131
|
+
.replace(/</g, '<')
|
|
132
|
+
.replace(/>/g, '>')
|
|
133
|
+
.replace(/&/g, '&')
|
|
134
|
+
.replace(/"/g, '"')
|
|
135
|
+
.replace(/'/g, "'")
|
|
136
|
+
.replace(/&#(\d+);/g, (_, code) => String.fromCharCode(parseInt(code, 10)))
|
|
137
|
+
.replace(/&#x([0-9a-fA-F]+);/g, (_, code) => String.fromCharCode(parseInt(code, 16)));
|
|
138
|
+
}
|
|
139
|
+
export function serializeXML(obj, rootName) {
|
|
140
|
+
if (obj === null || obj === undefined) {
|
|
141
|
+
return rootName ? `<${rootName}/>` : '';
|
|
142
|
+
}
|
|
143
|
+
if (typeof obj !== 'object') {
|
|
144
|
+
return rootName ? `<${rootName}>${encodeXMLEntities(String(obj))}</${rootName}>` : encodeXMLEntities(String(obj));
|
|
145
|
+
}
|
|
146
|
+
const keys = Object.keys(obj);
|
|
147
|
+
if (keys.length === 1 && !rootName) {
|
|
148
|
+
const key = keys[0];
|
|
149
|
+
return serializeXML(obj[key], key);
|
|
150
|
+
}
|
|
151
|
+
let xml = '';
|
|
152
|
+
let attributes = '';
|
|
153
|
+
let textContent = '';
|
|
154
|
+
for (const key of keys) {
|
|
155
|
+
const value = obj[key];
|
|
156
|
+
if (key === '@attributes') {
|
|
157
|
+
for (const [attrName, attrValue] of Object.entries(value)) {
|
|
158
|
+
attributes += ` ${attrName}="${encodeXMLEntities(String(attrValue))}"`;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (key === '#text') {
|
|
162
|
+
textContent = encodeXMLEntities(String(value));
|
|
163
|
+
}
|
|
164
|
+
else if (Array.isArray(value)) {
|
|
165
|
+
for (const item of value) {
|
|
166
|
+
xml += serializeXML(item, key);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
xml += serializeXML(value, key);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (rootName) {
|
|
174
|
+
if (xml || textContent) {
|
|
175
|
+
return `<${rootName}${attributes}>${textContent}${xml}</${rootName}>`;
|
|
176
|
+
}
|
|
177
|
+
return `<${rootName}${attributes}/>`;
|
|
178
|
+
}
|
|
179
|
+
return xml;
|
|
180
|
+
}
|
|
181
|
+
function encodeXMLEntities(str) {
|
|
182
|
+
return str
|
|
183
|
+
.replace(/&/g, '&')
|
|
184
|
+
.replace(/</g, '<')
|
|
185
|
+
.replace(/>/g, '>')
|
|
186
|
+
.replace(/"/g, '"')
|
|
187
|
+
.replace(/'/g, ''');
|
|
188
|
+
}
|
|
189
|
+
export async function xmlResponse(promise, parser = parseXML) {
|
|
190
|
+
const response = await promise;
|
|
191
|
+
const text = await response.text();
|
|
192
|
+
return parser(text);
|
|
193
|
+
}
|
|
194
|
+
export { parseXML as parse, serializeXML as serialize };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Middleware } from '../types/index.js';
|
|
2
|
+
export interface XSRFPluginOptions {
|
|
3
|
+
cookieName?: string;
|
|
4
|
+
headerName?: string;
|
|
5
|
+
token?: string;
|
|
6
|
+
cookies?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function xsrfPlugin(options?: XSRFPluginOptions): Middleware;
|
|
9
|
+
export declare function createXSRFMiddleware(config: boolean | XSRFPluginOptions): Middleware | null;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function parseCookies(cookieString) {
|
|
2
|
+
const cookies = {};
|
|
3
|
+
if (!cookieString) {
|
|
4
|
+
return cookies;
|
|
5
|
+
}
|
|
6
|
+
const pairs = cookieString.split(';');
|
|
7
|
+
for (const pair of pairs) {
|
|
8
|
+
const [key, ...valueParts] = pair.split('=');
|
|
9
|
+
const trimmedKey = key?.trim();
|
|
10
|
+
const value = valueParts.join('=').trim();
|
|
11
|
+
if (trimmedKey) {
|
|
12
|
+
cookies[trimmedKey] = decodeURIComponent(value || '');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return cookies;
|
|
16
|
+
}
|
|
17
|
+
function getXSRFToken(cookieName, cookies) {
|
|
18
|
+
if (cookies) {
|
|
19
|
+
const parsed = parseCookies(cookies);
|
|
20
|
+
return parsed[cookieName] || null;
|
|
21
|
+
}
|
|
22
|
+
if (typeof document !== 'undefined' && document.cookie) {
|
|
23
|
+
const parsed = parseCookies(document.cookie);
|
|
24
|
+
return parsed[cookieName] || null;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
export function xsrfPlugin(options = {}) {
|
|
29
|
+
const { cookieName = 'XSRF-TOKEN', headerName = 'X-XSRF-TOKEN', token: manualToken, cookies } = options;
|
|
30
|
+
return async (req, next) => {
|
|
31
|
+
const token = manualToken || getXSRFToken(cookieName, cookies);
|
|
32
|
+
if (token) {
|
|
33
|
+
if (!req.headers.has(headerName)) {
|
|
34
|
+
req.headers.set(headerName, token);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return next(req);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function createXSRFMiddleware(config) {
|
|
41
|
+
if (!config) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
if (config === true) {
|
|
45
|
+
return xsrfPlugin();
|
|
46
|
+
}
|
|
47
|
+
return xsrfPlugin(config);
|
|
48
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Client, type ExtendedClientOptions } from '../core/client.js';
|
|
2
|
+
import { type RequestPromise } from '../core/request-promise.js';
|
|
3
|
+
import type { RequestOptions } from '../types/index.js';
|
|
4
|
+
export declare function get(url: string, options?: RequestOptions): RequestPromise;
|
|
5
|
+
export declare function post(url: string, options?: RequestOptions): RequestPromise;
|
|
6
|
+
export declare function put(url: string, options?: RequestOptions): RequestPromise;
|
|
7
|
+
export declare function patch(url: string, options?: RequestOptions): RequestPromise;
|
|
8
|
+
export declare function del(url: string, options?: RequestOptions): RequestPromise;
|
|
9
|
+
export declare function head(url: string, options?: RequestOptions): RequestPromise;
|
|
10
|
+
export declare function options(url: string, options?: RequestOptions): RequestPromise;
|
|
11
|
+
export declare function ws(url: string, protocols?: string | string[]): WebSocket;
|
|
12
|
+
export declare const recker: {
|
|
13
|
+
get: typeof get;
|
|
14
|
+
post: typeof post;
|
|
15
|
+
put: typeof put;
|
|
16
|
+
patch: typeof patch;
|
|
17
|
+
delete: typeof del;
|
|
18
|
+
head: typeof head;
|
|
19
|
+
options: typeof options;
|
|
20
|
+
ws: typeof ws;
|
|
21
|
+
client: (opts?: ExtendedClientOptions) => Client;
|
|
22
|
+
reset: () => void;
|
|
23
|
+
isBrowser: true;
|
|
24
|
+
unavailable: readonly ["whois", "whoisAvailable", "dns", "dnsSecurity", "dnsClient", "whoisClient", "ai", "aiClient"];
|
|
25
|
+
};
|
|
26
|
+
export default recker;
|