{"version":3,"file":"index.mjs","names":[],"sources":["../../src/storage/storage.ts"],"sourcesContent":["/* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD */\n/* SPDX-License-Identifier: Apache-2.0 */\n\n/**\n * Storage service module for JS apps — wraps `brookesia_service_storage` RPC.\n *\n * Provides KV storage (namespace-based key-value) and file system queries.\n *\n * @example\n * import storage from '@brookesia/service/storage';\n * if (storage.available()) {\n *   storage.set('config', 'theme', 'dark');\n *   brookesia.print(storage.get('config', 'theme'));\n *   storage.close();\n * }\n */\n\nimport {\n  closeStorage,\n  fsCopyTree,\n  fsList,\n  fsMkdir,\n  fsReadText,\n  fsRemove,\n  fsRename,\n  fsStat,\n  fsWriteText,\n  getFileSystemCapacity,\n  getFileSystems,\n  isStorageAvailable,\n  kvErase,\n  kvGet,\n  kvList,\n  kvSet,\n  makeKvKey,\n  makeKvNamespace,\n  openStorage,\n  type FileEntry,\n  type FileInfo,\n  type FileSystemCapacity,\n  type FileSystemInfo,\n  type KvNameResult,\n  type StorageClientOptions,\n  type StorageEntryInfo,\n  type StorageHandle,\n  type StorageKeyValueMap,\n  type StorageValue,\n} from './storage-client.js';\n\nexport type {\n  FileEntry,\n  FileInfo,\n  FileSystemCapacity,\n  FileSystemInfo,\n  KvNameResult,\n  StorageEntryInfo,\n  StorageKeyValueMap,\n  StorageValue,\n};\n\nexport type StorageModuleOptions = StorageClientOptions;\n\ntype State = {\n  handle: StorageHandle | null;\n  options: StorageModuleOptions;\n};\n\nconst state: State = { handle: null, options: {} };\n\nfunction storageNamespace(name?: string): string {\n  const n = name?.trim();\n  return n && n.length > 0 ? n : 'storage';\n}\n\nfunction handle(): StorageHandle {\n  if (state.handle !== null) {\n    return state.handle;\n  }\n  if (!isStorageAvailable(state.options)) {\n    throw new Error('Storage service is not available');\n  }\n  state.handle = openStorage(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/storage`\n */\nexport function configure(options: StorageModuleOptions): void {\n  if (state.handle !== null) {\n    closeStorage(state.handle, state.options);\n  }\n  state.handle = null;\n  state.options = options;\n}\n\nconst storage = {\n  /**\n   * Whether the device registered the Storage service.\n   * @returns `true` when `brookesia.service_available('Storage')` is true\n   */\n  available(): boolean {\n    return isStorageAvailable(state.options);\n  },\n\n  // ── KV operations ──────────────────────────────────────\n\n  /**\n   * Write one key-value pair (maps to C++ `KVSet`).\n   *\n   * @param ns - KV namespace; empty uses default `storage`\n   * @param key - Key name within the namespace\n   * @param value - `string`, `number`, or `boolean`\n   */\n  set(ns: string, key: string, value: StorageValue): void {\n    kvSet(handle(), storageNamespace(ns), { [key]: value }, state.options);\n  },\n\n  /**\n   * Write multiple keys in one RPC call (maps to C++ `KVSet` / `KeyValuePairs`).\n   *\n   * @param ns - KV namespace\n   * @param pairs - Map of key → value\n   *\n   * @example\n   * storage.write('my_app', { theme: 'dark', count: 42 });\n   */\n  write(ns: string, pairs: StorageKeyValueMap): void {\n    kvSet(handle(), storageNamespace(ns), pairs, state.options);\n  },\n\n  /**\n   * Read one or more keys (maps to C++ `KVGet`).\n   *\n   * @param ns - KV namespace\n   * @param keyOrKeys - Single key (`string`), multiple keys (`string[]`), or `[]` for entire namespace\n   * @returns Single value when `keyOrKeys` is a string; otherwise a key-value map. Missing keys are omitted.\n   */\n  get(ns: string, keyOrKeys: string | string[]): StorageValue | StorageKeyValueMap | undefined {\n    if (typeof keyOrKeys === 'string') {\n      return kvGet(handle(), storageNamespace(ns), [keyOrKeys], state.options)[keyOrKeys];\n    }\n    return kvGet(handle(), storageNamespace(ns), keyOrKeys, state.options);\n  },\n\n  /**\n   * List entry metadata in a namespace (maps to C++ `KVList`).\n   *\n   * @param ns - KV namespace; defaults to `storage`\n   * @returns Array of `{ key, type, size, ... }` entries\n   */\n  list(ns?: string): StorageEntryInfo[] {\n    return kvList(handle(), storageNamespace(ns), state.options);\n  },\n\n  /**\n   * Erase keys from a namespace (maps to C++ `KVErase`).\n   *\n   * @param ns - KV namespace\n   * @param keys - Keys to remove; omit or pass `[]` to clear the whole namespace\n   */\n  erase(ns: string, keys?: string[]): void {\n    kvErase(handle(), storageNamespace(ns), keys ?? [], state.options);\n  },\n\n  // ── File system operations ─────────────────────────────\n\n  /**\n   * List mounted storage file systems (maps to C++ `GetFileSystems`).\n   * @returns Mount points such as `littlefs`, `sdcard`\n   */\n  getFileSystems(): FileSystemInfo[] {\n    return getFileSystems(handle(), state.options);\n  },\n\n  /**\n   * Get capacity info for one mounted file system (maps to C++ `GetFileSystemCapacity`).\n   *\n   * @param mountPoint - Mount point name from {@link getFileSystems}\n   */\n  getFileSystemCapacity(mountPoint: string): FileSystemCapacity {\n    return getFileSystemCapacity(handle(), mountPoint, state.options);\n  },\n\n  // ── File system operations ─────────────────────────────\n\n  /**\n   * Stat a file-system path: get type, size, and mtime (maps to C++ `FSStat`).\n   *\n   * @param path - Absolute path under a mounted file system\n   */\n  fsStat(path: string): FileInfo {\n    return fsStat(handle(), path, state.options);\n  },\n\n  /**\n   * List direct children under a file-system directory (maps to C++ `FSList`).\n   *\n   * @param dirPath - Absolute directory path\n   */\n  fsList(dirPath: string): FileEntry[] {\n    return fsList(handle(), dirPath, state.options);\n  },\n\n  /**\n   * Create a directory (mkdir -p) on a mounted file system (maps to C++ `FSMkdir`).\n   *\n   * @param dirPath - Absolute directory path\n   */\n  fsMkdir(dirPath: string): void {\n    fsMkdir(handle(), dirPath, state.options);\n  },\n\n  /**\n   * Read a text file from a mounted file system (maps to C++ `FSReadText`).\n   *\n   * @param filePath - Absolute file path\n   * @returns File contents as a string\n   */\n  fsReadText(filePath: string): string {\n    return fsReadText(handle(), filePath, state.options);\n  },\n\n  /**\n   * Write a text file to a mounted file system (maps to C++ `FSWriteText`).\n   *\n   * @param filePath - Absolute file path\n   * @param data - Text content to write\n   */\n  fsWriteText(filePath: string, data: string): void {\n    fsWriteText(handle(), filePath, data, state.options);\n  },\n\n  /**\n   * Remove a file or empty directory (maps to C++ `FSRemove`).\n   *\n   * @param filePath - Absolute path to remove\n   */\n  fsRemove(filePath: string): void {\n    fsRemove(handle(), filePath, state.options);\n  },\n\n  /**\n   * Rename (move) a file or directory (maps to C++ `FSRename`).\n   *\n   * @param from - Source absolute path\n   * @param to - Destination absolute path\n   */\n  fsRename(from: string, to: string): void {\n    fsRename(handle(), from, to, state.options);\n  },\n\n  /**\n   * Recursively copy a file or directory tree (maps to C++ `FSCopyTree`).\n   *\n   * @param from - Source absolute path\n   * @param to - Destination absolute path\n   * @param overwrite - Overwrite existing destination files\n   */\n  fsCopyTree(from: string, to: string, overwrite: boolean): void {\n    fsCopyTree(handle(), from, to, overwrite, state.options);\n  },\n\n  // ── KV name utilities ──────────────────────────────────\n\n  /**\n   * Generate a KV key that satisfies backend length limits (maps to C++ `MakeKVKey`).\n   *\n   * @param parts - Key segments joined by `separator`\n   * @param separator - Join character (default `.`)\n   */\n  makeKvKey(parts: string[], separator = '.'): KvNameResult {\n    return makeKvKey(handle(), parts, separator, state.options);\n  },\n\n  /**\n   * Generate a KV namespace that satisfies backend limits (maps to C++ `MakeKVNamespace`).\n   *\n   * @param parts - Namespace segments joined by `separator`\n   * @param separator - Join character (default `.`)\n   */\n  makeKvNamespace(parts: string[], separator = '.'): KvNameResult {\n    return makeKvNamespace(handle(), parts, separator, state.options);\n  },\n\n  // ── Lifecycle ──────────────────────────────────────────\n\n  /** Release the Storage service binding. Safe to call multiple times. */\n  close(): void {\n    if (state.handle === null) {\n      return;\n    }\n    closeStorage(state.handle, state.options);\n    state.handle = null;\n  },\n};\n\nexport default storage;\n"],"mappings":"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"}