Created
October 29, 2022 07:33
-
-
Save josephrocca/332e516102e039c2190a48da43519c5f to your computer and use it in GitHub Desktop.
AWS S3 (v3) working in Deno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as AWS from "./aws_sdk_client_s3_v3.198.0-es.js"; | |
let s3 = new AWS.S3({ | |
region: "YOUR_REGION", | |
endpoint: "YOUR_ENDPOINT_URL_IF_NECCESSARY", | |
credentials: { | |
accessKeyId: "YOUR_ACCESS_KEY", | |
secretAccessKey: "YOUR_SECRET", | |
}, | |
}); | |
let result = await s3.putObject({ | |
Bucket: "YOUR_BUCKET_NAME", | |
Key: "hello_world.txt", | |
Body: "Hello World! | |
}); | |
console.log("Success."); | |
// HOW TO CREATE aws_sdk_client_s3_v3.198.0-es.js YOURSELF: | |
// (because you shouldn't trust random scripts like this on the web) | |
// (and also because you may want to update to a newer version) | |
// STEP 1: Run this command: deno bundle https://cdn.skypack.dev/@aws-sdk/client-s3@3.198.0/dist-es/index.js | |
// STEP 2: Manually replace all instances of `thing.__proto__ = otherThing` with `Object.setPrototypeOf(thing, otherThing)` until this is fixed: https://github.com/skypackjs/skypack-cdn/issues/327 | |
// That's it. |
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// deno-fmt-ignore-file | |
// deno-lint-ignore-file | |
// This code was bundled using `deno bundle` and it's not recommended to edit it manually | |
function parseQueryString(querystring) { | |
const query = {}; | |
querystring = querystring.replace(/^\?/, ""); | |
if (querystring) { | |
for (const pair of querystring.split("&")){ | |
let [key, value = null] = pair.split("="); | |
key = decodeURIComponent(key); | |
if (value) { | |
value = decodeURIComponent(value); | |
} | |
if (!(key in query)) { | |
query[key] = value; | |
} else if (Array.isArray(query[key])) { | |
query[key].push(value); | |
} else { | |
query[key] = [ | |
query[key], | |
value | |
]; | |
} | |
} | |
} | |
return query; | |
} | |
const parseUrl = (url)=>{ | |
if (typeof url === "string") { | |
return parseUrl(new URL(url)); | |
} | |
const { hostname , pathname , port , protocol , search } = url; | |
let query; | |
if (search) { | |
query = parseQueryString(search); | |
} | |
return { | |
hostname, | |
port: port ? parseInt(port) : void 0, | |
protocol, | |
path: pathname, | |
query | |
}; | |
}; | |
const deserializerMiddleware = (options, deserializer)=>(next, context)=>async (args)=>{ | |
const { response } = await next(args); | |
try { | |
const parsed = await deserializer(response, options); | |
return { | |
response, | |
output: parsed | |
}; | |
} catch (error) { | |
Object.defineProperty(error, "$response", { | |
value: response | |
}); | |
throw error; | |
} | |
}; | |
const serializerMiddleware = (options, serializer)=>(next, context)=>async (args)=>{ | |
var _a; | |
const endpoint = ((_a = context.endpointV2) == null ? void 0 : _a.url) && options.urlParser ? async ()=>options.urlParser(context.endpointV2.url) : options.endpoint; | |
if (!endpoint) { | |
throw new Error("No valid endpoint provider available."); | |
} | |
const request = await serializer(args.input, { | |
...options, | |
endpoint | |
}); | |
return next({ | |
...args, | |
request | |
}); | |
}; | |
const deserializerMiddlewareOption = { | |
name: "deserializerMiddleware", | |
step: "deserialize", | |
tags: [ | |
"DESERIALIZER" | |
], | |
override: true | |
}; | |
const serializerMiddlewareOption = { | |
name: "serializerMiddleware", | |
step: "serialize", | |
tags: [ | |
"SERIALIZER" | |
], | |
override: true | |
}; | |
function getSerdePlugin(config, serializer, deserializer) { | |
return { | |
applyToStack: (commandStack)=>{ | |
commandStack.add(deserializerMiddleware(config, deserializer), deserializerMiddlewareOption); | |
commandStack.add(serializerMiddleware(config, serializer), serializerMiddlewareOption); | |
} | |
}; | |
} | |
const normalizeProvider = (input)=>{ | |
if (typeof input === "function") return input; | |
const promisified = Promise.resolve(input); | |
return ()=>promisified; | |
}; | |
const resolveParamsForS3 = async (endpointParams)=>{ | |
const bucket = (endpointParams == null ? void 0 : endpointParams.Bucket) || ""; | |
if (typeof endpointParams.Bucket === "string") { | |
endpointParams.Bucket = bucket.replace(/#/g, encodeURIComponent("#")).replace(/\?/g, encodeURIComponent("?")); | |
} | |
if (isArnBucketName(bucket)) { | |
if (endpointParams.ForcePathStyle === true) { | |
throw new Error("Path-style addressing cannot be used with ARN buckets"); | |
} | |
} else if (!isDnsCompatibleBucketName(bucket) || bucket.indexOf(".") !== -1 && !String(endpointParams.Endpoint).startsWith("http:") || bucket.toLowerCase() !== bucket || bucket.length < 3) { | |
endpointParams.ForcePathStyle = true; | |
} | |
if (endpointParams.DisableMultiRegionAccessPoints) { | |
endpointParams.disableMultiRegionAccessPoints = true; | |
endpointParams.DisableMRAP = true; | |
} | |
return endpointParams; | |
}; | |
const DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/; | |
const IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/; | |
const DOTS_PATTERN = /\.\./; | |
const isDnsCompatibleBucketName = (bucketName)=>DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName); | |
const isArnBucketName = (bucketName)=>{ | |
const [arn, partition, service, region, account, typeOrId] = bucketName.split(":"); | |
const isArn = arn === "arn" && bucketName.split(":").length >= 6; | |
const isValidArn = [ | |
arn, | |
partition, | |
service, | |
account, | |
typeOrId | |
].filter(Boolean).length === 5; | |
if (isArn && !isValidArn) { | |
throw new Error(`Invalid ARN: ${bucketName} was an invalid ARN.`); | |
} | |
return arn === "arn" && !!partition && !!service && !!account && !!typeOrId; | |
}; | |
const createConfigValueProvider = (configKey, canonicalEndpointParamKey, config)=>{ | |
const configProvider = async ()=>{ | |
var _a; | |
const configValue = (_a = config[configKey]) != null ? _a : config[canonicalEndpointParamKey]; | |
if (typeof configValue === "function") { | |
return configValue(); | |
} | |
return configValue; | |
}; | |
if (configKey === "endpoint" || canonicalEndpointParamKey === "endpoint") { | |
return async ()=>{ | |
const endpoint = await configProvider(); | |
if (endpoint && typeof endpoint === "object") { | |
if ("url" in endpoint) { | |
return endpoint.url.href; | |
} | |
if ("hostname" in endpoint) { | |
const { protocol , hostname , port , path } = endpoint; | |
return `${protocol}//${hostname}${port ? ":" + port : ""}${path}`; | |
} | |
} | |
return endpoint; | |
}; | |
} | |
return configProvider; | |
}; | |
const getEndpointFromInstructions = async (commandInput, instructionsSupplier, clientConfig, context)=>{ | |
const endpointParams = await resolveParams(commandInput, instructionsSupplier, clientConfig); | |
if (typeof clientConfig.endpointProvider !== "function") { | |
throw new Error("config.endpointProvider is not set."); | |
} | |
const endpoint = clientConfig.endpointProvider(endpointParams, context); | |
return endpoint; | |
}; | |
const resolveParams = async (commandInput, instructionsSupplier, clientConfig)=>{ | |
var _a; | |
const endpointParams = {}; | |
const instructions = ((_a = instructionsSupplier == null ? void 0 : instructionsSupplier.getEndpointParameterInstructions) == null ? void 0 : _a.call(instructionsSupplier)) || {}; | |
for (const [name, instruction] of Object.entries(instructions)){ | |
switch(instruction.type){ | |
case "staticContextParams": | |
endpointParams[name] = instruction.value; | |
break; | |
case "contextParams": | |
endpointParams[name] = commandInput[instruction.name]; | |
break; | |
case "clientContextParams": | |
case "builtInParams": | |
endpointParams[name] = await createConfigValueProvider(instruction.name, name, clientConfig)(); | |
break; | |
default: | |
throw new Error("Unrecognized endpoint parameter instruction: " + JSON.stringify(instruction)); | |
} | |
} | |
if (Object.keys(instructions).length === 0) { | |
Object.assign(endpointParams, clientConfig); | |
} | |
if (String(clientConfig.serviceId).toLowerCase() === "s3") { | |
await resolveParamsForS3(endpointParams); | |
} | |
return endpointParams; | |
}; | |
const toEndpointV1 = (endpoint)=>{ | |
if (typeof endpoint === "object") { | |
if ("url" in endpoint) { | |
return parseUrl(endpoint.url); | |
} | |
return endpoint; | |
} | |
return parseUrl(endpoint); | |
}; | |
const endpointMiddleware = ({ config , instructions })=>{ | |
return (next, context)=>async (args)=>{ | |
var _a, _b; | |
const endpoint = await getEndpointFromInstructions(args.input, { | |
getEndpointParameterInstructions () { | |
return instructions; | |
} | |
}, { | |
...config | |
}, context); | |
context.endpointV2 = endpoint; | |
context.authSchemes = (_a = endpoint.properties) == null ? void 0 : _a.authSchemes; | |
const authScheme = (_b = context.authSchemes) == null ? void 0 : _b[0]; | |
if (authScheme) { | |
context["signing_region"] = authScheme.signingRegion; | |
context["signing_service"] = authScheme.signingName; | |
} | |
return next({ | |
...args | |
}); | |
}; | |
}; | |
const endpointMiddlewareOptions = { | |
step: "serialize", | |
tags: [ | |
"ENDPOINT_PARAMETERS", | |
"ENDPOINT_V2", | |
"ENDPOINT" | |
], | |
name: "endpointV2Middleware", | |
override: true, | |
relation: "before", | |
toMiddleware: serializerMiddlewareOption.name | |
}; | |
const getEndpointPlugin = (config, instructions)=>({ | |
applyToStack: (clientStack)=>{ | |
clientStack.addRelativeTo(endpointMiddleware({ | |
config, | |
instructions | |
}), endpointMiddlewareOptions); | |
} | |
}); | |
const resolveEndpointConfig = (input)=>{ | |
var _a, _b, _c; | |
const tls = (_a = input.tls) != null ? _a : true; | |
const { endpoint } = input; | |
const customEndpointProvider = endpoint != null ? async ()=>toEndpointV1(await normalizeProvider(endpoint)()) : void 0; | |
const isCustomEndpoint = !!endpoint; | |
return { | |
...input, | |
endpoint: customEndpointProvider, | |
tls, | |
isCustomEndpoint, | |
useDualstackEndpoint: normalizeProvider((_b = input.useDualstackEndpoint) != null ? _b : false), | |
useFipsEndpoint: normalizeProvider((_c = input.useFipsEndpoint) != null ? _c : false) | |
}; | |
}; | |
const constructStack = ()=>{ | |
let absoluteEntries = []; | |
let relativeEntries = []; | |
const entriesNameSet = new Set(); | |
const sort = (entries)=>entries.sort((a, b)=>stepWeights[b.step] - stepWeights[a.step] || priorityWeights[b.priority || "normal"] - priorityWeights[a.priority || "normal"]); | |
const removeByName = (toRemove)=>{ | |
let isRemoved = false; | |
const filterCb = (entry)=>{ | |
if (entry.name && entry.name === toRemove) { | |
isRemoved = true; | |
entriesNameSet.delete(toRemove); | |
return false; | |
} | |
return true; | |
}; | |
absoluteEntries = absoluteEntries.filter(filterCb); | |
relativeEntries = relativeEntries.filter(filterCb); | |
return isRemoved; | |
}; | |
const removeByReference = (toRemove)=>{ | |
let isRemoved = false; | |
const filterCb = (entry)=>{ | |
if (entry.middleware === toRemove) { | |
isRemoved = true; | |
if (entry.name) entriesNameSet.delete(entry.name); | |
return false; | |
} | |
return true; | |
}; | |
absoluteEntries = absoluteEntries.filter(filterCb); | |
relativeEntries = relativeEntries.filter(filterCb); | |
return isRemoved; | |
}; | |
const cloneTo = (toStack)=>{ | |
absoluteEntries.forEach((entry)=>{ | |
toStack.add(entry.middleware, { | |
...entry | |
}); | |
}); | |
relativeEntries.forEach((entry)=>{ | |
toStack.addRelativeTo(entry.middleware, { | |
...entry | |
}); | |
}); | |
return toStack; | |
}; | |
const expandRelativeMiddlewareList = (from)=>{ | |
const expandedMiddlewareList = []; | |
from.before.forEach((entry)=>{ | |
if (entry.before.length === 0 && entry.after.length === 0) { | |
expandedMiddlewareList.push(entry); | |
} else { | |
expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry)); | |
} | |
}); | |
expandedMiddlewareList.push(from); | |
from.after.reverse().forEach((entry)=>{ | |
if (entry.before.length === 0 && entry.after.length === 0) { | |
expandedMiddlewareList.push(entry); | |
} else { | |
expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry)); | |
} | |
}); | |
return expandedMiddlewareList; | |
}; | |
const getMiddlewareList = (debug = false)=>{ | |
const normalizedAbsoluteEntries = []; | |
const normalizedRelativeEntries = []; | |
const normalizedEntriesNameMap = {}; | |
absoluteEntries.forEach((entry)=>{ | |
const normalizedEntry = { | |
...entry, | |
before: [], | |
after: [] | |
}; | |
if (normalizedEntry.name) normalizedEntriesNameMap[normalizedEntry.name] = normalizedEntry; | |
normalizedAbsoluteEntries.push(normalizedEntry); | |
}); | |
relativeEntries.forEach((entry)=>{ | |
const normalizedEntry = { | |
...entry, | |
before: [], | |
after: [] | |
}; | |
if (normalizedEntry.name) normalizedEntriesNameMap[normalizedEntry.name] = normalizedEntry; | |
normalizedRelativeEntries.push(normalizedEntry); | |
}); | |
normalizedRelativeEntries.forEach((entry)=>{ | |
if (entry.toMiddleware) { | |
const toMiddleware = normalizedEntriesNameMap[entry.toMiddleware]; | |
if (toMiddleware === void 0) { | |
if (debug) { | |
return; | |
} | |
throw new Error(`${entry.toMiddleware} is not found when adding ${entry.name || "anonymous"} middleware ${entry.relation} ${entry.toMiddleware}`); | |
} | |
if (entry.relation === "after") { | |
toMiddleware.after.push(entry); | |
} | |
if (entry.relation === "before") { | |
toMiddleware.before.push(entry); | |
} | |
} | |
}); | |
const mainChain = sort(normalizedAbsoluteEntries).map(expandRelativeMiddlewareList).reduce((wholeList, expendedMiddlewareList)=>{ | |
wholeList.push(...expendedMiddlewareList); | |
return wholeList; | |
}, []); | |
return mainChain; | |
}; | |
const stack = { | |
add: (middleware, options = {})=>{ | |
const { name , override } = options; | |
const entry = { | |
step: "initialize", | |
priority: "normal", | |
middleware, | |
...options | |
}; | |
if (name) { | |
if (entriesNameSet.has(name)) { | |
if (!override) throw new Error(`Duplicate middleware name '${name}'`); | |
const toOverrideIndex = absoluteEntries.findIndex((entry2)=>entry2.name === name); | |
const toOverride = absoluteEntries[toOverrideIndex]; | |
if (toOverride.step !== entry.step || toOverride.priority !== entry.priority) { | |
throw new Error(`"${name}" middleware with ${toOverride.priority} priority in ${toOverride.step} step cannot be overridden by same-name middleware with ${entry.priority} priority in ${entry.step} step.`); | |
} | |
absoluteEntries.splice(toOverrideIndex, 1); | |
} | |
entriesNameSet.add(name); | |
} | |
absoluteEntries.push(entry); | |
}, | |
addRelativeTo: (middleware, options)=>{ | |
const { name , override } = options; | |
const entry = { | |
middleware, | |
...options | |
}; | |
if (name) { | |
if (entriesNameSet.has(name)) { | |
if (!override) throw new Error(`Duplicate middleware name '${name}'`); | |
const toOverrideIndex = relativeEntries.findIndex((entry2)=>entry2.name === name); | |
const toOverride = relativeEntries[toOverrideIndex]; | |
if (toOverride.toMiddleware !== entry.toMiddleware || toOverride.relation !== entry.relation) { | |
throw new Error(`"${name}" middleware ${toOverride.relation} "${toOverride.toMiddleware}" middleware cannot be overridden by same-name middleware ${entry.relation} "${entry.toMiddleware}" middleware.`); | |
} | |
relativeEntries.splice(toOverrideIndex, 1); | |
} | |
entriesNameSet.add(name); | |
} | |
relativeEntries.push(entry); | |
}, | |
clone: ()=>cloneTo(constructStack()), | |
use: (plugin)=>{ | |
plugin.applyToStack(stack); | |
}, | |
remove: (toRemove)=>{ | |
if (typeof toRemove === "string") return removeByName(toRemove); | |
else return removeByReference(toRemove); | |
}, | |
removeByTag: (toRemove)=>{ | |
let isRemoved = false; | |
const filterCb = (entry)=>{ | |
const { tags , name } = entry; | |
if (tags && tags.includes(toRemove)) { | |
if (name) entriesNameSet.delete(name); | |
isRemoved = true; | |
return false; | |
} | |
return true; | |
}; | |
absoluteEntries = absoluteEntries.filter(filterCb); | |
relativeEntries = relativeEntries.filter(filterCb); | |
return isRemoved; | |
}, | |
concat: (from)=>{ | |
const cloned = cloneTo(constructStack()); | |
cloned.use(from); | |
return cloned; | |
}, | |
applyToStack: cloneTo, | |
identify: ()=>{ | |
return getMiddlewareList(true).map((mw)=>{ | |
return mw.name + ": " + (mw.tags || []).join(","); | |
}); | |
}, | |
resolve: (handler, context)=>{ | |
for (const middleware of getMiddlewareList().map((entry)=>entry.middleware).reverse()){ | |
handler = middleware(handler, context); | |
} | |
return handler; | |
} | |
}; | |
return stack; | |
}; | |
const stepWeights = { | |
initialize: 5, | |
serialize: 4, | |
build: 3, | |
finalizeRequest: 2, | |
deserialize: 1 | |
}; | |
const priorityWeights = { | |
high: 3, | |
normal: 2, | |
low: 1 | |
}; | |
class Client { | |
constructor(config2){ | |
this.middlewareStack = constructStack(); | |
this.config = config2; | |
} | |
send(command, optionsOrCb, cb) { | |
const options = typeof optionsOrCb !== "function" ? optionsOrCb : void 0; | |
const callback = typeof optionsOrCb === "function" ? optionsOrCb : cb; | |
const handler = command.resolveMiddleware(this.middlewareStack, this.config, options); | |
if (callback) { | |
handler(command).then((result)=>callback(null, result.output), (err)=>callback(err)).catch(()=>{}); | |
} else { | |
return handler(command).then((result)=>result.output); | |
} | |
} | |
destroy() { | |
if (this.config.requestHandler.destroy) this.config.requestHandler.destroy(); | |
} | |
} | |
class Command { | |
constructor(){ | |
this.middlewareStack = constructStack(); | |
} | |
} | |
const SENSITIVE_STRING = "***SensitiveInformation***"; | |
const parseBoolean = (value)=>{ | |
switch(value){ | |
case "true": | |
return true; | |
case "false": | |
return false; | |
default: | |
throw new Error(`Unable to parse boolean value "${value}"`); | |
} | |
}; | |
const expectNumber = (value)=>{ | |
if (value === null || value === void 0) { | |
return void 0; | |
} | |
if (typeof value === "string") { | |
const parsed = parseFloat(value); | |
if (!Number.isNaN(parsed)) { | |
if (String(parsed) !== String(value)) { | |
logger.warn(stackTraceWarning(`Expected number but observed string: ${value}`)); | |
} | |
return parsed; | |
} | |
} | |
if (typeof value === "number") { | |
return value; | |
} | |
throw new TypeError(`Expected number, got ${typeof value}: ${value}`); | |
}; | |
const MAX_FLOAT = Math.ceil(2 ** 127 * (2 - 2 ** -23)); | |
const expectFloat32 = (value)=>{ | |
const expected = expectNumber(value); | |
if (expected !== void 0 && !Number.isNaN(expected) && expected !== Infinity && expected !== -Infinity) { | |
if (Math.abs(expected) > MAX_FLOAT) { | |
throw new TypeError(`Expected 32-bit float, got ${value}`); | |
} | |
} | |
return expected; | |
}; | |
const expectLong = (value)=>{ | |
if (value === null || value === void 0) { | |
return void 0; | |
} | |
if (Number.isInteger(value) && !Number.isNaN(value)) { | |
return value; | |
} | |
throw new TypeError(`Expected integer, got ${typeof value}: ${value}`); | |
}; | |
const expectInt32 = (value)=>expectSizedInt(value, 32); | |
const expectShort = (value)=>expectSizedInt(value, 16); | |
const expectByte = (value)=>expectSizedInt(value, 8); | |
const expectSizedInt = (value, size)=>{ | |
const expected = expectLong(value); | |
if (expected !== void 0 && castInt(expected, size) !== expected) { | |
throw new TypeError(`Expected ${size}-bit integer, got ${value}`); | |
} | |
return expected; | |
}; | |
const castInt = (value, size)=>{ | |
switch(size){ | |
case 32: | |
return Int32Array.of(value)[0]; | |
case 16: | |
return Int16Array.of(value)[0]; | |
case 8: | |
return Int8Array.of(value)[0]; | |
} | |
}; | |
const expectNonNull = (value, location)=>{ | |
if (value === null || value === void 0) { | |
if (location) { | |
throw new TypeError(`Expected a non-null value for ${location}`); | |
} | |
throw new TypeError("Expected a non-null value"); | |
} | |
return value; | |
}; | |
const expectObject = (value)=>{ | |
if (value === null || value === void 0) { | |
return void 0; | |
} | |
if (typeof value === "object" && !Array.isArray(value)) { | |
return value; | |
} | |
const receivedType = Array.isArray(value) ? "array" : typeof value; | |
throw new TypeError(`Expected object, got ${receivedType}: ${value}`); | |
}; | |
const expectString = (value)=>{ | |
if (value === null || value === void 0) { | |
return void 0; | |
} | |
if (typeof value === "string") { | |
return value; | |
} | |
if ([ | |
"boolean", | |
"number", | |
"bigint" | |
].includes(typeof value)) { | |
logger.warn(stackTraceWarning(`Expected string, got ${typeof value}: ${value}`)); | |
return String(value); | |
} | |
throw new TypeError(`Expected string, got ${typeof value}: ${value}`); | |
}; | |
const expectUnion = (value)=>{ | |
if (value === null || value === void 0) { | |
return void 0; | |
} | |
const asObject = expectObject(value); | |
const setKeys = Object.entries(asObject).filter(([, v])=>v != null).map(([k])=>k); | |
if (setKeys.length === 0) { | |
throw new TypeError(`Unions must have exactly one non-null member. None were found.`); | |
} | |
if (setKeys.length > 1) { | |
throw new TypeError(`Unions must have exactly one non-null member. Keys ${setKeys} were not null.`); | |
} | |
return asObject; | |
}; | |
const strictParseFloat32 = (value)=>{ | |
if (typeof value == "string") { | |
return expectFloat32(parseNumber(value)); | |
} | |
return expectFloat32(value); | |
}; | |
const NUMBER_REGEX = /(-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)|(-?Infinity)|(NaN)/g; | |
const parseNumber = (value)=>{ | |
const matches = value.match(NUMBER_REGEX); | |
if (matches === null || matches[0].length !== value.length) { | |
throw new TypeError(`Expected real number, got implicit NaN`); | |
} | |
return parseFloat(value); | |
}; | |
const strictParseLong = (value)=>{ | |
if (typeof value === "string") { | |
return expectLong(parseNumber(value)); | |
} | |
return expectLong(value); | |
}; | |
const strictParseInt32 = (value)=>{ | |
if (typeof value === "string") { | |
return expectInt32(parseNumber(value)); | |
} | |
return expectInt32(value); | |
}; | |
const strictParseShort = (value)=>{ | |
if (typeof value === "string") { | |
return expectShort(parseNumber(value)); | |
} | |
return expectShort(value); | |
}; | |
const strictParseByte = (value)=>{ | |
if (typeof value === "string") { | |
return expectByte(parseNumber(value)); | |
} | |
return expectByte(value); | |
}; | |
const stackTraceWarning = (message)=>{ | |
return String(new TypeError(message).stack || message).split("\n").slice(0, 5).filter((s)=>!s.includes("stackTraceWarning")).join("\n"); | |
}; | |
const logger = { | |
warn: console.warn | |
}; | |
const DAYS = [ | |
"Sun", | |
"Mon", | |
"Tue", | |
"Wed", | |
"Thu", | |
"Fri", | |
"Sat" | |
]; | |
const MONTHS = [ | |
"Jan", | |
"Feb", | |
"Mar", | |
"Apr", | |
"May", | |
"Jun", | |
"Jul", | |
"Aug", | |
"Sep", | |
"Oct", | |
"Nov", | |
"Dec" | |
]; | |
function dateToUtcString(date) { | |
const year = date.getUTCFullYear(); | |
const month = date.getUTCMonth(); | |
const dayOfWeek = date.getUTCDay(); | |
const dayOfMonthInt = date.getUTCDate(); | |
const hoursInt = date.getUTCHours(); | |
const minutesInt = date.getUTCMinutes(); | |
const secondsInt = date.getUTCSeconds(); | |
const dayOfMonthString = dayOfMonthInt < 10 ? `0${dayOfMonthInt}` : `${dayOfMonthInt}`; | |
const hoursString = hoursInt < 10 ? `0${hoursInt}` : `${hoursInt}`; | |
const minutesString = minutesInt < 10 ? `0${minutesInt}` : `${minutesInt}`; | |
const secondsString = secondsInt < 10 ? `0${secondsInt}` : `${secondsInt}`; | |
return `${DAYS[dayOfWeek]}, ${dayOfMonthString} ${MONTHS[month]} ${year} ${hoursString}:${minutesString}:${secondsString} GMT`; | |
} | |
const RFC3339 = new RegExp(/^(\d{4})-(\d{2})-(\d{2})[tT](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?[zZ]$/); | |
const parseRfc3339DateTime = (value)=>{ | |
if (value === null || value === void 0) { | |
return void 0; | |
} | |
if (typeof value !== "string") { | |
throw new TypeError("RFC-3339 date-times must be expressed as strings"); | |
} | |
const match = RFC3339.exec(value); | |
if (!match) { | |
throw new TypeError("Invalid RFC-3339 date-time value"); | |
} | |
const [_, yearStr, monthStr, dayStr, hours, minutes, seconds, fractionalMilliseconds] = match; | |
const year = strictParseShort(stripLeadingZeroes(yearStr)); | |
const month = parseDateValue(monthStr, "month", 1, 12); | |
const day = parseDateValue(dayStr, "day", 1, 31); | |
return buildDate(year, month, day, { | |
hours, | |
minutes, | |
seconds, | |
fractionalMilliseconds | |
}); | |
}; | |
const IMF_FIXDATE = new RegExp(/^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? GMT$/); | |
const RFC_850_DATE = new RegExp(/^(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? GMT$/); | |
const ASC_TIME = new RegExp(/^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( [1-9]|\d{2}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? (\d{4})$/); | |
const parseRfc7231DateTime = (value)=>{ | |
if (value === null || value === void 0) { | |
return void 0; | |
} | |
if (typeof value !== "string") { | |
throw new TypeError("RFC-7231 date-times must be expressed as strings"); | |
} | |
let match = IMF_FIXDATE.exec(value); | |
if (match) { | |
const [_, dayStr, monthStr, yearStr, hours, minutes, seconds, fractionalMilliseconds] = match; | |
return buildDate(strictParseShort(stripLeadingZeroes(yearStr)), parseMonthByShortName(monthStr), parseDateValue(dayStr, "day", 1, 31), { | |
hours, | |
minutes, | |
seconds, | |
fractionalMilliseconds | |
}); | |
} | |
match = RFC_850_DATE.exec(value); | |
if (match) { | |
const [_1, dayStr1, monthStr1, yearStr1, hours1, minutes1, seconds1, fractionalMilliseconds1] = match; | |
return adjustRfc850Year(buildDate(parseTwoDigitYear(yearStr1), parseMonthByShortName(monthStr1), parseDateValue(dayStr1, "day", 1, 31), { | |
hours: hours1, | |
minutes: minutes1, | |
seconds: seconds1, | |
fractionalMilliseconds: fractionalMilliseconds1 | |
})); | |
} | |
match = ASC_TIME.exec(value); | |
if (match) { | |
const [_2, monthStr2, dayStr2, hours2, minutes2, seconds2, fractionalMilliseconds2, yearStr2] = match; | |
return buildDate(strictParseShort(stripLeadingZeroes(yearStr2)), parseMonthByShortName(monthStr2), parseDateValue(dayStr2.trimLeft(), "day", 1, 31), { | |
hours: hours2, | |
minutes: minutes2, | |
seconds: seconds2, | |
fractionalMilliseconds: fractionalMilliseconds2 | |
}); | |
} | |
throw new TypeError("Invalid RFC-7231 date-time value"); | |
}; | |
const buildDate = (year, month, day, time)=>{ | |
const adjustedMonth = month - 1; | |
validateDayOfMonth(year, adjustedMonth, day); | |
return new Date(Date.UTC(year, adjustedMonth, day, parseDateValue(time.hours, "hour", 0, 23), parseDateValue(time.minutes, "minute", 0, 59), parseDateValue(time.seconds, "seconds", 0, 60), parseMilliseconds(time.fractionalMilliseconds))); | |
}; | |
const parseTwoDigitYear = (value)=>{ | |
const thisYear = new Date().getUTCFullYear(); | |
const valueInThisCentury = Math.floor(thisYear / 100) * 100 + strictParseShort(stripLeadingZeroes(value)); | |
if (valueInThisCentury < thisYear) { | |
return valueInThisCentury + 100; | |
} | |
return valueInThisCentury; | |
}; | |
const FIFTY_YEARS_IN_MILLIS = 50 * 365 * 24 * 60 * 60 * 1e3; | |
const adjustRfc850Year = (input)=>{ | |
if (input.getTime() - new Date().getTime() > FIFTY_YEARS_IN_MILLIS) { | |
return new Date(Date.UTC(input.getUTCFullYear() - 100, input.getUTCMonth(), input.getUTCDate(), input.getUTCHours(), input.getUTCMinutes(), input.getUTCSeconds(), input.getUTCMilliseconds())); | |
} | |
return input; | |
}; | |
const parseMonthByShortName = (value)=>{ | |
const monthIdx = MONTHS.indexOf(value); | |
if (monthIdx < 0) { | |
throw new TypeError(`Invalid month: ${value}`); | |
} | |
return monthIdx + 1; | |
}; | |
const DAYS_IN_MONTH = [ | |
31, | |
28, | |
31, | |
30, | |
31, | |
30, | |
31, | |
31, | |
30, | |
31, | |
30, | |
31 | |
]; | |
const validateDayOfMonth = (year, month, day)=>{ | |
let maxDays = DAYS_IN_MONTH[month]; | |
if (month === 1 && isLeapYear(year)) { | |
maxDays = 29; | |
} | |
if (day > maxDays) { | |
throw new TypeError(`Invalid day for ${MONTHS[month]} in ${year}: ${day}`); | |
} | |
}; | |
const isLeapYear = (year)=>{ | |
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); | |
}; | |
const parseDateValue = (value, type, lower, upper)=>{ | |
const dateVal = strictParseByte(stripLeadingZeroes(value)); | |
if (dateVal < lower || dateVal > upper) { | |
throw new TypeError(`${type} must be between ${lower} and ${upper}, inclusive`); | |
} | |
return dateVal; | |
}; | |
const parseMilliseconds = (value)=>{ | |
if (value === null || value === void 0) { | |
return 0; | |
} | |
return strictParseFloat32("0." + value) * 1e3; | |
}; | |
const stripLeadingZeroes = (value)=>{ | |
let idx = 0; | |
while(idx < value.length - 1 && value.charAt(idx) === "0"){ | |
idx++; | |
} | |
if (idx === 0) { | |
return value; | |
} | |
return value.slice(idx); | |
}; | |
class ServiceException extends Error { | |
constructor(options){ | |
super(options.message); | |
Object.setPrototypeOf(this, ServiceException.prototype); | |
this.name = options.name; | |
this.$fault = options.$fault; | |
this.$metadata = options.$metadata; | |
} | |
} | |
const decorateServiceException = (exception, additions = {})=>{ | |
Object.entries(additions).filter(([, v])=>v !== void 0).forEach(([k, v])=>{ | |
if (exception[k] == void 0 || exception[k] === "") { | |
exception[k] = v; | |
} | |
}); | |
const message = exception.message || exception.Message || "UnknownError"; | |
exception.message = message; | |
delete exception.Message; | |
return exception; | |
}; | |
const throwDefaultError = ({ output , parsedBody , exceptionCtor , errorCode })=>{ | |
const $metadata = deserializeMetadata(output); | |
const statusCode = $metadata.httpStatusCode ? $metadata.httpStatusCode + "" : void 0; | |
const response = new exceptionCtor({ | |
name: parsedBody.code || parsedBody.Code || errorCode || statusCode || "UnknownError", | |
$fault: "client", | |
$metadata | |
}); | |
throw decorateServiceException(response, parsedBody); | |
}; | |
const deserializeMetadata = (output)=>{ | |
var _a; | |
return { | |
httpStatusCode: output.statusCode, | |
requestId: (_a = output.headers["x-amzn-requestid"]) != null ? _a : output.headers["x-amzn-request-id"], | |
extendedRequestId: output.headers["x-amz-id-2"], | |
cfId: output.headers["x-amz-cf-id"] | |
}; | |
}; | |
const loadConfigsForDefaultMode = (mode)=>{ | |
switch(mode){ | |
case "standard": | |
return { | |
retryMode: "standard", | |
connectionTimeout: 3100 | |
}; | |
case "in-region": | |
return { | |
retryMode: "standard", | |
connectionTimeout: 1100 | |
}; | |
case "cross-region": | |
return { | |
retryMode: "standard", | |
connectionTimeout: 3100 | |
}; | |
case "mobile": | |
return { | |
retryMode: "standard", | |
connectionTimeout: 3e4 | |
}; | |
default: | |
return {}; | |
} | |
}; | |
function defaultSetTimout() { | |
throw new Error("setTimeout has not been defined"); | |
} | |
function defaultClearTimeout() { | |
throw new Error("clearTimeout has not been defined"); | |
} | |
var cachedSetTimeout = defaultSetTimout; | |
var cachedClearTimeout = defaultClearTimeout; | |
var globalContext; | |
if (typeof window !== "undefined") { | |
globalContext = window; | |
} else if (typeof self !== "undefined") { | |
globalContext = self; | |
} else { | |
globalContext = {}; | |
} | |
if (typeof globalContext.setTimeout === "function") { | |
cachedSetTimeout = setTimeout; | |
} | |
if (typeof globalContext.clearTimeout === "function") { | |
cachedClearTimeout = clearTimeout; | |
} | |
function Item(fun, array) { | |
this.fun = fun; | |
this.array = array; | |
} | |
Item.prototype.run = function() { | |
this.fun.apply(null, this.array); | |
}; | |
var performance = globalContext.performance || {}; | |
performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || function() { | |
return new Date().getTime(); | |
}; | |
new Date(); | |
function extendedEncodeURIComponent(str) { | |
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { | |
return "%" + c.charCodeAt(0).toString(16).toUpperCase(); | |
}); | |
} | |
const getArrayIfSingleItem = (mayBeArray)=>Array.isArray(mayBeArray) ? mayBeArray : [ | |
mayBeArray | |
]; | |
const getValueFromTextNode = (obj)=>{ | |
const textNodeName = "#text"; | |
for(const key in obj){ | |
if (obj.hasOwnProperty(key) && obj[key][textNodeName] !== void 0) { | |
obj[key] = obj[key][textNodeName]; | |
} else if (typeof obj[key] === "object" && obj[key] !== null) { | |
obj[key] = getValueFromTextNode(obj[key]); | |
} | |
} | |
return obj; | |
}; | |
const StringWrapper = function() { | |
const Class = Object.getPrototypeOf(this).constructor; | |
const Constructor = Function.bind.apply(String, [ | |
null, | |
...arguments | |
]); | |
const instance = new Constructor(); | |
Object.setPrototypeOf(instance, Class.prototype); | |
return instance; | |
}; | |
StringWrapper.prototype = Object.create(String.prototype, { | |
constructor: { | |
value: StringWrapper, | |
enumerable: false, | |
writable: true, | |
configurable: true | |
} | |
}); | |
Object.setPrototypeOf(StringWrapper, String); | |
function map(arg0, arg1, arg2) { | |
let target; | |
let filter; | |
let instructions; | |
if (typeof arg1 === "undefined" && typeof arg2 === "undefined") { | |
target = {}; | |
instructions = arg0; | |
} else { | |
target = arg0; | |
if (typeof arg1 === "function") { | |
filter = arg1; | |
instructions = arg2; | |
return mapWithFilter(target, filter, instructions); | |
} else { | |
instructions = arg1; | |
} | |
} | |
for (const key of Object.keys(instructions)){ | |
if (!Array.isArray(instructions[key])) { | |
target[key] = instructions[key]; | |
continue; | |
} | |
let [filter2, value] = instructions[key]; | |
if (typeof value === "function") { | |
let _value; | |
const defaultFilterPassed = filter2 === void 0 && (_value = value()) != null; | |
const customFilterPassed = typeof filter2 === "function" && !!filter2(void 0) || typeof filter2 !== "function" && !!filter2; | |
if (defaultFilterPassed) { | |
target[key] = _value; | |
} else if (customFilterPassed) { | |
target[key] = value(); | |
} | |
} else { | |
const defaultFilterPassed1 = filter2 === void 0 && value != null; | |
const customFilterPassed1 = typeof filter2 === "function" && !!filter2(value) || typeof filter2 !== "function" && !!filter2; | |
if (defaultFilterPassed1 || customFilterPassed1) { | |
target[key] = value; | |
} | |
} | |
} | |
return target; | |
} | |
const mapWithFilter = (target, filter, instructions)=>{ | |
return map(target, Object.entries(instructions).reduce((_instructions, [key, value])=>{ | |
if (Array.isArray(value)) { | |
_instructions[key] = value; | |
} else { | |
if (typeof value === "function") { | |
_instructions[key] = [ | |
filter, | |
value() | |
]; | |
} else { | |
_instructions[key] = [ | |
filter, | |
value | |
]; | |
} | |
} | |
return _instructions; | |
}, {})); | |
}; | |
const resolvedPath = (resolvedPath2, input, memberName, labelValueProvider, uriLabel, isGreedyLabel)=>{ | |
if (input != null && input[memberName] !== void 0) { | |
const labelValue = labelValueProvider(); | |
if (labelValue.length <= 0) { | |
throw new Error("Empty value provided for input HTTP label: " + memberName + "."); | |
} | |
resolvedPath2 = resolvedPath2.replace(uriLabel, isGreedyLabel ? labelValue.split("/").map((segment)=>extendedEncodeURIComponent(segment)).join("/") : extendedEncodeURIComponent(labelValue)); | |
} else { | |
throw new Error("No value provided for input HTTP label: " + memberName + "."); | |
} | |
return resolvedPath2; | |
}; | |
class HttpRequest { | |
constructor(options){ | |
this.method = options.method || "GET"; | |
this.hostname = options.hostname || "localhost"; | |
this.port = options.port; | |
this.query = options.query || {}; | |
this.headers = options.headers || {}; | |
this.body = options.body; | |
this.protocol = options.protocol ? options.protocol.slice(-1) !== ":" ? `${options.protocol}:` : options.protocol : "https:"; | |
this.path = options.path ? options.path.charAt(0) !== "/" ? `/${options.path}` : options.path : "/"; | |
} | |
static isInstance(request) { | |
if (!request) return false; | |
const req = request; | |
return "method" in req && "protocol" in req && "hostname" in req && "path" in req && typeof req["query"] === "object" && typeof req["headers"] === "object"; | |
} | |
clone() { | |
const cloned = new HttpRequest({ | |
...this, | |
headers: { | |
...this.headers | |
} | |
}); | |
if (cloned.query) cloned.query = cloneQuery(cloned.query); | |
return cloned; | |
} | |
} | |
function cloneQuery(query) { | |
return Object.keys(query).reduce((carry, paramName)=>{ | |
const param = query[paramName]; | |
return { | |
...carry, | |
[paramName]: Array.isArray(param) ? [ | |
...param | |
] : param | |
}; | |
}, {}); | |
} | |
class HttpResponse { | |
constructor(options){ | |
this.statusCode = options.statusCode; | |
this.headers = options.headers || {}; | |
this.body = options.body; | |
} | |
static isInstance(response) { | |
if (!response) return false; | |
const resp = response; | |
return typeof resp.statusCode === "number" && typeof resp.headers === "object"; | |
} | |
} | |
function isValidHostname(hostname) { | |
const hostPattern = /^[a-z0-9][a-z0-9\.\-]*[a-z0-9]$/; | |
return hostPattern.test(hostname); | |
} | |
function escapeAttribute(value) { | |
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """); | |
} | |
function escapeElement(value) { | |
return value.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/\r/g, "
").replace(/\n/g, "
").replace(/\u0085/g, "…").replace(/\u2028/, "
"); | |
} | |
class XmlText { | |
constructor(value){ | |
this.value = value; | |
} | |
toString() { | |
return escapeElement("" + this.value); | |
} | |
} | |
class XmlNode { | |
constructor(name, children = []){ | |
this.name = name; | |
this.children = children; | |
this.attributes = {}; | |
} | |
static of(name, childText, withName) { | |
const node = new XmlNode(name); | |
if (childText !== void 0) { | |
node.addChildNode(new XmlText(childText)); | |
} | |
if (withName !== void 0) { | |
node.withName(withName); | |
} | |
return node; | |
} | |
withName(name) { | |
this.name = name; | |
return this; | |
} | |
addAttribute(name, value) { | |
this.attributes[name] = value; | |
return this; | |
} | |
addChildNode(child) { | |
this.children.push(child); | |
return this; | |
} | |
removeAttribute(name) { | |
delete this.attributes[name]; | |
return this; | |
} | |
toString() { | |
const hasChildren = Boolean(this.children.length); | |
let xmlText = `<${this.name}`; | |
const attributes = this.attributes; | |
for (const attributeName of Object.keys(attributes)){ | |
const attribute = attributes[attributeName]; | |
if (typeof attribute !== "undefined" && attribute !== null) { | |
xmlText += ` ${attributeName}="${escapeAttribute("" + attribute)}"`; | |
} | |
} | |
return xmlText += !hasChildren ? "/>" : `>${this.children.map((c)=>c.toString()).join("")}</${this.name}>`; | |
} | |
} | |
const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/; | |
const numRegex = /^([\-\+])?(0*)(\.[0-9]+([eE]\-?[0-9]+)?|[0-9]+(\.[0-9]+([eE]\-?[0-9]+)?)?)$/; | |
if (!Number.parseInt && window.parseInt) { | |
Number.parseInt = window.parseInt; | |
} | |
if (!Number.parseFloat && window.parseFloat) { | |
Number.parseFloat = window.parseFloat; | |
} | |
const consider = { | |
hex: true, | |
leadingZeros: true, | |
decimalPoint: ".", | |
eNotation: true | |
}; | |
function toNumber(str, options = {}) { | |
options = Object.assign({}, consider, options); | |
if (!str || typeof str !== "string") return str; | |
let trimmedStr = str.trim(); | |
if (options.skipLike !== void 0 && options.skipLike.test(trimmedStr)) return str; | |
else if (options.hex && hexRegex.test(trimmedStr)) { | |
return Number.parseInt(trimmedStr, 16); | |
} else { | |
const match = numRegex.exec(trimmedStr); | |
if (match) { | |
const sign = match[1]; | |
const leadingZeros = match[2]; | |
let numTrimmedByZeros = trimZeros(match[3]); | |
const eNotation = match[4] || match[6]; | |
if (!options.leadingZeros && leadingZeros.length > 0 && sign && trimmedStr[2] !== ".") return str; | |
else if (!options.leadingZeros && leadingZeros.length > 0 && !sign && trimmedStr[1] !== ".") return str; | |
else { | |
const num = Number(trimmedStr); | |
const numStr = "" + num; | |
if (numStr.search(/[eE]/) !== -1) { | |
if (options.eNotation) return num; | |
else return str; | |
} else if (eNotation) { | |
if (options.eNotation) return num; | |
else return str; | |
} else if (trimmedStr.indexOf(".") !== -1) { | |
if (numStr === "0" && numTrimmedByZeros === "") return num; | |
else if (numStr === numTrimmedByZeros) return num; | |
else if (sign && numStr === "-" + numTrimmedByZeros) return num; | |
else return str; | |
} | |
if (leadingZeros) { | |
if (numTrimmedByZeros === numStr) return num; | |
else if (sign + numTrimmedByZeros === numStr) return num; | |
else return str; | |
} | |
if (trimmedStr === numStr) return num; | |
else if (trimmedStr === sign + numStr) return num; | |
return str; | |
} | |
} else { | |
return str; | |
} | |
} | |
} | |
function trimZeros(numStr) { | |
if (numStr && numStr.indexOf(".") !== -1) { | |
numStr = numStr.replace(/0+$/, ""); | |
if (numStr === ".") numStr = "0"; | |
else if (numStr[0] === ".") numStr = "0" + numStr; | |
else if (numStr[numStr.length - 1] === ".") numStr = numStr.substr(0, numStr.length - 1); | |
return numStr; | |
} | |
return numStr; | |
} | |
var strnum = toNumber; | |
function createCommonjsModule(fn, basedir, module) { | |
return module = { | |
path: basedir, | |
exports: {}, | |
require: function(path, base) { | |
return commonjsRequire(path, base === void 0 || base === null ? module.path : base); | |
} | |
}, fn(module, module.exports), module.exports; | |
} | |
function commonjsRequire() { | |
throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs"); | |
} | |
var util = createCommonjsModule(function(module, exports) { | |
const nameStartChar = ":A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; | |
const nameChar = nameStartChar + "\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; | |
const nameRegexp = "[" + nameStartChar + "][" + nameChar + "]*"; | |
const regexName = new RegExp("^" + nameRegexp + "$"); | |
const getAllMatches = function(string, regex) { | |
const matches = []; | |
let match = regex.exec(string); | |
while(match){ | |
const allmatches = []; | |
allmatches.startIndex = regex.lastIndex - match[0].length; | |
const len = match.length; | |
for(let index = 0; index < len; index++){ | |
allmatches.push(match[index]); | |
} | |
matches.push(allmatches); | |
match = regex.exec(string); | |
} | |
return matches; | |
}; | |
const isName = function(string) { | |
const match = regexName.exec(string); | |
return !(match === null || typeof match === "undefined"); | |
}; | |
exports.isExist = function(v) { | |
return typeof v !== "undefined"; | |
}; | |
exports.isEmptyObject = function(obj) { | |
return Object.keys(obj).length === 0; | |
}; | |
exports.merge = function(target, a, arrayMode) { | |
if (a) { | |
const keys = Object.keys(a); | |
const len = keys.length; | |
for(let i = 0; i < len; i++){ | |
if (arrayMode === "strict") { | |
target[keys[i]] = [ | |
a[keys[i]] | |
]; | |
} else { | |
target[keys[i]] = a[keys[i]]; | |
} | |
} | |
} | |
}; | |
exports.getValue = function(v) { | |
if (exports.isExist(v)) { | |
return v; | |
} else { | |
return ""; | |
} | |
}; | |
exports.isName = isName; | |
exports.getAllMatches = getAllMatches; | |
exports.nameRegexp = nameRegexp; | |
}); | |
const defaultOptions = { | |
allowBooleanAttributes: false, | |
unpairedTags: [] | |
}; | |
var validate = function(xmlData, options) { | |
options = Object.assign({}, defaultOptions, options); | |
const tags = []; | |
let tagFound = false; | |
let reachedRoot = false; | |
if (xmlData[0] === "\uFEFF") { | |
xmlData = xmlData.substr(1); | |
} | |
for(let i = 0; i < xmlData.length; i++){ | |
if (xmlData[i] === "<" && xmlData[i + 1] === "?") { | |
i += 2; | |
i = readPI(xmlData, i); | |
if (i.err) return i; | |
} else if (xmlData[i] === "<") { | |
let tagStartPos = i; | |
i++; | |
if (xmlData[i] === "!") { | |
i = readCommentAndCDATA(xmlData, i); | |
continue; | |
} else { | |
let closingTag = false; | |
if (xmlData[i] === "/") { | |
closingTag = true; | |
i++; | |
} | |
let tagName = ""; | |
for(; i < xmlData.length && xmlData[i] !== ">" && xmlData[i] !== " " && xmlData[i] !== " " && xmlData[i] !== "\n" && xmlData[i] !== "\r"; i++){ | |
tagName += xmlData[i]; | |
} | |
tagName = tagName.trim(); | |
if (tagName[tagName.length - 1] === "/") { | |
tagName = tagName.substring(0, tagName.length - 1); | |
i--; | |
} | |
if (!validateTagName(tagName)) { | |
let msg; | |
if (tagName.trim().length === 0) { | |
msg = "Invalid space after '<'."; | |
} else { | |
msg = "Tag '" + tagName + "' is an invalid name."; | |
} | |
return getErrorObject("InvalidTag", msg, getLineNumberForPosition(xmlData, i)); | |
} | |
const result = readAttributeStr(xmlData, i); | |
if (result === false) { | |
return getErrorObject("InvalidAttr", "Attributes for '" + tagName + "' have open quote.", getLineNumberForPosition(xmlData, i)); | |
} | |
let attrStr = result.value; | |
i = result.index; | |
if (attrStr[attrStr.length - 1] === "/") { | |
const attrStrStart = i - attrStr.length; | |
attrStr = attrStr.substring(0, attrStr.length - 1); | |
const isValid = validateAttributeString(attrStr, options); | |
if (isValid === true) { | |
tagFound = true; | |
} else { | |
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line)); | |
} | |
} else if (closingTag) { | |
if (!result.tagClosed) { | |
return getErrorObject("InvalidTag", "Closing tag '" + tagName + "' doesn't have proper closing.", getLineNumberForPosition(xmlData, i)); | |
} else if (attrStr.trim().length > 0) { | |
return getErrorObject("InvalidTag", "Closing tag '" + tagName + "' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos)); | |
} else { | |
const otg = tags.pop(); | |
if (tagName !== otg.tagName) { | |
let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos); | |
return getErrorObject("InvalidTag", "Expected closing tag '" + otg.tagName + "' (opened in line " + openPos.line + ", col " + openPos.col + ") instead of closing tag '" + tagName + "'.", getLineNumberForPosition(xmlData, tagStartPos)); | |
} | |
if (tags.length == 0) { | |
reachedRoot = true; | |
} | |
} | |
} else { | |
const isValid1 = validateAttributeString(attrStr, options); | |
if (isValid1 !== true) { | |
return getErrorObject(isValid1.err.code, isValid1.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid1.err.line)); | |
} | |
if (reachedRoot === true) { | |
return getErrorObject("InvalidXml", "Multiple possible root nodes found.", getLineNumberForPosition(xmlData, i)); | |
} else if (options.unpairedTags.indexOf(tagName) !== -1) ; | |
else { | |
tags.push({ | |
tagName, | |
tagStartPos | |
}); | |
} | |
tagFound = true; | |
} | |
for(i++; i < xmlData.length; i++){ | |
if (xmlData[i] === "<") { | |
if (xmlData[i + 1] === "!") { | |
i++; | |
i = readCommentAndCDATA(xmlData, i); | |
continue; | |
} else if (xmlData[i + 1] === "?") { | |
i = readPI(xmlData, ++i); | |
if (i.err) return i; | |
} else { | |
break; | |
} | |
} else if (xmlData[i] === "&") { | |
const afterAmp = validateAmpersand(xmlData, i); | |
if (afterAmp == -1) return getErrorObject("InvalidChar", "char '&' is not expected.", getLineNumberForPosition(xmlData, i)); | |
i = afterAmp; | |
} else { | |
if (reachedRoot === true && !isWhiteSpace(xmlData[i])) { | |
return getErrorObject("InvalidXml", "Extra text at the end", getLineNumberForPosition(xmlData, i)); | |
} | |
} | |
} | |
if (xmlData[i] === "<") { | |
i--; | |
} | |
} | |
} else { | |
if (isWhiteSpace(xmlData[i])) { | |
continue; | |
} | |
return getErrorObject("InvalidChar", "char '" + xmlData[i] + "' is not expected.", getLineNumberForPosition(xmlData, i)); | |
} | |
} | |
if (!tagFound) { | |
return getErrorObject("InvalidXml", "Start tag expected.", 1); | |
} else if (tags.length == 1) { | |
return getErrorObject("InvalidTag", "Unclosed tag '" + tags[0].tagName + "'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos)); | |
} else if (tags.length > 0) { | |
return getErrorObject("InvalidXml", "Invalid '" + JSON.stringify(tags.map((t)=>t.tagName), null, 4).replace(/\r?\n/g, "") + "' found.", { | |
line: 1, | |
col: 1 | |
}); | |
} | |
return true; | |
}; | |
function isWhiteSpace(__char) { | |
return __char === " " || __char === " " || __char === "\n" || __char === "\r"; | |
} | |
function readPI(xmlData, i) { | |
const start = i; | |
for(; i < xmlData.length; i++){ | |
if (xmlData[i] == "?" || xmlData[i] == " ") { | |
const tagname = xmlData.substr(start, i - start); | |
if (i > 5 && tagname === "xml") { | |
return getErrorObject("InvalidXml", "XML declaration allowed only at the start of the document.", getLineNumberForPosition(xmlData, i)); | |
} else if (xmlData[i] == "?" && xmlData[i + 1] == ">") { | |
i++; | |
break; | |
} else { | |
continue; | |
} | |
} | |
} | |
return i; | |
} | |
function readCommentAndCDATA(xmlData, i) { | |
if (xmlData.length > i + 5 && xmlData[i + 1] === "-" && xmlData[i + 2] === "-") { | |
for(i += 3; i < xmlData.length; i++){ | |
if (xmlData[i] === "-" && xmlData[i + 1] === "-" && xmlData[i + 2] === ">") { | |
i += 2; | |
break; | |
} | |
} | |
} else if (xmlData.length > i + 8 && xmlData[i + 1] === "D" && xmlData[i + 2] === "O" && xmlData[i + 3] === "C" && xmlData[i + 4] === "T" && xmlData[i + 5] === "Y" && xmlData[i + 6] === "P" && xmlData[i + 7] === "E") { | |
let angleBracketsCount = 1; | |
for(i += 8; i < xmlData.length; i++){ | |
if (xmlData[i] === "<") { | |
angleBracketsCount++; | |
} else if (xmlData[i] === ">") { | |
angleBracketsCount--; | |
if (angleBracketsCount === 0) { | |
break; | |
} | |
} | |
} | |
} else if (xmlData.length > i + 9 && xmlData[i + 1] === "[" && xmlData[i + 2] === "C" && xmlData[i + 3] === "D" && xmlData[i + 4] === "A" && xmlData[i + 5] === "T" && xmlData[i + 6] === "A" && xmlData[i + 7] === "[") { | |
for(i += 8; i < xmlData.length; i++){ | |
if (xmlData[i] === "]" && xmlData[i + 1] === "]" && xmlData[i + 2] === ">") { | |
i += 2; | |
break; | |
} | |
} | |
} | |
return i; | |
} | |
const doubleQuote = '"'; | |
const singleQuote = "'"; | |
function readAttributeStr(xmlData, i) { | |
let attrStr = ""; | |
let startChar = ""; | |
let tagClosed = false; | |
for(; i < xmlData.length; i++){ | |
if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) { | |
if (startChar === "") { | |
startChar = xmlData[i]; | |
} else if (startChar !== xmlData[i]) ; | |
else { | |
startChar = ""; | |
} | |
} else if (xmlData[i] === ">") { | |
if (startChar === "") { | |
tagClosed = true; | |
break; | |
} | |
} | |
attrStr += xmlData[i]; | |
} | |
if (startChar !== "") { | |
return false; | |
} | |
return { | |
value: attrStr, | |
index: i, | |
tagClosed | |
}; | |
} | |
const validAttrStrRegxp = new RegExp(`(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['"])(([\\s\\S])*?)\\5)?`, "g"); | |
function validateAttributeString(attrStr, options) { | |
const matches = util.getAllMatches(attrStr, validAttrStrRegxp); | |
const attrNames = {}; | |
for(let i = 0; i < matches.length; i++){ | |
if (matches[i][1].length === 0) { | |
return getErrorObject("InvalidAttr", "Attribute '" + matches[i][2] + "' has no space in starting.", getPositionFromMatch(matches[i])); | |
} else if (matches[i][3] !== void 0 && matches[i][4] === void 0) { | |
return getErrorObject("InvalidAttr", "Attribute '" + matches[i][2] + "' is without value.", getPositionFromMatch(matches[i])); | |
} else if (matches[i][3] === void 0 && !options.allowBooleanAttributes) { | |
return getErrorObject("InvalidAttr", "boolean attribute '" + matches[i][2] + "' is not allowed.", getPositionFromMatch(matches[i])); | |
} | |
const attrName = matches[i][2]; | |
if (!validateAttrName(attrName)) { | |
return getErrorObject("InvalidAttr", "Attribute '" + attrName + "' is an invalid name.", getPositionFromMatch(matches[i])); | |
} | |
if (!attrNames.hasOwnProperty(attrName)) { | |
attrNames[attrName] = 1; | |
} else { | |
return getErrorObject("InvalidAttr", "Attribute '" + attrName + "' is repeated.", getPositionFromMatch(matches[i])); | |
} | |
} | |
return true; | |
} | |
function validateNumberAmpersand(xmlData, i) { | |
let re = /\d/; | |
if (xmlData[i] === "x") { | |
i++; | |
re = /[\da-fA-F]/; | |
} | |
for(; i < xmlData.length; i++){ | |
if (xmlData[i] === ";") return i; | |
if (!xmlData[i].match(re)) break; | |
} | |
return -1; | |
} | |
function validateAmpersand(xmlData, i) { | |
i++; | |
if (xmlData[i] === ";") return -1; | |
if (xmlData[i] === "#") { | |
i++; | |
return validateNumberAmpersand(xmlData, i); | |
} | |
let count = 0; | |
for(; i < xmlData.length; i++, count++){ | |
if (xmlData[i].match(/\w/) && count < 20) continue; | |
if (xmlData[i] === ";") break; | |
return -1; | |
} | |
return i; | |
} | |
function getErrorObject(code, message, lineNumber) { | |
return { | |
err: { | |
code, | |
msg: message, | |
line: lineNumber.line || lineNumber, | |
col: lineNumber.col | |
} | |
}; | |
} | |
function validateAttrName(attrName) { | |
return util.isName(attrName); | |
} | |
function validateTagName(tagname) { | |
return util.isName(tagname); | |
} | |
function getLineNumberForPosition(xmlData, index) { | |
const lines = xmlData.substring(0, index).split(/\r?\n/); | |
return { | |
line: lines.length, | |
col: lines[lines.length - 1].length + 1 | |
}; | |
} | |
function getPositionFromMatch(match) { | |
return match.startIndex + match[1].length; | |
} | |
var validator = { | |
validate | |
}; | |
const defaultOptions$1 = { | |
preserveOrder: false, | |
attributeNamePrefix: "@_", | |
attributesGroupName: false, | |
textNodeName: "#text", | |
ignoreAttributes: true, | |
removeNSPrefix: false, | |
allowBooleanAttributes: false, | |
parseTagValue: true, | |
parseAttributeValue: false, | |
trimValues: true, | |
cdataPropName: false, | |
numberParseOptions: { | |
hex: true, | |
leadingZeros: true | |
}, | |
tagValueProcessor: function(tagName, val) { | |
return val; | |
}, | |
attributeValueProcessor: function(attrName, val) { | |
return val; | |
}, | |
stopNodes: [], | |
alwaysCreateTextNode: false, | |
isArray: ()=>false, | |
commentPropName: false, | |
unpairedTags: [], | |
processEntities: true, | |
htmlEntities: false, | |
ignoreDeclaration: false, | |
ignorePiTags: false, | |
transformTagName: false | |
}; | |
const buildOptions = function(options) { | |
return Object.assign({}, defaultOptions$1, options); | |
}; | |
var buildOptions_1 = buildOptions; | |
var defaultOptions_1 = defaultOptions$1; | |
var OptionsBuilder = { | |
buildOptions: buildOptions_1, | |
defaultOptions: defaultOptions_1 | |
}; | |
class XmlNode1 { | |
constructor(tagname){ | |
this.tagname = tagname; | |
this.child = []; | |
this[":@"] = {}; | |
} | |
add(key, val) { | |
this.child.push({ | |
[key]: val | |
}); | |
} | |
addChild(node) { | |
if (node[":@"] && Object.keys(node[":@"]).length > 0) { | |
this.child.push({ | |
[node.tagname]: node.child, | |
[":@"]: node[":@"] | |
}); | |
} else { | |
this.child.push({ | |
[node.tagname]: node.child | |
}); | |
} | |
} | |
} | |
var xmlNode = XmlNode1; | |
function readDocType(xmlData, i) { | |
const entities = {}; | |
if (xmlData[i + 3] === "O" && xmlData[i + 4] === "C" && xmlData[i + 5] === "T" && xmlData[i + 6] === "Y" && xmlData[i + 7] === "P" && xmlData[i + 8] === "E") { | |
i = i + 9; | |
let angleBracketsCount = 1; | |
let hasBody = false, entity = false, comment = false; | |
let exp = ""; | |
for(; i < xmlData.length; i++){ | |
if (xmlData[i] === "<") { | |
if (hasBody && xmlData[i + 1] === "!" && xmlData[i + 2] === "E" && xmlData[i + 3] === "N" && xmlData[i + 4] === "T" && xmlData[i + 5] === "I" && xmlData[i + 6] === "T" && xmlData[i + 7] === "Y") { | |
i += 7; | |
entity = true; | |
} else if (hasBody && xmlData[i + 1] === "!" && xmlData[i + 2] === "E" && xmlData[i + 3] === "L" && xmlData[i + 4] === "E" && xmlData[i + 5] === "M" && xmlData[i + 6] === "E" && xmlData[i + 7] === "N" && xmlData[i + 8] === "T") { | |
i += 8; | |
} else if (hasBody && xmlData[i + 1] === "!" && xmlData[i + 2] === "A" && xmlData[i + 3] === "T" && xmlData[i + 4] === "T" && xmlData[i + 5] === "L" && xmlData[i + 6] === "I" && xmlData[i + 7] === "S" && xmlData[i + 8] === "T") { | |
i += 8; | |
} else if (hasBody && xmlData[i + 1] === "!" && xmlData[i + 2] === "N" && xmlData[i + 3] === "O" && xmlData[i + 4] === "T" && xmlData[i + 5] === "A" && xmlData[i + 6] === "T" && xmlData[i + 7] === "I" && xmlData[i + 8] === "O" && xmlData[i + 9] === "N") { | |
i += 9; | |
} else if (xmlData[i + 1] === "!" && xmlData[i + 2] === "-" && xmlData[i + 3] === "-") { | |
comment = true; | |
} else { | |
throw new Error("Invalid DOCTYPE"); | |
} | |
angleBracketsCount++; | |
exp = ""; | |
} else if (xmlData[i] === ">") { | |
if (comment) { | |
if (xmlData[i - 1] === "-" && xmlData[i - 2] === "-") { | |
comment = false; | |
} else { | |
throw new Error(`Invalid XML comment in DOCTYPE`); | |
} | |
} else if (entity) { | |
parseEntityExp(exp, entities); | |
entity = false; | |
} | |
angleBracketsCount--; | |
if (angleBracketsCount === 0) { | |
break; | |
} | |
} else if (xmlData[i] === "[") { | |
hasBody = true; | |
} else { | |
exp += xmlData[i]; | |
} | |
} | |
if (angleBracketsCount !== 0) { | |
throw new Error(`Unclosed DOCTYPE`); | |
} | |
} else { | |
throw new Error(`Invalid Tag instead of DOCTYPE`); | |
} | |
return { | |
entities, | |
i | |
}; | |
} | |
const entityRegex = RegExp(`^\\s([a-zA-z0-0]+)[ ](['"])([^&]+)\\2`); | |
function parseEntityExp(exp, entities) { | |
const match = entityRegex.exec(exp); | |
if (match) { | |
entities[match[1]] = { | |
regx: RegExp(`&${match[1]};`, "g"), | |
val: match[3] | |
}; | |
} | |
} | |
var DocTypeReader = readDocType; | |
"<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)".replace(/NAME/g, util.nameRegexp); | |
class OrderedObjParser { | |
constructor(options){ | |
this.options = options; | |
this.currentNode = null; | |
this.tagsNodeStack = []; | |
this.docTypeEntities = {}; | |
this.lastEntities = { | |
apos: { | |
regex: /&(apos|#39|#x27);/g, | |
val: "'" | |
}, | |
gt: { | |
regex: /&(gt|#62|#x3E);/g, | |
val: ">" | |
}, | |
lt: { | |
regex: /&(lt|#60|#x3C);/g, | |
val: "<" | |
}, | |
quot: { | |
regex: /&(quot|#34|#x22);/g, | |
val: '"' | |
} | |
}; | |
this.ampEntity = { | |
regex: /&(amp|#38|#x26);/g, | |
val: "&" | |
}; | |
this.htmlEntities = { | |
space: { | |
regex: /&(nbsp|#160);/g, | |
val: " " | |
}, | |
cent: { | |
regex: /&(cent|#162);/g, | |
val: "\xA2" | |
}, | |
pound: { | |
regex: /&(pound|#163);/g, | |
val: "\xA3" | |
}, | |
yen: { | |
regex: /&(yen|#165);/g, | |
val: "\xA5" | |
}, | |
euro: { | |
regex: /&(euro|#8364);/g, | |
val: "\u20AC" | |
}, | |
copyright: { | |
regex: /&(copy|#169);/g, | |
val: "\xA9" | |
}, | |
reg: { | |
regex: /&(reg|#174);/g, | |
val: "\xAE" | |
}, | |
inr: { | |
regex: /&(inr|#8377);/g, | |
val: "\u20B9" | |
} | |
}; | |
this.addExternalEntities = addExternalEntities; | |
this.parseXml = parseXml; | |
this.parseTextData = parseTextData; | |
this.resolveNameSpace = resolveNameSpace; | |
this.buildAttributesMap = buildAttributesMap; | |
this.isItStopNode = isItStopNode; | |
this.replaceEntitiesValue = replaceEntitiesValue; | |
this.readStopNodeData = readStopNodeData; | |
this.saveTextToParentTag = saveTextToParentTag; | |
} | |
} | |
function addExternalEntities(externalEntities) { | |
const entKeys = Object.keys(externalEntities); | |
for(let i = 0; i < entKeys.length; i++){ | |
const ent = entKeys[i]; | |
this.lastEntities[ent] = { | |
regex: new RegExp("&" + ent + ";", "g"), | |
val: externalEntities[ent] | |
}; | |
} | |
} | |
function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) { | |
if (val !== void 0) { | |
if (this.options.trimValues && !dontTrim) { | |
val = val.trim(); | |
} | |
if (val.length > 0) { | |
if (!escapeEntities) val = this.replaceEntitiesValue(val); | |
const newval = this.options.tagValueProcessor(tagName, val, jPath, hasAttributes, isLeafNode); | |
if (newval === null || newval === void 0) { | |
return val; | |
} else if (typeof newval !== typeof val || newval !== val) { | |
return newval; | |
} else if (this.options.trimValues) { | |
return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions); | |
} else { | |
const trimmedVal = val.trim(); | |
if (trimmedVal === val) { | |
return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions); | |
} else { | |
return val; | |
} | |
} | |
} | |
} | |
} | |
function resolveNameSpace(tagname) { | |
if (this.options.removeNSPrefix) { | |
const tags = tagname.split(":"); | |
const prefix = tagname.charAt(0) === "/" ? "/" : ""; | |
if (tags[0] === "xmlns") { | |
return ""; | |
} | |
if (tags.length === 2) { | |
tagname = prefix + tags[1]; | |
} | |
} | |
return tagname; | |
} | |
const attrsRegx = new RegExp(`([^\\s=]+)\\s*(=\\s*(['"])([\\s\\S]*?)\\3)?`, "gm"); | |
function buildAttributesMap(attrStr, jPath) { | |
if (!this.options.ignoreAttributes && typeof attrStr === "string") { | |
const matches = util.getAllMatches(attrStr, attrsRegx); | |
const len = matches.length; | |
const attrs = {}; | |
for(let i = 0; i < len; i++){ | |
const attrName = this.resolveNameSpace(matches[i][1]); | |
let oldVal = matches[i][4]; | |
const aName = this.options.attributeNamePrefix + attrName; | |
if (attrName.length) { | |
if (oldVal !== void 0) { | |
if (this.options.trimValues) { | |
oldVal = oldVal.trim(); | |
} | |
oldVal = this.replaceEntitiesValue(oldVal); | |
const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPath); | |
if (newVal === null || newVal === void 0) { | |
attrs[aName] = oldVal; | |
} else if (typeof newVal !== typeof oldVal || newVal !== oldVal) { | |
attrs[aName] = newVal; | |
} else { | |
attrs[aName] = parseValue(oldVal, this.options.parseAttributeValue, this.options.numberParseOptions); | |
} | |
} else if (this.options.allowBooleanAttributes) { | |
attrs[aName] = true; | |
} | |
} | |
} | |
if (!Object.keys(attrs).length) { | |
return; | |
} | |
if (this.options.attributesGroupName) { | |
const attrCollection = {}; | |
attrCollection[this.options.attributesGroupName] = attrs; | |
return attrCollection; | |
} | |
return attrs; | |
} | |
} | |
const parseXml = function(xmlData) { | |
xmlData = xmlData.replace(/\r\n?/g, "\n"); | |
const xmlObj = new xmlNode("!xml"); | |
let currentNode = xmlObj; | |
let textData = ""; | |
let jPath = ""; | |
for(let i = 0; i < xmlData.length; i++){ | |
const ch = xmlData[i]; | |
if (ch === "<") { | |
if (xmlData[i + 1] === "/") { | |
const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed."); | |
let tagName = xmlData.substring(i + 2, closeIndex).trim(); | |
if (this.options.removeNSPrefix) { | |
const colonIndex = tagName.indexOf(":"); | |
if (colonIndex !== -1) { | |
tagName = tagName.substr(colonIndex + 1); | |
} | |
} | |
if (this.options.transformTagName) { | |
tagName = this.options.transformTagName(tagName); | |
} | |
if (currentNode) { | |
textData = this.saveTextToParentTag(textData, currentNode, jPath); | |
} | |
jPath = jPath.substr(0, jPath.lastIndexOf(".")); | |
currentNode = this.tagsNodeStack.pop(); | |
textData = ""; | |
i = closeIndex; | |
} else if (xmlData[i + 1] === "?") { | |
let tagData = readTagExp(xmlData, i, false, "?>"); | |
if (!tagData) throw new Error("Pi Tag is not closed."); | |
textData = this.saveTextToParentTag(textData, currentNode, jPath); | |
if (this.options.ignoreDeclaration && tagData.tagName === "?xml" || this.options.ignorePiTags) ; | |
else { | |
const childNode = new xmlNode(tagData.tagName); | |
childNode.add(this.options.textNodeName, ""); | |
if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) { | |
childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath); | |
} | |
currentNode.addChild(childNode); | |
} | |
i = tagData.closeIndex + 1; | |
} else if (xmlData.substr(i + 1, 3) === "!--") { | |
const endIndex = findClosingIndex(xmlData, "-->", i + 4, "Comment is not closed."); | |
if (this.options.commentPropName) { | |
const comment = xmlData.substring(i + 4, endIndex - 2); | |
textData = this.saveTextToParentTag(textData, currentNode, jPath); | |
currentNode.add(this.options.commentPropName, [ | |
{ | |
[this.options.textNodeName]: comment | |
} | |
]); | |
} | |
i = endIndex; | |
} else if (xmlData.substr(i + 1, 2) === "!D") { | |
const result = DocTypeReader(xmlData, i); | |
this.docTypeEntities = result.entities; | |
i = result.i; | |
} else if (xmlData.substr(i + 1, 2) === "![") { | |
const closeIndex1 = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2; | |
const tagExp = xmlData.substring(i + 9, closeIndex1); | |
textData = this.saveTextToParentTag(textData, currentNode, jPath); | |
if (this.options.cdataPropName) { | |
currentNode.add(this.options.cdataPropName, [ | |
{ | |
[this.options.textNodeName]: tagExp | |
} | |
]); | |
} else { | |
let val = this.parseTextData(tagExp, currentNode.tagname, jPath, true, false, true); | |
if (val == void 0) val = ""; | |
currentNode.add(this.options.textNodeName, val); | |
} | |
i = closeIndex1 + 2; | |
} else { | |
let result1 = readTagExp(xmlData, i, this.options.removeNSPrefix); | |
let tagName1 = result1.tagName; | |
let tagExp1 = result1.tagExp; | |
let attrExpPresent = result1.attrExpPresent; | |
let closeIndex2 = result1.closeIndex; | |
if (this.options.transformTagName) { | |
tagName1 = this.options.transformTagName(tagName1); | |
} | |
if (currentNode && textData) { | |
if (currentNode.tagname !== "!xml") { | |
textData = this.saveTextToParentTag(textData, currentNode, jPath, false); | |
} | |
} | |
if (tagName1 !== xmlObj.tagname) { | |
jPath += jPath ? "." + tagName1 : tagName1; | |
} | |
const lastTag = currentNode; | |
if (lastTag && this.options.unpairedTags.indexOf(lastTag.tagname) !== -1) { | |
currentNode = this.tagsNodeStack.pop(); | |
} | |
if (this.isItStopNode(this.options.stopNodes, jPath, tagName1)) { | |
let tagContent = ""; | |
if (tagExp1.length > 0 && tagExp1.lastIndexOf("/") === tagExp1.length - 1) { | |
i = result1.closeIndex; | |
} else if (this.options.unpairedTags.indexOf(tagName1) !== -1) { | |
i = result1.closeIndex; | |
} else { | |
const result2 = this.readStopNodeData(xmlData, tagName1, closeIndex2 + 1); | |
if (!result2) throw new Error(`Unexpected end of ${tagName1}`); | |
i = result2.i; | |
tagContent = result2.tagContent; | |
} | |
const childNode1 = new xmlNode(tagName1); | |
if (tagName1 !== tagExp1 && attrExpPresent) { | |
childNode1[":@"] = this.buildAttributesMap(tagExp1, jPath); | |
} | |
if (tagContent) { | |
tagContent = this.parseTextData(tagContent, tagName1, jPath, true, attrExpPresent, true, true); | |
} | |
jPath = jPath.substr(0, jPath.lastIndexOf(".")); | |
childNode1.add(this.options.textNodeName, tagContent); | |
currentNode.addChild(childNode1); | |
} else { | |
if (tagExp1.length > 0 && tagExp1.lastIndexOf("/") === tagExp1.length - 1) { | |
if (tagName1[tagName1.length - 1] === "/") { | |
tagName1 = tagName1.substr(0, tagName1.length - 1); | |
tagExp1 = tagName1; | |
} else { | |
tagExp1 = tagExp1.substr(0, tagExp1.length - 1); | |
} | |
if (this.options.transformTagName) { | |
tagName1 = this.options.transformTagName(tagName1); | |
} | |
const childNode2 = new xmlNode(tagName1); | |
if (tagName1 !== tagExp1 && attrExpPresent) { | |
childNode2[":@"] = this.buildAttributesMap(tagExp1, jPath); | |
} | |
jPath = jPath.substr(0, jPath.lastIndexOf(".")); | |
currentNode.addChild(childNode2); | |
} else { | |
const childNode3 = new xmlNode(tagName1); | |
this.tagsNodeStack.push(currentNode); | |
if (tagName1 !== tagExp1 && attrExpPresent) { | |
childNode3[":@"] = this.buildAttributesMap(tagExp1, jPath); | |
} | |
currentNode.addChild(childNode3); | |
currentNode = childNode3; | |
} | |
textData = ""; | |
i = closeIndex2; | |
} | |
} | |
} else { | |
textData += xmlData[i]; | |
} | |
} | |
return xmlObj.child; | |
}; | |
const replaceEntitiesValue = function(val) { | |
if (this.options.processEntities) { | |
for(let entityName in this.docTypeEntities){ | |
const entity = this.docTypeEntities[entityName]; | |
val = val.replace(entity.regx, entity.val); | |
} | |
for(let entityName1 in this.lastEntities){ | |
const entity1 = this.lastEntities[entityName1]; | |
val = val.replace(entity1.regex, entity1.val); | |
} | |
if (this.options.htmlEntities) { | |
for(let entityName2 in this.htmlEntities){ | |
const entity2 = this.htmlEntities[entityName2]; | |
val = val.replace(entity2.regex, entity2.val); | |
} | |
} | |
val = val.replace(this.ampEntity.regex, this.ampEntity.val); | |
} | |
return val; | |
}; | |
function saveTextToParentTag(textData, currentNode, jPath, isLeafNode) { | |
if (textData) { | |
if (isLeafNode === void 0) isLeafNode = Object.keys(currentNode.child).length === 0; | |
textData = this.parseTextData(textData, currentNode.tagname, jPath, false, currentNode[":@"] ? Object.keys(currentNode[":@"]).length !== 0 : false, isLeafNode); | |
if (textData !== void 0 && textData !== "") currentNode.add(this.options.textNodeName, textData); | |
textData = ""; | |
} | |
return textData; | |
} | |
function isItStopNode(stopNodes, jPath, currentTagName) { | |
const allNodesExp = "*." + currentTagName; | |
for(const stopNodePath in stopNodes){ | |
const stopNodeExp = stopNodes[stopNodePath]; | |
if (allNodesExp === stopNodeExp || jPath === stopNodeExp) return true; | |
} | |
return false; | |
} | |
function tagExpWithClosingIndex(xmlData, i, closingChar = ">") { | |
let attrBoundary; | |
let tagExp = ""; | |
for(let index = i; index < xmlData.length; index++){ | |
let ch = xmlData[index]; | |
if (attrBoundary) { | |
if (ch === attrBoundary) attrBoundary = ""; | |
} else if (ch === '"' || ch === "'") { | |
attrBoundary = ch; | |
} else if (ch === closingChar[0]) { | |
if (closingChar[1]) { | |
if (xmlData[index + 1] === closingChar[1]) { | |
return { | |
data: tagExp, | |
index | |
}; | |
} | |
} else { | |
return { | |
data: tagExp, | |
index | |
}; | |
} | |
} else if (ch === " ") { | |
ch = " "; | |
} | |
tagExp += ch; | |
} | |
} | |
function findClosingIndex(xmlData, str, i, errMsg) { | |
const closingIndex = xmlData.indexOf(str, i); | |
if (closingIndex === -1) { | |
throw new Error(errMsg); | |
} else { | |
return closingIndex + str.length - 1; | |
} | |
} | |
function readTagExp(xmlData, i, removeNSPrefix, closingChar = ">") { | |
const result = tagExpWithClosingIndex(xmlData, i + 1, closingChar); | |
if (!result) return; | |
let tagExp = result.data; | |
const closeIndex = result.index; | |
const separatorIndex = tagExp.search(/\s/); | |
let tagName = tagExp; | |
let attrExpPresent = true; | |
if (separatorIndex !== -1) { | |
tagName = tagExp.substr(0, separatorIndex).replace(/\s\s*$/, ""); | |
tagExp = tagExp.substr(separatorIndex + 1); | |
} | |
if (removeNSPrefix) { | |
const colonIndex = tagName.indexOf(":"); | |
if (colonIndex !== -1) { | |
tagName = tagName.substr(colonIndex + 1); | |
attrExpPresent = tagName !== result.data.substr(colonIndex + 1); | |
} | |
} | |
return { | |
tagName, | |
tagExp, | |
closeIndex, | |
attrExpPresent | |
}; | |
} | |
function readStopNodeData(xmlData, tagName, i) { | |
const startIndex = i; | |
let openTagCount = 1; | |
for(; i < xmlData.length; i++){ | |
if (xmlData[i] === "<") { | |
if (xmlData[i + 1] === "/") { | |
const closeIndex = findClosingIndex(xmlData, ">", i, `${tagName} is not closed`); | |
let closeTagName = xmlData.substring(i + 2, closeIndex).trim(); | |
if (closeTagName === tagName) { | |
openTagCount--; | |
if (openTagCount === 0) { | |
return { | |
tagContent: xmlData.substring(startIndex, i), | |
i: closeIndex | |
}; | |
} | |
} | |
i = closeIndex; | |
} else if (xmlData[i + 1] === "?") { | |
const closeIndex1 = findClosingIndex(xmlData, "?>", i + 1, "StopNode is not closed."); | |
i = closeIndex1; | |
} else if (xmlData.substr(i + 1, 3) === "!--") { | |
const closeIndex2 = findClosingIndex(xmlData, "-->", i + 3, "StopNode is not closed."); | |
i = closeIndex2; | |
} else if (xmlData.substr(i + 1, 2) === "![") { | |
const closeIndex3 = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2; | |
i = closeIndex3; | |
} else { | |
const tagData = readTagExp(xmlData, i, ">"); | |
if (tagData) { | |
const openTagName = tagData && tagData.tagName; | |
if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length - 1] !== "/") { | |
openTagCount++; | |
} | |
i = tagData.closeIndex; | |
} | |
} | |
} | |
} | |
} | |
function parseValue(val, shouldParse, options) { | |
if (shouldParse && typeof val === "string") { | |
const newval = val.trim(); | |
if (newval === "true") return true; | |
else if (newval === "false") return false; | |
else return strnum(val, options); | |
} else { | |
if (util.isExist(val)) { | |
return val; | |
} else { | |
return ""; | |
} | |
} | |
} | |
var OrderedObjParser_1 = OrderedObjParser; | |
function prettify(node, options) { | |
return compress(node, options); | |
} | |
function compress(arr, options, jPath) { | |
let text; | |
const compressedObj = {}; | |
for(let i = 0; i < arr.length; i++){ | |
const tagObj = arr[i]; | |
const property = propName(tagObj); | |
let newJpath = ""; | |
if (jPath === void 0) newJpath = property; | |
else newJpath = jPath + "." + property; | |
if (property === options.textNodeName) { | |
if (text === void 0) text = tagObj[property]; | |
else text += "" + tagObj[property]; | |
} else if (property === void 0) { | |
continue; | |
} else if (tagObj[property]) { | |
let val = compress(tagObj[property], options, newJpath); | |
const isLeaf = isLeafTag(val, options); | |
if (tagObj[":@"]) { | |
assignAttributes(val, tagObj[":@"], newJpath, options); | |
} else if (Object.keys(val).length === 1 && val[options.textNodeName] !== void 0 && !options.alwaysCreateTextNode) { | |
val = val[options.textNodeName]; | |
} else if (Object.keys(val).length === 0) { | |
if (options.alwaysCreateTextNode) val[options.textNodeName] = ""; | |
else val = ""; | |
} | |
if (compressedObj[property] !== void 0 && compressedObj.hasOwnProperty(property)) { | |
if (!Array.isArray(compressedObj[property])) { | |
compressedObj[property] = [ | |
compressedObj[property] | |
]; | |
} | |
compressedObj[property].push(val); | |
} else { | |
if (options.isArray(property, newJpath, isLeaf)) { | |
compressedObj[property] = [ | |
val | |
]; | |
} else { | |
compressedObj[property] = val; | |
} | |
} | |
} | |
} | |
if (typeof text === "string") { | |
if (text.length > 0) compressedObj[options.textNodeName] = text; | |
} else if (text !== void 0) compressedObj[options.textNodeName] = text; | |
return compressedObj; | |
} | |
function propName(obj) { | |
const keys = Object.keys(obj); | |
for(let i = 0; i < keys.length; i++){ | |
const key = keys[i]; | |
if (key !== ":@") return key; | |
} | |
} | |
function assignAttributes(obj, attrMap, jpath, options) { | |
if (attrMap) { | |
const keys = Object.keys(attrMap); | |
const len = keys.length; | |
for(let i = 0; i < len; i++){ | |
const atrrName = keys[i]; | |
if (options.isArray(atrrName, jpath + "." + atrrName, true, true)) { | |
obj[atrrName] = [ | |
attrMap[atrrName] | |
]; | |
} else { | |
obj[atrrName] = attrMap[atrrName]; | |
} | |
} | |
} | |
} | |
function isLeafTag(obj, options) { | |
const propCount = Object.keys(obj).length; | |
if (propCount === 0 || propCount === 1 && obj[options.textNodeName]) return true; | |
return false; | |
} | |
var prettify_1 = prettify; | |
var node2json = { | |
prettify: prettify_1 | |
}; | |
const { buildOptions: buildOptions$1 } = OptionsBuilder; | |
const { prettify: prettify$1 } = node2json; | |
class XMLParser { | |
constructor(options){ | |
this.externalEntities = {}; | |
this.options = buildOptions$1(options); | |
} | |
parse(xmlData, validationOption) { | |
if (typeof xmlData === "string") ; | |
else if (xmlData.toString) { | |
xmlData = xmlData.toString(); | |
} else { | |
throw new Error("XML data is accepted in String or Bytes[] form."); | |
} | |
if (validationOption) { | |
if (validationOption === true) validationOption = {}; | |
const result = validator.validate(xmlData, validationOption); | |
if (result !== true) { | |
throw Error(`${result.err.msg}:${result.err.line}:${result.err.col}`); | |
} | |
} | |
const orderedObjParser = new OrderedObjParser_1(this.options); | |
orderedObjParser.addExternalEntities(this.externalEntities); | |
const orderedResult = orderedObjParser.parseXml(xmlData); | |
if (this.options.preserveOrder || orderedResult === void 0) return orderedResult; | |
else return prettify$1(orderedResult, this.options); | |
} | |
addEntity(key, value) { | |
if (value.indexOf("&") !== -1) { | |
throw new Error("Entity value can't have '&'"); | |
} else if (key.indexOf("&") !== -1 || key.indexOf(";") !== -1) { | |
throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for '
'"); | |
} else if (value === "&") { | |
throw new Error("An entity with value '&' is not permitted"); | |
} else { | |
this.externalEntities[key] = value; | |
} | |
} | |
} | |
var XMLParser_1 = XMLParser; | |
const EOL = "\n"; | |
function toXml(jArray, options) { | |
return arrToStr(jArray, options, "", 0); | |
} | |
function arrToStr(arr, options, jPath, level) { | |
let xmlStr = ""; | |
let indentation = ""; | |
if (options.format && options.indentBy.length > 0) { | |
indentation = EOL + "" + options.indentBy.repeat(level); | |
} | |
for(let i = 0; i < arr.length; i++){ | |
const tagObj = arr[i]; | |
const tagName = propName$1(tagObj); | |
let newJPath = ""; | |
if (jPath.length === 0) newJPath = tagName; | |
else newJPath = `${jPath}.${tagName}`; | |
if (tagName === options.textNodeName) { | |
let tagText = tagObj[tagName]; | |
if (!isStopNode(newJPath, options)) { | |
tagText = options.tagValueProcessor(tagName, tagText); | |
tagText = replaceEntitiesValue$1(tagText, options); | |
} | |
xmlStr += indentation + tagText; | |
continue; | |
} else if (tagName === options.cdataPropName) { | |
xmlStr += indentation + `<![CDATA[${tagObj[tagName][0][options.textNodeName]}]]>`; | |
continue; | |
} else if (tagName === options.commentPropName) { | |
xmlStr += indentation + `<!--${tagObj[tagName][0][options.textNodeName]}-->`; | |
continue; | |
} else if (tagName[0] === "?") { | |
const attStr2 = attr_to_str(tagObj[":@"], options); | |
const tempInd = tagName === "?xml" ? "" : indentation; | |
let piTextNodeName = tagObj[tagName][0][options.textNodeName]; | |
piTextNodeName = piTextNodeName.length !== 0 ? " " + piTextNodeName : ""; | |
xmlStr += tempInd + `<${tagName}${piTextNodeName}${attStr2}?>`; | |
continue; | |
} | |
const attStr = attr_to_str(tagObj[":@"], options); | |
let tagStart = indentation + `<${tagName}${attStr}`; | |
let tagValue = arrToStr(tagObj[tagName], options, newJPath, level + 1); | |
if (options.unpairedTags.indexOf(tagName) !== -1) { | |
if (options.suppressUnpairedNode) xmlStr += tagStart + ">"; | |
else xmlStr += tagStart + "/>"; | |
} else if ((!tagValue || tagValue.length === 0) && options.suppressEmptyNode) { | |
xmlStr += tagStart + "/>"; | |
} else { | |
xmlStr += tagStart + `>${tagValue}${indentation}</${tagName}>`; | |
} | |
} | |
return xmlStr; | |
} | |
function propName$1(obj) { | |
const keys = Object.keys(obj); | |
for(let i = 0; i < keys.length; i++){ | |
const key = keys[i]; | |
if (key !== ":@") return key; | |
} | |
} | |
function attr_to_str(attrMap, options) { | |
let attrStr = ""; | |
if (attrMap && !options.ignoreAttributes) { | |
for(let attr in attrMap){ | |
let attrVal = options.attributeValueProcessor(attr, attrMap[attr]); | |
attrVal = replaceEntitiesValue$1(attrVal, options); | |
if (attrVal === true && options.suppressBooleanAttributes) { | |
attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}`; | |
} else { | |
attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}="${attrVal}"`; | |
} | |
} | |
} | |
return attrStr; | |
} | |
function isStopNode(jPath, options) { | |
jPath = jPath.substr(0, jPath.length - options.textNodeName.length - 1); | |
let tagName = jPath.substr(jPath.lastIndexOf(".") + 1); | |
for(let index in options.stopNodes){ | |
if (options.stopNodes[index] === jPath || options.stopNodes[index] === "*." + tagName) return true; | |
} | |
return false; | |
} | |
function replaceEntitiesValue$1(textValue, options) { | |
if (textValue && textValue.length > 0 && options.processEntities) { | |
for(let i = 0; i < options.entities.length; i++){ | |
const entity = options.entities[i]; | |
textValue = textValue.replace(entity.regex, entity.val); | |
} | |
} | |
return textValue; | |
} | |
var orderedJs2Xml = toXml; | |
const defaultOptions$2 = { | |
attributeNamePrefix: "@_", | |
attributesGroupName: false, | |
textNodeName: "#text", | |
ignoreAttributes: true, | |
cdataPropName: false, | |
format: false, | |
indentBy: " ", | |
suppressEmptyNode: false, | |
suppressUnpairedNode: true, | |
suppressBooleanAttributes: true, | |
tagValueProcessor: function(key, a) { | |
return a; | |
}, | |
attributeValueProcessor: function(attrName, a) { | |
return a; | |
}, | |
preserveOrder: false, | |
commentPropName: false, | |
unpairedTags: [], | |
entities: [ | |
{ | |
regex: new RegExp("&", "g"), | |
val: "&" | |
}, | |
{ | |
regex: new RegExp(">", "g"), | |
val: ">" | |
}, | |
{ | |
regex: new RegExp("<", "g"), | |
val: "<" | |
}, | |
{ | |
regex: new RegExp("'", "g"), | |
val: "'" | |
}, | |
{ | |
regex: new RegExp('"', "g"), | |
val: """ | |
} | |
], | |
processEntities: true, | |
stopNodes: [], | |
transformTagName: false | |
}; | |
function Builder(options) { | |
this.options = Object.assign({}, defaultOptions$2, options); | |
if (this.options.ignoreAttributes || this.options.attributesGroupName) { | |
this.isAttribute = function() { | |
return false; | |
}; | |
} else { | |
this.attrPrefixLen = this.options.attributeNamePrefix.length; | |
this.isAttribute = isAttribute; | |
} | |
this.processTextOrObjNode = processTextOrObjNode; | |
if (this.options.format) { | |
this.indentate = indentate; | |
this.tagEndChar = ">\n"; | |
this.newLine = "\n"; | |
} else { | |
this.indentate = function() { | |
return ""; | |
}; | |
this.tagEndChar = ">"; | |
this.newLine = ""; | |
} | |
if (this.options.suppressEmptyNode) { | |
this.buildTextNode = buildEmptyTextNode; | |
this.buildObjNode = buildEmptyObjNode; | |
} else { | |
this.buildTextNode = buildTextValNode; | |
this.buildObjNode = buildObjectNode; | |
} | |
this.buildTextValNode = buildTextValNode; | |
this.buildObjectNode = buildObjectNode; | |
this.replaceEntitiesValue = replaceEntitiesValue$2; | |
this.buildAttrPairStr = buildAttrPairStr; | |
} | |
Builder.prototype.build = function(jObj) { | |
if (this.options.preserveOrder) { | |
return orderedJs2Xml(jObj, this.options); | |
} else { | |
if (Array.isArray(jObj) && this.options.arrayNodeName && this.options.arrayNodeName.length > 1) { | |
jObj = { | |
[this.options.arrayNodeName]: jObj | |
}; | |
} | |
return this.j2x(jObj, 0).val; | |
} | |
}; | |
Builder.prototype.j2x = function(jObj, level) { | |
let attrStr = ""; | |
let val = ""; | |
for(let key in jObj){ | |
if (typeof jObj[key] === "undefined") ; | |
else if (jObj[key] === null) { | |
if (key[0] === "?") val += this.indentate(level) + "<" + key + "?" + this.tagEndChar; | |
else val += this.indentate(level) + "<" + key + "/" + this.tagEndChar; | |
} else if (jObj[key] instanceof Date) { | |
val += this.buildTextNode(jObj[key], key, "", level); | |
} else if (typeof jObj[key] !== "object") { | |
const attr = this.isAttribute(key); | |
if (attr) { | |
attrStr += this.buildAttrPairStr(attr, "" + jObj[key]); | |
} else { | |
if (key === this.options.textNodeName) { | |
let newval = this.options.tagValueProcessor(key, "" + jObj[key]); | |
val += this.replaceEntitiesValue(newval); | |
} else { | |
val += this.buildTextNode(jObj[key], key, "", level); | |
} | |
} | |
} else if (Array.isArray(jObj[key])) { | |
const arrLen = jObj[key].length; | |
for(let j = 0; j < arrLen; j++){ | |
const item = jObj[key][j]; | |
if (typeof item === "undefined") ; | |
else if (item === null) { | |
if (key[0] === "?") val += this.indentate(level) + "<" + key + "?" + this.tagEndChar; | |
else val += this.indentate(level) + "<" + key + "/" + this.tagEndChar; | |
} else if (typeof item === "object") { | |
val += this.processTextOrObjNode(item, key, level); | |
} else { | |
val += this.buildTextNode(item, key, "", level); | |
} | |
} | |
} else { | |
if (this.options.attributesGroupName && key === this.options.attributesGroupName) { | |
const Ks = Object.keys(jObj[key]); | |
const L = Ks.length; | |
for(let j1 = 0; j1 < L; j1++){ | |
attrStr += this.buildAttrPairStr(Ks[j1], "" + jObj[key][Ks[j1]]); | |
} | |
} else { | |
val += this.processTextOrObjNode(jObj[key], key, level); | |
} | |
} | |
} | |
return { | |
attrStr, | |
val | |
}; | |
}; | |
function buildAttrPairStr(attrName, val) { | |
val = this.options.attributeValueProcessor(attrName, "" + val); | |
val = this.replaceEntitiesValue(val); | |
if (this.options.suppressBooleanAttributes && val === "true") { | |
return " " + attrName; | |
} else return " " + attrName + '="' + val + '"'; | |
} | |
function processTextOrObjNode(object, key, level) { | |
const result = this.j2x(object, level + 1); | |
if (object[this.options.textNodeName] !== void 0 && Object.keys(object).length === 1) { | |
return this.buildTextNode(object[this.options.textNodeName], key, result.attrStr, level); | |
} else { | |
return this.buildObjNode(result.val, key, result.attrStr, level); | |
} | |
} | |
function buildObjectNode(val, key, attrStr, level) { | |
let tagEndExp = "</" + key + this.tagEndChar; | |
let piClosingChar = ""; | |
if (key[0] === "?") { | |
piClosingChar = "?"; | |
tagEndExp = ""; | |
} | |
if (attrStr && val.indexOf("<") === -1) { | |
return this.indentate(level) + "<" + key + attrStr + piClosingChar + ">" + val + tagEndExp; | |
} else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) { | |
return this.indentate(level) + `<!--${val}-->` + this.newLine; | |
} else { | |
return this.indentate(level) + "<" + key + attrStr + piClosingChar + this.tagEndChar + val + this.indentate(level) + tagEndExp; | |
} | |
} | |
function buildEmptyObjNode(val, key, attrStr, level) { | |
if (val !== "") { | |
return this.buildObjectNode(val, key, attrStr, level); | |
} else { | |
if (key[0] === "?") return this.indentate(level) + "<" + key + attrStr + "?" + this.tagEndChar; | |
else return this.indentate(level) + "<" + key + attrStr + "/" + this.tagEndChar; | |
} | |
} | |
function buildTextValNode(val, key, attrStr, level) { | |
if (this.options.cdataPropName !== false && key === this.options.cdataPropName) { | |
return this.indentate(level) + `<![CDATA[${val}]]>` + this.newLine; | |
} else if (this.options.commentPropName !== false && key === this.options.commentPropName) { | |
return this.indentate(level) + `<!--${val}-->` + this.newLine; | |
} else { | |
let textValue = this.options.tagValueProcessor(key, val); | |
textValue = this.replaceEntitiesValue(textValue); | |
if (textValue === "" && this.options.unpairedTags.indexOf(key) !== -1) { | |
if (this.options.suppressUnpairedNode) { | |
return this.indentate(level) + "<" + key + this.tagEndChar; | |
} else { | |
return this.indentate(level) + "<" + key + "/" + this.tagEndChar; | |
} | |
} else { | |
return this.indentate(level) + "<" + key + attrStr + ">" + textValue + "</" + key + this.tagEndChar; | |
} | |
} | |
} | |
function replaceEntitiesValue$2(textValue) { | |
if (textValue && textValue.length > 0 && this.options.processEntities) { | |
for(let i = 0; i < this.options.entities.length; i++){ | |
const entity = this.options.entities[i]; | |
textValue = textValue.replace(entity.regex, entity.val); | |
} | |
} | |
return textValue; | |
} | |
function buildEmptyTextNode(val, key, attrStr, level) { | |
if (val === "" && this.options.unpairedTags.indexOf(key) !== -1) { | |
if (this.options.suppressUnpairedNode) { | |
return this.indentate(level) + "<" + key + this.tagEndChar; | |
} else { | |
return this.indentate(level) + "<" + key + "/" + this.tagEndChar; | |
} | |
} else if (val !== "") { | |
return this.buildTextValNode(val, key, attrStr, level); | |
} else { | |
if (key[0] === "?") return this.indentate(level) + "<" + key + attrStr + "?" + this.tagEndChar; | |
else return this.indentate(level) + "<" + key + attrStr + "/" + this.tagEndChar; | |
} | |
} | |
function indentate(level) { | |
return this.options.indentBy.repeat(level); | |
} | |
function isAttribute(name) { | |
if (name.startsWith(this.options.attributeNamePrefix)) { | |
return name.substr(this.attrPrefixLen); | |
} else { | |
return false; | |
} | |
} | |
var json2xml = Builder; | |
var fxp = { | |
XMLParser: XMLParser_1, | |
XMLValidator: validator, | |
XMLBuilder: json2xml | |
}; | |
fxp.XMLBuilder; | |
fxp.XMLParser; | |
fxp.XMLValidator; | |
const validate1 = (str)=>typeof str === "string" && str.indexOf("arn:") === 0 && str.split(":").length >= 6; | |
var SelectorType; | |
(function(SelectorType2) { | |
SelectorType2["ENV"] = "env"; | |
SelectorType2["CONFIG"] = "shared config entry"; | |
})(SelectorType || (SelectorType = {})); | |
const S3_HOSTNAME_PATTERN = /^(.+\.)?s3(-fips)?(\.dualstack)?[.-]([a-z0-9-]+)\./; | |
const S3_US_EAST_1_ALTNAME_PATTERN = /^s3(-external-1)?\.amazonaws\.com$/; | |
const AWS_PARTITION_SUFFIX = "amazonaws.com"; | |
const getRegionalSuffix = (hostname)=>{ | |
const parts = hostname.match(S3_HOSTNAME_PATTERN); | |
return [ | |
parts[4], | |
hostname.replace(new RegExp(`^${parts[0]}`), "") | |
]; | |
}; | |
const getSuffixForArnEndpoint = (hostname)=>S3_US_EAST_1_ALTNAME_PATTERN.test(hostname) ? [ | |
hostname.replace(`.${AWS_PARTITION_SUFFIX}`, ""), | |
AWS_PARTITION_SUFFIX | |
] : getRegionalSuffix(hostname); | |
const CONTENT_LENGTH_HEADER = "content-length"; | |
function checkContentLengthHeader() { | |
return (next, context)=>async (args)=>{ | |
var _a; | |
const { request } = args; | |
if (HttpRequest.isInstance(request)) { | |
if (!request.headers[CONTENT_LENGTH_HEADER]) { | |
const message = `Are you using a Stream of unknown length as the Body of a PutObject request? Consider using Upload instead from @aws-sdk/lib-storage.`; | |
if (typeof ((_a = context == null ? void 0 : context.logger) == null ? void 0 : _a.warn) === "function") { | |
context.logger.warn(message); | |
} else { | |
console.warn(message); | |
} | |
} | |
} | |
return next({ | |
...args | |
}); | |
}; | |
} | |
const checkContentLengthHeaderMiddlewareOptions = { | |
step: "finalizeRequest", | |
tags: [ | |
"CHECK_CONTENT_LENGTH_HEADER" | |
], | |
name: "getCheckContentLengthHeaderPlugin", | |
override: true | |
}; | |
const getCheckContentLengthHeaderPlugin = (unused)=>({ | |
applyToStack: (clientStack)=>{ | |
clientStack.add(checkContentLengthHeader(), checkContentLengthHeaderMiddlewareOptions); | |
} | |
}); | |
const resolveS3Config = (input)=>{ | |
var _a, _b, _c; | |
return { | |
...input, | |
forcePathStyle: (_a = input.forcePathStyle) != null ? _a : false, | |
useAccelerateEndpoint: (_b = input.useAccelerateEndpoint) != null ? _b : false, | |
disableMultiregionAccessPoints: (_c = input.disableMultiregionAccessPoints) != null ? _c : false | |
}; | |
}; | |
const throw200ExceptionsMiddleware = (config)=>(next)=>async (args)=>{ | |
const result = await next(args); | |
const { response } = result; | |
if (!HttpResponse.isInstance(response)) return result; | |
const { statusCode , body } = response; | |
if (statusCode < 200 || statusCode >= 300) return result; | |
const bodyBytes = await collectBody(body, config); | |
const bodyString = await collectBodyString(bodyBytes, config); | |
if (bodyBytes.length === 0) { | |
const err = new Error("S3 aborted request"); | |
err.name = "InternalError"; | |
throw err; | |
} | |
if (bodyString && bodyString.match("<Error>")) { | |
response.statusCode = 400; | |
} | |
response.body = bodyBytes; | |
return result; | |
}; | |
const collectBody = (streamBody = new Uint8Array(), context)=>{ | |
if (streamBody instanceof Uint8Array) { | |
return Promise.resolve(streamBody); | |
} | |
return context.streamCollector(streamBody) || Promise.resolve(new Uint8Array()); | |
}; | |
const collectBodyString = (streamBody, context)=>collectBody(streamBody, context).then((body)=>context.utf8Encoder(body)); | |
const throw200ExceptionsMiddlewareOptions = { | |
relation: "after", | |
toMiddleware: "deserializerMiddleware", | |
tags: [ | |
"THROW_200_EXCEPTIONS", | |
"S3" | |
], | |
name: "throw200ExceptionsMiddleware", | |
override: true | |
}; | |
const getThrow200ExceptionsPlugin = (config)=>({ | |
applyToStack: (clientStack)=>{ | |
clientStack.addRelativeTo(throw200ExceptionsMiddleware(config), throw200ExceptionsMiddlewareOptions); | |
} | |
}); | |
function validateBucketNameMiddleware() { | |
return (next)=>async (args)=>{ | |
const { input: { Bucket } } = args; | |
if (typeof Bucket === "string" && !validate1(Bucket) && Bucket.indexOf("/") >= 0) { | |
const err = new Error(`Bucket name shouldn't contain '/', received '${Bucket}'`); | |
err.name = "InvalidBucketName"; | |
throw err; | |
} | |
return next({ | |
...args | |
}); | |
}; | |
} | |
const validateBucketNameMiddlewareOptions = { | |
step: "initialize", | |
tags: [ | |
"VALIDATE_BUCKET_NAME" | |
], | |
name: "validateBucketNameMiddleware", | |
override: true | |
}; | |
const getValidateBucketNamePlugin = (unused)=>({ | |
applyToStack: (clientStack)=>{ | |
clientStack.add(validateBucketNameMiddleware(), validateBucketNameMiddlewareOptions); | |
} | |
}); | |
const writeGetObjectResponseEndpointMiddleware = (config)=>(next, context)=>async (args)=>{ | |
const { region: regionProvider , isCustomEndpoint , disableHostPrefix } = config; | |
const region = await regionProvider(); | |
const { request , input } = args; | |
if (!HttpRequest.isInstance(request)) return next({ | |
...args | |
}); | |
let hostname = request.hostname; | |
if (hostname.endsWith("s3.amazonaws.com") || hostname.endsWith("s3-external-1.amazonaws.com")) { | |
return next({ | |
...args | |
}); | |
} | |
if (!isCustomEndpoint) { | |
const [, suffix] = getSuffixForArnEndpoint(request.hostname); | |
hostname = `s3-object-lambda.${region}.${suffix}`; | |
} | |
if (!disableHostPrefix && input.RequestRoute) { | |
hostname = `${input.RequestRoute}.${hostname}`; | |
} | |
request.hostname = hostname; | |
context["signing_service"] = "s3-object-lambda"; | |
if (config.runtime === "node" && !request.headers["content-length"]) { | |
request.headers["transfer-encoding"] = "chunked"; | |
} | |
return next({ | |
...args | |
}); | |
}; | |
const writeGetObjectResponseEndpointMiddlewareOptions = { | |
relation: "after", | |
toMiddleware: "contentLengthMiddleware", | |
tags: [ | |
"WRITE_GET_OBJECT_RESPONSE", | |
"S3", | |
"ENDPOINT" | |
], | |
name: "writeGetObjectResponseEndpointMiddleware", | |
override: true | |
}; | |
const getWriteGetObjectResponseEndpointPlugin = (config)=>({ | |
applyToStack: (clientStack)=>{ | |
clientStack.addRelativeTo(writeGetObjectResponseEndpointMiddleware(config), writeGetObjectResponseEndpointMiddlewareOptions); | |
} | |
}); | |
function ssecMiddleware(options) { | |
return (next)=>async (args)=>{ | |
let input = { | |
...args.input | |
}; | |
const properties = [ | |
{ | |
target: "SSECustomerKey", | |
hash: "SSECustomerKeyMD5" | |
}, | |
{ | |
target: "CopySourceSSECustomerKey", | |
hash: "CopySourceSSECustomerKeyMD5" | |
} | |
]; | |
for (const prop of properties){ | |
const value = input[prop.target]; | |
if (value) { | |
const valueView = ArrayBuffer.isView(value) ? new Uint8Array(value.buffer, value.byteOffset, value.byteLength) : typeof value === "string" ? options.utf8Decoder(value) : new Uint8Array(value); | |
const encoded = options.base64Encoder(valueView); | |
const hash = new options.md5(); | |
hash.update(valueView); | |
input = { | |
...input, | |
[prop.target]: encoded, | |
[prop.hash]: options.base64Encoder(await hash.digest()) | |
}; | |
} | |
} | |
return next({ | |
...args, | |
input | |
}); | |
}; | |
} | |
const ssecMiddlewareOptions = { | |
name: "ssecMiddleware", | |
step: "initialize", | |
tags: [ | |
"SSE" | |
], | |
override: true | |
}; | |
const getSsecPlugin = (config)=>({ | |
applyToStack: (clientStack)=>{ | |
clientStack.add(ssecMiddleware(config), ssecMiddlewareOptions); | |
} | |
}); | |
function locationConstraintMiddleware(options) { | |
return (next)=>async (args)=>{ | |
const { CreateBucketConfiguration } = args.input; | |
const region = await options.region(); | |
if (!CreateBucketConfiguration || !CreateBucketConfiguration.LocationConstraint) { | |
args = { | |
...args, | |
input: { | |
...args.input, | |
CreateBucketConfiguration: region === "us-east-1" ? void 0 : { | |
LocationConstraint: region | |
} | |
} | |
}; | |
} | |
return next(args); | |
}; | |
} | |
const locationConstraintMiddlewareOptions = { | |
step: "initialize", | |
tags: [ | |
"LOCATION_CONSTRAINT", | |
"CREATE_BUCKET_CONFIGURATION" | |
], | |
name: "locationConstraintMiddleware", | |
override: true | |
}; | |
const getLocationConstraintPlugin = (config)=>({ | |
applyToStack: (clientStack)=>{ | |
clientStack.add(locationConstraintMiddleware(config), locationConstraintMiddlewareOptions); | |
} | |
}); | |
const isArrayBuffer = (arg)=>typeof ArrayBuffer === "function" && arg instanceof ArrayBuffer || Object.prototype.toString.call(arg) === "[object ArrayBuffer]"; | |
var extendStatics = function(d, b) { | |
extendStatics = Object.setPrototypeOf || ({ | |
__proto__: [] | |
}) instanceof Array && function(d2, b2) { | |
// d2.__proto__ = b2; | |
Object.setPrototypeOf(d2, b2); | |
} || function(d2, b2) { | |
for(var p in b2)if (b2.hasOwnProperty(p)) d2[p] = b2[p]; | |
}; | |
return extendStatics(d, b); | |
}; | |
function __extends(d, b) { | |
extendStatics(d, b); | |
function __() { | |
this.constructor = d; | |
} | |
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | |
} | |
var __assign = function() { | |
__assign = Object.assign || function __assign2(t) { | |
for(var s, i = 1, n = arguments.length; i < n; i++){ | |
s = arguments[i]; | |
for(var p in s)if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; | |
} | |
return t; | |
}; | |
return __assign.apply(this, arguments); | |
}; | |
function __rest(s, e) { | |
var t = {}; | |
for(var p in s)if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; | |
if (s != null && typeof Object.getOwnPropertySymbols === "function") for(var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++){ | |
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; | |
} | |
return t; | |
} | |
function __decorate(decorators, target, key, desc) { | |
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | |
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); | |
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; | |
return c > 3 && r && Object.defineProperty(target, key, r), r; | |
} | |
function __param(paramIndex, decorator) { | |
return function(target, key) { | |
decorator(target, key, paramIndex); | |
}; | |
} | |
function __metadata(metadataKey, metadataValue) { |