{"version":3,"file":"silentium-web-api.min.mjs","sources":["../src/fetch/FetchedData.ts","../src/fetch/RequestJson.ts","../src/dom/Elements.ts","../src/dom/Element.ts","../src/console/Log.ts","../src/timer/Timer.ts","../src/storage/StorageRecord.ts"],"sourcesContent":["import { Message, MessageType } from \"silentium\";\n\nexport interface FetchRequestType {\n  baseUrl?: string;\n  url: string;\n  method: string;\n  credentials?: RequestCredentials;\n  headers?: Record<string, string>;\n  body?: unknown;\n  query?: Record<string, unknown>;\n}\n\n/**\n * Wrapper around FetchAPI\n * https://kosukhin.github.io/patron-web-api/#/fetch/fetched\n * https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\n */\nexport function FetchedData(\n  $request: MessageType<Partial<FetchRequestType>>,\n  $abort?: MessageType,\n) {\n  return Message<string>(function FetchedDataImpl(resolve, reject) {\n    const abortController = new AbortController();\n    if ($abort) {\n      $abort.then((abort) => {\n        if (abort) {\n          abortController.abort();\n        }\n      });\n    }\n    $request.then((request) => {\n      const { baseUrl, url, method, credentials, headers, body, query } =\n        request;\n      let urlWithQuery: URL;\n      try {\n        urlWithQuery = new URL(String(url), baseUrl);\n      } catch {\n        reject(new Error(\"Invalid URL\"));\n        return;\n      }\n      Object.entries(query ?? {}).forEach(([key, value]) =>\n        urlWithQuery.searchParams.append(key, String(value)),\n      );\n      const options: RequestInit = {\n        method,\n        credentials,\n        headers,\n        body: body as BodyInit,\n        signal: abortController.signal,\n      };\n      fetch(urlWithQuery.toString(), options)\n        .then((response) => response.text())\n        .then(resolve)\n        .catch(reject);\n    });\n  });\n}\n","import { Message, MessageType } from \"silentium\";\nimport { FetchRequestType } from \"./FetchedData\";\n\n/**\n * Represents a request for JSON data.\n */\nexport function RequestJson($request: MessageType<Partial<FetchRequestType>>) {\n  return Message<Partial<FetchRequestType>>(\n    function RequestJsonImpl(resolve, reject) {\n      $request.then((r) => {\n        try {\n          resolve({\n            ...r,\n            headers: {\n              ...(r.headers ?? {}),\n              \"Content-Type\": \"application/json\",\n            },\n            body: JSON.stringify(r.body),\n          });\n        } catch {\n          reject(new Error(\"Failed to parse JSON\"));\n        }\n      });\n    },\n  );\n}\n","import { Actual, MaybeMessage, Message } from \"silentium\";\n\n/**\n * Represents a collection of elements that match a given CSS selector.\n */\nexport function Elements<T extends HTMLElement>(\n  _selector: MaybeMessage<string>,\n) {\n  const $selector = Actual(_selector);\n  return Message<T[]>(function ElementsImpl(r) {\n    $selector.then((selector) => {\n      const element = document.querySelectorAll(selector);\n      if (element.length > 0) {\n        r(Array.from(element) as T[]);\n      } else {\n        const targetNode = document;\n        const config = {\n          childList: true,\n          subtree: true,\n          attributes: true,\n          attributeFilter: [\"class\", \"id\"],\n        };\n\n        const observer = new MutationObserver((mutationsList) => {\n          for (const mutation of mutationsList) {\n            if (mutation.type === \"childList\") {\n              // Check if any added nodes match the selector or contain matching elements\n              const checkNodes = (nodes: NodeList) => {\n                for (const node of Array.from(nodes)) {\n                  if (node.nodeType === Node.ELEMENT_NODE) {\n                    const element = node as Element;\n                    if (element.matches && element.matches(selector)) {\n                      const allElements = document.querySelectorAll(selector);\n                      if (allElements.length > 0) {\n                        r(Array.from(allElements) as T[]);\n                        observer.disconnect();\n                        return true;\n                      }\n                    }\n                    // Check if this node contains matching elements\n                    if (\n                      element.querySelector &&\n                      element.querySelector(selector)\n                    ) {\n                      const allElements = document.querySelectorAll(selector);\n                      if (allElements.length > 0) {\n                        r(Array.from(allElements) as T[]);\n                        observer.disconnect();\n                        return true;\n                      }\n                    }\n                  }\n                }\n                return false;\n              };\n\n              if (checkNodes(mutation.addedNodes)) {\n                break;\n              }\n            } else if (mutation.type === \"attributes\") {\n              // Check if the mutated element now matches the selector\n              const target = mutation.target as Element;\n              if (target.matches && target.matches(selector)) {\n                const allElements = document.querySelectorAll(selector);\n                if (allElements.length > 0) {\n                  r(Array.from(allElements) as T[]);\n                  observer.disconnect();\n                  break;\n                }\n              }\n            }\n          }\n        });\n\n        observer.observe(targetNode, config);\n      }\n    });\n  });\n}\n","import { Actual, MaybeMessage, Message } from \"silentium\";\n\n/**\n * Represents an element that matches a given CSS selector.\n * If the element exists immediately, returns it.\n * If not, waits for it to appear in the DOM.\n */\nexport function Element<T extends HTMLElement>(\n  _selector: MaybeMessage<string>,\n) {\n  const $selector = Actual(_selector);\n  return Message<T>(function ElementImpl(r) {\n    $selector.then((selector) => {\n      const element = document.querySelector(selector) as T | null;\n      if (element) {\n        r(element);\n      } else {\n        const targetNode = document;\n        const config = {\n          childList: true,\n          subtree: true,\n          attributes: true,\n          attributeFilter: [\"class\", \"id\"],\n        };\n\n        const observer = new MutationObserver((mutationsList) => {\n          for (const mutation of mutationsList) {\n            if (mutation.type === \"childList\") {\n              // Check added nodes and their descendants\n              const checkNodes = (nodes: NodeList) => {\n                for (const node of Array.from(nodes)) {\n                  if (node.nodeType === Node.ELEMENT_NODE) {\n                    const element = node as Element;\n                    if (element.matches && element.matches(selector)) {\n                      r(element as T);\n                      observer.disconnect();\n                      return true;\n                    }\n                    // Check descendants\n                    if (\n                      element.querySelector &&\n                      element.querySelector(selector)\n                    ) {\n                      const found = element.querySelector(selector) as T;\n                      r(found);\n                      observer.disconnect();\n                      return true;\n                    }\n                  }\n                }\n                return false;\n              };\n\n              if (checkNodes(mutation.addedNodes)) {\n                break;\n              }\n            } else if (mutation.type === \"attributes\") {\n              // Check if the mutated element now matches the selector\n              const target = mutation.target as Element;\n              if (target.matches && target.matches(selector)) {\n                r(target as T);\n                observer.disconnect();\n                break;\n              }\n            }\n          }\n        });\n\n        observer.observe(targetNode, config);\n      }\n    });\n  });\n}\n","/**\n * Transport for log values to console\n */\nexport function Log(group: string) {\n  return (v: unknown) => {\n    console.log(group, v);\n  };\n}\n","import { Message } from \"silentium\";\n\nexport function Timer(delay: number) {\n  return Message<number>((t) => {\n    setTimeout(() => {\n      t(delay);\n    }, delay);\n  });\n}\n","import { Late, Source, MessageType, Primitive } from \"silentium\";\n\n/**\n * Data representation from Storage API\n */\nexport function StorageRecord<T = string>(\n  $name: MessageType<string>,\n  defaultValue?: unknown,\n  storageType: \"localStorage\" | \"sessionStorage\" = \"localStorage\",\n) {\n  const nameSync = Primitive($name);\n  const resultSrc = Late<T>();\n  return Source<T>(\n    (resolve) => {\n      resultSrc.then(resolve);\n      const storage = window[storageType];\n      $name.then((name) => {\n        window.addEventListener(\"storage\", (e) => {\n          if (e.storageArea === storage) {\n            if (e.key === name) {\n              const newValue = e.newValue\n                ? JSON.parse(e.newValue)\n                : defaultValue;\n              if (newValue !== undefined && newValue !== null) {\n                resultSrc.use(newValue as T);\n              }\n            }\n          }\n        });\n        if (storage[name]) {\n          try {\n            resultSrc.use(JSON.parse(storage[name]));\n          } catch {\n            console.warn(`LocalStorageRecord cant parse value ${name}`);\n          }\n        } else if (defaultValue !== undefined) {\n          resultSrc.use(defaultValue as T);\n        }\n      });\n    },\n    (v) => {\n      const storage = window[storageType];\n      resultSrc.use(v);\n\n      try {\n        storage[nameSync.primitiveWithException()] = JSON.stringify(v);\n      } catch {\n        console.warn(`LocalStorageRecord cant stringify value`);\n      }\n    },\n  );\n}\n"],"names":["FetchedData","$request","$abort","Message","resolve","reject","abortController","AbortController","then","abort","request","baseUrl","url","method","credentials","headers","body","query","urlWithQuery","URL","String","Error","Object","entries","forEach","key","value","searchParams","append","options","signal","fetch","toString","response","text","catch","RequestJson","r","JSON","stringify","Elements","_selector","$selector","Actual","selector","element","document","querySelectorAll","length","Array","from","targetNode","config","childList","subtree","attributes","attributeFilter","observer","MutationObserver","mutationsList","mutation","type","nodes","node","nodeType","Node","ELEMENT_NODE","matches","allElements","disconnect","querySelector","checkNodes","addedNodes","target","observe","Element","found","Log","group","v","console","log","Timer","delay","t","setTimeout","StorageRecord","$name","defaultValue","storageType","nameSync","Primitive","resultSrc","Late","Source","storage","window","name","addEventListener","e","storageArea","newValue","parse","use","warn","primitiveWithException"],"mappings":"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"}