{"version":3,"sources":["../src/profiles/base.ts"],"names":["parseRawBytes","value","hasCapability","capabilities","capability","BaseProfile","device","cleanup","characteristic","options","callback","unsubscribe","candidate","event","decodeNativeOverflow","detail","meta","defineProfile","config","serviceUUID","resolveUUID","characteristics","name","definition","canonical","GeneratedProfile","raw","cb","serialized","mode"],"mappings":"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","file":"chunk-FANWIUKA.mjs","sourcesContent":["import type {\n  NotificationCallback,\n  NativeOverflowEvent,\n  BeacioDevice,\n  WriteFragmentedOptions,\n  WriteFragmentedResult,\n  WriteLimits,\n  WriteOptions,\n} from '../index';\nimport { resolveUUID } from '../uuid';\n\n// Sound top type for \"any characteristic definition\": TRead is covariant\n// (parse return → unknown), TWrite is contravariant (serialize param → never),\n// so every CharacteristicDefinition<A, B> is assignable here without `any`.\ntype AnyCharacteristicDefinition = CharacteristicDefinition<unknown, never>;\n\nexport function parseRawBytes(value: BufferSource): DataView {\n  if (value instanceof DataView) {\n    return new DataView(value.buffer, value.byteOffset, value.byteLength);\n  }\n\n  if (value instanceof ArrayBuffer) {\n    return new DataView(value);\n  }\n\n  return new DataView(value.buffer, value.byteOffset, value.byteLength);\n}\n\ntype UUIDLike = string;\ntype Capability = 'read' | 'write' | 'writeWithoutResponse' | 'notify';\ntype CapabilitySet = readonly Capability[];\n\ntype CharacteristicReadConfig<T> = {\n  capabilities: readonly ['read'] | readonly ['read', ...Capability[]];\n  parse: (dv: DataView) => T;\n};\n\ntype CharacteristicWriteConfig<W> = {\n  capabilities: readonly ['write'] | readonly ['writeWithoutResponse'] | readonly ['write', ...Capability[]] | readonly ['writeWithoutResponse', ...Capability[]];\n  serialize: (value: W) => BufferSource;\n};\n\ntype CharacteristicReadWriteConfig<T, W> = {\n  capabilities:\n    | readonly ['read', 'write']\n    | readonly ['read', 'writeWithoutResponse']\n    | readonly ['write', 'read']\n    | readonly ['writeWithoutResponse', 'read']\n    | readonly ['read', 'write', ...Capability[]]\n    | readonly ['read', 'writeWithoutResponse', ...Capability[]]\n    | readonly ['write', 'read', ...Capability[]]\n    | readonly ['writeWithoutResponse', 'read', ...Capability[]];\n  parse: (dv: DataView) => T;\n  serialize: (value: W) => BufferSource;\n};\n\nexport type CharacteristicDefinition<TRead = never, TWrite = never> = {\n  uuid: UUIDLike;\n} & (\n  | CharacteristicReadConfig<TRead>\n  | CharacteristicWriteConfig<TWrite>\n  | CharacteristicReadWriteConfig<TRead, TWrite>\n);\n\nexport interface ProfileConfig<C extends Record<string, AnyCharacteristicDefinition>> {\n  name: string;\n  service: UUIDLike;\n  characteristics: C;\n}\n\ntype CapabilityOf<T extends AnyCharacteristicDefinition> = T['capabilities'][number];\ntype ReadableKeys<C extends Record<string, AnyCharacteristicDefinition>> = {\n  [K in keyof C]: 'read' extends CapabilityOf<C[K]> ? K : never;\n}[keyof C] & string;\ntype WritableKeys<C extends Record<string, AnyCharacteristicDefinition>> = {\n  [K in keyof C]: 'write' extends CapabilityOf<C[K]>\n    ? K\n    : 'writeWithoutResponse' extends CapabilityOf<C[K]>\n      ? K\n      : never;\n}[keyof C] & string;\ntype NotifiableKeys<C extends Record<string, AnyCharacteristicDefinition>> = {\n  [K in keyof C]: 'notify' extends CapabilityOf<C[K]> ? K : never;\n}[keyof C] & string;\n\ntype ReadValue<T> = T extends { parse: (dv: DataView) => infer TResult } ? TResult : never;\ntype WriteValue<T> = T extends { serialize: (value: infer TValue) => BufferSource } ? TValue : never;\ntype CanonicalCharacteristic<C extends AnyCharacteristicDefinition> = Omit<C, 'uuid'> & { uuid: string };\ntype ReadParser<T> = { parse: (dv: DataView) => T };\ntype WriteSerializer<T> = { serialize: (value: T) => BufferSource };\n\nfunction hasCapability(capabilities: CapabilitySet, capability: Capability): boolean {\n  return capabilities.includes(capability);\n}\n\nexport abstract class BaseProfile {\n  protected device: BeacioDevice;\n  protected abstract readonly service: string;\n  private cleanups: (() => void)[] = [];\n\n  constructor(device: BeacioDevice) {\n    this.device = device;\n  }\n\n  async connect(): Promise<void> {\n    await this.device.connect();\n  }\n\n  stop(): void {\n    for (const cleanup of this.cleanups.splice(0)) {\n      cleanup();\n    }\n  }\n\n  dispose(): void {\n    this.stop();\n  }\n\n  protected async read(characteristic: string): Promise<DataView> {\n    return this.device.read(this.service, characteristic);\n  }\n\n  protected async write(characteristic: string, value: BufferSource): Promise<void> {\n    return this.device.write(this.service, characteristic, value);\n  }\n\n  protected async writeWithoutResponse(characteristic: string, value: BufferSource): Promise<void> {\n    return this.device.writeWithoutResponse(this.service, characteristic, value);\n  }\n\n  /**\n   * Send a payload of any size to `characteristic`, fragmenting it into\n   * MTU-sized chunks. This is a thin passthrough to {@link BeacioDevice.writeFragmented},\n   * which owns the (already-clamped) chunk-size derivation via the branded\n   * `ChunkSize` smart-constructors in the core write-chunker — so the stride is\n   * guaranteed `>= 1` and a zero-stride infinite loop is unrepresentable.\n   *\n   * Profiles MUST use this instead of hand-rolling a `for (offset += step)` /\n   * `subarray()` / `writeWithoutResponse()` chunk loop (enforced by the\n   * `no-restricted-syntax` guard scoped to `packages/profiles/src`). Defaults to\n   * `mode: 'without-response'` — the serial-pipe convention (Nordic UART, HM-10).\n   *\n   * @param characteristic - Target characteristic UUID or alias on this profile's service.\n   * @param value - Bytes to send. Accepts any {@link BufferSource}.\n   * @param options - Fragmentation/retry overrides; `mode` defaults to `'without-response'`.\n   * @returns The {@link WriteFragmentedResult} (bytes written, chunk size/count, retries).\n   */\n  protected async sendChunked(\n    characteristic: string,\n    value: BufferSource,\n    options: WriteFragmentedOptions = {},\n  ): Promise<WriteFragmentedResult> {\n    return this.device.writeFragmented(this.service, characteristic, value, {\n      mode: 'without-response',\n      ...options,\n    });\n  }\n\n  protected async writeValue(characteristic: string, value: BufferSource, options?: WriteOptions): Promise<void> {\n    if (options?.mode === 'without-response') {\n      return this.device.writeWithoutResponse(this.service, characteristic, value, options);\n    }\n    return this.device.write(this.service, characteristic, value, options);\n  }\n\n  protected async getWriteLimits(): Promise<WriteLimits> {\n    return this.device.getWriteLimits();\n  }\n\n  protected async getMtu(): Promise<number | null> {\n    return this.device.getMtu();\n  }\n\n  protected subscribe(characteristic: string, callback: NotificationCallback): () => void {\n    const unsubscribe = this.device.subscribe(this.service, characteristic, callback);\n    this.cleanups.push(unsubscribe);\n    return () => {\n      unsubscribe();\n      this.cleanups = this.cleanups.filter((candidate) => candidate !== unsubscribe);\n    };\n  }\n\n  /**\n   * Observe NATIVE notification-queue overflows for `characteristic` on this\n   * profile's service. The bounded Swift `EventQueue` evicts notifications under\n   * sustained high-frequency load and the polyfill surfaces each eviction as a\n   * `beacio:overflow` `CustomEvent` on the characteristic; this decodes that\n   * event's `detail` into a typed {@link NativeOverflowEvent} and forwards it to\n   * `callback`.\n   *\n   * Lifecycle parity with {@link subscribe}: the returned unsubscribe is also\n   * registered into the profile's cleanup set, so {@link stop}/{@link dispose}\n   * detach the listener too. A staleness `callback` should typically re-read the\n   * affected characteristic to resynchronise any UI tracking the last notified\n   * value rather than trusting that (now-stale) value.\n   *\n   * @param characteristic - Characteristic UUID or alias on this profile's service.\n   * @param callback - Called with the decoded eviction metadata on each overflow.\n   * @returns Unsubscribe function.\n   */\n  protected onOverflow(characteristic: string, callback: (event: NativeOverflowEvent) => void): () => void {\n    const unsubscribe = this.device.onCharacteristicOverflow(this.service, characteristic, (event) => {\n      callback(decodeNativeOverflow(event));\n    });\n    this.cleanups.push(unsubscribe);\n    return () => {\n      unsubscribe();\n      this.cleanups = this.cleanups.filter((candidate) => candidate !== unsubscribe);\n    };\n  }\n}\n\n/**\n * Decode a `beacio:overflow` {@link Event} (a `CustomEvent` whose `detail` carries\n * the native bounded-queue eviction metadata) into a typed\n * {@link NativeOverflowEvent}. Each field is `undefined` when the native bridge\n * omitted it (forward-compat guard); a conforming bridge supplies all four. Total\n * and side-effect-free — never throws on a malformed or detail-less event.\n */\nfunction decodeNativeOverflow(event: Event): NativeOverflowEvent {\n  const detail = (event as CustomEvent).detail as unknown;\n  const meta = (detail && typeof detail === 'object') ? (detail as Record<string, unknown>) : {};\n  return {\n    evictedCount: typeof meta.evictedCount === 'number' ? meta.evictedCount : undefined,\n    queueCapacity: typeof meta.queueCapacity === 'number' ? meta.queueCapacity : undefined,\n    seq: typeof meta.seq === 'number' ? meta.seq : undefined,\n    timestamp: typeof meta.timestamp === 'number' ? meta.timestamp : undefined,\n  };\n}\n\ntype DefinedProfileInstance<C extends Record<string, AnyCharacteristicDefinition>> = BaseProfile & {\n  readChar<K extends ReadableKeys<C>>(name: K): Promise<ReadValue<C[K]>>;\n  subscribeChar<K extends Extract<ReadableKeys<C>, NotifiableKeys<C>>>(name: K, cb: (value: ReadValue<C[K]>) => void): () => void;\n  writeChar<K extends WritableKeys<C>>(name: K, value: WriteValue<C[K]>, options?: WriteOptions): Promise<void>;\n  getCharacteristicCapabilities<K extends keyof C & string>(name: K): ReadonlyArray<Capability>;\n  getCharacteristicUUID<K extends keyof C & string>(name: K): string;\n  getServiceUUID(): string;\n  getWriteLimits(): Promise<WriteLimits>;\n  getMtu(): Promise<number | null>;\n};\n\nexport interface DefinedProfile<C extends Record<string, AnyCharacteristicDefinition>> {\n  new (device: BeacioDevice): DefinedProfileInstance<C>;\n  readonly profileName: string;\n  readonly serviceUUID: string;\n  readonly characteristics: {\n    [K in keyof C]: Omit<C[K], 'uuid'> & { uuid: string };\n  };\n}\n\nexport function defineProfile<C extends Record<string, AnyCharacteristicDefinition>>(\n  config: ProfileConfig<C>,\n): DefinedProfile<C> {\n  const serviceUUID = resolveUUID(config.service);\n  const characteristics = Object.fromEntries(\n    Object.entries(config.characteristics).map(([name, definition]) => {\n      const canonical = {\n        ...definition,\n        uuid: resolveUUID(definition.uuid),\n      };\n\n      if (hasCapability(canonical.capabilities, 'read') && typeof (canonical as { parse?: unknown }).parse !== 'function') {\n        throw new Error(`Characteristic ${name} declares read capability but is missing parse()`);\n      }\n\n      if (\n        (hasCapability(canonical.capabilities, 'write') || hasCapability(canonical.capabilities, 'writeWithoutResponse'))\n        && typeof (canonical as { serialize?: unknown }).serialize !== 'function'\n      ) {\n        throw new Error(`Characteristic ${name} declares write capability but is missing serialize()`);\n      }\n\n      return [name, canonical];\n    }),\n  ) as unknown as {\n    [K in keyof C]: Omit<C[K], 'uuid'> & { uuid: string };\n  };\n\n  class GeneratedProfile extends BaseProfile {\n    static readonly profileName = config.name;\n    static readonly serviceUUID = serviceUUID;\n    static readonly characteristics = characteristics;\n\n    protected readonly service = serviceUUID;\n\n    getCharacteristicCapabilities<K extends keyof C & string>(name: K): ReadonlyArray<Capability> {\n      return characteristics[name].capabilities;\n    }\n\n    getCharacteristicUUID<K extends keyof C & string>(name: K): string {\n      return characteristics[name].uuid;\n    }\n\n    getServiceUUID(): string {\n      return serviceUUID;\n    }\n\n    async readChar<K extends ReadableKeys<C>>(name: K): Promise<ReadValue<C[K]>> {\n      const characteristic = characteristics[name] as unknown as CanonicalCharacteristic<C[K]> & ReadParser<ReadValue<C[K]>>;\n      const raw = await this.read(characteristic.uuid);\n      return characteristic.parse(raw);\n    }\n\n    subscribeChar<K extends Extract<ReadableKeys<C>, NotifiableKeys<C>>>(name: K, cb: (value: ReadValue<C[K]>) => void): () => void {\n      const characteristic = characteristics[name] as unknown as CanonicalCharacteristic<C[K]> & ReadParser<ReadValue<C[K]>>;\n      return this.subscribe(characteristic.uuid, (value) => {\n        cb(characteristic.parse(value));\n      });\n    }\n\n    async writeChar<K extends WritableKeys<C>>(name: K, value: WriteValue<C[K]>, options?: WriteOptions): Promise<void> {\n      const characteristic = characteristics[name] as unknown as CanonicalCharacteristic<C[K]> & WriteSerializer<WriteValue<C[K]>>;\n      const serialized = characteristic.serialize(value);\n      const mode = options?.mode ?? (hasCapability(characteristic.capabilities, 'write') ? 'with-response' : 'without-response');\n      await this.writeValue(characteristic.uuid, serialized, { ...options, mode });\n    }\n\n    async getWriteLimits(): Promise<WriteLimits> {\n      return super.getWriteLimits();\n    }\n\n    async getMtu(): Promise<number | null> {\n      return super.getMtu();\n  }\n}\n\n  return GeneratedProfile as unknown as DefinedProfile<C>;\n}\n"]}