{"version":3,"file":"fs-store.cjs","names":["PFrameInternal"],"sources":["../src/fs-store.ts"],"sourcesContent":["import type { Readable } from \"node:stream\";\nimport { stat, open, type FileHandle } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { PFrameInternal } from \"@milaboratories/pl-model-middle-layer\";\nimport { ensureError, isAbortError } from \"@milaboratories/pl-model-common\";\n\n/** Object store for serving files from a local directory */\nexport class FileSystemStore extends PFrameInternal.BaseObjectStore {\n  private readonly rootDir: string;\n\n  private constructor(options: PFrameInternal.FsStoreOptions) {\n    super(options);\n\n    this.rootDir = options.rootDir;\n  }\n\n  static async init(options: PFrameInternal.FsStoreOptions): Promise<FileSystemStore> {\n    const resolvedRootDir = resolve(options.rootDir);\n\n    const rootStats = await stat(resolvedRootDir).catch(() => {\n      throw new Error(`File system store root directory does not exist: ${resolvedRootDir}`);\n    });\n    if (!rootStats.isDirectory()) {\n      throw new Error(`File system store root path is not a directory: ${resolvedRootDir}`);\n    }\n\n    return new FileSystemStore({\n      ...options,\n      rootDir: resolvedRootDir,\n    });\n  }\n\n  override async request(\n    filename: PFrameInternal.ParquetFileName,\n    params: {\n      method: PFrameInternal.HttpMethod;\n      range?: PFrameInternal.HttpRange;\n      signal: AbortSignal;\n      callback: (response: PFrameInternal.ObjectStoreResponse) => Promise<void>;\n    },\n  ): Promise<void> {\n    let file: FileHandle | undefined;\n    const respond = async (response: PFrameInternal.ObjectStoreResponse) => {\n      try {\n        await params.callback(response).finally(async () => await file?.close());\n      } catch (error: unknown) {\n        this.logger(\n          \"warn\",\n          `File system store received unexpected rejection from callback: ${ensureError(error)}`,\n        );\n      }\n    };\n\n    try {\n      try {\n        const path = join(this.rootDir, filename);\n        file = await open(path, \"r\");\n      } catch (error: unknown) {\n        this.logger(\n          \"error\",\n          `File system store failed to open file ${filename}: ${ensureError(error)}`,\n        );\n        return await respond({ type: \"NotFound\" });\n      }\n      params.signal.throwIfAborted();\n\n      let size: number;\n      try {\n        ({ size } = await file.stat());\n      } catch (error: unknown) {\n        this.logger(\n          \"error\",\n          `File system store failed to get size of file ${filename}: ${ensureError(error)}`,\n        );\n        return await respond({ type: \"InternalError\" });\n      }\n      params.signal.throwIfAborted();\n\n      const range = this.translate(size, params.range);\n      if (!range) {\n        return await respond({ type: \"RangeNotSatisfiable\", size });\n      }\n\n      if (params.method === \"HEAD\") {\n        return await respond({ type: \"Ok\", size, range });\n      }\n\n      let data: Readable;\n      try {\n        data = file.createReadStream({\n          start: range.start,\n          end: range.end,\n          autoClose: false,\n        });\n        this.logger(\n          \"info\",\n          `File system store created read stream for ${filename}[${range.start}..=${range.end}]`,\n        );\n      } catch (error: unknown) {\n        this.logger(\n          \"error\",\n          `File system store failed to create read stream for ${filename}[${range.start}..=${range.end}]: ${ensureError(error)}`,\n        );\n        return await respond({ type: \"InternalError\" });\n      }\n\n      return await respond({ type: \"Ok\", size, range, data });\n    } catch (error: unknown) {\n      if (!isAbortError(error)) {\n        this.logger(\"warn\", `File system store unhandled error: ${ensureError(error)}`);\n      }\n      return await respond({ type: \"InternalError\" });\n    }\n  }\n}\n"],"mappings":";;;;;;AAOA,IAAa,kBAAb,MAAa,wBAAwBA,sCAAAA,eAAe,gBAAgB;CAClE;CAEA,YAAoB,SAAwC;AAC1D,QAAM,QAAQ;AAEd,OAAK,UAAU,QAAQ;;CAGzB,aAAa,KAAK,SAAkE;EAClF,MAAM,mBAAA,GAAA,UAAA,SAA0B,QAAQ,QAAQ;AAKhD,MAAI,EAHc,OAAA,GAAA,iBAAA,MAAW,gBAAgB,CAAC,YAAY;AACxD,SAAM,IAAI,MAAM,oDAAoD,kBAAkB;IACtF,EACa,aAAa,CAC1B,OAAM,IAAI,MAAM,mDAAmD,kBAAkB;AAGvF,SAAO,IAAI,gBAAgB;GACzB,GAAG;GACH,SAAS;GACV,CAAC;;CAGJ,MAAe,QACb,UACA,QAMe;EACf,IAAI;EACJ,MAAM,UAAU,OAAO,aAAiD;AACtE,OAAI;AACF,UAAM,OAAO,SAAS,SAAS,CAAC,QAAQ,YAAY,MAAM,MAAM,OAAO,CAAC;YACjE,OAAgB;AACvB,SAAK,OACH,QACA,mEAAA,GAAA,gCAAA,aAA8E,MAAM,GACrF;;;AAIL,MAAI;AACF,OAAI;AAEF,WAAO,OAAA,GAAA,iBAAA,OAAA,GAAA,UAAA,MADW,KAAK,SAAS,SAAS,EACjB,IAAI;YACrB,OAAgB;AACvB,SAAK,OACH,SACA,yCAAyC,SAAS,KAAA,GAAA,gCAAA,aAAgB,MAAM,GACzE;AACD,WAAO,MAAM,QAAQ,EAAE,MAAM,YAAY,CAAC;;AAE5C,UAAO,OAAO,gBAAgB;GAE9B,IAAI;AACJ,OAAI;AACF,KAAC,CAAE,QAAS,MAAM,KAAK,MAAM;YACtB,OAAgB;AACvB,SAAK,OACH,SACA,gDAAgD,SAAS,KAAA,GAAA,gCAAA,aAAgB,MAAM,GAChF;AACD,WAAO,MAAM,QAAQ,EAAE,MAAM,iBAAiB,CAAC;;AAEjD,UAAO,OAAO,gBAAgB;GAE9B,MAAM,QAAQ,KAAK,UAAU,MAAM,OAAO,MAAM;AAChD,OAAI,CAAC,MACH,QAAO,MAAM,QAAQ;IAAE,MAAM;IAAuB;IAAM,CAAC;AAG7D,OAAI,OAAO,WAAW,OACpB,QAAO,MAAM,QAAQ;IAAE,MAAM;IAAM;IAAM;IAAO,CAAC;GAGnD,IAAI;AACJ,OAAI;AACF,WAAO,KAAK,iBAAiB;KAC3B,OAAO,MAAM;KACb,KAAK,MAAM;KACX,WAAW;KACZ,CAAC;AACF,SAAK,OACH,QACA,6CAA6C,SAAS,GAAG,MAAM,MAAM,KAAK,MAAM,IAAI,GACrF;YACM,OAAgB;AACvB,SAAK,OACH,SACA,sDAAsD,SAAS,GAAG,MAAM,MAAM,KAAK,MAAM,IAAI,MAAA,GAAA,gCAAA,aAAiB,MAAM,GACrH;AACD,WAAO,MAAM,QAAQ,EAAE,MAAM,iBAAiB,CAAC;;AAGjD,UAAO,MAAM,QAAQ;IAAE,MAAM;IAAM;IAAM;IAAO;IAAM,CAAC;WAChD,OAAgB;AACvB,OAAI,EAAA,GAAA,gCAAA,cAAc,MAAM,CACtB,MAAK,OAAO,QAAQ,uCAAA,GAAA,gCAAA,aAAkD,MAAM,GAAG;AAEjF,UAAO,MAAM,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}