{"version":3,"file":"loader-b24frame.cjs","sources":["../../src/loader-b24frame.ts"],"sourcesContent":["import type { TypeHttpOptions } from './types/http'\nimport type { B24FrameQueryParams } from './types/auth'\nimport type { RestrictionParams } from './types/limiters'\nimport type { ApiVersion } from './types/b24'\nimport type { KeepAuthFreshParams } from './frame/auth-keep-alive'\nimport { B24Frame } from './frame'\nimport { SdkError } from './core/sdk-error'\n\n// The single in-flight (or resolved) initialization. Every caller shares it, so\n// concurrent callers await ONE handshake and a resolved value is returned\n// instantly. On failure it is cleared so a later call can retry from scratch.\n// This replaces the former 50ms busy-poll + four coordination booleans\n// (isInit / connectError / isMakeFirstCall / isStartWatch) with a single cached\n// promise — same public contract, no polling, no stranded awaiters. (#142)\nlet initPromise: null | Promise<B24Frame> = null\n\nfunction parseFrameQueryParams(): B24FrameQueryParams {\n  const queryParams: B24FrameQueryParams = {\n    DOMAIN: null,\n    PROTOCOL: false,\n    APP_SID: null,\n    LANG: null\n  }\n\n  if (window.name) {\n    const [domain, protocol, appSid] = window.name.split('|')\n    queryParams.DOMAIN = domain\n    queryParams.PROTOCOL = Number.parseInt(protocol ?? '0') === 1\n    queryParams.APP_SID = appSid\n    queryParams.LANG = null\n  }\n\n  return queryParams\n}\n\nasync function makeFrame(\n  options?: {\n    version?: ApiVersion\n    restrictionParams?: Partial<RestrictionParams>\n    httpOptions?: TypeHttpOptions\n    keepAuthFresh?: boolean | KeepAuthFreshParams\n  }\n): Promise<B24Frame> {\n  const queryParams = parseFrameQueryParams()\n\n  if (!queryParams.DOMAIN || !queryParams.APP_SID) {\n    // Opened outside the Bitrix24 iframe (direct URL, dev server, install\n    // screen): window.name carries no DOMAIN/APP_SID. Fail fast — do NOT build a\n    // B24Frame (which would subscribe a window `message` listener and post to an\n    // invalid origin). (#142)\n    throw new SdkError({\n      code: 'JSSDK_CLIENT_SIDE_WARNING',\n      description: 'Well done! Now paste this URL into the Bitrix24 app settings',\n      status: 500\n    })\n  }\n\n  const b24Frame = new B24Frame(queryParams, options)\n\n  try {\n    await b24Frame.init()\n  } catch (error) {\n    // The frame's constructor already subscribed a window `message` listener;\n    // tear it down so a retry can't leave two live handlers cross-talking.\n    // Guarded so a throwing destroy() can't mask the real init error. (#142)\n    try {\n      b24Frame.destroy()\n    } catch {\n      // ignore — init already failed; we only care about detaching listeners\n    }\n    throw error\n  }\n\n  return b24Frame\n}\n\nexport async function initializeB24Frame(\n  options?: {\n    version?: ApiVersion\n    restrictionParams?: Partial<RestrictionParams>\n    /**\n     * Axios settings for both transports, merged over the SDK's own defaults —\n     * see {@link TypeHttpOptions}. Forwarded to the `B24Frame` constructor\n     * unchanged: this factory is the documented way to build a frame, so an\n     * option it cannot carry is an option a frame app does not have. The key it\n     * exists for is `adapter`, and a frame app is exactly the audience for it —\n     * a browser is where the SDK asks axios for `fetch`, and\n     * `{ adapter: 'xhr' }` here is the way back.\n     */\n    httpOptions?: TypeHttpOptions\n    /**\n     * Keep the frame access token alive while the tab is open (#532).\n     *\n     * Off by default. The SDK's automatic refresh only runs when a request goes\n     * through `$b24`, so an app that reads the token with `auth.getAuthData()`\n     * and sends it to its own backend never refreshes: after `AUTH_EXPIRES`\n     * seconds of an idle tab the token is gone and the app's own calls start\n     * answering 401.\n     *\n     * ```ts\n     * const $b24 = await initializeB24Frame({ keepAuthFresh: true })\n     * ```\n     *\n     * With it on, a timer refreshes the token shortly before it expires and\n     * re-checks whenever the tab becomes visible again (a background tab's\n     * timers are throttled, a frozen tab's do not run at all). Refreshing the\n     * frame token is a `postMessage` to the parent window, so this costs no\n     * REST calls, and a failed refresh is never thrown at the app.\n     *\n     * Pass an object to tune the schedule — see {@link KeepAuthFreshParams}.\n     * It stays opt-in because it changes when an app talks to the parent\n     * window, and Bitrix warns that refreshing too often risks an application\n     * being auto-blocked.\n     */\n    keepAuthFresh?: boolean | KeepAuthFreshParams\n  }\n): Promise<B24Frame> {\n  // Concurrent callers (and calls after a success) share the one promise — a\n  // later caller's `options` are ignored; the first caller's frame is returned.\n  if (initPromise !== null) {\n    return initPromise\n  }\n\n  const pending = makeFrame(options)\n  initPromise = pending\n\n  // Drop the cached promise on failure so a subsequent call retries from\n  // scratch; keep it on success so the resolved frame is reused, until that\n  // frame is destroyed. The caller's own rejection still propagates via the returned `pending`.\n  pending.then((frame) => {\n    // `destroy()` removes the frame's `message` listener, so a destroyed frame\n    // still posts commands but never hears an answer: every call on it hangs.\n    // Forget it on destroy, so the next call builds a fresh frame (#486).\n    const destroy = frame.destroy.bind(frame)\n    frame.destroy = () => {\n      if (initPromise === pending) {\n        initPromise = null\n      }\n      destroy()\n    }\n  }, () => {\n    if (initPromise === pending) {\n      initPromise = null\n    }\n  })\n\n  return pending\n}\n"],"names":["SdkError","B24Frame"],"mappings":";;;;;;;;;;;;;;;AAcA,IAAI,WAAA,GAAwC,IAAA;AAE5C,SAAS,qBAAA,GAA6C;AACpD,EAAA,MAAM,WAAA,GAAmC;AAAA,IACvC,MAAA,EAAQ,IAAA;AAAA,IACR,QAAA,EAAU,KAAA;AAAA,IACV,OAAA,EAAS,IAAA;AAAA,IACT,IAAA,EAAM;AAAA,GACR;AAEA,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,MAAM,CAAC,QAAQ,QAAA,EAAU,MAAM,IAAI,MAAA,CAAO,IAAA,CAAK,MAAM,GAAG,CAAA;AACxD,IAAA,WAAA,CAAY,MAAA,GAAS,MAAA;AACrB,IAAA,WAAA,CAAY,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,QAAA,IAAY,GAAG,CAAA,KAAM,CAAA;AAC5D,IAAA,WAAA,CAAY,OAAA,GAAU,MAAA;AACtB,IAAA,WAAA,CAAY,IAAA,GAAO,IAAA;AAAA,EACrB;AAEA,EAAA,OAAO,WAAA;AACT;AAjBS,MAAA,CAAA,qBAAA,EAAA,uBAAA,CAAA;AAmBT,eAAe,UACb,OAAA,EAMmB;AACnB,EAAA,MAAM,cAAc,qBAAA,EAAsB;AAE1C,EAAA,IAAI,CAAC,WAAA,CAAY,MAAA,IAAU,CAAC,YAAY,OAAA,EAAS;AAK/C,IAAA,MAAM,IAAIA,iBAAA,CAAS;AAAA,MACjB,IAAA,EAAM,2BAAA;AAAA,MACN,WAAA,EAAa,8DAAA;AAAA,MACb,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,QAAA,GAAW,IAAIC,YAAA,CAAS,WAAA,EAAa,OAAO,CAAA;AAElD,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,IAAA,EAAK;AAAA,EACtB,SAAS,KAAA,EAAO;AAId,IAAA,IAAI;AACF,MAAA,QAAA,CAAS,OAAA,EAAQ;AAAA,IACnB,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AAEA,EAAA,OAAO,QAAA;AACT;AAvCe,MAAA,CAAA,SAAA,EAAA,WAAA,CAAA;AAyCf,eAAsB,mBACpB,OAAA,EAuCmB;AAGnB,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,UAAU,OAAO,CAAA;AACjC,EAAA,WAAA,GAAc,OAAA;AAKd,EAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,KAAA,KAAU;AAItB,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA;AACxC,IAAA,KAAA,CAAM,UAAU,MAAM;AACpB,MAAA,IAAI,gBAAgB,OAAA,EAAS;AAC3B,QAAA,WAAA,GAAc,IAAA;AAAA,MAChB;AACA,MAAA,OAAA,EAAQ;AAAA,IACV,CAAA;AAAA,EACF,GAAG,MAAM;AACP,IAAA,IAAI,gBAAgB,OAAA,EAAS;AAC3B,MAAA,WAAA,GAAc,IAAA;AAAA,IAChB;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,OAAA;AACT;AAvEsB,MAAA,CAAA,kBAAA,EAAA,oBAAA,CAAA;;;;"}