{"version":3,"file":"index.mjs","names":[],"sources":["../../src/custom/custom.ts"],"sourcesContent":["/* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD */\n/* SPDX-License-Identifier: Apache-2.0 */\n\n/**\n * Custom service module for JS apps — wraps `brookesia_service_custom` RPC.\n *\n * Functions and events are registered at runtime on the device; callers invoke\n * them by name via `call()`.\n *\n * @example\n * import custom from '@brookesia/service/custom';\n * if (custom.available()) {\n *   const sum = custom.call<number>('add', { a: 1, b: 2 });\n *   brookesia.print(sum);\n *   custom.close();\n * }\n */\n\nimport {\n  callCustomFunction,\n  closeCustom,\n  isCustomAvailable,\n  openCustom,\n  type CustomClientOptions,\n  type CustomHandle,\n} from './custom-client.ts';\n\nexport type CustomModuleOptions = CustomClientOptions;\n\ntype State = {\n  handle: CustomHandle | null;\n  options: CustomModuleOptions;\n};\n\nconst state: State = { handle: null, options: {} };\n\nfunction handle(): CustomHandle {\n  if (state.handle !== null) {\n    return state.handle;\n  }\n  if (!isCustomAvailable(state.options)) {\n    throw new Error('Custom service is not available');\n  }\n  state.handle = openCustom(state.options);\n  return state.handle;\n}\n\n/**\n * Inject a mock RPC host and reset the cached service handle (vitest / Node only).\n *\n * @param options - Client options, typically `{ host }` from `@brookesia/service/hosts/custom`\n */\nexport function configure(options: CustomModuleOptions): void {\n  if (state.handle !== null) {\n    closeCustom(state.handle, state.options);\n  }\n  state.handle = null;\n  state.options = options;\n}\n\nconst custom = {\n  /** @returns `true` when CustomService is registered (firmware must link it) */\n  available(): boolean {\n    return isCustomAvailable(state.options);\n  },\n\n  /** Release the Custom service binding. */\n  close(): void {\n    if (state.handle === null) {\n      return;\n    }\n    closeCustom(state.handle, state.options);\n    state.handle = null;\n  },\n\n  /**\n   * Invoke a function registered at runtime on the device.\n   *\n   * Function names and parameter schemas are defined by firmware via\n   * `CustomService::register_function` — there is no fixed API list.\n   *\n   * @param functionName - Registered RPC function name\n   * @param params - JSON-serializable argument object\n   * @returns Parsed return value (type parameter is caller-side only)\n   *\n   * @example\n   * const sum = custom.call<number>('add', { a: 1, b: 2 });\n   */\n  call<T = unknown>(functionName: string, params: Record<string, unknown> = {}): T {\n    return callCustomFunction<T>(handle(), functionName, params, state.options);\n  },\n};\n\nexport default custom;\n"],"mappings":";;;;;;;;;;;;;;;;AAkCA,MAAM,QAAe;CAAE,QAAQ;CAAM,SAAS,CAAC;AAAE;AAEjD,SAAS,SAAuB;CAC9B,IAAI,MAAM,WAAW,MACnB,OAAO,MAAM;CAEf,IAAI,CAAC,kBAAkB,MAAM,OAAO,GAClC,MAAM,IAAI,MAAM,iCAAiC;CAEnD,MAAM,SAAS,WAAW,MAAM,OAAO;CACvC,OAAO,MAAM;AACf;;;;;;AAOA,SAAgB,UAAU,SAAoC;CAC5D,IAAI,MAAM,WAAW,MACnB,YAAY,MAAM,QAAQ,MAAM,OAAO;CAEzC,MAAM,SAAS;CACf,MAAM,UAAU;AAClB;AAEA,MAAM,SAAS;;CAEb,YAAqB;EACnB,OAAO,kBAAkB,MAAM,OAAO;CACxC;;CAGA,QAAc;EACZ,IAAI,MAAM,WAAW,MACnB;EAEF,YAAY,MAAM,QAAQ,MAAM,OAAO;EACvC,MAAM,SAAS;CACjB;;;;;;;;;;;;;;CAeA,KAAkB,cAAsB,SAAkC,CAAC,GAAM;EAC/E,OAAO,mBAAsB,OAAO,GAAG,cAAc,QAAQ,MAAM,OAAO;CAC5E;AACF"}