{"version":3,"sources":["datex-over-http.ts"],"sourcesContent":["import { Datex } from \"datex-core-legacy/mod.ts\"\n\nimport { DX_PTR } from \"datex-core-legacy/runtime/constants.ts\";\nimport { JSTransferableFunction } from \"datex-core-legacy/types/js-function.ts\";\nimport { client_type } from \"datex-core-legacy/utils/constants.ts\";\nimport { BACKEND_EXPORT } from \"datex-core-legacy/utils/interface-generator.ts\";\n\nexport const BOUND_TO_ORIGIN = Symbol(\"BOUND_TO_ORIGIN\")\n\n/**\n * Wraps a function so that it is always called in the original context.\n * \n * In standalone mode, the function is always called on the backend endpoint.\n * \n * This is the default behavior when setting event listeners in JSX.\n * \n * - uses datex-over-http when DATEX is not available\n * - parameters must be json compatible\n * @param fn\n */\nexport function bindToOrigin<F extends (...args:unknown[])=>unknown>(fn: F, context?:any, name?:string, forceDatex = false): F extends (...args: infer A) => infer R ? (...args: A) => Promise<Awaited<Promise<R>>> : never  {\n\t\n\tif (typeof fn !== \"function\") throw new Error(\"bindToOrigin: Must be a function\");\n\t// @ts-ignore already bound\n\tif (fn[BOUND_TO_ORIGIN]) return fn as any;\n\t// @ts-ignore if backend export\n\tif (fn[BACKEND_EXPORT]) return fn as any;\n\t// @ts-ignore already bound\n\tif (fn.uix_bound || fn.ntarget?.uix_bound) return <any>fn;\n\n\tif (context && !fn.bind) throw new Error(\"bindToOrigin: Cannot bind arrow function to context\");\n\n\t// @ts-ignore\n\tfn = $(Datex.Function.createFromJSFunction(fn, context));\n\n\t// @ts-ignore\n\tconst ptr:Datex.Pointer = (globalThis.Datex ? Datex.Pointer.getByValue(fn) : fn[DX_PTR]) ?? fn.ntarget?.[DX_PTR];\n\tif (!ptr) throw new Error(\"bindToOrigin: function must be bound to a DATEX pointer\");\n\t// prevent garbage collection\n\tptr.is_persistent = true;\n\t\n\tif (forceDatex) {\n\t\tfn.toString = ()=>{\n\t\t\treturn `async ${name??'function'} (...args) {\n\t\t\t\tconst { callDatex } = await import(\"uix/standalone/call-compat.ts\" /*lazy*/);\n\t\t\t\treturn callDatex('${ptr.idString()}', args);\n\t\t\t}`\n\t\t}\n\t}\n\telse {\n\t\tfn.toString = ()=>{\n\t\t\treturn `async ${name??'function'} (...args) {\n\t\t\t\tconst { callCompat } = await import(\"uix/standalone/call-compat.ts\" /*lazy*/);\n\t\t\t\treturn callCompat('${ptr.idString()}', args);\n\t\t\t}`\n\t\t}\n\t}\n\n\t// @ts-ignore\n\tfn[BOUND_TO_ORIGIN] = true;\n\n\treturn <any>fn;\n}\n\n\n\n\n/**\n * Wraps a value so that it is always loaded from the original context.\n * \n * - uses datex-over-http when DATEX is not available\n * @param fn\n */\nexport function getValueInitializer(value:any, forceDatex = false): string {\n\t\n\tvalue = $(value);\n\t// @ts-ignore\n\tconst ptr:Datex.Pointer = value.idString ? value : (globalThis.Datex ? Datex.Pointer.getByValue(value) : value[DX_PTR]);\n\tif (!ptr) throw new Error(\"getValueInitializer: value must be bound to a DATEX pointer\");\n\t// prevent garbage collection\n\tptr.is_persistent = true;\n\t\n\tif (forceDatex) {\n\t\treturn `await (async () => {\n\t\t\tawait import(\"datex-core-legacy\" /*lazy*/);\n\t\t\tawait Datex.Supranet.connect();\n\t\t\treturn datex('${ptr.idString()}');\n\t\t})()\n\t\t`\n\t}\n\telse {\n\t\treturn `await (async () => {\n\t\t\t// use datex\n\t\t\tif (globalThis.datex && globalThis.Datex) {\n\t\t\t\tawait Datex.Supranet.connect();\n\t\t\t\treturn datex('${ptr.idString()}');\n\t\t\t}\n\t\t\t// use datex-over-http\n\t\t\telse {\n\t\t\t\tconst res = await fetch(\"/@uix/datex\", {method:\"POST\", keepalive: true, headers: {\"Content-Type\": \"text/datex\"}, body:\"${ptr.idString()}\"});\n\t\t\t\tconst text = await res.text();\n\t\t\t\tif (res.ok) {\n\t\t\t\t\ttry {return JSON.parse(text)}\n\t\t\t\t\tcatch {return \"Value is not valid JSON\"}\n\t\t\t\t}\n\t\t\t\telse throw new Error(text)\n\t\t\t}\n\t\t})()\n\t\t`\n\t}\n}\n\n\n/**\n * Creates a function that can be called to update a remote pointer value\n * \n * - uses datex-over-http when DATEX is not available\n * @param fn\n */\nexport function getValueUpdater(ref:Datex.ReactiveValue, forceDatex = false, keepAlive = false, type: \"number\"|\"string\"|\"bigint\"|\"boolean\"|\"Date\"): string {\n\t\n\t// prevent garbage collection\n\tif (ref instanceof Datex.Pointer) ref.is_persistent = true;\n\n\tconst ptrString = Datex.Runtime.valueToDatexString(ref);\n\t\n\tif (forceDatex) {\n\t\tif (keepAlive) throw new Error(\"Cannot use keepAlive=true with forceDatex=true\")\n\t\treturn `async (val) => {\n\t\t\tif (globalThis._prevent_uix_form_value_updates) {\n \t\t\t\tconsole.warn(\"Prevented form value updates\");\n \t\t\t\treturn;\n \t\t\t};\n\t\t\tawait import(\"datex-core-legacy\" /*lazy*/);\n\t\t\tawait Datex.Supranet.connect();\n\t\t\treturn datex('${ptrString}=?', [val]);\n\t\t}\n\t\t`\n\t}\n\telse {\n\t\t// TODO: remove sendBeacon as fallback for firefox if keepAlive needed\n\t\treturn `async (val) => {\n\t\t\tif (globalThis._prevent_uix_form_value_updates) {\n \t\t\t\tconsole.warn(\"Prevented form value updates\");\n \t\t\t\treturn;\n \t\t\t};\n\t\t\t// cast value\n\t\t\t${\n\t\t\t\ttype == \"number\" ? \"val = Number(val)\":\n\t\t\t\ttype == \"bigint\" ? \"val = BigInt(val)\":\n\t\t\t\ttype == \"boolean\" ? \"val = Boolean(val)\":\n\t\t\t\ttype == \"Date\" ? \"val = new Date(val)\":\n\t\t\t\ttype == \"string\" ? \"val = String(val)\":\n\t\t\t\t\"\"\n\t\t\t}\n\t\t\t// use datex\n\t\t\tif (globalThis.datex && globalThis.Datex) {\n\t\t\t\tawait Datex.Supranet.connect();\n\t\t\t\treturn datex('${ptrString}=?', [val]);\n\t\t\t}\n\t\t\t// use datex-over-http\n\t\t\telse {\n\t\t\t\t${keepAlive ? `if (navigator.userAgent.includes(\"Firefox/\")) {navigator.sendBeacon(\"/@uix/datex\", \"${ptrString}=\" + JSON.stringify(val)); return};`: \"\"}\n\t\t\t\tconst res = await fetch(\"/@uix/datex\", {method:\"POST\", keepalive: true, headers: {\"Content-Type\": \"text/datex\"}, body:\"${ptrString}=\" + JSON.stringify(val)});\n\t\t\t\tif (res.ok) return true\n\t\t\t\telse throw new Error(await res.text())\n\t\t\t}\n\t\t}\n\t\t`\n\t}\n}\n\n\n\n\n/**\n * Force a function (e.g. event handler) to be run on the frontend.\n * \n * The function will also be called on the frontend in standalone mode.\n * Most UIX Apis and the outer module context are not available inside the wrapped function.\n * \n * This is the counterpart to UIX.bindToOrigin, which always ensures that\n * the module context is available inside the wrapped function.\n */\nexport function bindToDisplayContext<F extends (...args:any)=>any>(fn: F): F extends (...args:any)=>Promise<any> ? Promise<F> : F {\n\tconst error = client_type == \"browser\" ? undefined : new Error(\"Function bound with bindToDisplayContext cannot be called from a backend function\");\n\treturn JSTransferableFunction.functionIsAsync(fn) ? \n\t\tJSTransferableFunction.createAsync(fn, {errorOnOriginContext: error}) : \n\t\tJSTransferableFunction.create(fn, {errorOnOriginContext: error}) as any;\n}"],"names":["Datex","DX_PTR","JSTransferableFunction","client_type","BACKEND_EXPORT","BOUND_TO_ORIGIN","Symbol","bindToOrigin","fn","context","name","forceDatex","Error","uix_bound","ntarget","bind","$","Function","createFromJSFunction","ptr","globalThis","Pointer","getByValue","is_persistent","toString","idString","getValueInitializer","value","getValueUpdater","ref","keepAlive","type","ptrString","Runtime","valueToDatexString","bindToDisplayContext","error","undefined","functionIsAsync","createAsync","errorOnOriginContext","create"],"mappings":"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","sourceRoot":"/lib/uix-0.4.39/src/app/","file":"datex-over-http.ts"}