hazo_files 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -20439,6 +20439,19 @@ var StorageCollisionExhausted = class extends Error {
20439
20439
  this.name = "StorageCollisionExhausted";
20440
20440
  }
20441
20441
  };
20442
+ var StorageNotConfigured = class extends Error {
20443
+ constructor() {
20444
+ super("Storage provider is not configured for this scope");
20445
+ this.name = "StorageNotConfigured";
20446
+ }
20447
+ };
20448
+ var StorageUnavailable = class extends Error {
20449
+ constructor(reason, message) {
20450
+ super(message);
20451
+ this.reason = reason;
20452
+ this.name = "StorageUnavailable";
20453
+ }
20454
+ };
20442
20455
 
20443
20456
  // src/naming/collision.ts
20444
20457
  async function writeWithCollisionRetry(opts) {
@@ -20472,8 +20485,412 @@ function removeRef(file2, ref_id, removed_at) {
20472
20485
  function countRefs(file2) {
20473
20486
  return file2.file_refs.filter((r) => !r.removed_at).length;
20474
20487
  }
20488
+
20489
+ // src/providers/app-file-server.ts
20490
+ import { createHmac } from "crypto";
20491
+ import {
20492
+ copyFileSync,
20493
+ existsSync as existsSync2,
20494
+ mkdirSync,
20495
+ readdirSync,
20496
+ readFileSync as readFileSync2,
20497
+ renameSync,
20498
+ rmSync,
20499
+ statSync,
20500
+ writeFileSync
20501
+ } from "fs";
20502
+ import { basename as basename2, dirname as dirname2, join as join4, normalize, sep } from "path";
20503
+ var AppFileServerProvider = class {
20504
+ constructor(opts) {
20505
+ this.provider_tag = "app_file_server";
20506
+ this.root = normalize(opts.root);
20507
+ this.secret = opts.hmac_secret;
20508
+ this.default_ttl = opts.default_ttl_seconds ?? 300;
20509
+ }
20510
+ resolve(path4) {
20511
+ const safe = normalize(path4).replace(/^([./\\])+/, "");
20512
+ if (safe.includes(`..${sep}`) || safe.startsWith("..")) {
20513
+ throw new Error(`Path escapes root: ${path4}`);
20514
+ }
20515
+ return join4(this.root, safe);
20516
+ }
20517
+ async put(path4, body, opts) {
20518
+ const abs = this.resolve(path4);
20519
+ if (opts?.ifNotExists && existsSync2(abs)) {
20520
+ throw new Error(`File exists: ${path4}`);
20521
+ }
20522
+ mkdirSync(dirname2(abs), { recursive: true });
20523
+ const buf = Buffer.isBuffer(body) ? body : await streamToBuffer(body);
20524
+ writeFileSync(abs, buf);
20525
+ return { provider: this.provider_tag, native_id: path4, size: buf.length };
20526
+ }
20527
+ async get(path4) {
20528
+ return readFileSync2(this.resolve(path4));
20529
+ }
20530
+ async delete(path4) {
20531
+ const abs = this.resolve(path4);
20532
+ if (existsSync2(abs)) rmSync(abs, { force: true });
20533
+ }
20534
+ async exists(path4) {
20535
+ return existsSync2(this.resolve(path4));
20536
+ }
20537
+ async getSignedUrl(path4, opts) {
20538
+ const ttl = opts?.ttl_seconds ?? this.default_ttl;
20539
+ const exp = Math.floor(Date.now() / 1e3) + ttl;
20540
+ const payload = `${path4}:${exp}`;
20541
+ const sig = createHmac("sha256", this.secret).update(payload).digest("base64url");
20542
+ const token = `${exp}.${sig}`;
20543
+ return `/api/files/serve/${token}/${path4}`;
20544
+ }
20545
+ /** Verify a token produced by `getSignedUrl`. Used by the `/api/files/serve` route. */
20546
+ verifySignedUrl(token, path4) {
20547
+ const [expStr, sig] = token.split(".");
20548
+ const exp = Number(expStr);
20549
+ if (!Number.isFinite(exp) || exp * 1e3 < Date.now()) return false;
20550
+ const expected = createHmac("sha256", this.secret).update(`${path4}:${exp}`).digest("base64url");
20551
+ return sig === expected;
20552
+ }
20553
+ async probe() {
20554
+ try {
20555
+ const test = join4(this.root, ".hazo_probe");
20556
+ mkdirSync(this.root, { recursive: true });
20557
+ writeFileSync(test, "probe");
20558
+ statSync(test);
20559
+ rmSync(test, { force: true });
20560
+ return { ok: true };
20561
+ } catch (err) {
20562
+ return { ok: false, error: "write_denied", message: String(err) };
20563
+ }
20564
+ }
20565
+ async list(prefix) {
20566
+ const abs = this.resolve(prefix);
20567
+ if (!existsSync2(abs)) return [];
20568
+ const stat = statSync(abs);
20569
+ if (!stat.isDirectory()) {
20570
+ return [{ path: prefix, name: basename2(prefix), size: stat.size, isDirectory: false }];
20571
+ }
20572
+ const entries = [];
20573
+ this.walkDir(abs, prefix, entries);
20574
+ return entries;
20575
+ }
20576
+ walkDir(absDir, logicalDir, out) {
20577
+ const base = logicalDir.endsWith("/") ? logicalDir : `${logicalDir}/`;
20578
+ for (const item of readdirSync(absDir, { withFileTypes: true })) {
20579
+ const logicalPath = `${base}${item.name}`;
20580
+ const absPath = join4(absDir, item.name);
20581
+ if (item.isDirectory()) {
20582
+ out.push({ path: logicalPath, name: item.name, size: 0, isDirectory: true });
20583
+ this.walkDir(absPath, logicalPath, out);
20584
+ } else {
20585
+ const st = statSync(absPath);
20586
+ out.push({ path: logicalPath, name: item.name, size: st.size, isDirectory: false });
20587
+ }
20588
+ }
20589
+ }
20590
+ async move(from, to) {
20591
+ const absFrom = this.resolve(from);
20592
+ const absTo = this.resolve(to);
20593
+ if (!existsSync2(absFrom)) throw new Error(`Not found: ${from}`);
20594
+ mkdirSync(dirname2(absTo), { recursive: true });
20595
+ try {
20596
+ renameSync(absFrom, absTo);
20597
+ } catch (err) {
20598
+ const e = err;
20599
+ if (e.code === "EXDEV") {
20600
+ copyFileSync(absFrom, absTo);
20601
+ rmSync(absFrom, { force: true });
20602
+ } else {
20603
+ throw err;
20604
+ }
20605
+ }
20606
+ }
20607
+ async rename(from, to) {
20608
+ return this.move(from, to);
20609
+ }
20610
+ };
20611
+ async function streamToBuffer(s) {
20612
+ const chunks = [];
20613
+ for await (const c of s) chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c));
20614
+ return Buffer.concat(chunks);
20615
+ }
20616
+
20617
+ // src/providers/in-memory.ts
20618
+ var InMemoryProvider = class {
20619
+ constructor() {
20620
+ this.provider_tag = "in_memory";
20621
+ this.store = /* @__PURE__ */ new Map();
20622
+ }
20623
+ async put(path4, body, opts) {
20624
+ if (opts?.ifNotExists && this.store.has(path4)) throw new Error(`File exists: ${path4}`);
20625
+ const buf = Buffer.isBuffer(body) ? body : await streamToBuffer2(body);
20626
+ this.store.set(path4, buf);
20627
+ return { provider: this.provider_tag, native_id: path4, size: buf.length };
20628
+ }
20629
+ async get(path4) {
20630
+ const buf = this.store.get(path4);
20631
+ if (!buf) throw new Error(`Not found: ${path4}`);
20632
+ return buf;
20633
+ }
20634
+ async delete(path4) {
20635
+ this.store.delete(path4);
20636
+ }
20637
+ async exists(path4) {
20638
+ return this.store.has(path4);
20639
+ }
20640
+ async getSignedUrl(path4, _opts) {
20641
+ const buf = this.store.get(path4);
20642
+ if (!buf) throw new Error(`Not found: ${path4}`);
20643
+ return `data:application/octet-stream;base64,${buf.toString("base64")}`;
20644
+ }
20645
+ async probe() {
20646
+ return { ok: true };
20647
+ }
20648
+ async list(prefix) {
20649
+ const base = prefix.replace(/\/$/, "");
20650
+ const matchPrefix = `${base}/`;
20651
+ const entries = [];
20652
+ const seenDirs = /* @__PURE__ */ new Set();
20653
+ for (const [key, buf] of this.store.entries()) {
20654
+ if (key !== base && !key.startsWith(matchPrefix)) continue;
20655
+ const rel = key.startsWith(matchPrefix) ? key.slice(matchPrefix.length) : "";
20656
+ if (!rel) {
20657
+ entries.push({ path: key, name: key.split("/").pop(), size: buf.length, isDirectory: false });
20658
+ continue;
20659
+ }
20660
+ const parts = rel.split("/");
20661
+ for (let i = 1; i < parts.length; i++) {
20662
+ const dirPath = matchPrefix + parts.slice(0, i).join("/");
20663
+ if (!seenDirs.has(dirPath)) {
20664
+ seenDirs.add(dirPath);
20665
+ entries.push({ path: dirPath, name: parts[i - 1], size: 0, isDirectory: true });
20666
+ }
20667
+ }
20668
+ entries.push({ path: key, name: parts[parts.length - 1], size: buf.length, isDirectory: false });
20669
+ }
20670
+ return entries;
20671
+ }
20672
+ async move(from, to) {
20673
+ const buf = this.store.get(from);
20674
+ if (!buf) throw new Error(`Not found: ${from}`);
20675
+ this.store.set(to, buf);
20676
+ this.store.delete(from);
20677
+ }
20678
+ async rename(from, to) {
20679
+ return this.move(from, to);
20680
+ }
20681
+ /** Test-only escape hatch — exposes the internal store for assertions. */
20682
+ snapshot() {
20683
+ return new Map(this.store);
20684
+ }
20685
+ };
20686
+ async function streamToBuffer2(s) {
20687
+ const chunks = [];
20688
+ for await (const c of s) chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c));
20689
+ return Buffer.concat(chunks);
20690
+ }
20691
+
20692
+ // src/providers/google-drive.ts
20693
+ import { google as google3 } from "googleapis";
20694
+ var GoogleDriveProvider = class {
20695
+ constructor(opts) {
20696
+ this.provider_tag = "gdrive";
20697
+ let credentials = {};
20698
+ try {
20699
+ credentials = JSON.parse(opts.service_account_json);
20700
+ } catch {
20701
+ }
20702
+ const auth = new google3.auth.GoogleAuth({
20703
+ credentials,
20704
+ scopes: ["https://www.googleapis.com/auth/drive"]
20705
+ });
20706
+ this.drive = google3.drive({ version: "v3", auth });
20707
+ this.driveId = opts.shared_drive_id;
20708
+ this.cache = opts.path_cache;
20709
+ }
20710
+ async probe() {
20711
+ try {
20712
+ await this.drive.drives.get({
20713
+ driveId: this.driveId,
20714
+ supportsAllDrives: true
20715
+ });
20716
+ return { ok: true };
20717
+ } catch (err) {
20718
+ const e = err;
20719
+ if (e?.code === 404) return { ok: false, error: "drive_not_shared", message: "SA cannot see Shared Drive" };
20720
+ if (e?.code === 403) return { ok: false, error: "write_denied", message: "SA lacks permission" };
20721
+ return { ok: false, error: "transient", message: String(err) };
20722
+ }
20723
+ }
20724
+ async put(path4, body, opts) {
20725
+ const segments = path4.split("/").filter(Boolean);
20726
+ const filename = segments.pop();
20727
+ const parentId = await this.resolvePath(segments, { create: true });
20728
+ if (opts?.ifNotExists) {
20729
+ const existing = await this.findChild(filename, parentId);
20730
+ if (existing) throw new Error(`File exists: ${path4}`);
20731
+ }
20732
+ const buf = Buffer.isBuffer(body) ? body : await streamToBuffer3(body);
20733
+ const res = await this.drive.files.create({
20734
+ requestBody: {
20735
+ name: filename,
20736
+ parents: [parentId],
20737
+ mimeType: opts?.contentType ?? "application/octet-stream"
20738
+ },
20739
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20740
+ media: { body: buf },
20741
+ fields: "id, name"
20742
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20743
+ });
20744
+ return { provider: this.provider_tag, native_id: res.data.id, size: buf.length };
20745
+ }
20746
+ async get(path4) {
20747
+ const id = await this.lookupFileId(path4);
20748
+ const res = await this.drive.files.get(
20749
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20750
+ { fileId: id, alt: "media", supportsAllDrives: true },
20751
+ { responseType: "arraybuffer" }
20752
+ );
20753
+ return Buffer.from(res.data);
20754
+ }
20755
+ async delete(path4) {
20756
+ try {
20757
+ const id = await this.lookupFileId(path4);
20758
+ await this.drive.files.delete({ fileId: id, supportsAllDrives: true });
20759
+ } catch (err) {
20760
+ const e = err;
20761
+ if (e?.code !== 404) throw err;
20762
+ }
20763
+ }
20764
+ async exists(path4) {
20765
+ try {
20766
+ await this.lookupFileId(path4);
20767
+ return true;
20768
+ } catch {
20769
+ return false;
20770
+ }
20771
+ }
20772
+ async getSignedUrl(path4, _opts) {
20773
+ const id = await this.lookupFileId(path4);
20774
+ return `https://drive.google.com/uc?id=${id}&export=download`;
20775
+ }
20776
+ async list(prefix) {
20777
+ const segments = prefix.split("/").filter(Boolean);
20778
+ let parentId;
20779
+ try {
20780
+ parentId = await this.resolvePath(segments, { create: false });
20781
+ } catch {
20782
+ return [];
20783
+ }
20784
+ const res = await this.drive.files.list({
20785
+ q: `'${parentId}' in parents and trashed=false`,
20786
+ driveId: this.driveId,
20787
+ corpora: "drive",
20788
+ includeItemsFromAllDrives: true,
20789
+ fields: "files(id, name, mimeType, size)"
20790
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20791
+ });
20792
+ const files = res.data.files ?? [];
20793
+ const base = prefix.endsWith("/") ? prefix : `${prefix}/`;
20794
+ return files.map((f) => ({
20795
+ path: `${base}${f.name}`,
20796
+ name: f.name,
20797
+ size: Number(f.size ?? 0),
20798
+ isDirectory: f.mimeType === "application/vnd.google-apps.folder"
20799
+ }));
20800
+ }
20801
+ async move(from, to) {
20802
+ const id = await this.lookupFileId(from);
20803
+ const fromSegs = from.split("/").filter(Boolean);
20804
+ fromSegs.pop();
20805
+ const toSegs = to.split("/").filter(Boolean);
20806
+ const newName = toSegs.pop();
20807
+ const oldParentId = await this.resolvePath(fromSegs, { create: false });
20808
+ const newParentId = await this.resolvePath(toSegs, { create: true });
20809
+ await this.drive.files.update({
20810
+ fileId: id,
20811
+ addParents: newParentId,
20812
+ removeParents: oldParentId,
20813
+ requestBody: { name: newName },
20814
+ supportsAllDrives: true,
20815
+ fields: "id, parents"
20816
+ });
20817
+ await this.cache.invalidate(from);
20818
+ }
20819
+ async rename(from, to) {
20820
+ const id = await this.lookupFileId(from);
20821
+ const segs = to.split("/").filter(Boolean);
20822
+ const newName = segs[segs.length - 1];
20823
+ await this.drive.files.update({
20824
+ fileId: id,
20825
+ requestBody: { name: newName },
20826
+ supportsAllDrives: true,
20827
+ fields: "id, name"
20828
+ });
20829
+ }
20830
+ async resolvePath(segments, opts) {
20831
+ let parentId = this.driveId;
20832
+ const accumulated = [];
20833
+ for (const segment of segments) {
20834
+ accumulated.push(segment);
20835
+ const cacheKey = accumulated.join("/");
20836
+ const cached2 = await this.cache.lookup(cacheKey);
20837
+ if (cached2) {
20838
+ parentId = cached2;
20839
+ continue;
20840
+ }
20841
+ let found = await this.findChild(segment, parentId, "application/vnd.google-apps.folder");
20842
+ if (!found && opts.create) {
20843
+ const created = await this.drive.files.create({
20844
+ requestBody: {
20845
+ name: segment,
20846
+ parents: [parentId],
20847
+ mimeType: "application/vnd.google-apps.folder"
20848
+ },
20849
+ fields: "id"
20850
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20851
+ });
20852
+ found = created.data.id;
20853
+ }
20854
+ if (!found) throw new Error(`Folder not found and create=false: ${cacheKey}`);
20855
+ await this.cache.write(cacheKey, found);
20856
+ parentId = found;
20857
+ }
20858
+ return parentId;
20859
+ }
20860
+ async findChild(name, parentId, mimeType) {
20861
+ const q = [
20862
+ `name='${name.replace(/'/g, "\\'")}'`,
20863
+ `'${parentId}' in parents`,
20864
+ `trashed=false`
20865
+ ];
20866
+ if (mimeType) q.push(`mimeType='${mimeType}'`);
20867
+ const res = await this.drive.files.list({
20868
+ q: q.join(" and "),
20869
+ driveId: this.driveId,
20870
+ corpora: "drive",
20871
+ includeItemsFromAllDrives: true,
20872
+ fields: "files(id, name)"
20873
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20874
+ });
20875
+ return res.data.files?.[0]?.id ?? null;
20876
+ }
20877
+ async lookupFileId(path4) {
20878
+ const segments = path4.split("/").filter(Boolean);
20879
+ const filename = segments.pop();
20880
+ const parentId = await this.resolvePath(segments, { create: false });
20881
+ const id = await this.findChild(filename, parentId);
20882
+ if (!id) throw Object.assign(new Error(`Not found: ${path4}`), { code: 404 });
20883
+ return id;
20884
+ }
20885
+ };
20886
+ async function streamToBuffer3(s) {
20887
+ const chunks = [];
20888
+ for await (const c of s) chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c));
20889
+ return Buffer.concat(chunks);
20890
+ }
20475
20891
  export {
20476
20892
  ALL_SYSTEM_VARIABLES,
20893
+ AppFileServerProvider,
20477
20894
  AuthenticationError,
20478
20895
  ConfigurationError,
20479
20896
  DEFAULT_DATE_FORMATS,
@@ -20489,6 +20906,7 @@ export {
20489
20906
  FileTooLargeError,
20490
20907
  GoogleDriveAuth,
20491
20908
  GoogleDriveModule,
20909
+ GoogleDriveProvider,
20492
20910
  HAZO_FILES_DEFAULT_TABLE_NAME,
20493
20911
  HAZO_FILES_MIGRATION_V2,
20494
20912
  HAZO_FILES_MIGRATION_V3,
@@ -20496,6 +20914,7 @@ export {
20496
20914
  HAZO_FILES_NAMING_TABLE_SCHEMA,
20497
20915
  HAZO_FILES_TABLE_SCHEMA,
20498
20916
  HazoError as HazoFilesError,
20917
+ InMemoryProvider,
20499
20918
  InvalidExtensionError,
20500
20919
  InvalidPathError,
20501
20920
  LLMExtractionService,
@@ -20507,6 +20926,9 @@ export {
20507
20926
  SYSTEM_COUNTER_VARIABLES,
20508
20927
  SYSTEM_DATE_VARIABLES,
20509
20928
  SYSTEM_FILE_VARIABLES,
20929
+ StorageCollisionExhausted,
20930
+ StorageNotConfigured,
20931
+ StorageUnavailable,
20510
20932
  TrackedFileManager,
20511
20933
  UploadExtractService,
20512
20934
  addExtractionToFileData,
@@ -2614,6 +2614,22 @@ interface ProbeResult {
2614
2614
  /** Free-form detail for logging. */
2615
2615
  message?: string;
2616
2616
  }
2617
+ /**
2618
+ * A single entry returned by `FileStorageProvider.list()`.
2619
+ *
2620
+ * `path` is the same logical namespace used by `put`/`get` — callers can pass
2621
+ * it directly back to those methods without any transformation.
2622
+ */
2623
+ interface FileEntry {
2624
+ /** Logical path within the provider (same namespace as put/get). */
2625
+ path: StoragePath;
2626
+ /** Bare filename or directory name (the last segment of `path`). */
2627
+ name: string;
2628
+ /** Size in bytes. 0 for directories. */
2629
+ size: number;
2630
+ /** True when this entry represents a directory. */
2631
+ isDirectory: boolean;
2632
+ }
2617
2633
  /**
2618
2634
  * Storage provider abstraction. Every method MUST be idempotent at the
2619
2635
  * data-content level — re-invoking put with identical body is allowed.
@@ -2628,6 +2644,24 @@ interface FileStorageProvider {
2628
2644
  getSignedUrl(path: StoragePath, opts?: SignedUrlOpts): Promise<string>;
2629
2645
  /** Used by validation cron + onboarding step 2. */
2630
2646
  probe(): Promise<ProbeResult>;
2647
+ /**
2648
+ * List all entries (files and sub-directories) under a logical path prefix.
2649
+ * Results are recursive — all descendants are included.
2650
+ * Returns an empty array when the prefix does not exist.
2651
+ */
2652
+ list(prefix: StoragePath): Promise<FileEntry[]>;
2653
+ /**
2654
+ * Move bytes from `from` to `to`, creating any intermediate directories.
2655
+ * The source is removed on success.
2656
+ * Throws with a message containing "Not found" when `from` does not exist.
2657
+ */
2658
+ move(from: StoragePath, to: StoragePath): Promise<void>;
2659
+ /**
2660
+ * Rename a file or directory. `to` is the full new logical path.
2661
+ * Implementations may delegate to `move`.
2662
+ * Throws with a message containing "Not found" when `from` does not exist.
2663
+ */
2664
+ rename(from: StoragePath, to: StoragePath): Promise<void>;
2631
2665
  }
2632
2666
  declare class StorageCollisionExhausted extends Error {
2633
2667
  attempts: number;
@@ -2665,6 +2699,10 @@ declare class AppFileServerProvider implements FileStorageProvider {
2665
2699
  /** Verify a token produced by `getSignedUrl`. Used by the `/api/files/serve` route. */
2666
2700
  verifySignedUrl(token: string, path: string): boolean;
2667
2701
  probe(): Promise<ProbeResult>;
2702
+ list(prefix: string): Promise<FileEntry[]>;
2703
+ private walkDir;
2704
+ move(from: string, to: string): Promise<void>;
2705
+ rename(from: string, to: string): Promise<void>;
2668
2706
  }
2669
2707
 
2670
2708
  declare class InMemoryProvider implements FileStorageProvider {
@@ -2676,6 +2714,9 @@ declare class InMemoryProvider implements FileStorageProvider {
2676
2714
  exists(path: string): Promise<boolean>;
2677
2715
  getSignedUrl(path: string, _opts?: SignedUrlOpts): Promise<string>;
2678
2716
  probe(): Promise<ProbeResult>;
2717
+ list(prefix: string): Promise<FileEntry[]>;
2718
+ move(from: string, to: string): Promise<void>;
2719
+ rename(from: string, to: string): Promise<void>;
2679
2720
  /** Test-only escape hatch — exposes the internal store for assertions. */
2680
2721
  snapshot(): Map<string, Buffer>;
2681
2722
  }
@@ -2705,6 +2746,9 @@ declare class GoogleDriveProvider implements FileStorageProvider {
2705
2746
  delete(path: string): Promise<void>;
2706
2747
  exists(path: string): Promise<boolean>;
2707
2748
  getSignedUrl(path: string, _opts?: SignedUrlOpts): Promise<string>;
2749
+ list(prefix: string): Promise<FileEntry[]>;
2750
+ move(from: string, to: string): Promise<void>;
2751
+ rename(from: string, to: string): Promise<void>;
2708
2752
  private resolvePath;
2709
2753
  private findChild;
2710
2754
  private lookupFileId;
@@ -3770,4 +3814,43 @@ declare function toV2Record(record: FileMetadataRecord): FileMetadataRecordV2;
3770
3814
  */
3771
3815
  declare function buildFileWithStatus(record: FileMetadataRecord): FileWithStatus;
3772
3816
 
3773
- export { ALL_SYSTEM_VARIABLES, type AddExtractionOptions, type AddRefOptions, type AppFileServerOpts, AppFileServerProvider, type AuthCallbacks, AuthenticationError, type CleanupOrphanedOptions, ConfigurationError, type ContentTagConfig, type CreateFolderOptions, type CrudServiceLike, DEFAULT_DATE_FORMATS, type DatabaseSchemaDefinition, type DatabaseTrackingConfig, DirectoryExistsError, DirectoryNotEmptyError, DirectoryNotFoundError, type DownloadOptions, type DrivePathCache, DropboxAuth, type DropboxAuthCallbacks, type DropboxAuthConfig, type DropboxConfig, DropboxModule, type DropboxTokenData, type ExtractionData, type ExtractionOptions, type ExtractionResult, type FileBrowserState, type FileDataStructure, FileExistsError, type FileInfo, type FileItem, FileManager, type FileManagerOptions, type FileMetadataInput, type FileMetadataRecord, type FileMetadataRecordV2, FileMetadataService, type FileMetadataServiceOptions, type FileMetadataUpdate, FileNotFoundError, type FileRef, type FileRefVisibility, type FileStatus, type FileStorageProvider, type FileSystemItem, FileTooLargeError, type FileWithStatus, type FindOrphanedOptions, type FolderItem, type GeneratedNameResult, type GoogleAuthConfig, GoogleDriveAuth, type GoogleDriveConfig, GoogleDriveModule, type GoogleDriveOpts, GoogleDriveProvider, HAZO_FILES_DEFAULT_TABLE_NAME, HAZO_FILES_JOB_TYPES, HAZO_FILES_MIGRATION_V2, HAZO_FILES_MIGRATION_V3, HAZO_FILES_MIGRATION_V4, HAZO_FILES_NAMING_DEFAULT_TABLE_NAME, HAZO_FILES_NAMING_TABLE_SCHEMA, HAZO_FILES_TABLE_SCHEMA, HAZO_FILE_QUOTAS_DEFAULT_TABLE_NAME, HAZO_FILE_QUOTAS_TABLE_SCHEMA, type HazoFileQuotasColumnDefinitions, type HazoFilesColumnDefinitions, type HazoFilesConfig, type HazoFilesJobType, type HazoFilesMigrationV2, type HazoFilesMigrationV3, type HazoFilesMigrationV4, type HazoFilesNamingColumnDefinitions, type HazoFilesNamingTableSchema, type HazoFilesServerInstance, type HazoFilesServerOptions, type HazoFilesTableSchema, type HazoLLMInstance, type HazoLogger, ImportSizeCapError, InMemoryProvider, InvalidExtensionError, InvalidPathError, LLMExtractionService, type LLMFactory, type LLMFactoryConfig, type LLMProvider, type ListNamingConventionsOptions, type ListOptions, type LocalStorageConfig, LocalStorageModule, type MetadataLogger, type MigrationExecutor, type MigrationSchemaDefinition, type MoveOptions, type NameGenerationOptions, type NamingConventionInput, type NamingConventionRecord, NamingConventionService, type NamingConventionServiceOptions, type NamingConventionType, type NamingConventionUpdate, type NamingRuleConfiguratorProps, type NamingRuleHistoryEntry, type NamingRuleSchema, type NamingVariable, OperationError, type OperationResult, type ParsedNamingConvention, type PatternSegment, PermissionDeniedError, type ProbeResult, type ProgressCallback, type PurgeJobHandlerOptions, type PurgeOnePayload, type PurgePlanPayload, type PurgePlanResult, type PutOpts, type PutResult, type QuotaCrudServiceLike, QuotaExceededError, QuotaService, type QuotaServiceOptions, type QuotaStatus, type QuotaThresholdEvent, type RemoveExtractionOptions, type RemoveRefsCriteria, type RenameOptions, SSRFError, SYSTEM_COUNTER_VARIABLES, SYSTEM_DATE_VARIABLES, SYSTEM_FILE_VARIABLES, type SignedUrlOpts, StorageCollisionExhausted, type StorageModule, StorageNotConfigured, type StoragePath, type StorageProvider, StorageUnavailable, type TokenData, TrackedFileManager, type TrackedFileManagerFullOptions, type TrackedFileManagerOptions, type TrackedUploadOptions, type TreeNode, type UploadExtractOptions, type UploadExtractResult, UploadExtractService, type UploadOptions, type UploadWithRefOptions, type UseNamingRuleActions, type UseNamingRuleReturn, type UseNamingRuleState, type VariableCategory, addExtractionToFileData, backfillV2Defaults, buildFileWithStatus, clearExtractions, clonePattern, computeFileHash, computeFileHashFromStream, computeFileHashSync, computeFileInfo, createAndInitializeModule, createBasicFileManager, createDropboxAuth, createDropboxModule, createEmptyFileDataStructure, createEmptyNamingRuleSchema, createFileItem, createFileManager, createFileMetadataService, createFileRef, createFolderItem, createGoogleDriveAuth, createGoogleDriveModule, createHazoFilesServer, createInitializedFileManager, createInitializedTrackedFileManager, createLLMExtractionService, createLiteralSegment, createLocalModule, createModule, createNamingConventionService, createPurgeJobHandlers, createQuotaService, createTrackedFileManager, createUploadExtractService, createVariableSegment, deepMerge, errorResult, filterItems, formatBytes, formatCounter, formatDateToken, generateExtractionId, generateId, generatePreviewName, generateRefId, generateSampleConfig, generateSegmentId, getBaseName, getBreadcrumbs, getDirName, getExtension, getExtensionFromMime, getExtractionById, getExtractionCount, getExtractions, getFileCategory, getFileMetadataValues, getMergedData, getMigrationForTable, getMigrationV3ForTable, getMigrationV4ForTable, getMimeType, getNameWithoutExtension, getNamingSchemaForTable, getParentPath, getPathSegments, getRegisteredProviders, getRelativePath, getSchemaForTable, getSystemVariablePreviewValues, hasExtension, hasExtractionStructure, hasFileContentChanged, hashesEqual, hazo_files_generate_file_name, hazo_files_generate_folder_name, isAudio, isChildPath, isCounterVariable, isDateVariable, isDocument, isFile, isFileMetadataVariable, isFolder, isImage, isPreviewable, isProviderRegistered, isText, isVideo, joinPath, loadConfig, loadConfigAsync, migrateToV2, migrateToV3, normalizePath, parseConfig, parseFileData, parseFileRefs, parsePatternString, patternToString, recalculateMergedData, registerModule, removeExtractionById, removeExtractionByIndex, removeRefFromArray, removeRefsByCriteriaFromArray, sanitizeFilename, saveConfig, sortItems, stringifyFileData, stringifyFileRefs, successResult, toV2Record, updateExtractionById, validateExtractionData, validateFileDataStructure, validateNamingRuleSchema, validatePath };
3817
+ interface ExternalFileLinkOptions {
3818
+ serve_base?: string;
3819
+ serve_path?: string;
3820
+ metadata?: FileMetadataRecord;
3821
+ }
3822
+ interface ExternalFileLink {
3823
+ url: string;
3824
+ link_type: 'provider_managed' | 'app_gated';
3825
+ storage_type: StorageProvider | string;
3826
+ }
3827
+ interface ExternalFileLinkDeps {
3828
+ metadataService: Pick<FileMetadataService, 'findById'>;
3829
+ }
3830
+ declare function external_file_link(file_id: string, deps: ExternalFileLinkDeps, opts?: ExternalFileLinkOptions): Promise<ExternalFileLink>;
3831
+ type ExternalFileLinkResult = ExternalFileLink | {
3832
+ error: string;
3833
+ };
3834
+ declare function external_file_links(file_ids: string[], deps: ExternalFileLinkDeps, opts?: ExternalFileLinkOptions): Promise<Record<string, ExternalFileLinkResult>>;
3835
+
3836
+ interface FileServeAuthContext {
3837
+ request: Request;
3838
+ file_id: string;
3839
+ }
3840
+ interface FileServeUser {
3841
+ user_id?: string;
3842
+ [k: string]: unknown;
3843
+ }
3844
+ interface FileServeHandlerOptions {
3845
+ provider: Pick<FileStorageProvider, 'get'>;
3846
+ metadataService: Pick<FileMetadataService, 'findById'>;
3847
+ authenticate?: (ctx: FileServeAuthContext) => Promise<FileServeUser | null>;
3848
+ authorize?: (ctx: FileServeAuthContext & {
3849
+ user: FileServeUser;
3850
+ metadata: FileMetadataRecord;
3851
+ }) => Promise<boolean>;
3852
+ get_file_id?: (request: Request) => string | null;
3853
+ }
3854
+ declare function createFileServeHandler(opts: FileServeHandlerOptions): (request: Request) => Promise<Response>;
3855
+
3856
+ export { ALL_SYSTEM_VARIABLES, type AddExtractionOptions, type AddRefOptions, type AppFileServerOpts, AppFileServerProvider, type AuthCallbacks, AuthenticationError, type CleanupOrphanedOptions, ConfigurationError, type ContentTagConfig, type CreateFolderOptions, type CrudServiceLike, DEFAULT_DATE_FORMATS, type DatabaseSchemaDefinition, type DatabaseTrackingConfig, DirectoryExistsError, DirectoryNotEmptyError, DirectoryNotFoundError, type DownloadOptions, type DrivePathCache, DropboxAuth, type DropboxAuthCallbacks, type DropboxAuthConfig, type DropboxConfig, DropboxModule, type DropboxTokenData, type ExternalFileLink, type ExternalFileLinkDeps, type ExternalFileLinkOptions, type ExternalFileLinkResult, type ExtractionData, type ExtractionOptions, type ExtractionResult, type FileBrowserState, type FileDataStructure, type FileEntry, FileExistsError, type FileInfo, type FileItem, FileManager, type FileManagerOptions, type FileMetadataInput, type FileMetadataRecord, type FileMetadataRecordV2, FileMetadataService, type FileMetadataServiceOptions, type FileMetadataUpdate, FileNotFoundError, type FileRef, type FileRefVisibility, type FileServeAuthContext, type FileServeHandlerOptions, type FileServeUser, type FileStatus, type FileStorageProvider, type FileSystemItem, FileTooLargeError, type FileWithStatus, type FindOrphanedOptions, type FolderItem, type GeneratedNameResult, type GoogleAuthConfig, GoogleDriveAuth, type GoogleDriveConfig, GoogleDriveModule, type GoogleDriveOpts, GoogleDriveProvider, HAZO_FILES_DEFAULT_TABLE_NAME, HAZO_FILES_JOB_TYPES, HAZO_FILES_MIGRATION_V2, HAZO_FILES_MIGRATION_V3, HAZO_FILES_MIGRATION_V4, HAZO_FILES_NAMING_DEFAULT_TABLE_NAME, HAZO_FILES_NAMING_TABLE_SCHEMA, HAZO_FILES_TABLE_SCHEMA, HAZO_FILE_QUOTAS_DEFAULT_TABLE_NAME, HAZO_FILE_QUOTAS_TABLE_SCHEMA, type HazoFileQuotasColumnDefinitions, type HazoFilesColumnDefinitions, type HazoFilesConfig, type HazoFilesJobType, type HazoFilesMigrationV2, type HazoFilesMigrationV3, type HazoFilesMigrationV4, type HazoFilesNamingColumnDefinitions, type HazoFilesNamingTableSchema, type HazoFilesServerInstance, type HazoFilesServerOptions, type HazoFilesTableSchema, type HazoLLMInstance, type HazoLogger, ImportSizeCapError, InMemoryProvider, InvalidExtensionError, InvalidPathError, LLMExtractionService, type LLMFactory, type LLMFactoryConfig, type LLMProvider, type ListNamingConventionsOptions, type ListOptions, type LocalStorageConfig, LocalStorageModule, type MetadataLogger, type MigrationExecutor, type MigrationSchemaDefinition, type MoveOptions, type NameGenerationOptions, type NamingConventionInput, type NamingConventionRecord, NamingConventionService, type NamingConventionServiceOptions, type NamingConventionType, type NamingConventionUpdate, type NamingRuleConfiguratorProps, type NamingRuleHistoryEntry, type NamingRuleSchema, type NamingVariable, OperationError, type OperationResult, type ParsedNamingConvention, type PatternSegment, PermissionDeniedError, type ProbeResult, type ProgressCallback, type PurgeJobHandlerOptions, type PurgeOnePayload, type PurgePlanPayload, type PurgePlanResult, type PutOpts, type PutResult, type QuotaCrudServiceLike, QuotaExceededError, QuotaService, type QuotaServiceOptions, type QuotaStatus, type QuotaThresholdEvent, type RemoveExtractionOptions, type RemoveRefsCriteria, type RenameOptions, SSRFError, SYSTEM_COUNTER_VARIABLES, SYSTEM_DATE_VARIABLES, SYSTEM_FILE_VARIABLES, type SignedUrlOpts, StorageCollisionExhausted, type StorageModule, StorageNotConfigured, type StoragePath, type StorageProvider, StorageUnavailable, type TokenData, TrackedFileManager, type TrackedFileManagerFullOptions, type TrackedFileManagerOptions, type TrackedUploadOptions, type TreeNode, type UploadExtractOptions, type UploadExtractResult, UploadExtractService, type UploadOptions, type UploadWithRefOptions, type UseNamingRuleActions, type UseNamingRuleReturn, type UseNamingRuleState, type VariableCategory, addExtractionToFileData, backfillV2Defaults, buildFileWithStatus, clearExtractions, clonePattern, computeFileHash, computeFileHashFromStream, computeFileHashSync, computeFileInfo, createAndInitializeModule, createBasicFileManager, createDropboxAuth, createDropboxModule, createEmptyFileDataStructure, createEmptyNamingRuleSchema, createFileItem, createFileManager, createFileMetadataService, createFileRef, createFileServeHandler, createFolderItem, createGoogleDriveAuth, createGoogleDriveModule, createHazoFilesServer, createInitializedFileManager, createInitializedTrackedFileManager, createLLMExtractionService, createLiteralSegment, createLocalModule, createModule, createNamingConventionService, createPurgeJobHandlers, createQuotaService, createTrackedFileManager, createUploadExtractService, createVariableSegment, deepMerge, errorResult, external_file_link, external_file_links, filterItems, formatBytes, formatCounter, formatDateToken, generateExtractionId, generateId, generatePreviewName, generateRefId, generateSampleConfig, generateSegmentId, getBaseName, getBreadcrumbs, getDirName, getExtension, getExtensionFromMime, getExtractionById, getExtractionCount, getExtractions, getFileCategory, getFileMetadataValues, getMergedData, getMigrationForTable, getMigrationV3ForTable, getMigrationV4ForTable, getMimeType, getNameWithoutExtension, getNamingSchemaForTable, getParentPath, getPathSegments, getRegisteredProviders, getRelativePath, getSchemaForTable, getSystemVariablePreviewValues, hasExtension, hasExtractionStructure, hasFileContentChanged, hashesEqual, hazo_files_generate_file_name, hazo_files_generate_folder_name, isAudio, isChildPath, isCounterVariable, isDateVariable, isDocument, isFile, isFileMetadataVariable, isFolder, isImage, isPreviewable, isProviderRegistered, isText, isVideo, joinPath, loadConfig, loadConfigAsync, migrateToV2, migrateToV3, normalizePath, parseConfig, parseFileData, parseFileRefs, parsePatternString, patternToString, recalculateMergedData, registerModule, removeExtractionById, removeExtractionByIndex, removeRefFromArray, removeRefsByCriteriaFromArray, sanitizeFilename, saveConfig, sortItems, stringifyFileData, stringifyFileRefs, successResult, toV2Record, updateExtractionById, validateExtractionData, validateFileDataStructure, validateNamingRuleSchema, validatePath };