@devvit/web-view-scripts 0.12.7-next-2025-12-15-19-58-48-962aee65f.0 → 0.12.7-next-2025-12-15-21-49-16-ffbcd4ee6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devvit/web-view-scripts",
|
|
3
|
-
"version": "0.12.7-next-2025-12-15-
|
|
3
|
+
"version": "0.12.7-next-2025-12-15-21-49-16-ffbcd4ee6.0",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,15 +34,15 @@
|
|
|
34
34
|
},
|
|
35
35
|
"types": "./dist/index.d.ts",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@devvit/protos": "0.12.7-next-2025-12-15-
|
|
38
|
-
"@devvit/shared": "0.12.7-next-2025-12-15-
|
|
39
|
-
"@devvit/shared-types": "0.12.7-next-2025-12-15-
|
|
37
|
+
"@devvit/protos": "0.12.7-next-2025-12-15-21-49-16-ffbcd4ee6.0",
|
|
38
|
+
"@devvit/shared": "0.12.7-next-2025-12-15-21-49-16-ffbcd4ee6.0",
|
|
39
|
+
"@devvit/shared-types": "0.12.7-next-2025-12-15-21-49-16-ffbcd4ee6.0",
|
|
40
40
|
"jwt-decode": "4.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@ampproject/filesize": "4.3.0",
|
|
44
|
-
"@devvit/repo-tools": "0.12.7-next-2025-12-15-
|
|
45
|
-
"@devvit/tsconfig": "0.12.7-next-2025-12-15-
|
|
44
|
+
"@devvit/repo-tools": "0.12.7-next-2025-12-15-21-49-16-ffbcd4ee6.0",
|
|
45
|
+
"@devvit/tsconfig": "0.12.7-next-2025-12-15-21-49-16-ffbcd4ee6.0",
|
|
46
46
|
"@types/jsdom": "21.1.7",
|
|
47
47
|
"esbuild": "0.25.9",
|
|
48
48
|
"eslint": "9.11.1",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"source": "./src/index.ts",
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "92ebe381eed08c7aeb37a5ab03dd8c2045aded8e"
|
|
61
61
|
}
|
package/scripts/devvit.v1.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";(()=>{var o={hash:"
|
|
1
|
+
"use strict";(()=>{var o={hash:"ffbcd4e",version:"0.12.7-dev"};var a;(function(t){t[t.EFFECT_REALTIME_SUB=0]="EFFECT_REALTIME_SUB",t[t.EFFECT_RERENDER_UI=1]="EFFECT_RERENDER_UI",t[t.EFFECT_RELOAD_PART=2]="EFFECT_RELOAD_PART",t[t.EFFECT_SHOW_FORM=3]="EFFECT_SHOW_FORM",t[t.EFFECT_SHOW_TOAST=4]="EFFECT_SHOW_TOAST",t[t.EFFECT_NAVIGATE_TO_URL=5]="EFFECT_NAVIGATE_TO_URL",t[t.EFFECT_SET_INTERVALS=7]="EFFECT_SET_INTERVALS",t[t.EFFECT_CREATE_ORDER=8]="EFFECT_CREATE_ORDER",t[t.EFFECT_WEB_VIEW=9]="EFFECT_WEB_VIEW",t[t.EFFECT_CAN_RUN_AS_USER=11]="EFFECT_CAN_RUN_AS_USER",t[t.EFFECT_TELEMETRY=12]="EFFECT_TELEMETRY",t[t.EFFECT_UPDATE_REQUEST_CONTEXT=13]="EFFECT_UPDATE_REQUEST_CONTEXT",t[t.UNRECOGNIZED=-1]="UNRECOGNIZED"})(a||(a={}));var p;(function(t){t[t.CLIENT=0]="CLIENT",t[t.UNRECOGNIZED=-1]="UNRECOGNIZED"})(p||(p={}));var b="devvit-internal",w={[a.EFFECT_SHOW_FORM]:!0,[a.EFFECT_CAN_RUN_AS_USER]:!0,[a.EFFECT_CREATE_ORDER]:!0},T=t=>new Promise(e=>{let r={...t,realtimeEffect:t.realtime,scope:p.CLIENT,type:b};if((t.showToast||t.navigateToUrl||t.showForm||t.type===a.EFFECT_CAN_RUN_AS_USER)&&(r.effect=t),w[t.type]){let n=crypto.randomUUID();r.id=n;let s=i=>{i.data?.type==="devvit-message"&&i.data?.data?.id===n&&(e(i.data.data),removeEventListener("message",s))};addEventListener("message",s),parent.postMessage(r,"*")}else parent.postMessage(r,"*"),e(void 0)});function R(){addEventListener("load",()=>{let t=performance.timeOrigin,e=performance.now(),r=performance.timeOrigin+e,n={event:"web-view-loaded",timeStart:t,timeEnd:r,duration:e};T({type:a.EFFECT_TELEMETRY,telemetry:{event:n.event,loaded:n},analytics:n})}),document.addEventListener("click",t=>{let e={event:"click",definition:A(t)?"strict":"default"};T({type:a.EFFECT_TELEMETRY,telemetry:{event:e.event,click:e},analytics:e})},{passive:!0})}function A(t){if(!t.isTrusted)return!1;let e=t.target;return globalThis.window.getComputedStyle(e)?.getPropertyValue("cursor")==="pointer"?!0:g(e)}function g(t){let e=["A","BUTTON","CANVAS","INPUT","SELECT","TEXTAREA","LABEL"],r=t;for(;r&&r.tagName!=="BODY";){if(e.includes(r.tagName)||["true","plaintext-only"].includes(r.getAttribute("contenteditable")??""))return!0;r=r.parentElement}return!1}var E;(function(t){t[t.CLIENT_UNSPECIFIED=0]="CLIENT_UNSPECIFIED",t[t.ANDROID=1]="ANDROID",t[t.IOS=2]="IOS",t[t.SHREDDIT=3]="SHREDDIT",t[t.UNRECOGNIZED=-1]="UNRECOGNIZED"})(E||(E={}));var C;(function(t){t[t.HEIGHT_UNSPECIFIED=0]="HEIGHT_UNSPECIFIED",t[t.REGULAR=1]="REGULAR",t[t.TALL=2]="TALL",t[t.UNRECOGNIZED=-1]="UNRECOGNIZED"})(C||(C={}));function l(t,e){if(!t)throw Error(e)}var d;(function(t){t.COMMENT="t1_",t.ACCOUNT="t2_",t.LINK="t3_",t.MESSAGE="t4_",t.SUBREDDIT="t5_",t.AWARD="t6_"})(d||(d={}));function O(t){return t.startsWith(d.ACCOUNT)}function U(t){return t.startsWith(d.LINK)}function y(t){return t.startsWith(d.SUBREDDIT)}function L(t){l(O(t),`Expected account id to start with ${d.ACCOUNT}, got ${t}`)}function V(t){l(U(t),`Expected link id to start with ${d.LINK}, got ${t}`)}function W(t){l(y(t),`Expected subreddit id to start with ${d.SUBREDDIT}, got ${t}`)}function m(t){return L(t),t}function v(t){return V(t),t}function f(t){return W(t),t}var _="clientVersion";function S(t){if(t.currentScript&&"src"in t.currentScript)return new URL(t.currentScript.src).searchParams.get(_)??void 0}var u=class extends Error{};u.prototype.name="InvalidTokenError";function M(t){return decodeURIComponent(atob(t).replace(/(.)/g,(e,r)=>{let n=r.charCodeAt(0).toString(16).toUpperCase();return n.length<2&&(n="0"+n),"%"+n}))}function G(t){let e=t.replace(/-/g,"+").replace(/_/g,"/");switch(e.length%4){case 0:break;case 2:e+="==";break;case 3:e+="=";break;default:throw new Error("base64 string is not of the correct length")}try{return M(e)}catch{return atob(e)}}function D(t,e){if(typeof t!="string")throw new u("Invalid token specified: must be a string");e||(e={});let r=e.header===!0?0:1,n=t.split(".")[r];if(typeof n!="string")throw new u(`Invalid token specified: missing part #${r+1}`);let s;try{s=G(n)}catch(i){throw new u(`Invalid token specified: invalid base64 for part #${r+1} (${i.message})`)}try{return JSON.parse(s)}catch(i){throw new u(`Invalid token specified: invalid json for part #${r+1} (${i.message})`)}}function I(t){if(t)try{return D(t)?.devvit}catch(e){throw Error("token decode failure",{cause:e})}}var N=(t,e,r)=>{let n=$(r.name,e.hash),s=j(n),i=I(n.signedRequestContext),c;if(i?c=k(i,s,n.postData):n.webViewContext&&(c=P(n.webViewContext,s,n.postData)),!c)throw Error("no context");let F=n.webViewClientData;globalThis.devvit={context:c,dependencies:{client:S(t),webViewScripts:o},entrypoints:F?.appConfig?.entrypoints??{},share:n?.shareParam?{userData:n?.shareParam.userData}:void 0,appPermissionState:n?.appPermissionState,token:n.signedRequestContext||n.webbitToken,webViewMode:n?.viewMode,startTime:n?.startTime??void 0}};function k(t,e,r){if(!t.app)throw Error("no RequestContext.app");if(!t.post)throw Error("no RequestContext.post");if(!t.subreddit)throw Error("no RequestContext.subreddit");return{appName:t.app.name,appVersion:t.app.version,client:e,postAuthorId:m(t.post.author),postData:r?.developerData,postId:v(t.post.id),snoovatar:t.user?.snoovatar,subredditId:f(t.subreddit.id),subredditName:t.subreddit.name,userId:t.user?.id?m(t.user.id):void 0,username:t.user?.name}}function P(t,e,r){return{appName:t.appName,appVersion:t.appVersion,client:e,postData:r?.developerData,postAuthorId:void 0,postId:v(t.postId),snoovatar:void 0,subredditId:f(t.subredditId),subredditName:t.subredditName,userId:t.userId?m(t.userId):void 0,username:void 0}}function $(t,e){if(t)return JSON.parse(t);let r=e?.slice(1);if(!r)throw Error("no bridge context");return JSON.parse(decodeURIComponent(r))}function j(t){if(!(t.client!==E.ANDROID&&t.client!==E.IOS||!t.nativeVersion))return{name:t.client===E.ANDROID?"ANDROID":"IOS",version:t.nativeVersion}}async function B(t,e,r,n,s){let i=new Request(n,s);return H(r,new URL(i.url))&&i.headers.set("Authorization",`Bearer ${t.token}`),await e(i)}function h(){globalThis.fetch=B.bind(void 0,globalThis.devvit,globalThis.fetch,location)}function H(t,e){return e.origin===t.origin}N(document,location,window);R();h();})();
|
|
2
2
|
//# sourceMappingURL=devvit.v1.min.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["<define:globalThis.webViewScriptsVersion>", "../../../protos/dist/json/devvit/ui/effects/v1alpha/effect.js", "../../../protos/dist/json/devvit/ui/effects/web_view/v1alpha/post_message.js", "../../../shared-types/dist/client/emit-effect.js", "../../src/analytics.ts", "../../../protos/dist/json/devvit/ui/effects/web_view/v1alpha/context.js", "../../../shared-types/dist/assert.js", "../../../shared-types/dist/tid.js", "../../../shared-types/dist/web-view-scripts-constants.js", "../../src/client.ts", "../../../../node_modules/jwt-decode/build/esm/index.js", "../../src/token.ts", "../../src/devvit-global.ts", "../../src/fetch.ts", "../../src/devvit.v1.ts"],
|
|
4
|
-
"sourcesContent": ["{\"hash\":\"962aee6\",\"version\":\"0.12.7-dev\"}", "/**\n * #effect.ts\n *\n * Code generated by ts-proto. DO NOT EDIT.\n * @packageDocumentation\n */\n/* eslint-disable */\nexport var EffectType;\n(function (EffectType) {\n /** EFFECT_REALTIME_SUB - Notify client to synchronize its realtime subscriptions */\n EffectType[EffectType[\"EFFECT_REALTIME_SUB\"] = 0] = \"EFFECT_REALTIME_SUB\";\n /** EFFECT_RERENDER_UI - Trigger a re-render for apps that have visible UI */\n EffectType[EffectType[\"EFFECT_RERENDER_UI\"] = 1] = \"EFFECT_RERENDER_UI\";\n /**\n * EFFECT_RELOAD_PART - Notify the client that parts of a subreddit, post, or comment should be reloaded\n *\n * @deprecated\n */\n EffectType[EffectType[\"EFFECT_RELOAD_PART\"] = 2] = \"EFFECT_RELOAD_PART\";\n /** EFFECT_SHOW_FORM - Display a user input form */\n EffectType[EffectType[\"EFFECT_SHOW_FORM\"] = 3] = \"EFFECT_SHOW_FORM\";\n /** EFFECT_SHOW_TOAST - Display a transient toast message */\n EffectType[EffectType[\"EFFECT_SHOW_TOAST\"] = 4] = \"EFFECT_SHOW_TOAST\";\n /** EFFECT_NAVIGATE_TO_URL - Notify the client to navigate to a URL */\n EffectType[EffectType[\"EFFECT_NAVIGATE_TO_URL\"] = 5] = \"EFFECT_NAVIGATE_TO_URL\";\n /** EFFECT_SET_INTERVALS - This updates the list of active timers. */\n EffectType[EffectType[\"EFFECT_SET_INTERVALS\"] = 7] = \"EFFECT_SET_INTERVALS\";\n /** EFFECT_CREATE_ORDER - This starts a purchase flow */\n EffectType[EffectType[\"EFFECT_CREATE_ORDER\"] = 8] = \"EFFECT_CREATE_ORDER\";\n /** EFFECT_WEB_VIEW - Control and communicate with WebViews */\n EffectType[EffectType[\"EFFECT_WEB_VIEW\"] = 9] = \"EFFECT_WEB_VIEW\";\n /** EFFECT_CAN_RUN_AS_USER - Check if the app can execute some actions as the user */\n EffectType[EffectType[\"EFFECT_CAN_RUN_AS_USER\"] = 11] = \"EFFECT_CAN_RUN_AS_USER\";\n /** EFFECT_TELEMETRY - Statistical data event for analytics. */\n EffectType[EffectType[\"EFFECT_TELEMETRY\"] = 12] = \"EFFECT_TELEMETRY\";\n /** EFFECT_UPDATE_REQUEST_CONTEXT - Request an updated signed request context */\n EffectType[EffectType[\"EFFECT_UPDATE_REQUEST_CONTEXT\"] = 13] = \"EFFECT_UPDATE_REQUEST_CONTEXT\";\n EffectType[EffectType[\"UNRECOGNIZED\"] = -1] = \"UNRECOGNIZED\";\n})(EffectType || (EffectType = {}));\n", "/**\n * #post_message.ts\n *\n * Code generated by ts-proto. DO NOT EDIT.\n * @packageDocumentation\n */\n/* eslint-disable */\n/**\n * Blocks only.\n *\n * @deprecated\n */\nexport var WebViewInternalMessageScope;\n(function (WebViewInternalMessageScope) {\n /** CLIENT - Message is intended for the client only */\n WebViewInternalMessageScope[WebViewInternalMessageScope[\"CLIENT\"] = 0] = \"CLIENT\";\n WebViewInternalMessageScope[WebViewInternalMessageScope[\"UNRECOGNIZED\"] = -1] = \"UNRECOGNIZED\";\n})(WebViewInternalMessageScope || (WebViewInternalMessageScope = {}));\n", "import { EffectType } from '@devvit/protos/json/devvit/ui/effects/v1alpha/effect.js';\nimport { WebViewInternalMessageScope, } from '@devvit/protos/json/devvit/ui/effects/web_view/v1alpha/post_message.js';\n/** `WebViewInternalMessage.type`. */\nexport const webViewInternalMessageType = 'devvit-internal';\nconst EFFECTS_WITH_RESPONSE = {\n [EffectType.EFFECT_SHOW_FORM]: true,\n [EffectType.EFFECT_CAN_RUN_AS_USER]: true,\n [EffectType.EFFECT_CREATE_ORDER]: true,\n};\n/**\n * Emits an effect to the parent window and handles the response if required.\n *\n * @param effect - The effect to be emitted to the parent window\n * @returns A promise that resolves with the response message for effects that require\n * a response, or resolves immediately with undefined for effects that don't\n *\n * @description\n * This function handles two types of effects:\n * 1. Effects that require a response: Creates a unique ID, sets up a message listener,\n * and resolves the promise when a matching response is received\n * 2. Effects that don't require a response: Posts the message and resolves immediately\n */\nexport const emitEffect = (effect) => {\n return new Promise((resolve) => {\n const message = {\n ...effect,\n realtimeEffect: effect.realtime, // to-do: remove deprecated field.\n scope: WebViewInternalMessageScope.CLIENT,\n type: webViewInternalMessageType,\n };\n // For temporary backward compatibility, we set both `message.effect_type` above, and `effect` below\n // Once mobile clients are updated to consume the strongly typed properties above, we can remove this block\n // *Do not* add new effects here, use the strongly typed properties above\n if (effect.showToast ||\n effect.navigateToUrl ||\n effect.showForm ||\n effect.type === EffectType.EFFECT_CAN_RUN_AS_USER) {\n message.effect = effect;\n }\n // Only set message id and add a listener for effects which require a response\n if (EFFECTS_WITH_RESPONSE[effect.type]) {\n const id = crypto.randomUUID();\n message.id = id;\n const handleEffect = (event) => {\n if (event.data?.type === 'devvit-message' && event.data?.data?.id === id) {\n resolve(event.data.data);\n removeEventListener('message', handleEffect);\n }\n };\n addEventListener('message', handleEffect);\n // Post message to the parent window, handled by client web view component\n parent.postMessage(message, '*');\n }\n else {\n parent.postMessage(message, '*');\n // Resolve immediately for effects that don't expect a response.\n resolve(undefined);\n }\n });\n};\n", "import { EffectType } from '@devvit/protos/json/devvit/ui/effects/v1alpha/effect.js';\nimport type {\n WebViewTelemetryClickEffect,\n WebViewTelemetryLoadedEffect,\n} from '@devvit/protos/json/devvit/ui/effects/web_view/v1alpha/telemetry.js';\nimport { emitEffect } from '@devvit/shared-types/client/emit-effect.js';\n\n/**\n * initAnalytics is added to all Devvit apps which use web views.\n *\n * This sends interaction events to the parent window via postMessage.\n * These metrics are used to inform app performance and feed ranking.\n */\nexport function initAnalytics(): void {\n addEventListener('load', () => {\n const timeStart = performance.timeOrigin;\n const duration = performance.now();\n const timeEnd = performance.timeOrigin + duration;\n const loaded: WebViewTelemetryLoadedEffect = {\n event: 'web-view-loaded',\n timeStart,\n timeEnd,\n duration,\n };\n\n // to-do: support devvit.debug.\n // if (devvit.debug.analytics) console.debug(`[analytics] loaded in ${duration} ms`);\n void emitEffect({\n type: EffectType.EFFECT_TELEMETRY,\n telemetry: { event: loaded.event, loaded },\n // to-do: remove once all clients support `telemetry`. Deprecated on\n // 2025-11-24.\n analytics: loaded,\n });\n });\n\n document.addEventListener(\n 'click',\n (event) => {\n const click: WebViewTelemetryClickEffect = {\n event: 'click',\n definition: isStrictClick(event) ? 'strict' : 'default',\n };\n void emitEffect({\n type: EffectType.EFFECT_TELEMETRY,\n telemetry: { event: click.event, click },\n // to-do: remove once all clients support `telemetry`. Deprecated on\n // 2025-11-24.\n analytics: click,\n });\n },\n { passive: true }\n );\n}\n\nfunction isStrictClick(event: MouseEvent): boolean {\n if (!event.isTrusted) {\n return false;\n }\n\n const eventTarget = event.target as HTMLElement;\n\n const computedStyles = globalThis.window.getComputedStyle(eventTarget);\n if (computedStyles?.getPropertyValue('cursor') === 'pointer') {\n return true;\n }\n\n return elementOrParentIsInteractive(eventTarget);\n}\n\nfunction elementOrParentIsInteractive(element: HTMLElement): boolean {\n const STRICT_CLICK_TAGNAMES = ['A', 'BUTTON', 'CANVAS', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL'];\n\n let currentElement: HTMLElement | null = element;\n\n while (currentElement && currentElement.tagName !== 'BODY') {\n if (STRICT_CLICK_TAGNAMES.includes(currentElement.tagName)) {\n return true;\n }\n\n if (['true', 'plaintext-only'].includes(currentElement.getAttribute('contenteditable') ?? '')) {\n return true;\n }\n\n currentElement = currentElement.parentElement;\n }\n\n return false;\n}\n", "/**\n * #context.ts\n *\n * Code generated by ts-proto. DO NOT EDIT.\n * @packageDocumentation\n */\n/* eslint-disable */\n/** The user client hosting the web view. */\nexport var Client;\n(function (Client) {\n Client[Client[\"CLIENT_UNSPECIFIED\"] = 0] = \"CLIENT_UNSPECIFIED\";\n Client[Client[\"ANDROID\"] = 1] = \"ANDROID\";\n Client[Client[\"IOS\"] = 2] = \"IOS\";\n Client[Client[\"SHREDDIT\"] = 3] = \"SHREDDIT\";\n Client[Client[\"UNRECOGNIZED\"] = -1] = \"UNRECOGNIZED\";\n})(Client || (Client = {}));\n/**\n * Inline height of post.\n *\n * @deprecated\n */\nexport var Height;\n(function (Height) {\n Height[Height[\"HEIGHT_UNSPECIFIED\"] = 0] = \"HEIGHT_UNSPECIFIED\";\n Height[Height[\"REGULAR\"] = 1] = \"REGULAR\";\n Height[Height[\"TALL\"] = 2] = \"TALL\";\n Height[Height[\"UNRECOGNIZED\"] = -1] = \"UNRECOGNIZED\";\n})(Height || (Height = {}));\n", "export function assert(condition, msg) {\n if (!condition)\n throw Error(msg);\n}\n", "import { assert } from './assert.js';\n/**\n * - **C**omment (T1).\n * - **A**ccount (T2).\n * - **L**ink (T3).\n * - **M**essage (T4).\n * - **S**ubreddit (T5).\n * - **T**rophies (T6).\n */\nexport var T_PREFIX;\n(function (T_PREFIX) {\n T_PREFIX[\"COMMENT\"] = \"t1_\";\n T_PREFIX[\"ACCOUNT\"] = \"t2_\";\n T_PREFIX[\"LINK\"] = \"t3_\";\n T_PREFIX[\"MESSAGE\"] = \"t4_\";\n T_PREFIX[\"SUBREDDIT\"] = \"t5_\";\n T_PREFIX[\"AWARD\"] = \"t6_\";\n})(T_PREFIX || (T_PREFIX = {}));\n// type guards\nexport function isT1(id) {\n return id.startsWith(T_PREFIX.COMMENT);\n}\nexport function isT2(id) {\n return id.startsWith(T_PREFIX.ACCOUNT);\n}\nexport function isT3(id) {\n return id.startsWith(T_PREFIX.LINK);\n}\nexport function isT4(id) {\n return id.startsWith(T_PREFIX.MESSAGE);\n}\nexport function isT5(id) {\n return id.startsWith(T_PREFIX.SUBREDDIT);\n}\nexport function isT6(id) {\n return id.startsWith(T_PREFIX.AWARD);\n}\n// assertion functions\nexport function assertT1(id) {\n assert(isT1(id), `Expected comment id to start with ${T_PREFIX.COMMENT}, got ${id}`);\n}\nexport function assertT2(id) {\n assert(isT2(id), `Expected account id to start with ${T_PREFIX.ACCOUNT}, got ${id}`);\n}\nexport function assertT3(id) {\n assert(isT3(id), `Expected link id to start with ${T_PREFIX.LINK}, got ${id}`);\n}\nexport function assertT4(id) {\n assert(isT4(id), `Expected message id to start with ${T_PREFIX.MESSAGE}, got ${id}`);\n}\nexport function assertT5(id) {\n assert(isT5(id), `Expected subreddit id to start with ${T_PREFIX.SUBREDDIT}, got ${id}`);\n}\nexport function assertT6(id) {\n assert(isT6(id), `Expected award id to start with ${T_PREFIX.AWARD}, got ${id}`);\n}\n// factory functions\nexport function T1(id) {\n assertT1(id);\n return id;\n}\nexport function T2(id) {\n assertT2(id);\n return id;\n}\nexport function T3(id) {\n assertT3(id);\n return id;\n}\nexport function T4(id) {\n assertT4(id);\n return id;\n}\nexport function T5(id) {\n assertT5(id);\n return id;\n}\nexport function T6(id) {\n assertT6(id);\n return id;\n}\nexport function asTid(id) {\n if (isT1(id)) {\n return T1(id);\n }\n if (isT2(id)) {\n return T2(id);\n }\n if (isT3(id)) {\n return T3(id);\n }\n if (isT4(id)) {\n return T4(id);\n }\n if (isT5(id)) {\n return T5(id);\n }\n if (isT6(id)) {\n return T6(id);\n }\n throw new Error(`Expected thing id to start with ${Object.values(T_PREFIX).join(', ')} got ${id}}`);\n}\n", "/**\n * The `@devvit/client` version query parameter name the web view's document\n * script tag:\n *\n * <script src=\"https://webview.devvit.net/scripts/devvit.v1.min.js?clientVersion=1.2.3\"></script>\n *\n * The value is the version of `@devvit/client` bundled with the app.\n * `@devvit/client` may have runtime dependencies on\n * `@devvit/web-view-scripts` (`devvit.v1.min.js`) which is not bundled. The\n * client version can be used to specialize behavior to match the static\n * expectations of the `@devvit/client` version.\n */\nexport const clientVersionQueryParam = 'clientVersion';\n", "import { clientVersionQueryParam } from '@devvit/shared-types/web-view-scripts-constants.js';\n\n/**\n * Queries the client version (eg, `'1.2.3'`) from the iframe document's script\n * tag:\n *\n * <script src=\"https://webview.devvit.net/scripts/devvit.v1.min.js?clientVersion=1.2.3\"></script>\n *\n * See `clientVersionQueryParam`.\n */\nexport function queryClientVersion(document: {\n readonly currentScript: { readonly src: string } | SVGScriptElement | null;\n}): string | undefined {\n if (document.currentScript && 'src' in document.currentScript)\n return (\n new URL(document.currentScript.src).searchParams.get(clientVersionQueryParam) ?? undefined\n );\n}\n", "export class InvalidTokenError extends Error {\n}\nInvalidTokenError.prototype.name = \"InvalidTokenError\";\nfunction b64DecodeUnicode(str) {\n return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => {\n let code = p.charCodeAt(0).toString(16).toUpperCase();\n if (code.length < 2) {\n code = \"0\" + code;\n }\n return \"%\" + code;\n }));\n}\nfunction base64UrlDecode(str) {\n let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (output.length % 4) {\n case 0:\n break;\n case 2:\n output += \"==\";\n break;\n case 3:\n output += \"=\";\n break;\n default:\n throw new Error(\"base64 string is not of the correct length\");\n }\n try {\n return b64DecodeUnicode(output);\n }\n catch (err) {\n return atob(output);\n }\n}\nexport function jwtDecode(token, options) {\n if (typeof token !== \"string\") {\n throw new InvalidTokenError(\"Invalid token specified: must be a string\");\n }\n options || (options = {});\n const pos = options.header === true ? 0 : 1;\n const part = token.split(\".\")[pos];\n if (typeof part !== \"string\") {\n throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);\n }\n let decoded;\n try {\n decoded = base64UrlDecode(part);\n }\n catch (e) {\n throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);\n }\n try {\n return JSON.parse(decoded);\n }\n catch (e) {\n throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);\n }\n}\n", "import type { RequestContext } from '@devvit/protos/json/devvit/platform/v1/request_context.js';\nimport { jwtDecode } from 'jwt-decode';\n\n// to-do: make a Protobuf for ContextClaims.\nexport type ContextClaims = { devvit: RequestContext };\n\nexport function decodeToken(token: string | undefined): RequestContext | undefined {\n if (!token) return;\n\n try {\n return jwtDecode<ContextClaims>(token)?.devvit;\n } catch (err) {\n throw Error('token decode failure', { cause: err });\n }\n}\n", "import type { DevvitPostData } from '@devvit/protos';\nimport type { RequestContext } from '@devvit/protos/json/devvit/platform/v1/request_context.js';\nimport {\n type BridgeContext,\n Client as ClientName,\n type WebViewClientData,\n type WebViewContext,\n} from '@devvit/protos/json/devvit/ui/effects/web_view/v1alpha/context.js';\nimport type { Context } from '@devvit/shared-types/client/client-context.js';\nimport type {\n DevvitGlobal,\n WebViewScriptsVersion,\n} from '@devvit/shared-types/client/devvit-global.js';\nimport type { Client } from '@devvit/shared-types/shared/client.js';\nimport { T2, T3, T5 } from '@devvit/shared-types/tid.js';\nimport { type WebbitToken } from '@devvit/shared-types/webbit.js';\n\nimport { queryClientVersion } from './client.js';\nimport { decodeToken } from './token.js';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var devvit: DevvitGlobal;\n /** Defined by build.js. */\n // eslint-disable-next-line no-var\n var webViewScriptsVersion: Readonly<WebViewScriptsVersion>;\n}\n\n/** @internal */\nexport const initDevvitGlobal = (\n document: { readonly currentScript: { readonly src: string } | SVGScriptElement | null },\n location: { readonly hash: string },\n window: { readonly name: string }\n): void => {\n const bridge = getBridgeContext(window.name, location.hash);\n\n const client = getClient(bridge);\n\n const reqCtx = decodeToken(bridge.signedRequestContext);\n\n let context;\n if (reqCtx) context = contextFromRequestContext(reqCtx, client, bridge.postData);\n else if (bridge.webViewContext)\n context = contextFromWebViewContext(bridge.webViewContext, client, bridge.postData);\n if (!context) throw Error('no context');\n\n // to-do: expose `devvitDebug`, `shredditVersion`.\n\n const clientData: WebViewClientData | undefined = bridge.webViewClientData;\n globalThis.devvit = {\n context,\n dependencies: {\n client: queryClientVersion(document),\n webViewScripts: globalThis.webViewScriptsVersion,\n },\n entrypoints: clientData?.appConfig?.entrypoints ?? {},\n share: bridge?.shareParam ? { userData: bridge?.shareParam.userData } : undefined,\n appPermissionState: bridge?.appPermissionState,\n token: (bridge.signedRequestContext || bridge.webbitToken) as WebbitToken,\n webViewMode: bridge?.viewMode,\n startTime: bridge?.startTime ?? undefined,\n };\n};\n\n/** @internal */\nexport function contextFromRequestContext(\n reqCtx: Readonly<RequestContext>,\n client: Client | undefined,\n postData: Readonly<DevvitPostData> | undefined\n): Context {\n if (!reqCtx.app) throw Error('no RequestContext.app');\n if (!reqCtx.post) throw Error('no RequestContext.post');\n if (!reqCtx.subreddit) throw Error('no RequestContext.subreddit');\n return {\n appName: reqCtx.app.name,\n appVersion: reqCtx.app.version,\n client,\n postAuthorId: T2(reqCtx.post.author),\n postData: postData?.developerData,\n postId: T3(reqCtx.post.id),\n snoovatar: reqCtx.user?.snoovatar,\n subredditId: T5(reqCtx.subreddit.id),\n subredditName: reqCtx.subreddit.name,\n userId: reqCtx.user?.id ? T2(reqCtx.user.id) : undefined,\n username: reqCtx.user?.name,\n };\n}\n\n/** @internal */\nexport function contextFromWebViewContext(\n webViewCtx: Readonly<WebViewContext>,\n client: Client | undefined,\n postData: Readonly<DevvitPostData> | undefined\n): Context {\n return {\n appName: webViewCtx.appName,\n appVersion: webViewCtx.appVersion,\n client,\n postData: postData?.developerData,\n postAuthorId: undefined,\n postId: T3(webViewCtx.postId),\n snoovatar: undefined,\n subredditId: T5(webViewCtx.subredditId),\n subredditName: webViewCtx.subredditName,\n userId: webViewCtx.userId ? T2(webViewCtx.userId) : undefined,\n username: undefined,\n };\n}\n\n/**\n * Extracts the BridgeContext from the hash.\n * @internal\n */\nexport function getBridgeContext(name: string | undefined, hash: string): BridgeContext {\n if (name) return JSON.parse(name);\n const json = hash?.slice(1); // Strip the leading '#' from the hash\n if (!json) throw Error('no bridge context');\n return JSON.parse(decodeURIComponent(json));\n}\n\n/** @internal */\nexport function getClient(bridge: Readonly<BridgeContext>): Client | undefined {\n if (\n (bridge.client !== ClientName.ANDROID && bridge.client !== ClientName.IOS) ||\n !bridge.nativeVersion\n )\n return;\n return {\n name: bridge.client === ClientName.ANDROID ? 'ANDROID' : ('IOS' as const),\n version: bridge.nativeVersion,\n };\n}\n", "import type { DevvitGlobal } from '@devvit/shared-types/client/devvit-global.js';\n\n/** Injects an auth token into /api/ requests. */\nexport async function fetch(\n devvit: Readonly<DevvitGlobal>,\n globalFetch: typeof globalThis.fetch,\n location: Readonly<Location>,\n input: RequestInfo | URL,\n init?: RequestInit\n): Promise<Response> {\n const req = new Request(input, init);\n if (isSameSite(location, new URL(req.url)))\n req.headers.set('Authorization', `Bearer ${devvit.token}`);\n // to-do: pass devvit-debug from BridgeContext.\n return await globalFetch(req);\n}\n\nexport function initFetch(): void {\n globalThis.fetch = fetch.bind(undefined, globalThis.devvit, globalThis.fetch, location);\n}\n\n/** @internal */\nexport function isSameSite(location: Readonly<Location>, url: URL): boolean {\n return url.origin === location.origin;\n}\n", "import { initAnalytics } from './analytics.js';\nimport { initDevvitGlobal } from './devvit-global.js';\nimport { initFetch } from './fetch.js';\n\ninitDevvitGlobal(document, location, window);\ninitAnalytics();\ninitFetch();\n"],
|
|
4
|
+
"sourcesContent": ["{\"hash\":\"ffbcd4e\",\"version\":\"0.12.7-dev\"}", "/**\n * #effect.ts\n *\n * Code generated by ts-proto. DO NOT EDIT.\n * @packageDocumentation\n */\n/* eslint-disable */\nexport var EffectType;\n(function (EffectType) {\n /** EFFECT_REALTIME_SUB - Notify client to synchronize its realtime subscriptions */\n EffectType[EffectType[\"EFFECT_REALTIME_SUB\"] = 0] = \"EFFECT_REALTIME_SUB\";\n /** EFFECT_RERENDER_UI - Trigger a re-render for apps that have visible UI */\n EffectType[EffectType[\"EFFECT_RERENDER_UI\"] = 1] = \"EFFECT_RERENDER_UI\";\n /**\n * EFFECT_RELOAD_PART - Notify the client that parts of a subreddit, post, or comment should be reloaded\n *\n * @deprecated\n */\n EffectType[EffectType[\"EFFECT_RELOAD_PART\"] = 2] = \"EFFECT_RELOAD_PART\";\n /** EFFECT_SHOW_FORM - Display a user input form */\n EffectType[EffectType[\"EFFECT_SHOW_FORM\"] = 3] = \"EFFECT_SHOW_FORM\";\n /** EFFECT_SHOW_TOAST - Display a transient toast message */\n EffectType[EffectType[\"EFFECT_SHOW_TOAST\"] = 4] = \"EFFECT_SHOW_TOAST\";\n /** EFFECT_NAVIGATE_TO_URL - Notify the client to navigate to a URL */\n EffectType[EffectType[\"EFFECT_NAVIGATE_TO_URL\"] = 5] = \"EFFECT_NAVIGATE_TO_URL\";\n /** EFFECT_SET_INTERVALS - This updates the list of active timers. */\n EffectType[EffectType[\"EFFECT_SET_INTERVALS\"] = 7] = \"EFFECT_SET_INTERVALS\";\n /** EFFECT_CREATE_ORDER - This starts a purchase flow */\n EffectType[EffectType[\"EFFECT_CREATE_ORDER\"] = 8] = \"EFFECT_CREATE_ORDER\";\n /** EFFECT_WEB_VIEW - Control and communicate with WebViews */\n EffectType[EffectType[\"EFFECT_WEB_VIEW\"] = 9] = \"EFFECT_WEB_VIEW\";\n /** EFFECT_CAN_RUN_AS_USER - Check if the app can execute some actions as the user */\n EffectType[EffectType[\"EFFECT_CAN_RUN_AS_USER\"] = 11] = \"EFFECT_CAN_RUN_AS_USER\";\n /** EFFECT_TELEMETRY - Statistical data event for analytics. */\n EffectType[EffectType[\"EFFECT_TELEMETRY\"] = 12] = \"EFFECT_TELEMETRY\";\n /** EFFECT_UPDATE_REQUEST_CONTEXT - Request an updated signed request context */\n EffectType[EffectType[\"EFFECT_UPDATE_REQUEST_CONTEXT\"] = 13] = \"EFFECT_UPDATE_REQUEST_CONTEXT\";\n EffectType[EffectType[\"UNRECOGNIZED\"] = -1] = \"UNRECOGNIZED\";\n})(EffectType || (EffectType = {}));\n", "/**\n * #post_message.ts\n *\n * Code generated by ts-proto. DO NOT EDIT.\n * @packageDocumentation\n */\n/* eslint-disable */\n/**\n * Blocks only.\n *\n * @deprecated\n */\nexport var WebViewInternalMessageScope;\n(function (WebViewInternalMessageScope) {\n /** CLIENT - Message is intended for the client only */\n WebViewInternalMessageScope[WebViewInternalMessageScope[\"CLIENT\"] = 0] = \"CLIENT\";\n WebViewInternalMessageScope[WebViewInternalMessageScope[\"UNRECOGNIZED\"] = -1] = \"UNRECOGNIZED\";\n})(WebViewInternalMessageScope || (WebViewInternalMessageScope = {}));\n", "import { EffectType } from '@devvit/protos/json/devvit/ui/effects/v1alpha/effect.js';\nimport { WebViewInternalMessageScope, } from '@devvit/protos/json/devvit/ui/effects/web_view/v1alpha/post_message.js';\n/** `WebViewInternalMessage.type`. */\nexport const webViewInternalMessageType = 'devvit-internal';\nconst EFFECTS_WITH_RESPONSE = {\n [EffectType.EFFECT_SHOW_FORM]: true,\n [EffectType.EFFECT_CAN_RUN_AS_USER]: true,\n [EffectType.EFFECT_CREATE_ORDER]: true,\n};\n/**\n * Emits an effect to the parent window and handles the response if required.\n *\n * @param effect - The effect to be emitted to the parent window\n * @returns A promise that resolves with the response message for effects that require\n * a response, or resolves immediately with undefined for effects that don't\n *\n * @description\n * This function handles two types of effects:\n * 1. Effects that require a response: Creates a unique ID, sets up a message listener,\n * and resolves the promise when a matching response is received\n * 2. Effects that don't require a response: Posts the message and resolves immediately\n */\nexport const emitEffect = (effect) => {\n return new Promise((resolve) => {\n const message = {\n ...effect,\n realtimeEffect: effect.realtime, // to-do: remove deprecated field.\n scope: WebViewInternalMessageScope.CLIENT,\n type: webViewInternalMessageType,\n };\n // For temporary backward compatibility, we set both `message.effect_type` above, and `effect` below\n // Once mobile clients are updated to consume the strongly typed properties above, we can remove this block\n // *Do not* add new effects here, use the strongly typed properties above\n if (effect.showToast ||\n effect.navigateToUrl ||\n effect.showForm ||\n effect.type === EffectType.EFFECT_CAN_RUN_AS_USER) {\n message.effect = effect;\n }\n // Only set message id and add a listener for effects which require a response\n if (EFFECTS_WITH_RESPONSE[effect.type]) {\n const id = crypto.randomUUID();\n message.id = id;\n const handleEffect = (event) => {\n if (event.data?.type === 'devvit-message' && event.data?.data?.id === id) {\n resolve(event.data.data);\n removeEventListener('message', handleEffect);\n }\n };\n addEventListener('message', handleEffect);\n // Post message to the parent window, handled by client web view component\n parent.postMessage(message, '*');\n }\n else {\n parent.postMessage(message, '*');\n // Resolve immediately for effects that don't expect a response.\n resolve(undefined);\n }\n });\n};\n", "import { EffectType } from '@devvit/protos/json/devvit/ui/effects/v1alpha/effect.js';\nimport type {\n WebViewTelemetryClickEffect,\n WebViewTelemetryLoadedEffect,\n} from '@devvit/protos/json/devvit/ui/effects/web_view/v1alpha/telemetry.js';\nimport { emitEffect } from '@devvit/shared-types/client/emit-effect.js';\n\n/**\n * initAnalytics is added to all Devvit apps which use web views.\n *\n * This sends interaction events to the parent window via postMessage.\n * These metrics are used to inform app performance and feed ranking.\n */\nexport function initAnalytics(): void {\n addEventListener('load', () => {\n const timeStart = performance.timeOrigin;\n const duration = performance.now();\n const timeEnd = performance.timeOrigin + duration;\n const loaded: WebViewTelemetryLoadedEffect = {\n event: 'web-view-loaded',\n timeStart,\n timeEnd,\n duration,\n };\n\n // to-do: support devvit.debug.\n // if (devvit.debug.analytics) console.debug(`[analytics] loaded in ${duration} ms`);\n void emitEffect({\n type: EffectType.EFFECT_TELEMETRY,\n telemetry: { event: loaded.event, loaded },\n // to-do: remove once all clients support `telemetry`. Deprecated on\n // 2025-11-24.\n analytics: loaded,\n });\n });\n\n document.addEventListener(\n 'click',\n (event) => {\n const click: WebViewTelemetryClickEffect = {\n event: 'click',\n definition: isStrictClick(event) ? 'strict' : 'default',\n };\n void emitEffect({\n type: EffectType.EFFECT_TELEMETRY,\n telemetry: { event: click.event, click },\n // to-do: remove once all clients support `telemetry`. Deprecated on\n // 2025-11-24.\n analytics: click,\n });\n },\n { passive: true }\n );\n}\n\nfunction isStrictClick(event: MouseEvent): boolean {\n if (!event.isTrusted) {\n return false;\n }\n\n const eventTarget = event.target as HTMLElement;\n\n const computedStyles = globalThis.window.getComputedStyle(eventTarget);\n if (computedStyles?.getPropertyValue('cursor') === 'pointer') {\n return true;\n }\n\n return elementOrParentIsInteractive(eventTarget);\n}\n\nfunction elementOrParentIsInteractive(element: HTMLElement): boolean {\n const STRICT_CLICK_TAGNAMES = ['A', 'BUTTON', 'CANVAS', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL'];\n\n let currentElement: HTMLElement | null = element;\n\n while (currentElement && currentElement.tagName !== 'BODY') {\n if (STRICT_CLICK_TAGNAMES.includes(currentElement.tagName)) {\n return true;\n }\n\n if (['true', 'plaintext-only'].includes(currentElement.getAttribute('contenteditable') ?? '')) {\n return true;\n }\n\n currentElement = currentElement.parentElement;\n }\n\n return false;\n}\n", "/**\n * #context.ts\n *\n * Code generated by ts-proto. DO NOT EDIT.\n * @packageDocumentation\n */\n/* eslint-disable */\n/** The user client hosting the web view. */\nexport var Client;\n(function (Client) {\n Client[Client[\"CLIENT_UNSPECIFIED\"] = 0] = \"CLIENT_UNSPECIFIED\";\n Client[Client[\"ANDROID\"] = 1] = \"ANDROID\";\n Client[Client[\"IOS\"] = 2] = \"IOS\";\n Client[Client[\"SHREDDIT\"] = 3] = \"SHREDDIT\";\n Client[Client[\"UNRECOGNIZED\"] = -1] = \"UNRECOGNIZED\";\n})(Client || (Client = {}));\n/**\n * Inline height of post.\n *\n * @deprecated\n */\nexport var Height;\n(function (Height) {\n Height[Height[\"HEIGHT_UNSPECIFIED\"] = 0] = \"HEIGHT_UNSPECIFIED\";\n Height[Height[\"REGULAR\"] = 1] = \"REGULAR\";\n Height[Height[\"TALL\"] = 2] = \"TALL\";\n Height[Height[\"UNRECOGNIZED\"] = -1] = \"UNRECOGNIZED\";\n})(Height || (Height = {}));\n", "export function assert(condition, msg) {\n if (!condition)\n throw Error(msg);\n}\n", "import { assert } from './assert.js';\n/**\n * - **C**omment (T1).\n * - **A**ccount (T2).\n * - **L**ink (T3).\n * - **M**essage (T4).\n * - **S**ubreddit (T5).\n * - **T**rophies (T6).\n */\nexport var T_PREFIX;\n(function (T_PREFIX) {\n T_PREFIX[\"COMMENT\"] = \"t1_\";\n T_PREFIX[\"ACCOUNT\"] = \"t2_\";\n T_PREFIX[\"LINK\"] = \"t3_\";\n T_PREFIX[\"MESSAGE\"] = \"t4_\";\n T_PREFIX[\"SUBREDDIT\"] = \"t5_\";\n T_PREFIX[\"AWARD\"] = \"t6_\";\n})(T_PREFIX || (T_PREFIX = {}));\n// type guards\nexport function isT1(id) {\n return id.startsWith(T_PREFIX.COMMENT);\n}\nexport function isT2(id) {\n return id.startsWith(T_PREFIX.ACCOUNT);\n}\nexport function isT3(id) {\n return id.startsWith(T_PREFIX.LINK);\n}\nexport function isT4(id) {\n return id.startsWith(T_PREFIX.MESSAGE);\n}\nexport function isT5(id) {\n return id.startsWith(T_PREFIX.SUBREDDIT);\n}\nexport function isT6(id) {\n return id.startsWith(T_PREFIX.AWARD);\n}\n// assertion functions\nexport function assertT1(id) {\n assert(isT1(id), `Expected comment id to start with ${T_PREFIX.COMMENT}, got ${id}`);\n}\nexport function assertT2(id) {\n assert(isT2(id), `Expected account id to start with ${T_PREFIX.ACCOUNT}, got ${id}`);\n}\nexport function assertT3(id) {\n assert(isT3(id), `Expected link id to start with ${T_PREFIX.LINK}, got ${id}`);\n}\nexport function assertT4(id) {\n assert(isT4(id), `Expected message id to start with ${T_PREFIX.MESSAGE}, got ${id}`);\n}\nexport function assertT5(id) {\n assert(isT5(id), `Expected subreddit id to start with ${T_PREFIX.SUBREDDIT}, got ${id}`);\n}\nexport function assertT6(id) {\n assert(isT6(id), `Expected award id to start with ${T_PREFIX.AWARD}, got ${id}`);\n}\n// factory functions\nexport function T1(id) {\n assertT1(id);\n return id;\n}\nexport function T2(id) {\n assertT2(id);\n return id;\n}\nexport function T3(id) {\n assertT3(id);\n return id;\n}\nexport function T4(id) {\n assertT4(id);\n return id;\n}\nexport function T5(id) {\n assertT5(id);\n return id;\n}\nexport function T6(id) {\n assertT6(id);\n return id;\n}\nexport function asTid(id) {\n if (isT1(id)) {\n return T1(id);\n }\n if (isT2(id)) {\n return T2(id);\n }\n if (isT3(id)) {\n return T3(id);\n }\n if (isT4(id)) {\n return T4(id);\n }\n if (isT5(id)) {\n return T5(id);\n }\n if (isT6(id)) {\n return T6(id);\n }\n throw new Error(`Expected thing id to start with ${Object.values(T_PREFIX).join(', ')} got ${id}}`);\n}\n", "/**\n * The `@devvit/client` version query parameter name the web view's document\n * script tag:\n *\n * <script src=\"https://webview.devvit.net/scripts/devvit.v1.min.js?clientVersion=1.2.3\"></script>\n *\n * The value is the version of `@devvit/client` bundled with the app.\n * `@devvit/client` may have runtime dependencies on\n * `@devvit/web-view-scripts` (`devvit.v1.min.js`) which is not bundled. The\n * client version can be used to specialize behavior to match the static\n * expectations of the `@devvit/client` version.\n */\nexport const clientVersionQueryParam = 'clientVersion';\n", "import { clientVersionQueryParam } from '@devvit/shared-types/web-view-scripts-constants.js';\n\n/**\n * Queries the client version (eg, `'1.2.3'`) from the iframe document's script\n * tag:\n *\n * <script src=\"https://webview.devvit.net/scripts/devvit.v1.min.js?clientVersion=1.2.3\"></script>\n *\n * See `clientVersionQueryParam`.\n */\nexport function queryClientVersion(document: {\n readonly currentScript: { readonly src: string } | SVGScriptElement | null;\n}): string | undefined {\n if (document.currentScript && 'src' in document.currentScript)\n return (\n new URL(document.currentScript.src).searchParams.get(clientVersionQueryParam) ?? undefined\n );\n}\n", "export class InvalidTokenError extends Error {\n}\nInvalidTokenError.prototype.name = \"InvalidTokenError\";\nfunction b64DecodeUnicode(str) {\n return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => {\n let code = p.charCodeAt(0).toString(16).toUpperCase();\n if (code.length < 2) {\n code = \"0\" + code;\n }\n return \"%\" + code;\n }));\n}\nfunction base64UrlDecode(str) {\n let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (output.length % 4) {\n case 0:\n break;\n case 2:\n output += \"==\";\n break;\n case 3:\n output += \"=\";\n break;\n default:\n throw new Error(\"base64 string is not of the correct length\");\n }\n try {\n return b64DecodeUnicode(output);\n }\n catch (err) {\n return atob(output);\n }\n}\nexport function jwtDecode(token, options) {\n if (typeof token !== \"string\") {\n throw new InvalidTokenError(\"Invalid token specified: must be a string\");\n }\n options || (options = {});\n const pos = options.header === true ? 0 : 1;\n const part = token.split(\".\")[pos];\n if (typeof part !== \"string\") {\n throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);\n }\n let decoded;\n try {\n decoded = base64UrlDecode(part);\n }\n catch (e) {\n throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);\n }\n try {\n return JSON.parse(decoded);\n }\n catch (e) {\n throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);\n }\n}\n", "import type { RequestContext } from '@devvit/protos/json/devvit/platform/v1/request_context.js';\nimport { jwtDecode } from 'jwt-decode';\n\n// to-do: make a Protobuf for ContextClaims.\nexport type ContextClaims = { devvit: RequestContext };\n\nexport function decodeToken(token: string | undefined): RequestContext | undefined {\n if (!token) return;\n\n try {\n return jwtDecode<ContextClaims>(token)?.devvit;\n } catch (err) {\n throw Error('token decode failure', { cause: err });\n }\n}\n", "import type { DevvitPostData } from '@devvit/protos';\nimport type { RequestContext } from '@devvit/protos/json/devvit/platform/v1/request_context.js';\nimport {\n type BridgeContext,\n Client as ClientName,\n type WebViewClientData,\n type WebViewContext,\n} from '@devvit/protos/json/devvit/ui/effects/web_view/v1alpha/context.js';\nimport type { Context } from '@devvit/shared-types/client/client-context.js';\nimport type {\n DevvitGlobal,\n WebViewScriptsVersion,\n} from '@devvit/shared-types/client/devvit-global.js';\nimport type { Client } from '@devvit/shared-types/shared/client.js';\nimport { T2, T3, T5 } from '@devvit/shared-types/tid.js';\nimport { type WebbitToken } from '@devvit/shared-types/webbit.js';\n\nimport { queryClientVersion } from './client.js';\nimport { decodeToken } from './token.js';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var devvit: DevvitGlobal;\n /** Defined by build.js. */\n // eslint-disable-next-line no-var\n var webViewScriptsVersion: Readonly<WebViewScriptsVersion>;\n}\n\n/** @internal */\nexport const initDevvitGlobal = (\n document: { readonly currentScript: { readonly src: string } | SVGScriptElement | null },\n location: { readonly hash: string },\n window: { readonly name: string }\n): void => {\n const bridge = getBridgeContext(window.name, location.hash);\n\n const client = getClient(bridge);\n\n const reqCtx = decodeToken(bridge.signedRequestContext);\n\n let context;\n if (reqCtx) context = contextFromRequestContext(reqCtx, client, bridge.postData);\n else if (bridge.webViewContext)\n context = contextFromWebViewContext(bridge.webViewContext, client, bridge.postData);\n if (!context) throw Error('no context');\n\n // to-do: expose `devvitDebug`, `shredditVersion`.\n\n const clientData: WebViewClientData | undefined = bridge.webViewClientData;\n globalThis.devvit = {\n context,\n dependencies: {\n client: queryClientVersion(document),\n webViewScripts: globalThis.webViewScriptsVersion,\n },\n entrypoints: clientData?.appConfig?.entrypoints ?? {},\n share: bridge?.shareParam ? { userData: bridge?.shareParam.userData } : undefined,\n appPermissionState: bridge?.appPermissionState,\n token: (bridge.signedRequestContext || bridge.webbitToken) as WebbitToken,\n webViewMode: bridge?.viewMode,\n startTime: bridge?.startTime ?? undefined,\n };\n};\n\n/** @internal */\nexport function contextFromRequestContext(\n reqCtx: Readonly<RequestContext>,\n client: Client | undefined,\n postData: Readonly<DevvitPostData> | undefined\n): Context {\n if (!reqCtx.app) throw Error('no RequestContext.app');\n if (!reqCtx.post) throw Error('no RequestContext.post');\n if (!reqCtx.subreddit) throw Error('no RequestContext.subreddit');\n return {\n appName: reqCtx.app.name,\n appVersion: reqCtx.app.version,\n client,\n postAuthorId: T2(reqCtx.post.author),\n postData: postData?.developerData,\n postId: T3(reqCtx.post.id),\n snoovatar: reqCtx.user?.snoovatar,\n subredditId: T5(reqCtx.subreddit.id),\n subredditName: reqCtx.subreddit.name,\n userId: reqCtx.user?.id ? T2(reqCtx.user.id) : undefined,\n username: reqCtx.user?.name,\n };\n}\n\n/** @internal */\nexport function contextFromWebViewContext(\n webViewCtx: Readonly<WebViewContext>,\n client: Client | undefined,\n postData: Readonly<DevvitPostData> | undefined\n): Context {\n return {\n appName: webViewCtx.appName,\n appVersion: webViewCtx.appVersion,\n client,\n postData: postData?.developerData,\n postAuthorId: undefined,\n postId: T3(webViewCtx.postId),\n snoovatar: undefined,\n subredditId: T5(webViewCtx.subredditId),\n subredditName: webViewCtx.subredditName,\n userId: webViewCtx.userId ? T2(webViewCtx.userId) : undefined,\n username: undefined,\n };\n}\n\n/**\n * Extracts the BridgeContext from the hash.\n * @internal\n */\nexport function getBridgeContext(name: string | undefined, hash: string): BridgeContext {\n if (name) return JSON.parse(name);\n const json = hash?.slice(1); // Strip the leading '#' from the hash\n if (!json) throw Error('no bridge context');\n return JSON.parse(decodeURIComponent(json));\n}\n\n/** @internal */\nexport function getClient(bridge: Readonly<BridgeContext>): Client | undefined {\n if (\n (bridge.client !== ClientName.ANDROID && bridge.client !== ClientName.IOS) ||\n !bridge.nativeVersion\n )\n return;\n return {\n name: bridge.client === ClientName.ANDROID ? 'ANDROID' : ('IOS' as const),\n version: bridge.nativeVersion,\n };\n}\n", "import type { DevvitGlobal } from '@devvit/shared-types/client/devvit-global.js';\n\n/** Injects an auth token into /api/ requests. */\nexport async function fetch(\n devvit: Readonly<DevvitGlobal>,\n globalFetch: typeof globalThis.fetch,\n location: Readonly<Location>,\n input: RequestInfo | URL,\n init?: RequestInit\n): Promise<Response> {\n const req = new Request(input, init);\n if (isSameSite(location, new URL(req.url)))\n req.headers.set('Authorization', `Bearer ${devvit.token}`);\n // to-do: pass devvit-debug from BridgeContext.\n return await globalFetch(req);\n}\n\nexport function initFetch(): void {\n globalThis.fetch = fetch.bind(undefined, globalThis.devvit, globalThis.fetch, location);\n}\n\n/** @internal */\nexport function isSameSite(location: Readonly<Location>, url: URL): boolean {\n return url.origin === location.origin;\n}\n", "import { initAnalytics } from './analytics.js';\nimport { initDevvitGlobal } from './devvit-global.js';\nimport { initFetch } from './fetch.js';\n\ninitDevvitGlobal(document, location, window);\ninitAnalytics();\ninitFetch();\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["define_globalThis_webViewScriptsVersion_default", "EffectType", "WebViewInternalMessageScope", "webViewInternalMessageType", "EFFECTS_WITH_RESPONSE", "EffectType", "emitEffect", "effect", "resolve", "message", "WebViewInternalMessageScope", "id", "handleEffect", "event", "initAnalytics", "timeStart", "duration", "timeEnd", "loaded", "emitEffect", "EffectType", "event", "click", "isStrictClick", "eventTarget", "elementOrParentIsInteractive", "element", "STRICT_CLICK_TAGNAMES", "currentElement", "Client", "Height", "assert", "condition", "msg", "T_PREFIX", "isT2", "id", "T_PREFIX", "isT3", "isT5", "id", "T_PREFIX", "assertT2", "id", "assert", "isT2", "T_PREFIX", "assertT3", "isT3", "assertT5", "id", "assert", "isT5", "T_PREFIX", "T2", "id", "assertT2", "T3", "assertT3", "T5", "id", "assertT5", "clientVersionQueryParam", "queryClientVersion", "document", "clientVersionQueryParam", "InvalidTokenError", "b64DecodeUnicode", "str", "m", "p", "code", "base64UrlDecode", "output", "jwtDecode", "token", "options", "pos", "part", "decoded", "e", "decodeToken", "token", "jwtDecode", "err", "initDevvitGlobal", "document", "location", "window", "bridge", "getBridgeContext", "client", "getClient", "reqCtx", "decodeToken", "context", "contextFromRequestContext", "contextFromWebViewContext", "clientData", "queryClientVersion", "define_globalThis_webViewScriptsVersion_default", "postData", "T2", "T3", "T5", "webViewCtx", "name", "hash", "json", "Client", "fetch", "devvit", "globalFetch", "location", "input", "init", "req", "isSameSite", "initFetch", "url", "initDevvitGlobal", "initAnalytics", "initFetch"]
|
|
7
7
|
}
|