{"version":3,"file":"extract-files-DO21H60k.js","sources":["../../node_modules/extract-files/extractFiles.mjs","../../node_modules/extract-files/isExtractableFile.mjs"],"sourcesContent":["// @ts-check\n\n// @deno-types=\"is-plain-obj/index.d.ts\"\nimport isPlainObject from \"is-plain-obj\";\n\n/** @typedef {import(\"./isExtractableFile.mjs\").default} isExtractableFile */\n\n/**\n * Recursively extracts files and their {@link ObjectPath object paths} within a\n * value, replacing them with `null` in a deep clone without mutating the\n * original value.\n * [`FileList`](https://developer.mozilla.org/en-US/docs/Web/API/Filelist)\n * instances are treated as\n * [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) instance\n * arrays.\n * @template Extractable Extractable file type.\n * @param {unknown} value Value to extract files from. Typically an object tree.\n * @param {(value: unknown) => value is Extractable} isExtractable Matches\n * extractable files. Typically {@linkcode isExtractableFile}.\n * @param {ObjectPath} [path] Prefix for object paths for extracted files.\n * Defaults to `\"\"`.\n * @returns {Extraction} Extraction result.\n * @example\n * Extracting files from an object.\n *\n * For the following:\n *\n * ```js\n * import extractFiles from \"extract-files/extractFiles.mjs\";\n * import isExtractableFile from \"extract-files/isExtractableFile.mjs\";\n *\n * const file1 = new File([\"1\"], \"1.txt\", { type: \"text/plain\" });\n * const file2 = new File([\"2\"], \"2.txt\", { type: \"text/plain\" });\n * const value = {\n * a: file1,\n * b: [file1, file2],\n * };\n *\n * const { clone, files } = extractFiles(value, isExtractableFile, \"prefix\");\n * ```\n *\n * `value` remains the same.\n *\n * `clone` is:\n *\n * ```json\n * {\n * \"a\": null,\n * \"b\": [null, null]\n * }\n * ```\n *\n * `files` is a\n * [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)\n * instance containing:\n *\n * | Key | Value |\n * | :------ | :--------------------------- |\n * | `file1` | `[\"prefix.a\", \"prefix.b.0\"]` |\n * | `file2` | `[\"prefix.b.1\"]` |\n */\nexport default function extractFiles(value, isExtractable, path = \"\") {\n if (!arguments.length) throw new TypeError(\"Argument 1 `value` is required.\");\n\n if (typeof isExtractable !== \"function\")\n throw new TypeError(\"Argument 2 `isExtractable` must be a function.\");\n\n if (typeof path !== \"string\")\n throw new TypeError(\"Argument 3 `path` must be a string.\");\n\n /**\n * Deeply clonable value.\n * @typedef {Array | FileList | {\n * [key: PropertyKey]: unknown\n * }} Cloneable\n */\n\n /**\n * Clone of a {@link Cloneable deeply cloneable value}.\n * @typedef {Exclude} Clone\n */\n\n /**\n * Map of values recursed within the input value and their clones, for reusing\n * clones of values that are referenced multiple times within the input value.\n * @type {Map}\n */\n const clones = new Map();\n\n /**\n * Extracted files and their object paths within the input value.\n * @type {Extraction[\"files\"]}\n */\n const files = new Map();\n\n /**\n * Recursively clones the value, extracting files.\n * @param {unknown} value Value to extract files from.\n * @param {ObjectPath} path Prefix for object paths for extracted files.\n * @param {Set} recursed Recursed values for avoiding infinite\n * recursion of circular references within the input value.\n * @returns {unknown} Clone of the value with files replaced with `null`.\n */\n function recurse(value, path, recursed) {\n if (isExtractable(value)) {\n const filePaths = files.get(value);\n\n filePaths ? filePaths.push(path) : files.set(value, [path]);\n\n return null;\n }\n\n const valueIsList =\n Array.isArray(value) ||\n (typeof FileList !== \"undefined\" && value instanceof FileList);\n const valueIsPlainObject = isPlainObject(value);\n\n if (valueIsList || valueIsPlainObject) {\n let clone = clones.get(value);\n\n const uncloned = !clone;\n\n if (uncloned) {\n clone = valueIsList\n ? []\n : // Replicate if the plain object is an `Object` instance.\n value instanceof /** @type {any} */ (Object)\n ? {}\n : Object.create(null);\n\n clones.set(value, /** @type {Clone} */ (clone));\n }\n\n if (!recursed.has(value)) {\n const pathPrefix = path ? `${path}.` : \"\";\n const recursedDeeper = new Set(recursed).add(value);\n\n if (valueIsList) {\n let index = 0;\n\n for (const item of value) {\n const itemClone = recurse(\n item,\n pathPrefix + index++,\n recursedDeeper\n );\n\n if (uncloned) /** @type {Array} */ (clone).push(itemClone);\n }\n } else\n for (const key in value) {\n const propertyClone = recurse(\n value[key],\n pathPrefix + key,\n recursedDeeper\n );\n\n if (uncloned)\n /** @type {{ [key: PropertyKey]: unknown }} */ (clone)[key] =\n propertyClone;\n }\n }\n\n return clone;\n }\n\n return value;\n }\n\n return {\n clone: recurse(value, path, new Set()),\n files,\n };\n}\n\n/**\n * An extraction result.\n * @template [Extractable=unknown] Extractable file type.\n * @typedef {object} Extraction\n * @prop {unknown} clone Clone of the original value with extracted files\n * recursively replaced with `null`.\n * @prop {Map>} files Extracted files and their\n * object paths within the original value.\n */\n\n/**\n * String notation for the path to a node in an object tree.\n * @typedef {string} ObjectPath\n * @see [`object-path` on npm](https://npm.im/object-path).\n * @example\n * An object path for object property `a`, array index `0`, object property `b`:\n *\n * ```\n * a.0.b\n * ```\n */\n","// @ts-check\n\n/**\n * Checks if a value is an {@link ExtractableFile extractable file}.\n * @param {unknown} value Value to check.\n * @returns {value is ExtractableFile} Is the value an\n * {@link ExtractableFile extractable file}.\n */\nexport default function isExtractableFile(value) {\n return (\n (typeof File !== \"undefined\" && value instanceof File) ||\n (typeof Blob !== \"undefined\" && value instanceof Blob)\n );\n}\n\n/**\n * An extractable file.\n * @typedef {File | Blob} ExtractableFile\n */\n"],"names":["extractFiles","value","isExtractable","path","arguments","length","TypeError","clones","Map","files","clone","recurse","recursed","filePaths","get","push","set","valueIsList","Array","isArray","FileList","valueIsPlainObject","isPlainObject","uncloned","Object","create","has","pathPrefix","recursedDeeper","Set","add","index","item","itemClone","key","propertyClone","isExtractableFile","File","Blob"],"mappings":"+CA6De,SAASA,EAAaC,EAAOC,EAAeC,EAAO,IAChE,IAAKC,UAAUC,OAAc,MAAA,IAAIC,UAAU,mCAE3C,GAA6B,mBAAlBJ,EACH,MAAA,IAAII,UAAU,kDAEtB,GAAoB,iBAATH,EACH,MAAA,IAAIG,UAAU,uCAmBhB,MAAAC,MAAaC,IAMbC,MAAYD,IA4EX,MAAA,CACLE,MAnEO,SAAAC,EAAQV,EAAOE,EAAMS,GACxB,GAAAV,EAAcD,GAAQ,CAClB,MAAAY,EAAYJ,EAAMK,IAAIb,GAIrB,OAFKY,EAAAA,EAAUE,KAAKZ,GAAQM,EAAMO,IAAIf,EAAO,CAACE,IAE9C,IACR,CAEK,MAAAc,EACJC,MAAMC,QAAQlB,IACO,oBAAbmB,UAA4BnB,aAAiBmB,SACjDC,EAAqBC,EAAcrB,GAEzC,GAAIgB,GAAeI,EAAoB,CACjC,IAAAX,EAAQH,EAAOO,IAAIb,GAEvB,MAAMsB,GAAYb,EAalB,GAXIa,IACFb,EAAQO,EACJ,GAEFhB,aAAqCuB,OACnC,CAAE,EACFA,OAAOC,OAAO,MAEXlB,EAAAS,IAAIf,EAA6BS,KAGrCE,EAASc,IAAIzB,GAAQ,CACxB,MAAM0B,EAAaxB,EAAO,GAAGA,KAAU,GACjCyB,EAAiB,IAAIC,IAAIjB,GAAUkB,IAAI7B,GAE7C,GAAIgB,EAAa,CACf,IAAIc,EAAQ,EAEZ,IAAA,MAAWC,KAAQ/B,EAAO,CACxB,MAAMgC,EAAYtB,EAChBqB,EACAL,EAAaI,IACbH,GAGEL,GAAyCb,EAAOK,KAAKkB,EAC1D,CACF,MACC,IAAA,MAAWC,KAAOjC,EAAO,CACvB,MAAMkC,EAAgBxB,EACpBV,EAAMiC,GACNP,EAAaO,EACbN,GAGEL,IAC8Cb,EAAOwB,GACrDC,EACL,CACJ,CAEM,OAAAzB,CACR,CAEMT,OAAAA,CACR,CAGQU,CAAQV,EAAOE,EAAM,IAAI0B,KAChCpB,QAEJ,CCrKe,SAAS2B,EAAkBnC,GAErC,MAAgB,oBAAToC,MAAwBpC,aAAiBoC,MAChC,oBAATC,MAAwBrC,aAAiBqC,IAErD","x_google_ignoreList":[0,1]}