@stacksjs/ts-cloud 0.9.3 → 0.9.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 (143) hide show
  1. package/dist/aws/index.js +1 -269
  2. package/dist/bin/chunk-00kg80qg.js +1 -0
  3. package/dist/bin/{chunk-hzqw8xm5.js → chunk-1k5kszjp.js} +1 -1
  4. package/dist/bin/{chunk-9v39615t.js → chunk-21e0mavm.js} +1 -1
  5. package/dist/bin/{chunk-waayf9ay.js → chunk-2empps47.js} +1 -1
  6. package/dist/bin/{chunk-14cwr6eh.js → chunk-3vqfexc4.js} +1 -1
  7. package/dist/bin/chunk-5ectjq0b.js +1 -0
  8. package/dist/bin/{chunk-b5gd39s8.js → chunk-5erkxpt7.js} +4 -4
  9. package/dist/bin/{chunk-41x17hw1.js → chunk-5mrtzemj.js} +1 -1
  10. package/dist/bin/{chunk-p8q9bq9g.js → chunk-5n9fmabb.js} +1 -1
  11. package/dist/bin/{chunk-gqf6jsmy.js → chunk-9knpg30y.js} +1 -1
  12. package/dist/bin/{chunk-r3kv0vm9.js → chunk-ddk4rt4j.js} +1 -1
  13. package/dist/bin/{chunk-avm7tnwe.js → chunk-e0rkrq70.js} +1 -1
  14. package/dist/bin/{chunk-ry030a6b.js → chunk-etrb03mt.js} +1 -1
  15. package/dist/bin/{chunk-8v7ddyvf.js → chunk-k9t9wvms.js} +1 -1
  16. package/dist/bin/{chunk-92mea34a.js → chunk-m7dgskt1.js} +1 -1
  17. package/dist/bin/{chunk-3r4fb59r.js → chunk-mz0wbbsj.js} +1 -1
  18. package/dist/bin/{chunk-b9qbp8j1.js → chunk-qk9qgepa.js} +1 -1
  19. package/dist/bin/chunk-rxcvf10f.js +7364 -0
  20. package/dist/bin/{chunk-r9hjwcj9.js → chunk-tga3hhwk.js} +1 -1
  21. package/dist/bin/{chunk-ynjvbphf.js → chunk-tx0tqq2k.js} +1 -1
  22. package/dist/bin/{chunk-57y1zxbf.js → chunk-vm3q5gf2.js} +1 -1
  23. package/dist/bin/{chunk-bz828v8q.js → chunk-y7s5r8y6.js} +1 -1
  24. package/dist/bin/{chunk-sgyffpgm.js → chunk-zmegvjp8.js} +1 -1
  25. package/dist/bin/cli.js +14 -14
  26. package/dist/bin/dashboard-server.js +1 -1
  27. package/dist/chunk-0ccta6z6.js +6 -0
  28. package/dist/chunk-0k1cs6pp.js +1 -0
  29. package/dist/chunk-1egjn203.js +704 -0
  30. package/dist/chunk-2wx29qga.js +5 -0
  31. package/dist/chunk-5m5rqmv7.js +1 -0
  32. package/dist/chunk-8ea5022g.js +114 -0
  33. package/dist/chunk-8xqn3c0w.js +2 -0
  34. package/dist/chunk-b4esxhmw.js +2 -0
  35. package/dist/chunk-b8e5wzwn.js +44 -0
  36. package/dist/chunk-bggt4n6e.js +2 -0
  37. package/dist/chunk-cwkg37rs.js +37 -0
  38. package/dist/chunk-dskvqt67.js +7355 -0
  39. package/dist/chunk-gahsdmxf.js +1617 -0
  40. package/dist/chunk-gnv3r2jg.js +1 -0
  41. package/dist/chunk-hg3c48cp.js +34 -0
  42. package/dist/chunk-m5azeva3.js +2 -0
  43. package/dist/chunk-r3qf56b3.js +92 -0
  44. package/dist/chunk-sdqa9ghv.js +141 -0
  45. package/dist/chunk-svrvvcm7.js +1 -0
  46. package/dist/chunk-v0p3hpc3.js +60 -0
  47. package/dist/chunk-wdzjbecg.js +50 -0
  48. package/dist/chunk-ww8k3g7j.js +1 -0
  49. package/dist/chunk-xmqfc62w.js +1 -0
  50. package/dist/chunk-xrebj679.js +435 -0
  51. package/dist/chunk-xt3s24vr.js +2 -0
  52. package/dist/chunk-y21zk0pn.js +4 -0
  53. package/dist/deploy/index.js +1 -168
  54. package/dist/dns/index.js +1 -41
  55. package/dist/drivers/index.js +1 -154
  56. package/dist/index.js +100 -6129
  57. package/dist/protection/index.js +1 -89
  58. package/dist/push/index.js +1 -509
  59. package/dist/spend/index.js +1 -173
  60. package/dist/ui/404.html +1 -1
  61. package/dist/ui/accept-invitation.html +1 -1
  62. package/dist/ui/access-denied.html +1 -1
  63. package/dist/ui/account/automation.html +6 -6
  64. package/dist/ui/account/security.html +2 -2
  65. package/dist/ui/applications/compose.html +6 -6
  66. package/dist/ui/applications/new.html +2 -2
  67. package/dist/ui/data/backups.html +5 -5
  68. package/dist/ui/data/services.html +5 -5
  69. package/dist/ui/data/volumes.html +6 -6
  70. package/dist/ui/index.html +6 -6
  71. package/dist/ui/infrastructure/topology.html +5 -5
  72. package/dist/ui/integrations.html +1 -1
  73. package/dist/ui/operations/alerts.html +5 -5
  74. package/dist/ui/operations/configuration.html +5 -5
  75. package/dist/ui/operations/jobs.html +5 -5
  76. package/dist/ui/operations/maintenance.html +5 -5
  77. package/dist/ui/operations/observability.html +6 -6
  78. package/dist/ui/operations/previews.html +6 -6
  79. package/dist/ui/operations/queue.html +6 -6
  80. package/dist/ui/operations/regions.html +6 -6
  81. package/dist/ui/operations/releases.html +6 -6
  82. package/dist/ui/operations/spend.html +6 -6
  83. package/dist/ui/operations/workloads.html +6 -6
  84. package/dist/ui/security.html +1 -1
  85. package/dist/ui/server/actions.html +5 -5
  86. package/dist/ui/server/activity.html +1 -1
  87. package/dist/ui/server/capacity.html +6 -6
  88. package/dist/ui/server/database.html +6 -6
  89. package/dist/ui/server/deployments.html +6 -6
  90. package/dist/ui/server/diagnostics.html +2 -2
  91. package/dist/ui/server/firewall.html +6 -6
  92. package/dist/ui/server/fleet.html +6 -6
  93. package/dist/ui/server/logs.html +6 -6
  94. package/dist/ui/server/metrics.html +6 -6
  95. package/dist/ui/server/security.html +2 -2
  96. package/dist/ui/server/services.html +1 -1
  97. package/dist/ui/server/sites.html +6 -6
  98. package/dist/ui/server/ssh-keys.html +6 -6
  99. package/dist/ui/server/team.html +6 -6
  100. package/dist/ui/server/terminal.html +1 -1
  101. package/dist/ui/serverless/alarms.html +5 -5
  102. package/dist/ui/serverless/assets.html +2 -2
  103. package/dist/ui/serverless/cost.html +1 -1
  104. package/dist/ui/serverless/data.html +6 -6
  105. package/dist/ui/serverless/deployments.html +2 -2
  106. package/dist/ui/serverless/firewall.html +1 -1
  107. package/dist/ui/serverless/functions.html +6 -6
  108. package/dist/ui/serverless/logs.html +6 -6
  109. package/dist/ui/serverless/metrics.html +2 -2
  110. package/dist/ui/serverless/queues.html +6 -6
  111. package/dist/ui/serverless/secrets.html +6 -6
  112. package/dist/ui/serverless/traces.html +6 -6
  113. package/dist/ui/serverless.html +5 -5
  114. package/package.json +3 -3
  115. package/dist/bin/chunk-jpjamjey.js +0 -6935
  116. package/dist/bin/chunk-m2zwtapr.js +0 -1
  117. package/dist/bin/chunk-rtczra13.js +0 -1
  118. package/dist/chunk-01d86gt1.js +0 -1324
  119. package/dist/chunk-050r7ycy.js +0 -46516
  120. package/dist/chunk-1c8dbv57.js +0 -7278
  121. package/dist/chunk-29rse4p1.js +0 -12203
  122. package/dist/chunk-32e7ya18.js +0 -642
  123. package/dist/chunk-4cjrg98a.js +0 -597
  124. package/dist/chunk-50jpda9q.js +0 -371
  125. package/dist/chunk-6a1t7fnq.js +0 -12121
  126. package/dist/chunk-728jvrr0.js +0 -1701
  127. package/dist/chunk-7m60qnc8.js +0 -1762
  128. package/dist/chunk-aa2dkn7b.js +0 -205
  129. package/dist/chunk-d48vtdj4.js +0 -433
  130. package/dist/chunk-f55nkpvb.js +0 -8
  131. package/dist/chunk-fgk8cqew.js +0 -152
  132. package/dist/chunk-he9a874b.js +0 -769
  133. package/dist/chunk-k2yyatfw.js +0 -10
  134. package/dist/chunk-k4px0bnv.js +0 -23
  135. package/dist/chunk-nsgqsmrh.js +0 -1779
  136. package/dist/chunk-q0st3se8.js +0 -42033
  137. package/dist/chunk-qr803fye.js +0 -2122
  138. package/dist/chunk-rds0sy87.js +0 -1771
  139. package/dist/chunk-ttz2ra5j.js +0 -12
  140. package/dist/chunk-v0bahtg2.js +0 -4
  141. package/dist/chunk-va2yd85b.js +0 -200
  142. package/dist/chunk-x9s0cqfx.js +0 -13
  143. package/dist/chunk-zqtpg06c.js +0 -1752
@@ -1,1752 +0,0 @@
1
- // src/aws/client.ts
2
- import * as crypto from "node:crypto";
3
- import { existsSync, readFileSync } from "node:fs";
4
- import { homedir } from "node:os";
5
- import { join } from "node:path";
6
-
7
- // ../../node_modules/@stacksjs/ts-xml/dist/index.js
8
- var xmlEntities = {
9
- amp: "&",
10
- lt: "<",
11
- gt: ">",
12
- quot: '"',
13
- apos: "'"
14
- };
15
- var htmlEntities = {
16
- nbsp: " ",
17
- copy: "©",
18
- reg: "®",
19
- trade: "™",
20
- euro: "€",
21
- pound: "£",
22
- yen: "¥",
23
- cent: "¢",
24
- deg: "°",
25
- micro: "µ",
26
- middot: "·",
27
- bull: "•",
28
- hellip: "…",
29
- prime: "′",
30
- Prime: "″",
31
- laquo: "«",
32
- raquo: "»",
33
- lsquo: "‘",
34
- rsquo: "’",
35
- ldquo: "“",
36
- rdquo: "”",
37
- ndash: "–",
38
- mdash: "—",
39
- iexcl: "¡",
40
- iquest: "¿",
41
- sect: "§",
42
- para: "¶",
43
- dagger: "†",
44
- Dagger: "‡",
45
- lsaquo: "‹",
46
- rsaquo: "›",
47
- oline: "‾",
48
- frasl: "⁄",
49
- ensp: " ",
50
- emsp: " ",
51
- thinsp: " ",
52
- zwnj: "‌",
53
- zwj: "‍",
54
- lrm: "‎",
55
- rlm: "‏",
56
- times: "×",
57
- divide: "÷",
58
- plusmn: "±",
59
- ne: "≠",
60
- le: "≤",
61
- ge: "≥",
62
- infin: "∞",
63
- fnof: "ƒ",
64
- Alpha: "Α",
65
- Beta: "Β",
66
- Gamma: "Γ",
67
- Delta: "Δ",
68
- Epsilon: "Ε",
69
- Zeta: "Ζ",
70
- Eta: "Η",
71
- Theta: "Θ",
72
- Iota: "Ι",
73
- Kappa: "Κ",
74
- Lambda: "Λ",
75
- Mu: "Μ",
76
- Nu: "Ν",
77
- Xi: "Ξ",
78
- Omicron: "Ο",
79
- Pi: "Π",
80
- Rho: "Ρ",
81
- Sigma: "Σ",
82
- Tau: "Τ",
83
- Upsilon: "Υ",
84
- Phi: "Φ",
85
- Chi: "Χ",
86
- Psi: "Ψ",
87
- Omega: "Ω",
88
- alpha: "α",
89
- beta: "β",
90
- gamma: "γ",
91
- delta: "δ",
92
- epsilon: "ε",
93
- zeta: "ζ",
94
- eta: "η",
95
- theta: "θ",
96
- iota: "ι",
97
- kappa: "κ",
98
- lambda: "λ",
99
- mu: "μ",
100
- nu: "ν",
101
- xi: "ξ",
102
- omicron: "ο",
103
- pi: "π",
104
- rho: "ρ",
105
- sigmaf: "ς",
106
- sigma: "σ",
107
- tau: "τ",
108
- upsilon: "υ",
109
- phi: "φ",
110
- chi: "χ",
111
- psi: "ψ",
112
- omega: "ω",
113
- thetasym: "ϑ",
114
- upsih: "ϒ",
115
- piv: "ϖ",
116
- larr: "←",
117
- uarr: "↑",
118
- rarr: "→",
119
- darr: "↓",
120
- harr: "↔",
121
- crarr: "↵",
122
- lArr: "⇐",
123
- uArr: "⇑",
124
- rArr: "⇒",
125
- dArr: "⇓",
126
- hArr: "⇔",
127
- forall: "∀",
128
- part: "∂",
129
- exist: "∃",
130
- empty: "∅",
131
- nabla: "∇",
132
- isin: "∈",
133
- notin: "∉",
134
- ni: "∋",
135
- prod: "∏",
136
- sum: "∑",
137
- minus: "−",
138
- lowast: "∗",
139
- radic: "√",
140
- prop: "∝",
141
- ang: "∠",
142
- and: "∧",
143
- or: "∨",
144
- cap: "∩",
145
- cup: "∪",
146
- int: "∫",
147
- there4: "∴",
148
- sim: "∼",
149
- cong: "≅",
150
- asymp: "≈",
151
- equiv: "≡",
152
- sub: "⊂",
153
- sup: "⊃",
154
- nsub: "⊄",
155
- sube: "⊆",
156
- supe: "⊇",
157
- oplus: "⊕",
158
- otimes: "⊗",
159
- perp: "⊥",
160
- sdot: "⋅",
161
- lceil: "⌈",
162
- rceil: "⌉",
163
- lfloor: "⌊",
164
- rfloor: "⌋",
165
- lang: "〈",
166
- rang: "〉",
167
- loz: "◊",
168
- spades: "♠",
169
- clubs: "♣",
170
- hearts: "♥",
171
- diams: "♦",
172
- Agrave: "À",
173
- Aacute: "Á",
174
- Acirc: "Â",
175
- Atilde: "Ã",
176
- Auml: "Ä",
177
- Aring: "Å",
178
- AElig: "Æ",
179
- Ccedil: "Ç",
180
- Egrave: "È",
181
- Eacute: "É",
182
- Ecirc: "Ê",
183
- Euml: "Ë",
184
- Igrave: "Ì",
185
- Iacute: "Í",
186
- Icirc: "Î",
187
- Iuml: "Ï",
188
- ETH: "Ð",
189
- Ntilde: "Ñ",
190
- Ograve: "Ò",
191
- Oacute: "Ó",
192
- Ocirc: "Ô",
193
- Otilde: "Õ",
194
- Ouml: "Ö",
195
- Oslash: "Ø",
196
- Ugrave: "Ù",
197
- Uacute: "Ú",
198
- Ucirc: "Û",
199
- Uuml: "Ü",
200
- Yacute: "Ý",
201
- THORN: "Þ",
202
- szlig: "ß",
203
- agrave: "à",
204
- aacute: "á",
205
- acirc: "â",
206
- atilde: "ã",
207
- auml: "ä",
208
- aring: "å",
209
- aelig: "æ",
210
- ccedil: "ç",
211
- egrave: "è",
212
- eacute: "é",
213
- ecirc: "ê",
214
- euml: "ë",
215
- igrave: "ì",
216
- iacute: "í",
217
- icirc: "î",
218
- iuml: "ï",
219
- eth: "ð",
220
- ntilde: "ñ",
221
- ograve: "ò",
222
- oacute: "ó",
223
- ocirc: "ô",
224
- otilde: "õ",
225
- ouml: "ö",
226
- oslash: "ø",
227
- ugrave: "ù",
228
- uacute: "ú",
229
- ucirc: "û",
230
- uuml: "ü",
231
- yacute: "ý",
232
- thorn: "þ",
233
- yuml: "ÿ",
234
- OElig: "Œ",
235
- oelig: "œ",
236
- Scaron: "Š",
237
- scaron: "š",
238
- Yuml: "Ÿ",
239
- circ: "ˆ",
240
- tilde: "˜"
241
- };
242
-
243
- class EntityDecoder {
244
- customEntities = {};
245
- useHtmlEntities;
246
- constructor(useHtmlEntities = false) {
247
- this.useHtmlEntities = useHtmlEntities;
248
- }
249
- addEntity(name, value) {
250
- this.customEntities[name] = value;
251
- }
252
- decodeEntities(text) {
253
- let ampIdx = text.indexOf("&");
254
- if (ampIdx === -1)
255
- return text;
256
- const len = text.length;
257
- let result = "";
258
- let lastPos = 0;
259
- while (ampIdx !== -1 && ampIdx < len) {
260
- if (ampIdx > lastPos)
261
- result += text.substring(lastPos, ampIdx);
262
- const semiIdx = text.indexOf(";", ampIdx + 1);
263
- if (semiIdx === -1 || semiIdx - ampIdx > 32) {
264
- result += "&";
265
- lastPos = ampIdx + 1;
266
- ampIdx = text.indexOf("&", lastPos);
267
- continue;
268
- }
269
- const entity = text.substring(ampIdx + 1, semiIdx);
270
- if (entity.charCodeAt(0) === 35) {
271
- const elen = entity.length;
272
- let code = 0;
273
- let valid = false;
274
- if (elen > 2 && (entity.charCodeAt(1) === 120 || entity.charCodeAt(1) === 88)) {
275
- valid = true;
276
- for (let k = 2;k < elen; k++) {
277
- const d = entity.charCodeAt(k);
278
- if (d >= 48 && d <= 57)
279
- code = code << 4 | d - 48;
280
- else if (d >= 65 && d <= 70)
281
- code = code << 4 | d - 55;
282
- else if (d >= 97 && d <= 102)
283
- code = code << 4 | d - 87;
284
- else {
285
- valid = false;
286
- break;
287
- }
288
- }
289
- } else if (elen > 1) {
290
- valid = true;
291
- for (let k = 1;k < elen; k++) {
292
- const d = entity.charCodeAt(k);
293
- if (d >= 48 && d <= 57)
294
- code = code * 10 + (d - 48);
295
- else {
296
- valid = false;
297
- break;
298
- }
299
- }
300
- }
301
- if (valid) {
302
- result += String.fromCodePoint(code);
303
- } else {
304
- result += text.substring(ampIdx, semiIdx + 1);
305
- }
306
- } else {
307
- let replacement = this.customEntities[entity];
308
- if (replacement === undefined) {
309
- const elen = entity.length;
310
- if (elen >= 2 && elen <= 4) {
311
- const e0 = entity.charCodeAt(0);
312
- if (e0 === 108 && elen === 2 && entity.charCodeAt(1) === 116)
313
- replacement = "<";
314
- else if (e0 === 103 && elen === 2 && entity.charCodeAt(1) === 116)
315
- replacement = ">";
316
- else if (e0 === 97 && elen === 3 && entity.charCodeAt(1) === 109 && entity.charCodeAt(2) === 112)
317
- replacement = "&";
318
- else if (e0 === 113 && elen === 4)
319
- replacement = entity === "quot" ? '"' : undefined;
320
- else if (e0 === 97 && elen === 4)
321
- replacement = entity === "apos" ? "'" : undefined;
322
- }
323
- if (replacement === undefined)
324
- replacement = xmlEntities[entity] ?? (this.useHtmlEntities ? htmlEntities[entity] : undefined);
325
- }
326
- if (replacement !== undefined) {
327
- result += replacement;
328
- } else {
329
- result += text.substring(ampIdx, semiIdx + 1);
330
- }
331
- }
332
- lastPos = semiIdx + 1;
333
- ampIdx = text.indexOf("&", lastPos);
334
- }
335
- if (lastPos < len)
336
- result += text.substring(lastPos);
337
- return result;
338
- }
339
- }
340
- var _encodeMap = [];
341
- _encodeMap[38] = "&amp;";
342
- _encodeMap[60] = "&lt;";
343
- _encodeMap[62] = "&gt;";
344
- _encodeMap[34] = "&quot;";
345
- _encodeMap[39] = "&apos;";
346
- var defaultParserOptions = {
347
- attributeNamePrefix: "@_",
348
- attributesGroupName: false,
349
- textNodeName: "#text",
350
- ignoreAttributes: true,
351
- removeNSPrefix: false,
352
- allowBooleanAttributes: false,
353
- alwaysCreateTextNode: false,
354
- trimValues: true,
355
- parseTagValue: true,
356
- parseAttributeValue: false,
357
- processEntities: true,
358
- htmlEntities: false,
359
- commentPropName: false,
360
- cdataPropName: false,
361
- piPropName: false,
362
- preserveOrder: false,
363
- stopNodes: [],
364
- unpairedTags: [],
365
- isArray: undefined,
366
- tagValueProcessor: undefined,
367
- attributeValueProcessor: undefined,
368
- updateTag: undefined,
369
- numberParseOptions: {
370
- hex: true,
371
- leadingZeros: true,
372
- scientific: true
373
- },
374
- ignorePiTags: false,
375
- transformAttributeName: undefined,
376
- transformTagName: undefined,
377
- ignoreDeclaration: false
378
- };
379
- function isWhitespace(ch) {
380
- return ch === 32 || ch === 9 || ch === 10 || ch === 13;
381
- }
382
- function isNameStartChar(ch) {
383
- return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch === 95 || ch === 58 || ch >= 192 && ch <= 214 || ch >= 216 && ch <= 246 || ch >= 248 && ch <= 767 || ch >= 880 && ch <= 893 || ch >= 895 && ch <= 8191 || ch >= 8204 && ch <= 8205 || ch >= 8304 && ch <= 8591 || ch >= 11264 && ch <= 12271 || ch >= 12289 && ch <= 55295 || ch >= 63744 && ch <= 64975 || ch >= 65008 && ch <= 65533;
384
- }
385
- function isNameChar(ch) {
386
- return isNameStartChar(ch) || ch === 45 || ch === 46 || ch >= 48 && ch <= 57 || ch === 183 || ch >= 768 && ch <= 879 || ch >= 8255 && ch <= 8256;
387
- }
388
- var RE_HEX = /^0x[\da-fA-F]+$/;
389
- var RE_SCIENTIFIC = /^[+-]?\d+(\.\d+)?[eE][+-]?\d+$/;
390
- var RE_NUMBER = /^[+-]?(\d+\.?\d*|\.\d+)$/;
391
- function isCDATA(xml, pos) {
392
- return xml.charCodeAt(pos) === 91 && xml.charCodeAt(pos + 1) === 67 && xml.charCodeAt(pos + 2) === 68 && xml.charCodeAt(pos + 3) === 65 && xml.charCodeAt(pos + 4) === 84 && xml.charCodeAt(pos + 5) === 65 && xml.charCodeAt(pos + 6) === 91;
393
- }
394
- function isDOCTYPE(xml, pos) {
395
- const c0 = xml.charCodeAt(pos);
396
- const c1 = xml.charCodeAt(pos + 1);
397
- const c2 = xml.charCodeAt(pos + 2);
398
- const c3 = xml.charCodeAt(pos + 3);
399
- const c4 = xml.charCodeAt(pos + 4);
400
- const c5 = xml.charCodeAt(pos + 5);
401
- const c6 = xml.charCodeAt(pos + 6);
402
- return (c0 === 68 || c0 === 100) && (c1 === 79 || c1 === 111) && (c2 === 67 || c2 === 99) && (c3 === 84 || c3 === 116) && (c4 === 89 || c4 === 121) && (c5 === 80 || c5 === 112) && (c6 === 69 || c6 === 101);
403
- }
404
- function readNameEnd(xml, pos, len) {
405
- if (pos >= len || !isNameStartChar(xml.charCodeAt(pos)))
406
- return pos;
407
- pos++;
408
- while (pos < len && isNameChar(xml.charCodeAt(pos)))
409
- pos++;
410
- return pos;
411
- }
412
-
413
- class XMLParser {
414
- options;
415
- entityDecoder;
416
- unpairedSet;
417
- exactStopNodes;
418
- wildcardStopSuffixes;
419
- needsJPath;
420
- _ignoreAttributes = true;
421
- _textNodeName = "#text";
422
- _commentPropName = false;
423
- _cdataPropName = false;
424
- _piPropName = false;
425
- _alwaysCreateTextNode = false;
426
- _trimValues = true;
427
- _processEntities = true;
428
- _parseTagValue = true;
429
- _parseAttributeValue = false;
430
- _removeNSPrefix = false;
431
- _attrPrefix = "@_";
432
- _attrsGroupName = false;
433
- _ignorePiTags = false;
434
- _ignoreDeclaration = false;
435
- constructor(options) {
436
- this.options = { ...defaultParserOptions, ...options };
437
- this.entityDecoder = new EntityDecoder(this.options.htmlEntities);
438
- this.unpairedSet = new Set(this.options.unpairedTags);
439
- this.exactStopNodes = new Set;
440
- this.wildcardStopSuffixes = [];
441
- for (const stopNode of this.options.stopNodes) {
442
- if (stopNode.startsWith("*.")) {
443
- this.wildcardStopSuffixes.push(stopNode.substring(2));
444
- } else {
445
- this.exactStopNodes.add(stopNode);
446
- }
447
- }
448
- this._ignoreAttributes = this.options.ignoreAttributes;
449
- this._textNodeName = this.options.textNodeName;
450
- this._commentPropName = this.options.commentPropName;
451
- this._cdataPropName = this.options.cdataPropName;
452
- this._piPropName = this.options.piPropName;
453
- this._alwaysCreateTextNode = this.options.alwaysCreateTextNode;
454
- this._trimValues = this.options.trimValues;
455
- this._processEntities = this.options.processEntities;
456
- this._parseTagValue = this.options.parseTagValue;
457
- this._parseAttributeValue = this.options.parseAttributeValue;
458
- this._removeNSPrefix = this.options.removeNSPrefix;
459
- this._attrPrefix = this.options.attributeNamePrefix;
460
- this._attrsGroupName = this.options.attributesGroupName;
461
- this._ignorePiTags = this.options.ignorePiTags;
462
- this._ignoreDeclaration = this.options.ignoreDeclaration;
463
- this.needsJPath = this.options.stopNodes.length > 0 || this.options.isArray !== undefined || this.options.updateTag !== undefined || this.options.tagValueProcessor !== undefined || this.options.attributeValueProcessor !== undefined;
464
- }
465
- addEntity(name, value) {
466
- this.entityDecoder.addEntity(name, value);
467
- }
468
- parse(xmlData) {
469
- if (xmlData instanceof Uint8Array) {
470
- xmlData = new TextDecoder().decode(xmlData);
471
- }
472
- const xml = xmlData;
473
- if (this.options.preserveOrder) {
474
- return this.parseOrdered(xml);
475
- }
476
- return this.parseUnordered(xml);
477
- }
478
- parseUnordered(xml) {
479
- const result = {};
480
- const len = xml.length;
481
- let i = 0;
482
- if (len > 0 && xml.charCodeAt(0) === 65279)
483
- i = 1;
484
- i = this.parseChildren(xml, i, len, result, "", []);
485
- return result;
486
- }
487
- parseOrdered(xml) {
488
- const len = xml.length;
489
- let i = 0;
490
- if (len > 0 && xml.charCodeAt(0) === 65279)
491
- i = 1;
492
- const result = [];
493
- this.parseChildrenOrdered(xml, i, len, result, "");
494
- return result;
495
- }
496
- readTagName(xml, pos, len) {
497
- const end = readNameEnd(xml, pos, len);
498
- return end;
499
- }
500
- extractTagName(xml, start, end) {
501
- let name = xml.substring(start, end);
502
- if (this._removeNSPrefix) {
503
- const colonIdx = name.indexOf(":");
504
- if (colonIdx !== -1)
505
- name = name.substring(colonIdx + 1);
506
- }
507
- if (this.options.transformTagName)
508
- name = this.options.transformTagName(name);
509
- return name;
510
- }
511
- parseAttributes(xml, pos, len, jPath, outAttrs) {
512
- let count = 0;
513
- const removeNS = this._removeNSPrefix;
514
- const transformAttr = this.options.transformAttributeName;
515
- const trimVals = this._trimValues;
516
- const processEnts = this._processEntities;
517
- const attrProcessor = this.options.attributeValueProcessor;
518
- while (pos < len) {
519
- let ch = xml.charCodeAt(pos);
520
- while (ch === 32 || ch === 9 || ch === 10 || ch === 13) {
521
- pos++;
522
- if (pos >= len)
523
- break;
524
- ch = xml.charCodeAt(pos);
525
- }
526
- if (pos >= len)
527
- break;
528
- if (ch === 62 || ch === 47)
529
- break;
530
- const attrStart = pos;
531
- if (!isNameStartChar(ch))
532
- break;
533
- pos++;
534
- while (pos < len && isNameChar(xml.charCodeAt(pos)))
535
- pos++;
536
- let attrName = xml.substring(attrStart, pos);
537
- if (removeNS) {
538
- const colonIdx = attrName.indexOf(":");
539
- if (colonIdx !== -1)
540
- attrName = attrName.substring(colonIdx + 1);
541
- }
542
- if (transformAttr)
543
- attrName = transformAttr(attrName);
544
- while (pos < len && isWhitespace(xml.charCodeAt(pos)))
545
- pos++;
546
- if (pos < len && xml.charCodeAt(pos) === 61) {
547
- pos++;
548
- while (pos < len && isWhitespace(xml.charCodeAt(pos)))
549
- pos++;
550
- if (pos >= len)
551
- break;
552
- const quoteChar = xml.charCodeAt(pos);
553
- if (quoteChar === 34 || quoteChar === 39) {
554
- pos++;
555
- const valueStart = pos;
556
- while (pos < len && xml.charCodeAt(pos) !== quoteChar)
557
- pos++;
558
- let value = xml.substring(valueStart, pos);
559
- if (trimVals && value.length > 0) {
560
- const f = value.charCodeAt(0);
561
- const l = value.charCodeAt(value.length - 1);
562
- if (f <= 32 || l <= 32)
563
- value = value.trim();
564
- }
565
- if (processEnts)
566
- value = this.entityDecoder.decodeEntities(value);
567
- if (attrProcessor)
568
- value = attrProcessor(attrName, value, jPath) ?? value;
569
- outAttrs[attrName] = value;
570
- count++;
571
- if (pos < len)
572
- pos++;
573
- }
574
- } else {
575
- outAttrs[attrName] = "true";
576
- count++;
577
- }
578
- }
579
- return count > 0 ? -pos - 1 : pos;
580
- }
581
- processTagValue(value, tagName, jPath, hasAttributes, isLeaf) {
582
- if (this._trimValues) {
583
- const vlen = value.length;
584
- if (vlen > 0) {
585
- const first = value.charCodeAt(0);
586
- const last = value.charCodeAt(vlen - 1);
587
- if (first <= 32 || last <= 32)
588
- value = value.trim();
589
- }
590
- }
591
- if (this._processEntities)
592
- value = this.entityDecoder.decodeEntities(value);
593
- if (this.options.tagValueProcessor) {
594
- const processed = this.options.tagValueProcessor(tagName, value, jPath, hasAttributes, isLeaf);
595
- if (processed !== undefined)
596
- value = processed;
597
- }
598
- if (!value)
599
- return value;
600
- if (this._parseTagValue)
601
- return this.parseValue(value);
602
- return value;
603
- }
604
- parseValue(val) {
605
- if (val === "true")
606
- return true;
607
- if (val === "false")
608
- return false;
609
- if (!val)
610
- return val;
611
- const firstCh = val.charCodeAt(0);
612
- const isNumStart = firstCh >= 48 && firstCh <= 57 || firstCh === 43 || firstCh === 45 || firstCh === 46;
613
- if (!isNumStart)
614
- return val;
615
- const opts = this.options.numberParseOptions;
616
- if (opts.skipLike?.test(val))
617
- return val;
618
- if (opts.hex && firstCh === 48 && RE_HEX.test(val))
619
- return Number.parseInt(val, 16);
620
- if (val.length > 1 && firstCh === 48 && val.charCodeAt(1) !== 46) {
621
- if (opts.leadingZeros)
622
- return val;
623
- }
624
- if (opts.scientific && RE_SCIENTIFIC.test(val)) {
625
- const num = Number(val);
626
- if (!Number.isNaN(num))
627
- return num;
628
- }
629
- if (RE_NUMBER.test(val)) {
630
- const num = Number(val);
631
- if (!Number.isNaN(num))
632
- return num;
633
- }
634
- return val;
635
- }
636
- parseAttributeValue(val) {
637
- if (!this._parseAttributeValue)
638
- return val;
639
- return this.parseValue(val);
640
- }
641
- isStopNode(jPath) {
642
- if (this.exactStopNodes.has(jPath))
643
- return true;
644
- for (const suffix of this.wildcardStopSuffixes) {
645
- if (jPath.endsWith(`.${suffix}`) || jPath === suffix)
646
- return true;
647
- }
648
- return false;
649
- }
650
- readStopNodeContent(xml, pos, len, tagName) {
651
- const closingTag = `</${tagName}`;
652
- const idx = xml.indexOf(closingTag, pos);
653
- if (idx === -1) {
654
- return { content: xml.substring(pos), pos: len };
655
- }
656
- const content = xml.substring(pos, idx);
657
- let endPos = idx + closingTag.length;
658
- while (endPos < len && xml.charCodeAt(endPos) !== 62)
659
- endPos++;
660
- if (endPos < len)
661
- endPos++;
662
- return { content, pos: endPos };
663
- }
664
- addToObj(obj, key, value, jPath, isLeaf, isAttribute) {
665
- const existing = obj[key];
666
- if (existing !== undefined) {
667
- if (!Array.isArray(existing)) {
668
- obj[key] = [existing, value];
669
- } else {
670
- existing.push(value);
671
- }
672
- } else if (this.options.isArray?.(key, jPath, isLeaf, isAttribute)) {
673
- obj[key] = [value];
674
- } else {
675
- obj[key] = value;
676
- }
677
- }
678
- flushText(textContent, cdataBuffer, jPath, parent) {
679
- if (!textContent && !cdataBuffer)
680
- return;
681
- const textNodeName = this._textNodeName;
682
- if (cdataBuffer) {
683
- let decodedText = textContent;
684
- if (decodedText && this._processEntities)
685
- decodedText = this.entityDecoder.decodeEntities(decodedText);
686
- let value = cdataBuffer + decodedText;
687
- if (this._trimValues && value.length > 0) {
688
- const f = value.charCodeAt(0);
689
- const l = value.charCodeAt(value.length - 1);
690
- if (f <= 32 || l <= 32)
691
- value = value.trim();
692
- }
693
- if (this.options.tagValueProcessor) {
694
- const processed = this.options.tagValueProcessor(textNodeName, value, jPath, false, true);
695
- if (processed !== undefined)
696
- value = processed;
697
- }
698
- if (value) {
699
- const parsed = this._parseTagValue ? this.parseValue(value) : value;
700
- if (parsed !== undefined && parsed !== "")
701
- this.addToObj(parent, textNodeName, parsed, jPath, true, false);
702
- }
703
- } else {
704
- const processed = this.processTagValue(textContent, textNodeName, jPath, false, true);
705
- if (processed !== undefined && processed !== "")
706
- this.addToObj(parent, textNodeName, processed, jPath, true, false);
707
- }
708
- }
709
- parseChildren(xml, pos, len, parent, jPath, unpairedStack) {
710
- let textContent = "";
711
- let cdataBuffer = "";
712
- const needsJPath = this.needsJPath;
713
- while (pos < len) {
714
- const ch = xml.charCodeAt(pos);
715
- if (ch !== 60) {
716
- const textStart = pos;
717
- pos++;
718
- while (pos < len && xml.charCodeAt(pos) !== 60)
719
- pos++;
720
- if (!textContent)
721
- textContent = xml.substring(textStart, pos);
722
- else
723
- textContent += xml.substring(textStart, pos);
724
- continue;
725
- }
726
- if (pos + 1 >= len)
727
- break;
728
- const nextCh = xml.charCodeAt(pos + 1);
729
- if (nextCh === 33 && pos + 3 < len && xml.charCodeAt(pos + 2) === 45 && xml.charCodeAt(pos + 3) === 45) {
730
- if (textContent || cdataBuffer) {
731
- this.flushText(textContent, cdataBuffer, jPath, parent);
732
- textContent = "";
733
- cdataBuffer = "";
734
- }
735
- pos += 4;
736
- const endComment = xml.indexOf("-->", pos);
737
- if (endComment === -1) {
738
- pos = len;
739
- break;
740
- }
741
- if (this._commentPropName) {
742
- const comment = xml.substring(pos, endComment);
743
- this.addToObj(parent, this._commentPropName, comment, jPath, true, false);
744
- }
745
- pos = endComment + 3;
746
- continue;
747
- }
748
- if (nextCh === 33 && pos + 8 < len && isCDATA(xml, pos + 2)) {
749
- pos += 9;
750
- const endCdata = xml.indexOf("]]>", pos);
751
- if (endCdata === -1) {
752
- pos = len;
753
- break;
754
- }
755
- const cdataContent = xml.substring(pos, endCdata);
756
- if (this._cdataPropName) {
757
- this.flushText(textContent, cdataBuffer, jPath, parent);
758
- textContent = "";
759
- cdataBuffer = "";
760
- this.addToObj(parent, this._cdataPropName, cdataContent, jPath, true, false);
761
- } else {
762
- if (textContent) {
763
- let decoded = textContent;
764
- if (this._processEntities)
765
- decoded = this.entityDecoder.decodeEntities(decoded);
766
- cdataBuffer += decoded;
767
- textContent = "";
768
- }
769
- cdataBuffer += cdataContent;
770
- }
771
- pos = endCdata + 3;
772
- continue;
773
- }
774
- if (nextCh === 33 && pos + 9 < len && isDOCTYPE(xml, pos + 2)) {
775
- pos += 9;
776
- let depth = 1;
777
- while (pos < len && depth > 0) {
778
- const c = xml.charCodeAt(pos);
779
- if (c === 60)
780
- depth++;
781
- else if (c === 62)
782
- depth--;
783
- pos++;
784
- }
785
- continue;
786
- }
787
- if (nextCh === 63) {
788
- pos += 2;
789
- const piNameStart = pos;
790
- while (pos < len && !isWhitespace(xml.charCodeAt(pos)) && xml.charCodeAt(pos) !== 63)
791
- pos++;
792
- const piTarget = xml.substring(piNameStart, pos);
793
- const endPi = xml.indexOf("?>", pos);
794
- if (endPi === -1) {
795
- pos = len;
796
- break;
797
- }
798
- const piContent = xml.substring(pos, endPi).trim();
799
- if (piTarget === "xml") {
800
- if (!this._ignoreDeclaration && this._piPropName) {
801
- const declAttrs = this.parsePiAttributes(piContent);
802
- this.addToObj(parent, this._piPropName, { [piTarget]: declAttrs }, jPath, true, false);
803
- }
804
- } else if (!this._ignorePiTags && this._piPropName) {
805
- this.addToObj(parent, this._piPropName, { [piTarget]: piContent }, jPath, true, false);
806
- }
807
- pos = endPi + 2;
808
- continue;
809
- }
810
- if (nextCh === 47) {
811
- if (textContent || cdataBuffer) {
812
- this.flushText(textContent, cdataBuffer, jPath, parent);
813
- textContent = "";
814
- cdataBuffer = "";
815
- }
816
- pos += 2;
817
- const nameStart2 = pos;
818
- const nameEnd2 = this.readTagName(xml, pos, len);
819
- const closingName = this.extractTagName(xml, nameStart2, nameEnd2);
820
- pos = nameEnd2;
821
- while (pos < len && isWhitespace(xml.charCodeAt(pos)))
822
- pos++;
823
- if (pos < len && xml.charCodeAt(pos) === 62)
824
- pos++;
825
- if (unpairedStack.length > 0 && unpairedStack[unpairedStack.length - 1] === closingName) {
826
- unpairedStack.pop();
827
- continue;
828
- }
829
- return pos;
830
- }
831
- if (textContent || cdataBuffer) {
832
- this.flushText(textContent, cdataBuffer, jPath, parent);
833
- textContent = "";
834
- cdataBuffer = "";
835
- }
836
- pos++;
837
- const nameStart = pos;
838
- const nameEnd = this.readTagName(xml, pos, len);
839
- const tagName = this.extractTagName(xml, nameStart, nameEnd);
840
- if (!tagName) {
841
- pos = nameEnd + 1;
842
- continue;
843
- }
844
- pos = nameEnd;
845
- const childJPath = needsJPath ? jPath ? `${jPath}.${tagName}` : tagName : "";
846
- let attrs = {};
847
- let hasAttrs = false;
848
- if (!this._ignoreAttributes) {
849
- const attrResult = this.parseAttributes(xml, pos, len, childJPath, attrs);
850
- if (attrResult < 0) {
851
- pos = -attrResult - 1;
852
- hasAttrs = true;
853
- } else {
854
- pos = attrResult;
855
- }
856
- } else {
857
- while (pos < len) {
858
- const c = xml.charCodeAt(pos);
859
- if (c === 62 || c === 47)
860
- break;
861
- if (c === 34 || c === 39) {
862
- pos++;
863
- while (pos < len && xml.charCodeAt(pos) !== c)
864
- pos++;
865
- }
866
- pos++;
867
- }
868
- }
869
- if (this.options.updateTag) {
870
- const newName = this.options.updateTag(tagName, childJPath, attrs);
871
- if (newName === false) {
872
- while (pos < len && isWhitespace(xml.charCodeAt(pos)))
873
- pos++;
874
- if (pos < len && xml.charCodeAt(pos) === 47) {
875
- pos += 2;
876
- } else if (pos < len && xml.charCodeAt(pos) === 62) {
877
- pos++;
878
- const closingTag = `</${tagName}>`;
879
- const closeIdx = xml.indexOf(closingTag, pos);
880
- if (closeIdx !== -1)
881
- pos = closeIdx + closingTag.length;
882
- }
883
- continue;
884
- }
885
- }
886
- while (pos < len && isWhitespace(xml.charCodeAt(pos)))
887
- pos++;
888
- if (pos < len && xml.charCodeAt(pos) === 47) {
889
- pos += 2;
890
- if (hasAttrs || this._alwaysCreateTextNode) {
891
- const childObj = {};
892
- if (hasAttrs)
893
- this.applyAttributes(childObj, attrs, childJPath);
894
- if (this._alwaysCreateTextNode)
895
- childObj[this._textNodeName] = "";
896
- this.addToObj(parent, tagName, childObj, childJPath, true, false);
897
- } else {
898
- this.addToObj(parent, tagName, "", childJPath, true, false);
899
- }
900
- continue;
901
- }
902
- if (pos < len && xml.charCodeAt(pos) === 62) {
903
- pos++;
904
- if (this.unpairedSet.has(tagName)) {
905
- if (hasAttrs) {
906
- const childObj2 = {};
907
- this.applyAttributes(childObj2, attrs, childJPath);
908
- this.addToObj(parent, tagName, childObj2, childJPath, true, false);
909
- } else {
910
- this.addToObj(parent, tagName, "", childJPath, true, false);
911
- }
912
- unpairedStack.push(tagName);
913
- continue;
914
- }
915
- if (this.exactStopNodes.size > 0 || this.wildcardStopSuffixes.length > 0) {
916
- if (this.isStopNode(childJPath)) {
917
- const stopResult = this.readStopNodeContent(xml, pos, len, tagName);
918
- const childObj2 = {};
919
- if (hasAttrs)
920
- this.applyAttributes(childObj2, attrs, childJPath);
921
- if (stopResult.content)
922
- childObj2[this._textNodeName] = stopResult.content;
923
- this.addToObj(parent, tagName, childObj2, childJPath, true, false);
924
- pos = stopResult.pos;
925
- continue;
926
- }
927
- }
928
- const childObj = {};
929
- if (hasAttrs)
930
- this.applyAttributes(childObj, attrs, childJPath);
931
- pos = this.parseChildren(xml, pos, len, childObj, childJPath, unpairedStack);
932
- const textNodeName = this._textNodeName;
933
- const textValue = childObj[textNodeName];
934
- if (!hasAttrs && !this._alwaysCreateTextNode) {
935
- let isLeaf = true;
936
- for (const k in childObj) {
937
- if (k !== textNodeName) {
938
- isLeaf = false;
939
- break;
940
- }
941
- }
942
- if (isLeaf) {
943
- this.addToObj(parent, tagName, textValue !== undefined ? textValue : "", childJPath, true, false);
944
- continue;
945
- }
946
- }
947
- this.addToObj(parent, tagName, childObj, childJPath, false, false);
948
- }
949
- }
950
- if (textContent || cdataBuffer) {
951
- this.flushText(textContent, cdataBuffer, jPath, parent);
952
- }
953
- return pos;
954
- }
955
- parseChildrenOrdered(xml, pos, len, parent, jPath) {
956
- let textContent = "";
957
- const needsJPath = this.needsJPath;
958
- while (pos < len) {
959
- const ch = xml.charCodeAt(pos);
960
- if (ch !== 60) {
961
- const textStart = pos;
962
- pos++;
963
- while (pos < len && xml.charCodeAt(pos) !== 60)
964
- pos++;
965
- if (!textContent)
966
- textContent = xml.substring(textStart, pos);
967
- else
968
- textContent += xml.substring(textStart, pos);
969
- continue;
970
- }
971
- if (pos + 1 >= len)
972
- break;
973
- const nextCh = xml.charCodeAt(pos + 1);
974
- if (nextCh === 33 && pos + 3 < len && xml.charCodeAt(pos + 2) === 45 && xml.charCodeAt(pos + 3) === 45) {
975
- if (textContent) {
976
- const processed = this.processTagValue(textContent, this._textNodeName, jPath, false, true);
977
- if (processed !== undefined && processed !== "")
978
- parent.push({ [this._textNodeName]: processed });
979
- textContent = "";
980
- }
981
- pos += 4;
982
- const endComment = xml.indexOf("-->", pos);
983
- if (endComment === -1) {
984
- pos = len;
985
- break;
986
- }
987
- if (this._commentPropName) {
988
- parent.push({ [this._commentPropName]: [{ [this._textNodeName]: xml.substring(pos, endComment) }] });
989
- }
990
- pos = endComment + 3;
991
- continue;
992
- }
993
- if (nextCh === 33 && pos + 8 < len && isCDATA(xml, pos + 2)) {
994
- pos += 9;
995
- const endCdata = xml.indexOf("]]>", pos);
996
- if (endCdata === -1) {
997
- pos = len;
998
- break;
999
- }
1000
- const cdataContent = xml.substring(pos, endCdata);
1001
- if (this._cdataPropName) {
1002
- if (textContent) {
1003
- const processed = this.processTagValue(textContent, this._textNodeName, jPath, false, true);
1004
- if (processed !== undefined && processed !== "")
1005
- parent.push({ [this._textNodeName]: processed });
1006
- textContent = "";
1007
- }
1008
- parent.push({ [this._cdataPropName]: [{ [this._textNodeName]: cdataContent }] });
1009
- } else {
1010
- textContent += cdataContent;
1011
- }
1012
- pos = endCdata + 3;
1013
- continue;
1014
- }
1015
- if (nextCh === 33 && pos + 9 < len && isDOCTYPE(xml, pos + 2)) {
1016
- pos += 9;
1017
- let depth = 1;
1018
- while (pos < len && depth > 0) {
1019
- const c = xml.charCodeAt(pos);
1020
- if (c === 60)
1021
- depth++;
1022
- else if (c === 62)
1023
- depth--;
1024
- pos++;
1025
- }
1026
- continue;
1027
- }
1028
- if (nextCh === 63) {
1029
- pos += 2;
1030
- const endPi = xml.indexOf("?>", pos);
1031
- if (endPi === -1) {
1032
- pos = len;
1033
- break;
1034
- }
1035
- pos = endPi + 2;
1036
- continue;
1037
- }
1038
- if (nextCh === 47) {
1039
- if (textContent) {
1040
- const processed = this.processTagValue(textContent, this._textNodeName, jPath, false, true);
1041
- if (processed !== undefined && processed !== "")
1042
- parent.push({ [this._textNodeName]: processed });
1043
- textContent = "";
1044
- }
1045
- pos += 2;
1046
- const nameEnd2 = this.readTagName(xml, pos, len);
1047
- pos = nameEnd2;
1048
- while (pos < len && isWhitespace(xml.charCodeAt(pos)))
1049
- pos++;
1050
- if (pos < len && xml.charCodeAt(pos) === 62)
1051
- pos++;
1052
- return pos;
1053
- }
1054
- if (textContent) {
1055
- const processed = this.processTagValue(textContent, this._textNodeName, jPath, false, true);
1056
- if (processed !== undefined && processed !== "")
1057
- parent.push({ [this._textNodeName]: processed });
1058
- textContent = "";
1059
- }
1060
- pos++;
1061
- const nameStart = pos;
1062
- const nameEnd = this.readTagName(xml, pos, len);
1063
- const tagName = this.extractTagName(xml, nameStart, nameEnd);
1064
- if (!tagName) {
1065
- pos = nameEnd + 1;
1066
- continue;
1067
- }
1068
- pos = nameEnd;
1069
- const childJPath = needsJPath ? jPath ? `${jPath}.${tagName}` : tagName : "";
1070
- let attrs = {};
1071
- let hasAttrs = false;
1072
- if (!this._ignoreAttributes) {
1073
- const attrResult = this.parseAttributes(xml, pos, len, childJPath, attrs);
1074
- if (attrResult < 0) {
1075
- pos = -attrResult - 1;
1076
- hasAttrs = true;
1077
- } else {
1078
- pos = attrResult;
1079
- }
1080
- } else {
1081
- while (pos < len) {
1082
- const c = xml.charCodeAt(pos);
1083
- if (c === 62 || c === 47)
1084
- break;
1085
- if (c === 34 || c === 39) {
1086
- pos++;
1087
- while (pos < len && xml.charCodeAt(pos) !== c)
1088
- pos++;
1089
- }
1090
- pos++;
1091
- }
1092
- }
1093
- while (pos < len && isWhitespace(xml.charCodeAt(pos)))
1094
- pos++;
1095
- const orderedNode = { [tagName]: [] };
1096
- if (hasAttrs) {
1097
- const attrKey = ":@";
1098
- orderedNode[attrKey] = {};
1099
- for (const name in attrs) {
1100
- orderedNode[attrKey][this._attrPrefix + name] = this.parseAttributeValue(attrs[name]);
1101
- }
1102
- }
1103
- if (pos < len && xml.charCodeAt(pos) === 47) {
1104
- pos += 2;
1105
- parent.push(orderedNode);
1106
- continue;
1107
- }
1108
- if (pos < len && xml.charCodeAt(pos) === 62) {
1109
- pos++;
1110
- pos = this.parseChildrenOrdered(xml, pos, len, orderedNode[tagName], childJPath);
1111
- parent.push(orderedNode);
1112
- }
1113
- }
1114
- if (textContent) {
1115
- const processed = this.processTagValue(textContent, this._textNodeName, jPath, false, true);
1116
- if (processed !== undefined && processed !== "")
1117
- parent.push({ [this._textNodeName]: processed });
1118
- }
1119
- return pos;
1120
- }
1121
- applyAttributes(obj, attrs, jPath) {
1122
- const prefix = this._attrPrefix;
1123
- if (this._attrsGroupName) {
1124
- const group = {};
1125
- for (const name in attrs) {
1126
- group[prefix + name] = this.parseAttributeValue(attrs[name]);
1127
- }
1128
- obj[this._attrsGroupName] = group;
1129
- } else {
1130
- for (const name in attrs) {
1131
- obj[prefix + name] = this.parseAttributeValue(attrs[name]);
1132
- }
1133
- }
1134
- }
1135
- parsePiAttributes(content) {
1136
- const attrs = {};
1137
- let i = 0;
1138
- const len = content.length;
1139
- while (i < len) {
1140
- while (i < len && isWhitespace(content.charCodeAt(i)))
1141
- i++;
1142
- if (i >= len)
1143
- break;
1144
- const nameStart = i;
1145
- while (i < len && !isWhitespace(content.charCodeAt(i)) && content.charCodeAt(i) !== 61)
1146
- i++;
1147
- const name = content.substring(nameStart, i);
1148
- if (!name)
1149
- break;
1150
- while (i < len && isWhitespace(content.charCodeAt(i)))
1151
- i++;
1152
- if (i < len && content.charCodeAt(i) === 61) {
1153
- i++;
1154
- while (i < len && isWhitespace(content.charCodeAt(i)))
1155
- i++;
1156
- if (i < len) {
1157
- const quote = content.charCodeAt(i);
1158
- if (quote === 34 || quote === 39) {
1159
- i++;
1160
- const valueStart = i;
1161
- while (i < len && content.charCodeAt(i) !== quote)
1162
- i++;
1163
- attrs[name] = content.substring(valueStart, i);
1164
- if (i < len)
1165
- i++;
1166
- }
1167
- }
1168
- }
1169
- }
1170
- return attrs;
1171
- }
1172
- }
1173
-
1174
- // src/aws/client.ts
1175
- function resolveS3Endpoint(options) {
1176
- const rawEndpoint = options.endpoint || `s3.${options.region}.amazonaws.com`;
1177
- const parsed = new URL(/^https?:\/\//i.test(rawEndpoint) ? rawEndpoint : `https://${rawEndpoint}`);
1178
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || parsed.pathname !== "/" && parsed.pathname !== "" || parsed.search || parsed.hash || parsed.username || parsed.password) {
1179
- throw new Error("S3 endpoint must be an HTTP(S) origin without a path");
1180
- }
1181
- const protocol = parsed.protocol.slice(0, -1);
1182
- const base = parsed.host;
1183
- if (!options.bucket) {
1184
- return { protocol, host: base, path: options.path };
1185
- }
1186
- if (options.forcePathStyle) {
1187
- const path = options.path === "/" ? `/${options.bucket}` : `/${options.bucket}${options.path}`;
1188
- return { protocol, host: base, path };
1189
- }
1190
- return { protocol, host: `${options.bucket}.${base}`, path: options.path };
1191
- }
1192
-
1193
- class AWSClient {
1194
- credentials;
1195
- config;
1196
- cache;
1197
- xmlParser;
1198
- constructor(credentials, config) {
1199
- this.config = {
1200
- maxRetries: 3,
1201
- retryDelay: 1000,
1202
- cacheEnabled: true,
1203
- defaultCacheTTL: 60000,
1204
- ...config
1205
- };
1206
- this.credentials = credentials || this.loadCredentials();
1207
- this.cache = new Map;
1208
- this.xmlParser = new XMLParser({
1209
- ignoreAttributes: false,
1210
- attributeNamePrefix: "@_",
1211
- textNodeName: "#text",
1212
- parseAttributeValue: true,
1213
- trimValues: true
1214
- });
1215
- }
1216
- loadCredentials() {
1217
- const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
1218
- const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
1219
- const sessionToken = process.env.AWS_SESSION_TOKEN;
1220
- if (accessKeyId && secretAccessKey) {
1221
- return {
1222
- accessKeyId,
1223
- secretAccessKey,
1224
- sessionToken
1225
- };
1226
- }
1227
- const fileCredentials = this.loadCredentialsFromFile();
1228
- if (fileCredentials) {
1229
- return fileCredentials;
1230
- }
1231
- return {
1232
- accessKeyId: "",
1233
- secretAccessKey: ""
1234
- };
1235
- }
1236
- loadCredentialsFromFile() {
1237
- const profile = this.config?.profile || process.env.AWS_PROFILE || "default";
1238
- const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE || join(homedir(), ".aws", "credentials");
1239
- if (!existsSync(credentialsPath)) {
1240
- return null;
1241
- }
1242
- try {
1243
- const content = readFileSync(credentialsPath, "utf-8");
1244
- const credentials = this.parseCredentialsFile(content, profile);
1245
- if (credentials.accessKeyId && credentials.secretAccessKey) {
1246
- return credentials;
1247
- }
1248
- } catch {}
1249
- return null;
1250
- }
1251
- parseCredentialsFile(content, profile) {
1252
- const lines = content.split(`
1253
- `);
1254
- let currentProfile = "";
1255
- let accessKeyId = "";
1256
- let secretAccessKey = "";
1257
- let sessionToken;
1258
- for (const line of lines) {
1259
- const trimmed = line.trim();
1260
- if (!trimmed || trimmed.startsWith("#")) {
1261
- continue;
1262
- }
1263
- const profileMatch = trimmed.match(/^\[([^\]]+)\]$/);
1264
- if (profileMatch) {
1265
- currentProfile = profileMatch[1];
1266
- continue;
1267
- }
1268
- if (currentProfile === profile) {
1269
- const [key, ...valueParts] = trimmed.split("=");
1270
- const value = valueParts.join("=").trim();
1271
- if (key.trim() === "aws_access_key_id") {
1272
- accessKeyId = value;
1273
- } else if (key.trim() === "aws_secret_access_key") {
1274
- secretAccessKey = value;
1275
- } else if (key.trim() === "aws_session_token") {
1276
- sessionToken = value;
1277
- }
1278
- }
1279
- }
1280
- return { accessKeyId, secretAccessKey, sessionToken };
1281
- }
1282
- ec2CredentialsCache;
1283
- async getCredentials() {
1284
- const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
1285
- const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
1286
- if (accessKeyId && secretAccessKey) {
1287
- return {
1288
- accessKeyId,
1289
- secretAccessKey,
1290
- sessionToken: process.env.AWS_SESSION_TOKEN
1291
- };
1292
- }
1293
- const fileCredentials = this.loadCredentialsFromFile();
1294
- if (fileCredentials) {
1295
- return fileCredentials;
1296
- }
1297
- if (this.ec2CredentialsCache) {
1298
- const now = Date.now();
1299
- if (this.ec2CredentialsCache.expiration > now + 5 * 60 * 1000) {
1300
- return this.ec2CredentialsCache.credentials;
1301
- }
1302
- }
1303
- try {
1304
- const tokenResponse = await fetch("http://169.254.169.254/latest/api/token", {
1305
- method: "PUT",
1306
- headers: {
1307
- "X-aws-ec2-metadata-token-ttl-seconds": "21600"
1308
- }
1309
- });
1310
- const token = await tokenResponse.text();
1311
- const roleResponse = await fetch("http://169.254.169.254/latest/meta-data/iam/security-credentials/", {
1312
- headers: { "X-aws-ec2-metadata-token": token }
1313
- });
1314
- const roleName = await roleResponse.text();
1315
- const credsResponse = await fetch(`http://169.254.169.254/latest/meta-data/iam/security-credentials/${roleName}`, {
1316
- headers: { "X-aws-ec2-metadata-token": token }
1317
- });
1318
- const credsData = await credsResponse.json();
1319
- const credentials = {
1320
- accessKeyId: credsData.AccessKeyId,
1321
- secretAccessKey: credsData.SecretAccessKey,
1322
- sessionToken: credsData.Token
1323
- };
1324
- this.ec2CredentialsCache = {
1325
- credentials,
1326
- expiration: new Date(credsData.Expiration).getTime()
1327
- };
1328
- return credentials;
1329
- } catch (error) {
1330
- throw new Error("AWS credentials not found. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, or run on an EC2 instance with an IAM role.");
1331
- }
1332
- }
1333
- async request(options) {
1334
- if (options.method === "GET" && this.config.cacheEnabled && options.cacheKey) {
1335
- const cached = this.getFromCache(options.cacheKey);
1336
- if (cached !== null) {
1337
- return cached;
1338
- }
1339
- }
1340
- const maxRetries = options.retries ?? this.config.maxRetries ?? 3;
1341
- let lastError = null;
1342
- for (let attempt = 0;attempt <= maxRetries; attempt++) {
1343
- try {
1344
- const result = await this.makeRequest(options);
1345
- if (options.method === "GET" && this.config.cacheEnabled && options.cacheKey) {
1346
- this.setInCache(options.cacheKey, result, options.cacheTTL ?? this.config.defaultCacheTTL ?? 60000);
1347
- }
1348
- return result;
1349
- } catch (error) {
1350
- lastError = error;
1351
- const isRetryable = this.shouldRetry(error);
1352
- if (!isRetryable) {
1353
- throw error;
1354
- }
1355
- if (attempt === maxRetries) {
1356
- throw error;
1357
- }
1358
- const delay = this.calculateRetryDelay(attempt);
1359
- await this.sleep(delay);
1360
- }
1361
- }
1362
- throw lastError || new Error("Request failed after retries");
1363
- }
1364
- async makeRequest(options) {
1365
- const credentials = options.credentials || (this.credentials?.accessKeyId ? this.credentials : await this.getCredentials());
1366
- if (!credentials || !credentials.accessKeyId || !credentials.secretAccessKey) {
1367
- throw new Error("AWS credentials not provided");
1368
- }
1369
- const url = this.buildUrl(options);
1370
- const headers = this.signRequest(options, credentials);
1371
- const response = await fetch(url, {
1372
- method: options.method,
1373
- headers,
1374
- body: options.body
1375
- });
1376
- const responseText = await response.text();
1377
- if (!response.ok) {
1378
- throw this.parseError(responseText, response.status, response.headers);
1379
- }
1380
- if (!responseText || responseText.trim() === "") {
1381
- if (options.returnHeaders) {
1382
- return { body: null, headers: this.headersToObject(response.headers) };
1383
- }
1384
- return null;
1385
- }
1386
- if (options.rawResponse) {
1387
- if (options.returnHeaders) {
1388
- return { body: responseText, headers: this.headersToObject(response.headers) };
1389
- }
1390
- return responseText;
1391
- }
1392
- let body;
1393
- if (responseText.startsWith("<")) {
1394
- body = this.parseXmlResponse(responseText);
1395
- } else {
1396
- try {
1397
- body = JSON.parse(responseText);
1398
- } catch {
1399
- body = responseText;
1400
- }
1401
- }
1402
- if (options.returnHeaders) {
1403
- return { body, headers: this.headersToObject(response.headers) };
1404
- }
1405
- return body;
1406
- }
1407
- headersToObject(headers) {
1408
- const result = {};
1409
- headers.forEach((value, key) => {
1410
- result[key] = value;
1411
- });
1412
- return result;
1413
- }
1414
- buildUrl(options) {
1415
- const { service, region, queryParams } = options;
1416
- let { path } = options;
1417
- let host;
1418
- let protocol = "https";
1419
- if (service === "s3") {
1420
- const resolved = resolveS3Endpoint({
1421
- region,
1422
- path,
1423
- bucket: options.bucket,
1424
- endpoint: this.config.endpoint,
1425
- forcePathStyle: this.config.forcePathStyle
1426
- });
1427
- protocol = resolved.protocol;
1428
- host = resolved.host;
1429
- path = resolved.path;
1430
- } else if (service === "cloudfront") {
1431
- host = "cloudfront.amazonaws.com";
1432
- } else if (service === "iam") {
1433
- host = "iam.amazonaws.com";
1434
- } else if (service === "route53") {
1435
- host = "route53.amazonaws.com";
1436
- } else if (service === "route53domains") {
1437
- host = "route53domains.us-east-1.amazonaws.com";
1438
- } else if (service === "ecr") {
1439
- host = `api.ecr.${region}.amazonaws.com`;
1440
- } else if (service === "ses") {
1441
- host = `email.${region}.amazonaws.com`;
1442
- } else {
1443
- host = `${service}.${region}.amazonaws.com`;
1444
- }
1445
- let url = `${protocol}://${host}${path}`;
1446
- if (queryParams && Object.keys(queryParams).length > 0) {
1447
- const queryString = Object.keys(queryParams).map((k) => `${this.uriEncode(k)}=${this.uriEncode(queryParams[k])}`).join("&");
1448
- url += `?${queryString}`;
1449
- }
1450
- return url;
1451
- }
1452
- signRequest(options, credentials) {
1453
- const { service, region, method, queryParams, body } = options;
1454
- let { path } = options;
1455
- const now = new Date;
1456
- const amzDate = this.getAmzDate(now);
1457
- const dateStamp = this.getDateStamp(now);
1458
- let host;
1459
- if (service === "s3") {
1460
- const resolved = resolveS3Endpoint({
1461
- region,
1462
- path,
1463
- bucket: options.bucket,
1464
- endpoint: this.config.endpoint,
1465
- forcePathStyle: this.config.forcePathStyle
1466
- });
1467
- host = resolved.host;
1468
- path = resolved.path;
1469
- } else if (service === "cloudfront") {
1470
- host = "cloudfront.amazonaws.com";
1471
- } else if (service === "iam") {
1472
- host = "iam.amazonaws.com";
1473
- } else if (service === "route53") {
1474
- host = "route53.amazonaws.com";
1475
- } else if (service === "route53domains") {
1476
- host = "route53domains.us-east-1.amazonaws.com";
1477
- } else if (service === "ecr") {
1478
- host = `api.ecr.${region}.amazonaws.com`;
1479
- } else if (service === "ses") {
1480
- host = `email.${region}.amazonaws.com`;
1481
- } else {
1482
- host = `${service}.${region}.amazonaws.com`;
1483
- }
1484
- const headers = {
1485
- host,
1486
- "x-amz-date": amzDate,
1487
- ...options.headers || {}
1488
- };
1489
- if (credentials.sessionToken) {
1490
- headers["x-amz-security-token"] = credentials.sessionToken;
1491
- }
1492
- if (body) {
1493
- const hasContentType = Object.keys(headers).some((k) => k.toLowerCase() === "content-type");
1494
- if (!hasContentType) {
1495
- headers["content-type"] = "application/x-www-form-urlencoded";
1496
- }
1497
- headers["content-length"] = Buffer.byteLength(body).toString();
1498
- }
1499
- const payloadHash = this.sha256(body || "");
1500
- headers["x-amz-content-sha256"] = payloadHash;
1501
- const canonicalUri = path;
1502
- const canonicalQueryString = queryParams ? Object.keys(queryParams).sort().map((k) => `${this.uriEncode(k)}=${this.uriEncode(queryParams[k])}`).join("&") : "";
1503
- const sortedHeaderKeys = Object.keys(headers).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
1504
- const canonicalHeaders = sortedHeaderKeys.map((key) => `${key.toLowerCase()}:${headers[key].trim()}
1505
- `).join("");
1506
- const signedHeaders = sortedHeaderKeys.map((key) => key.toLowerCase()).join(";");
1507
- const canonicalRequest = [
1508
- method,
1509
- canonicalUri,
1510
- canonicalQueryString,
1511
- canonicalHeaders,
1512
- signedHeaders,
1513
- payloadHash
1514
- ].join(`
1515
- `);
1516
- const algorithm = "AWS4-HMAC-SHA256";
1517
- let signingService = service;
1518
- if (service === "email")
1519
- signingService = "ses";
1520
- const credentialScope = `${dateStamp}/${region}/${signingService}/aws4_request`;
1521
- const stringToSign = [algorithm, amzDate, credentialScope, this.sha256(canonicalRequest)].join(`
1522
- `);
1523
- const signingKey = this.getSignatureKey(credentials.secretAccessKey, dateStamp, region, signingService);
1524
- const signature = this.hmac(signingKey, stringToSign);
1525
- const authorizationHeader = `${algorithm} Credential=${credentials.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
1526
- return {
1527
- ...headers,
1528
- Authorization: authorizationHeader
1529
- };
1530
- }
1531
- getAmzDate(date) {
1532
- return date.toISOString().replace(/[:-]|\.\d{3}/g, "");
1533
- }
1534
- getDateStamp(date) {
1535
- return date.toISOString().slice(0, 10).replace(/-/g, "");
1536
- }
1537
- uriEncode(str) {
1538
- return encodeURIComponent(str).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
1539
- }
1540
- sha256(data) {
1541
- return crypto.createHash("sha256").update(data, "utf8").digest("hex");
1542
- }
1543
- hmac(key, data) {
1544
- return crypto.createHmac("sha256", key).update(data, "utf8").digest("hex");
1545
- }
1546
- getSignatureKey(key, dateStamp, region, service) {
1547
- const kDate = crypto.createHmac("sha256", `AWS4${key}`).update(dateStamp).digest();
1548
- const kRegion = crypto.createHmac("sha256", kDate).update(region).digest();
1549
- const kService = crypto.createHmac("sha256", kRegion).update(service).digest();
1550
- const kSigning = crypto.createHmac("sha256", kService).update("aws4_request").digest();
1551
- return kSigning;
1552
- }
1553
- parseXmlResponse(xml) {
1554
- try {
1555
- const parsed = this.xmlParser.parse(xml);
1556
- if (parsed.ErrorResponse) {
1557
- throw this.createErrorFromXml(parsed.ErrorResponse.Error);
1558
- }
1559
- const keys = Object.keys(parsed);
1560
- if (keys.length === 1) {
1561
- return parsed[keys[0]];
1562
- }
1563
- return parsed;
1564
- } catch (error) {
1565
- if (error.code || error.statusCode) {
1566
- throw error;
1567
- }
1568
- return {};
1569
- }
1570
- }
1571
- parseError(responseText, statusCode, headers) {
1572
- const error = new Error;
1573
- error.statusCode = statusCode;
1574
- error.requestId = headers.get("x-amzn-requestid") || headers.get("x-amz-request-id") || undefined;
1575
- if (responseText.startsWith("<")) {
1576
- try {
1577
- const parsed = this.xmlParser.parse(responseText);
1578
- if (parsed.ErrorResponse?.Error) {
1579
- const awsError = parsed.ErrorResponse.Error;
1580
- error.code = awsError.Code;
1581
- error.message = `AWS Error [${awsError.Code}]: ${awsError.Message || "Unknown error"}`;
1582
- error.type = awsError.Type;
1583
- return error;
1584
- }
1585
- if (parsed.Error) {
1586
- error.code = parsed.Error.Code;
1587
- error.message = `AWS Error [${parsed.Error.Code}]: ${parsed.Error.Message || "Unknown error"}`;
1588
- return error;
1589
- }
1590
- } catch {}
1591
- }
1592
- try {
1593
- const json = JSON.parse(responseText);
1594
- if (json.__type || json.code) {
1595
- error.code = json.__type || json.code;
1596
- error.message = `AWS Error [${error.code}]: ${json.message || json.Message || "Unknown error"}`;
1597
- return error;
1598
- }
1599
- } catch {}
1600
- error.message = `AWS API Error (${statusCode}): ${responseText}`;
1601
- return error;
1602
- }
1603
- createErrorFromXml(errorData) {
1604
- const error = new Error;
1605
- error.code = errorData.Code;
1606
- error.message = `AWS Error [${errorData.Code}]: ${errorData.Message || "Unknown error"}`;
1607
- error.type = errorData.Type;
1608
- return error;
1609
- }
1610
- isRetryableError(code) {
1611
- const retryableCodes = [
1612
- "RequestTimeout",
1613
- "RequestTimeoutException",
1614
- "PriorRequestNotComplete",
1615
- "ConnectionError",
1616
- "ThrottlingException",
1617
- "Throttling",
1618
- "TooManyRequestsException",
1619
- "ProvisionedThroughputExceededException",
1620
- "RequestLimitExceeded",
1621
- "BandwidthLimitExceeded",
1622
- "SlowDown",
1623
- "ServiceUnavailable",
1624
- "ServiceUnavailableException",
1625
- "InternalError",
1626
- "InternalFailure",
1627
- "InternalServerError",
1628
- "InternalServiceException",
1629
- "TransientError",
1630
- "TransientFailure",
1631
- "IDPCommunicationErrorException",
1632
- "NetworkError",
1633
- "ConnectionRefusedException",
1634
- "EC2ThrottledException",
1635
- "503 Slow Down",
1636
- "500 InternalError"
1637
- ];
1638
- return retryableCodes.includes(code);
1639
- }
1640
- isRetryableStatusCode(statusCode) {
1641
- return statusCode >= 500 || statusCode === 429;
1642
- }
1643
- shouldRetry(error) {
1644
- if (error.name === "FetchError" || error.name === "TypeError" || error.code === "ECONNRESET") {
1645
- return true;
1646
- }
1647
- if (error.code && this.isRetryableError(error.code)) {
1648
- return true;
1649
- }
1650
- if (error.statusCode && this.isRetryableStatusCode(error.statusCode)) {
1651
- return true;
1652
- }
1653
- if (error.statusCode && error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429) {
1654
- return false;
1655
- }
1656
- if (error.statusCode) {
1657
- return false;
1658
- }
1659
- return true;
1660
- }
1661
- calculateRetryDelay(attempt) {
1662
- const baseDelay = this.config.retryDelay ?? 1000;
1663
- const maxDelay = 30000;
1664
- const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
1665
- const jitter = Math.random() * 0.3 * delay;
1666
- return delay + jitter;
1667
- }
1668
- sleep(ms) {
1669
- return new Promise((resolve) => setTimeout(resolve, ms));
1670
- }
1671
- getFromCache(key) {
1672
- const entry = this.cache.get(key);
1673
- if (!entry) {
1674
- return null;
1675
- }
1676
- if (Date.now() > entry.expires) {
1677
- this.cache.delete(key);
1678
- return null;
1679
- }
1680
- return entry.data;
1681
- }
1682
- setInCache(key, data, ttl) {
1683
- this.cache.set(key, {
1684
- data,
1685
- expires: Date.now() + ttl
1686
- });
1687
- }
1688
- clearCache() {
1689
- this.cache.clear();
1690
- }
1691
- clearExpiredCache() {
1692
- const now = Date.now();
1693
- for (const [key, entry] of this.cache.entries()) {
1694
- if (now > entry.expires) {
1695
- this.cache.delete(key);
1696
- }
1697
- }
1698
- }
1699
- }
1700
- function buildQueryParams(params) {
1701
- const result = {};
1702
- for (const [key, value] of Object.entries(params)) {
1703
- if (value === undefined || value === null) {
1704
- continue;
1705
- }
1706
- if (Array.isArray(value)) {
1707
- value.forEach((item, index) => {
1708
- result[`${key}.${index + 1}`] = String(item);
1709
- });
1710
- } else if (typeof value === "object") {
1711
- for (const [subKey, subValue] of Object.entries(value)) {
1712
- result[`${key}.${subKey}`] = String(subValue);
1713
- }
1714
- } else {
1715
- result[key] = String(value);
1716
- }
1717
- }
1718
- return result;
1719
- }
1720
- function detectCredentialSource() {
1721
- const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
1722
- const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
1723
- const emptyEnvKey = accessKeyId === "";
1724
- const emptyEnvSecret = secretAccessKey === "";
1725
- if (accessKeyId && secretAccessKey) {
1726
- return {
1727
- source: "env",
1728
- emptyEnvKey,
1729
- emptyEnvSecret,
1730
- description: "environment variables (AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY)"
1731
- };
1732
- }
1733
- const profile = process.env.AWS_PROFILE || "default";
1734
- const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE || join(homedir(), ".aws", "credentials");
1735
- if (existsSync(credentialsPath)) {
1736
- return {
1737
- source: "file",
1738
- profile,
1739
- emptyEnvKey,
1740
- emptyEnvSecret,
1741
- description: `~/.aws/credentials (profile: ${profile})`
1742
- };
1743
- }
1744
- return {
1745
- source: "ec2",
1746
- emptyEnvKey,
1747
- emptyEnvSecret,
1748
- description: "EC2 instance metadata service (IMDSv2)"
1749
- };
1750
- }
1751
-
1752
- export { resolveS3Endpoint, AWSClient, buildQueryParams, detectCredentialSource };