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/CHANGE_LOG.md +24 -0
- package/README.md +45 -2
- package/dist/index.d.mts +125 -1
- package/dist/index.d.ts +125 -1
- package/dist/index.js +418 -0
- package/dist/index.mjs +422 -0
- package/dist/server/index.d.mts +84 -1
- package/dist/server/index.d.ts +84 -1
- package/dist/server/index.js +264 -0
- package/dist/server/index.mjs +265 -1
- package/dist/testing/index.d.mts +37 -0
- package/dist/testing/index.d.ts +37 -0
- package/dist/testing/index.js +33 -0
- package/dist/testing/index.mjs +33 -0
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ALL_SYSTEM_VARIABLES: () => ALL_SYSTEM_VARIABLES,
|
|
34
|
+
AppFileServerProvider: () => AppFileServerProvider,
|
|
34
35
|
AuthenticationError: () => AuthenticationError,
|
|
35
36
|
ConfigurationError: () => ConfigurationError,
|
|
36
37
|
DEFAULT_DATE_FORMATS: () => DEFAULT_DATE_FORMATS,
|
|
@@ -46,6 +47,7 @@ __export(index_exports, {
|
|
|
46
47
|
FileTooLargeError: () => FileTooLargeError,
|
|
47
48
|
GoogleDriveAuth: () => GoogleDriveAuth,
|
|
48
49
|
GoogleDriveModule: () => GoogleDriveModule,
|
|
50
|
+
GoogleDriveProvider: () => GoogleDriveProvider,
|
|
49
51
|
HAZO_FILES_DEFAULT_TABLE_NAME: () => HAZO_FILES_DEFAULT_TABLE_NAME,
|
|
50
52
|
HAZO_FILES_MIGRATION_V2: () => HAZO_FILES_MIGRATION_V2,
|
|
51
53
|
HAZO_FILES_MIGRATION_V3: () => HAZO_FILES_MIGRATION_V3,
|
|
@@ -53,6 +55,7 @@ __export(index_exports, {
|
|
|
53
55
|
HAZO_FILES_NAMING_TABLE_SCHEMA: () => HAZO_FILES_NAMING_TABLE_SCHEMA,
|
|
54
56
|
HAZO_FILES_TABLE_SCHEMA: () => HAZO_FILES_TABLE_SCHEMA,
|
|
55
57
|
HazoFilesError: () => import_hazo_core2.HazoError,
|
|
58
|
+
InMemoryProvider: () => InMemoryProvider,
|
|
56
59
|
InvalidExtensionError: () => InvalidExtensionError,
|
|
57
60
|
InvalidPathError: () => InvalidPathError,
|
|
58
61
|
LLMExtractionService: () => LLMExtractionService,
|
|
@@ -64,6 +67,9 @@ __export(index_exports, {
|
|
|
64
67
|
SYSTEM_COUNTER_VARIABLES: () => SYSTEM_COUNTER_VARIABLES,
|
|
65
68
|
SYSTEM_DATE_VARIABLES: () => SYSTEM_DATE_VARIABLES,
|
|
66
69
|
SYSTEM_FILE_VARIABLES: () => SYSTEM_FILE_VARIABLES,
|
|
70
|
+
StorageCollisionExhausted: () => StorageCollisionExhausted,
|
|
71
|
+
StorageNotConfigured: () => StorageNotConfigured,
|
|
72
|
+
StorageUnavailable: () => StorageUnavailable,
|
|
67
73
|
TrackedFileManager: () => TrackedFileManager,
|
|
68
74
|
UploadExtractService: () => UploadExtractService,
|
|
69
75
|
addExtractionToFileData: () => addExtractionToFileData,
|
|
@@ -20613,6 +20619,19 @@ var StorageCollisionExhausted = class extends Error {
|
|
|
20613
20619
|
this.name = "StorageCollisionExhausted";
|
|
20614
20620
|
}
|
|
20615
20621
|
};
|
|
20622
|
+
var StorageNotConfigured = class extends Error {
|
|
20623
|
+
constructor() {
|
|
20624
|
+
super("Storage provider is not configured for this scope");
|
|
20625
|
+
this.name = "StorageNotConfigured";
|
|
20626
|
+
}
|
|
20627
|
+
};
|
|
20628
|
+
var StorageUnavailable = class extends Error {
|
|
20629
|
+
constructor(reason, message) {
|
|
20630
|
+
super(message);
|
|
20631
|
+
this.reason = reason;
|
|
20632
|
+
this.name = "StorageUnavailable";
|
|
20633
|
+
}
|
|
20634
|
+
};
|
|
20616
20635
|
|
|
20617
20636
|
// src/naming/collision.ts
|
|
20618
20637
|
async function writeWithCollisionRetry(opts) {
|
|
@@ -20646,9 +20665,403 @@ function removeRef(file2, ref_id, removed_at) {
|
|
|
20646
20665
|
function countRefs(file2) {
|
|
20647
20666
|
return file2.file_refs.filter((r) => !r.removed_at).length;
|
|
20648
20667
|
}
|
|
20668
|
+
|
|
20669
|
+
// src/providers/app-file-server.ts
|
|
20670
|
+
var import_node_crypto = require("crypto");
|
|
20671
|
+
var import_node_fs = require("fs");
|
|
20672
|
+
var import_node_path = require("path");
|
|
20673
|
+
var AppFileServerProvider = class {
|
|
20674
|
+
constructor(opts) {
|
|
20675
|
+
this.provider_tag = "app_file_server";
|
|
20676
|
+
this.root = (0, import_node_path.normalize)(opts.root);
|
|
20677
|
+
this.secret = opts.hmac_secret;
|
|
20678
|
+
this.default_ttl = opts.default_ttl_seconds ?? 300;
|
|
20679
|
+
}
|
|
20680
|
+
resolve(path4) {
|
|
20681
|
+
const safe = (0, import_node_path.normalize)(path4).replace(/^([./\\])+/, "");
|
|
20682
|
+
if (safe.includes(`..${import_node_path.sep}`) || safe.startsWith("..")) {
|
|
20683
|
+
throw new Error(`Path escapes root: ${path4}`);
|
|
20684
|
+
}
|
|
20685
|
+
return (0, import_node_path.join)(this.root, safe);
|
|
20686
|
+
}
|
|
20687
|
+
async put(path4, body, opts) {
|
|
20688
|
+
const abs = this.resolve(path4);
|
|
20689
|
+
if (opts?.ifNotExists && (0, import_node_fs.existsSync)(abs)) {
|
|
20690
|
+
throw new Error(`File exists: ${path4}`);
|
|
20691
|
+
}
|
|
20692
|
+
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(abs), { recursive: true });
|
|
20693
|
+
const buf = Buffer.isBuffer(body) ? body : await streamToBuffer(body);
|
|
20694
|
+
(0, import_node_fs.writeFileSync)(abs, buf);
|
|
20695
|
+
return { provider: this.provider_tag, native_id: path4, size: buf.length };
|
|
20696
|
+
}
|
|
20697
|
+
async get(path4) {
|
|
20698
|
+
return (0, import_node_fs.readFileSync)(this.resolve(path4));
|
|
20699
|
+
}
|
|
20700
|
+
async delete(path4) {
|
|
20701
|
+
const abs = this.resolve(path4);
|
|
20702
|
+
if ((0, import_node_fs.existsSync)(abs)) (0, import_node_fs.rmSync)(abs, { force: true });
|
|
20703
|
+
}
|
|
20704
|
+
async exists(path4) {
|
|
20705
|
+
return (0, import_node_fs.existsSync)(this.resolve(path4));
|
|
20706
|
+
}
|
|
20707
|
+
async getSignedUrl(path4, opts) {
|
|
20708
|
+
const ttl = opts?.ttl_seconds ?? this.default_ttl;
|
|
20709
|
+
const exp = Math.floor(Date.now() / 1e3) + ttl;
|
|
20710
|
+
const payload = `${path4}:${exp}`;
|
|
20711
|
+
const sig = (0, import_node_crypto.createHmac)("sha256", this.secret).update(payload).digest("base64url");
|
|
20712
|
+
const token = `${exp}.${sig}`;
|
|
20713
|
+
return `/api/files/serve/${token}/${path4}`;
|
|
20714
|
+
}
|
|
20715
|
+
/** Verify a token produced by `getSignedUrl`. Used by the `/api/files/serve` route. */
|
|
20716
|
+
verifySignedUrl(token, path4) {
|
|
20717
|
+
const [expStr, sig] = token.split(".");
|
|
20718
|
+
const exp = Number(expStr);
|
|
20719
|
+
if (!Number.isFinite(exp) || exp * 1e3 < Date.now()) return false;
|
|
20720
|
+
const expected = (0, import_node_crypto.createHmac)("sha256", this.secret).update(`${path4}:${exp}`).digest("base64url");
|
|
20721
|
+
return sig === expected;
|
|
20722
|
+
}
|
|
20723
|
+
async probe() {
|
|
20724
|
+
try {
|
|
20725
|
+
const test = (0, import_node_path.join)(this.root, ".hazo_probe");
|
|
20726
|
+
(0, import_node_fs.mkdirSync)(this.root, { recursive: true });
|
|
20727
|
+
(0, import_node_fs.writeFileSync)(test, "probe");
|
|
20728
|
+
(0, import_node_fs.statSync)(test);
|
|
20729
|
+
(0, import_node_fs.rmSync)(test, { force: true });
|
|
20730
|
+
return { ok: true };
|
|
20731
|
+
} catch (err) {
|
|
20732
|
+
return { ok: false, error: "write_denied", message: String(err) };
|
|
20733
|
+
}
|
|
20734
|
+
}
|
|
20735
|
+
async list(prefix) {
|
|
20736
|
+
const abs = this.resolve(prefix);
|
|
20737
|
+
if (!(0, import_node_fs.existsSync)(abs)) return [];
|
|
20738
|
+
const stat = (0, import_node_fs.statSync)(abs);
|
|
20739
|
+
if (!stat.isDirectory()) {
|
|
20740
|
+
return [{ path: prefix, name: (0, import_node_path.basename)(prefix), size: stat.size, isDirectory: false }];
|
|
20741
|
+
}
|
|
20742
|
+
const entries = [];
|
|
20743
|
+
this.walkDir(abs, prefix, entries);
|
|
20744
|
+
return entries;
|
|
20745
|
+
}
|
|
20746
|
+
walkDir(absDir, logicalDir, out) {
|
|
20747
|
+
const base = logicalDir.endsWith("/") ? logicalDir : `${logicalDir}/`;
|
|
20748
|
+
for (const item of (0, import_node_fs.readdirSync)(absDir, { withFileTypes: true })) {
|
|
20749
|
+
const logicalPath = `${base}${item.name}`;
|
|
20750
|
+
const absPath = (0, import_node_path.join)(absDir, item.name);
|
|
20751
|
+
if (item.isDirectory()) {
|
|
20752
|
+
out.push({ path: logicalPath, name: item.name, size: 0, isDirectory: true });
|
|
20753
|
+
this.walkDir(absPath, logicalPath, out);
|
|
20754
|
+
} else {
|
|
20755
|
+
const st = (0, import_node_fs.statSync)(absPath);
|
|
20756
|
+
out.push({ path: logicalPath, name: item.name, size: st.size, isDirectory: false });
|
|
20757
|
+
}
|
|
20758
|
+
}
|
|
20759
|
+
}
|
|
20760
|
+
async move(from, to) {
|
|
20761
|
+
const absFrom = this.resolve(from);
|
|
20762
|
+
const absTo = this.resolve(to);
|
|
20763
|
+
if (!(0, import_node_fs.existsSync)(absFrom)) throw new Error(`Not found: ${from}`);
|
|
20764
|
+
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(absTo), { recursive: true });
|
|
20765
|
+
try {
|
|
20766
|
+
(0, import_node_fs.renameSync)(absFrom, absTo);
|
|
20767
|
+
} catch (err) {
|
|
20768
|
+
const e = err;
|
|
20769
|
+
if (e.code === "EXDEV") {
|
|
20770
|
+
(0, import_node_fs.copyFileSync)(absFrom, absTo);
|
|
20771
|
+
(0, import_node_fs.rmSync)(absFrom, { force: true });
|
|
20772
|
+
} else {
|
|
20773
|
+
throw err;
|
|
20774
|
+
}
|
|
20775
|
+
}
|
|
20776
|
+
}
|
|
20777
|
+
async rename(from, to) {
|
|
20778
|
+
return this.move(from, to);
|
|
20779
|
+
}
|
|
20780
|
+
};
|
|
20781
|
+
async function streamToBuffer(s) {
|
|
20782
|
+
const chunks = [];
|
|
20783
|
+
for await (const c of s) chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c));
|
|
20784
|
+
return Buffer.concat(chunks);
|
|
20785
|
+
}
|
|
20786
|
+
|
|
20787
|
+
// src/providers/in-memory.ts
|
|
20788
|
+
var InMemoryProvider = class {
|
|
20789
|
+
constructor() {
|
|
20790
|
+
this.provider_tag = "in_memory";
|
|
20791
|
+
this.store = /* @__PURE__ */ new Map();
|
|
20792
|
+
}
|
|
20793
|
+
async put(path4, body, opts) {
|
|
20794
|
+
if (opts?.ifNotExists && this.store.has(path4)) throw new Error(`File exists: ${path4}`);
|
|
20795
|
+
const buf = Buffer.isBuffer(body) ? body : await streamToBuffer2(body);
|
|
20796
|
+
this.store.set(path4, buf);
|
|
20797
|
+
return { provider: this.provider_tag, native_id: path4, size: buf.length };
|
|
20798
|
+
}
|
|
20799
|
+
async get(path4) {
|
|
20800
|
+
const buf = this.store.get(path4);
|
|
20801
|
+
if (!buf) throw new Error(`Not found: ${path4}`);
|
|
20802
|
+
return buf;
|
|
20803
|
+
}
|
|
20804
|
+
async delete(path4) {
|
|
20805
|
+
this.store.delete(path4);
|
|
20806
|
+
}
|
|
20807
|
+
async exists(path4) {
|
|
20808
|
+
return this.store.has(path4);
|
|
20809
|
+
}
|
|
20810
|
+
async getSignedUrl(path4, _opts) {
|
|
20811
|
+
const buf = this.store.get(path4);
|
|
20812
|
+
if (!buf) throw new Error(`Not found: ${path4}`);
|
|
20813
|
+
return `data:application/octet-stream;base64,${buf.toString("base64")}`;
|
|
20814
|
+
}
|
|
20815
|
+
async probe() {
|
|
20816
|
+
return { ok: true };
|
|
20817
|
+
}
|
|
20818
|
+
async list(prefix) {
|
|
20819
|
+
const base = prefix.replace(/\/$/, "");
|
|
20820
|
+
const matchPrefix = `${base}/`;
|
|
20821
|
+
const entries = [];
|
|
20822
|
+
const seenDirs = /* @__PURE__ */ new Set();
|
|
20823
|
+
for (const [key, buf] of this.store.entries()) {
|
|
20824
|
+
if (key !== base && !key.startsWith(matchPrefix)) continue;
|
|
20825
|
+
const rel = key.startsWith(matchPrefix) ? key.slice(matchPrefix.length) : "";
|
|
20826
|
+
if (!rel) {
|
|
20827
|
+
entries.push({ path: key, name: key.split("/").pop(), size: buf.length, isDirectory: false });
|
|
20828
|
+
continue;
|
|
20829
|
+
}
|
|
20830
|
+
const parts = rel.split("/");
|
|
20831
|
+
for (let i = 1; i < parts.length; i++) {
|
|
20832
|
+
const dirPath = matchPrefix + parts.slice(0, i).join("/");
|
|
20833
|
+
if (!seenDirs.has(dirPath)) {
|
|
20834
|
+
seenDirs.add(dirPath);
|
|
20835
|
+
entries.push({ path: dirPath, name: parts[i - 1], size: 0, isDirectory: true });
|
|
20836
|
+
}
|
|
20837
|
+
}
|
|
20838
|
+
entries.push({ path: key, name: parts[parts.length - 1], size: buf.length, isDirectory: false });
|
|
20839
|
+
}
|
|
20840
|
+
return entries;
|
|
20841
|
+
}
|
|
20842
|
+
async move(from, to) {
|
|
20843
|
+
const buf = this.store.get(from);
|
|
20844
|
+
if (!buf) throw new Error(`Not found: ${from}`);
|
|
20845
|
+
this.store.set(to, buf);
|
|
20846
|
+
this.store.delete(from);
|
|
20847
|
+
}
|
|
20848
|
+
async rename(from, to) {
|
|
20849
|
+
return this.move(from, to);
|
|
20850
|
+
}
|
|
20851
|
+
/** Test-only escape hatch — exposes the internal store for assertions. */
|
|
20852
|
+
snapshot() {
|
|
20853
|
+
return new Map(this.store);
|
|
20854
|
+
}
|
|
20855
|
+
};
|
|
20856
|
+
async function streamToBuffer2(s) {
|
|
20857
|
+
const chunks = [];
|
|
20858
|
+
for await (const c of s) chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c));
|
|
20859
|
+
return Buffer.concat(chunks);
|
|
20860
|
+
}
|
|
20861
|
+
|
|
20862
|
+
// src/providers/google-drive.ts
|
|
20863
|
+
var import_googleapis3 = require("googleapis");
|
|
20864
|
+
var GoogleDriveProvider = class {
|
|
20865
|
+
constructor(opts) {
|
|
20866
|
+
this.provider_tag = "gdrive";
|
|
20867
|
+
let credentials = {};
|
|
20868
|
+
try {
|
|
20869
|
+
credentials = JSON.parse(opts.service_account_json);
|
|
20870
|
+
} catch {
|
|
20871
|
+
}
|
|
20872
|
+
const auth = new import_googleapis3.google.auth.GoogleAuth({
|
|
20873
|
+
credentials,
|
|
20874
|
+
scopes: ["https://www.googleapis.com/auth/drive"]
|
|
20875
|
+
});
|
|
20876
|
+
this.drive = import_googleapis3.google.drive({ version: "v3", auth });
|
|
20877
|
+
this.driveId = opts.shared_drive_id;
|
|
20878
|
+
this.cache = opts.path_cache;
|
|
20879
|
+
}
|
|
20880
|
+
async probe() {
|
|
20881
|
+
try {
|
|
20882
|
+
await this.drive.drives.get({
|
|
20883
|
+
driveId: this.driveId,
|
|
20884
|
+
supportsAllDrives: true
|
|
20885
|
+
});
|
|
20886
|
+
return { ok: true };
|
|
20887
|
+
} catch (err) {
|
|
20888
|
+
const e = err;
|
|
20889
|
+
if (e?.code === 404) return { ok: false, error: "drive_not_shared", message: "SA cannot see Shared Drive" };
|
|
20890
|
+
if (e?.code === 403) return { ok: false, error: "write_denied", message: "SA lacks permission" };
|
|
20891
|
+
return { ok: false, error: "transient", message: String(err) };
|
|
20892
|
+
}
|
|
20893
|
+
}
|
|
20894
|
+
async put(path4, body, opts) {
|
|
20895
|
+
const segments = path4.split("/").filter(Boolean);
|
|
20896
|
+
const filename = segments.pop();
|
|
20897
|
+
const parentId = await this.resolvePath(segments, { create: true });
|
|
20898
|
+
if (opts?.ifNotExists) {
|
|
20899
|
+
const existing = await this.findChild(filename, parentId);
|
|
20900
|
+
if (existing) throw new Error(`File exists: ${path4}`);
|
|
20901
|
+
}
|
|
20902
|
+
const buf = Buffer.isBuffer(body) ? body : await streamToBuffer3(body);
|
|
20903
|
+
const res = await this.drive.files.create({
|
|
20904
|
+
requestBody: {
|
|
20905
|
+
name: filename,
|
|
20906
|
+
parents: [parentId],
|
|
20907
|
+
mimeType: opts?.contentType ?? "application/octet-stream"
|
|
20908
|
+
},
|
|
20909
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20910
|
+
media: { body: buf },
|
|
20911
|
+
fields: "id, name"
|
|
20912
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20913
|
+
});
|
|
20914
|
+
return { provider: this.provider_tag, native_id: res.data.id, size: buf.length };
|
|
20915
|
+
}
|
|
20916
|
+
async get(path4) {
|
|
20917
|
+
const id = await this.lookupFileId(path4);
|
|
20918
|
+
const res = await this.drive.files.get(
|
|
20919
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20920
|
+
{ fileId: id, alt: "media", supportsAllDrives: true },
|
|
20921
|
+
{ responseType: "arraybuffer" }
|
|
20922
|
+
);
|
|
20923
|
+
return Buffer.from(res.data);
|
|
20924
|
+
}
|
|
20925
|
+
async delete(path4) {
|
|
20926
|
+
try {
|
|
20927
|
+
const id = await this.lookupFileId(path4);
|
|
20928
|
+
await this.drive.files.delete({ fileId: id, supportsAllDrives: true });
|
|
20929
|
+
} catch (err) {
|
|
20930
|
+
const e = err;
|
|
20931
|
+
if (e?.code !== 404) throw err;
|
|
20932
|
+
}
|
|
20933
|
+
}
|
|
20934
|
+
async exists(path4) {
|
|
20935
|
+
try {
|
|
20936
|
+
await this.lookupFileId(path4);
|
|
20937
|
+
return true;
|
|
20938
|
+
} catch {
|
|
20939
|
+
return false;
|
|
20940
|
+
}
|
|
20941
|
+
}
|
|
20942
|
+
async getSignedUrl(path4, _opts) {
|
|
20943
|
+
const id = await this.lookupFileId(path4);
|
|
20944
|
+
return `https://drive.google.com/uc?id=${id}&export=download`;
|
|
20945
|
+
}
|
|
20946
|
+
async list(prefix) {
|
|
20947
|
+
const segments = prefix.split("/").filter(Boolean);
|
|
20948
|
+
let parentId;
|
|
20949
|
+
try {
|
|
20950
|
+
parentId = await this.resolvePath(segments, { create: false });
|
|
20951
|
+
} catch {
|
|
20952
|
+
return [];
|
|
20953
|
+
}
|
|
20954
|
+
const res = await this.drive.files.list({
|
|
20955
|
+
q: `'${parentId}' in parents and trashed=false`,
|
|
20956
|
+
driveId: this.driveId,
|
|
20957
|
+
corpora: "drive",
|
|
20958
|
+
includeItemsFromAllDrives: true,
|
|
20959
|
+
fields: "files(id, name, mimeType, size)"
|
|
20960
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20961
|
+
});
|
|
20962
|
+
const files = res.data.files ?? [];
|
|
20963
|
+
const base = prefix.endsWith("/") ? prefix : `${prefix}/`;
|
|
20964
|
+
return files.map((f) => ({
|
|
20965
|
+
path: `${base}${f.name}`,
|
|
20966
|
+
name: f.name,
|
|
20967
|
+
size: Number(f.size ?? 0),
|
|
20968
|
+
isDirectory: f.mimeType === "application/vnd.google-apps.folder"
|
|
20969
|
+
}));
|
|
20970
|
+
}
|
|
20971
|
+
async move(from, to) {
|
|
20972
|
+
const id = await this.lookupFileId(from);
|
|
20973
|
+
const fromSegs = from.split("/").filter(Boolean);
|
|
20974
|
+
fromSegs.pop();
|
|
20975
|
+
const toSegs = to.split("/").filter(Boolean);
|
|
20976
|
+
const newName = toSegs.pop();
|
|
20977
|
+
const oldParentId = await this.resolvePath(fromSegs, { create: false });
|
|
20978
|
+
const newParentId = await this.resolvePath(toSegs, { create: true });
|
|
20979
|
+
await this.drive.files.update({
|
|
20980
|
+
fileId: id,
|
|
20981
|
+
addParents: newParentId,
|
|
20982
|
+
removeParents: oldParentId,
|
|
20983
|
+
requestBody: { name: newName },
|
|
20984
|
+
supportsAllDrives: true,
|
|
20985
|
+
fields: "id, parents"
|
|
20986
|
+
});
|
|
20987
|
+
await this.cache.invalidate(from);
|
|
20988
|
+
}
|
|
20989
|
+
async rename(from, to) {
|
|
20990
|
+
const id = await this.lookupFileId(from);
|
|
20991
|
+
const segs = to.split("/").filter(Boolean);
|
|
20992
|
+
const newName = segs[segs.length - 1];
|
|
20993
|
+
await this.drive.files.update({
|
|
20994
|
+
fileId: id,
|
|
20995
|
+
requestBody: { name: newName },
|
|
20996
|
+
supportsAllDrives: true,
|
|
20997
|
+
fields: "id, name"
|
|
20998
|
+
});
|
|
20999
|
+
}
|
|
21000
|
+
async resolvePath(segments, opts) {
|
|
21001
|
+
let parentId = this.driveId;
|
|
21002
|
+
const accumulated = [];
|
|
21003
|
+
for (const segment of segments) {
|
|
21004
|
+
accumulated.push(segment);
|
|
21005
|
+
const cacheKey = accumulated.join("/");
|
|
21006
|
+
const cached2 = await this.cache.lookup(cacheKey);
|
|
21007
|
+
if (cached2) {
|
|
21008
|
+
parentId = cached2;
|
|
21009
|
+
continue;
|
|
21010
|
+
}
|
|
21011
|
+
let found = await this.findChild(segment, parentId, "application/vnd.google-apps.folder");
|
|
21012
|
+
if (!found && opts.create) {
|
|
21013
|
+
const created = await this.drive.files.create({
|
|
21014
|
+
requestBody: {
|
|
21015
|
+
name: segment,
|
|
21016
|
+
parents: [parentId],
|
|
21017
|
+
mimeType: "application/vnd.google-apps.folder"
|
|
21018
|
+
},
|
|
21019
|
+
fields: "id"
|
|
21020
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21021
|
+
});
|
|
21022
|
+
found = created.data.id;
|
|
21023
|
+
}
|
|
21024
|
+
if (!found) throw new Error(`Folder not found and create=false: ${cacheKey}`);
|
|
21025
|
+
await this.cache.write(cacheKey, found);
|
|
21026
|
+
parentId = found;
|
|
21027
|
+
}
|
|
21028
|
+
return parentId;
|
|
21029
|
+
}
|
|
21030
|
+
async findChild(name, parentId, mimeType) {
|
|
21031
|
+
const q = [
|
|
21032
|
+
`name='${name.replace(/'/g, "\\'")}'`,
|
|
21033
|
+
`'${parentId}' in parents`,
|
|
21034
|
+
`trashed=false`
|
|
21035
|
+
];
|
|
21036
|
+
if (mimeType) q.push(`mimeType='${mimeType}'`);
|
|
21037
|
+
const res = await this.drive.files.list({
|
|
21038
|
+
q: q.join(" and "),
|
|
21039
|
+
driveId: this.driveId,
|
|
21040
|
+
corpora: "drive",
|
|
21041
|
+
includeItemsFromAllDrives: true,
|
|
21042
|
+
fields: "files(id, name)"
|
|
21043
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21044
|
+
});
|
|
21045
|
+
return res.data.files?.[0]?.id ?? null;
|
|
21046
|
+
}
|
|
21047
|
+
async lookupFileId(path4) {
|
|
21048
|
+
const segments = path4.split("/").filter(Boolean);
|
|
21049
|
+
const filename = segments.pop();
|
|
21050
|
+
const parentId = await this.resolvePath(segments, { create: false });
|
|
21051
|
+
const id = await this.findChild(filename, parentId);
|
|
21052
|
+
if (!id) throw Object.assign(new Error(`Not found: ${path4}`), { code: 404 });
|
|
21053
|
+
return id;
|
|
21054
|
+
}
|
|
21055
|
+
};
|
|
21056
|
+
async function streamToBuffer3(s) {
|
|
21057
|
+
const chunks = [];
|
|
21058
|
+
for await (const c of s) chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c));
|
|
21059
|
+
return Buffer.concat(chunks);
|
|
21060
|
+
}
|
|
20649
21061
|
// Annotate the CommonJS export names for ESM import in node:
|
|
20650
21062
|
0 && (module.exports = {
|
|
20651
21063
|
ALL_SYSTEM_VARIABLES,
|
|
21064
|
+
AppFileServerProvider,
|
|
20652
21065
|
AuthenticationError,
|
|
20653
21066
|
ConfigurationError,
|
|
20654
21067
|
DEFAULT_DATE_FORMATS,
|
|
@@ -20664,6 +21077,7 @@ function countRefs(file2) {
|
|
|
20664
21077
|
FileTooLargeError,
|
|
20665
21078
|
GoogleDriveAuth,
|
|
20666
21079
|
GoogleDriveModule,
|
|
21080
|
+
GoogleDriveProvider,
|
|
20667
21081
|
HAZO_FILES_DEFAULT_TABLE_NAME,
|
|
20668
21082
|
HAZO_FILES_MIGRATION_V2,
|
|
20669
21083
|
HAZO_FILES_MIGRATION_V3,
|
|
@@ -20671,6 +21085,7 @@ function countRefs(file2) {
|
|
|
20671
21085
|
HAZO_FILES_NAMING_TABLE_SCHEMA,
|
|
20672
21086
|
HAZO_FILES_TABLE_SCHEMA,
|
|
20673
21087
|
HazoFilesError,
|
|
21088
|
+
InMemoryProvider,
|
|
20674
21089
|
InvalidExtensionError,
|
|
20675
21090
|
InvalidPathError,
|
|
20676
21091
|
LLMExtractionService,
|
|
@@ -20682,6 +21097,9 @@ function countRefs(file2) {
|
|
|
20682
21097
|
SYSTEM_COUNTER_VARIABLES,
|
|
20683
21098
|
SYSTEM_DATE_VARIABLES,
|
|
20684
21099
|
SYSTEM_FILE_VARIABLES,
|
|
21100
|
+
StorageCollisionExhausted,
|
|
21101
|
+
StorageNotConfigured,
|
|
21102
|
+
StorageUnavailable,
|
|
20685
21103
|
TrackedFileManager,
|
|
20686
21104
|
UploadExtractService,
|
|
20687
21105
|
addExtractionToFileData,
|