hazo_files 1.4.4 → 1.4.5

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/README.md CHANGED
@@ -45,13 +45,20 @@ For the NamingRuleConfigurator component (drag-and-drop interface), also install
45
45
  npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
46
46
  ```
47
47
 
48
+ For cloud storage providers (install only what you need):
49
+
50
+ ```bash
51
+ npm install googleapis # Google Drive support
52
+ npm install dropbox # Dropbox support
53
+ ```
54
+
48
55
  For database tracking and LLM extraction features (optional):
49
56
 
50
57
  ```bash
51
58
  npm install hazo_connect # Database tracking
52
59
  npm install hazo_llm_api # LLM document extraction
53
60
  npm install server-only # Server-side safety (recommended)
54
- # Note: xxhash-wasm is included automatically as a dependency
61
+ npm install xxhash-wasm # File change detection (optional)
55
62
  ```
56
63
 
57
64
  ### Tailwind CSS v4 Setup (Required for UI Components)
@@ -1,8 +1,9 @@
1
1
  ; Hazo Files Configuration
2
2
  ; This file configures the file management system
3
+ ; Copy to hazo_files_config.ini and fill in your values
3
4
 
4
5
  [general]
5
- ; Available providers: local, google_drive
6
+ ; Available providers: local, google_drive, dropbox
6
7
  provider = local
7
8
 
8
9
  [local]
@@ -25,6 +26,18 @@ access_token =
25
26
  ; Optional: Root folder ID to use as base (empty = root of Drive)
26
27
  root_folder_id =
27
28
 
29
+ [dropbox]
30
+ ; Dropbox OAuth credentials
31
+ ; These can also be set via environment variables:
32
+ ; HAZO_DROPBOX_CLIENT_ID, HAZO_DROPBOX_CLIENT_SECRET, etc.
33
+ client_id =
34
+ client_secret =
35
+ redirect_uri = http://localhost:3000/api/auth/callback/dropbox
36
+ refresh_token =
37
+ access_token =
38
+ ; Optional: Root folder path within Dropbox (empty = root)
39
+ root_path =
40
+
28
41
  [naming]
29
42
  ; Comma-separated list of supported date format tokens for naming rules
30
43
  ; Available: YYYY, YY, MM, M, DD, D, MMM, MMMM, YYYY-MM-DD, YYYY-MMM-DD, DD-MM-YYYY, MM-DD-YYYY
package/dist/index.d.mts CHANGED
@@ -685,9 +685,9 @@ declare class FileManager {
685
685
  */
686
686
  initialize(config?: HazoFilesConfig): Promise<void>;
687
687
  /**
688
- * Initialize synchronously (uses sync config loading)
688
+ * @deprecated Storage modules require async initialization. Use initialize() instead.
689
689
  */
690
- initializeSync(config?: HazoFilesConfig): void;
690
+ initializeSync(_config?: HazoFilesConfig): void;
691
691
  /**
692
692
  * Check if manager is initialized
693
693
  */
package/dist/index.d.ts CHANGED
@@ -685,9 +685,9 @@ declare class FileManager {
685
685
  */
686
686
  initialize(config?: HazoFilesConfig): Promise<void>;
687
687
  /**
688
- * Initialize synchronously (uses sync config loading)
688
+ * @deprecated Storage modules require async initialization. Use initialize() instead.
689
689
  */
690
- initializeSync(config?: HazoFilesConfig): void;
690
+ initializeSync(_config?: HazoFilesConfig): void;
691
691
  /**
692
692
  * Check if manager is initialized
693
693
  */
package/dist/index.js CHANGED
@@ -1096,6 +1096,9 @@ var LocalStorageModule = class extends BaseStorageModule {
1096
1096
  if (!stats || stats.isDirectory()) {
1097
1097
  throw new FileNotFoundError(virtualPath);
1098
1098
  }
1099
+ if (newName.includes("/") || newName.includes("\\") || newName.includes("..")) {
1100
+ throw new InvalidPathError(newName, 'Name must not contain path separators or ".."');
1101
+ }
1099
1102
  this.validateExtension(newName);
1100
1103
  const parentDir = path2.dirname(fullPath);
1101
1104
  const newFullPath = path2.join(parentDir, newName);
@@ -1110,7 +1113,7 @@ var LocalStorageModule = class extends BaseStorageModule {
1110
1113
  const item = await this.statToItem(newFullPath, newStats);
1111
1114
  return this.successResult(item);
1112
1115
  } catch (error) {
1113
- if (error instanceof FileNotFoundError || error instanceof FileExistsError || error instanceof InvalidExtensionError) {
1116
+ if (error instanceof FileNotFoundError || error instanceof FileExistsError || error instanceof InvalidExtensionError || error instanceof InvalidPathError) {
1114
1117
  return this.errorResult(error.message);
1115
1118
  }
1116
1119
  return this.errorResult(`Failed to rename file: ${error.message}`);
@@ -1124,6 +1127,9 @@ var LocalStorageModule = class extends BaseStorageModule {
1124
1127
  if (!stats || !stats.isDirectory()) {
1125
1128
  throw new DirectoryNotFoundError(virtualPath);
1126
1129
  }
1130
+ if (newName.includes("/") || newName.includes("\\") || newName.includes("..")) {
1131
+ throw new InvalidPathError(newName, 'Name must not contain path separators or ".."');
1132
+ }
1127
1133
  const parentDir = path2.dirname(fullPath);
1128
1134
  const newFullPath = path2.join(parentDir, newName);
1129
1135
  if (!options.overwrite) {
@@ -1137,7 +1143,7 @@ var LocalStorageModule = class extends BaseStorageModule {
1137
1143
  const item = await this.statToItem(newFullPath, newStats);
1138
1144
  return this.successResult(item);
1139
1145
  } catch (error) {
1140
- if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError) {
1146
+ if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError || error instanceof InvalidPathError) {
1141
1147
  return this.errorResult(error.message);
1142
1148
  }
1143
1149
  return this.errorResult(`Failed to rename folder: ${error.message}`);
@@ -1279,9 +1285,12 @@ var GoogleDriveAuth = class {
1279
1285
  */
1280
1286
  async exchangeCodeForTokens(code) {
1281
1287
  const { tokens } = await this.oauth2Client.getToken(code);
1288
+ if (!tokens.access_token) {
1289
+ throw new Error("No access token received from Google OAuth");
1290
+ }
1282
1291
  this.tokens = {
1283
1292
  accessToken: tokens.access_token,
1284
- refreshToken: tokens.refresh_token,
1293
+ refreshToken: tokens.refresh_token ?? this.tokens?.refreshToken ?? "",
1285
1294
  expiryDate: tokens.expiry_date || void 0,
1286
1295
  scope: tokens.scope || void 0
1287
1296
  };
@@ -1466,7 +1475,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1466
1475
  const segments = normalized.split("/").filter(Boolean);
1467
1476
  let currentParentId = this.rootFolderId;
1468
1477
  for (const segment of segments) {
1469
- const query = `name='${segment}' and '${currentParentId}' in parents and trashed=false`;
1478
+ const escapedSegment = segment.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1479
+ const query = `name='${escapedSegment}' and '${currentParentId}' in parents and trashed=false`;
1470
1480
  const response = await this.drive.files.list({
1471
1481
  q: query,
1472
1482
  fields: "files(id, name, mimeType)",
@@ -1534,7 +1544,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1534
1544
  if (!parentId) {
1535
1545
  throw new DirectoryNotFoundError(parentPath);
1536
1546
  }
1537
- const existingQuery = `name='${folderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;
1547
+ const escapedFolderName = folderName.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1548
+ const existingQuery = `name='${escapedFolderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;
1538
1549
  const existingResponse = await this.drive.files.list({
1539
1550
  q: existingQuery,
1540
1551
  fields: "files(id)",
@@ -1597,7 +1608,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1597
1608
  throw new DirectoryNotFoundError(parentPath);
1598
1609
  }
1599
1610
  if (!options.overwrite) {
1600
- const existingQuery = `name='${fileName}' and '${parentId}' in parents and trashed=false`;
1611
+ const escapedFileName = fileName.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1612
+ const existingQuery = `name='${escapedFileName}' and '${parentId}' in parents and trashed=false`;
1601
1613
  const existingResponse = await this.drive.files.list({
1602
1614
  q: existingQuery,
1603
1615
  fields: "files(id)",
@@ -2552,20 +2564,12 @@ var FileManager = class {
2552
2564
  this.initialized = true;
2553
2565
  }
2554
2566
  /**
2555
- * Initialize synchronously (uses sync config loading)
2567
+ * @deprecated Storage modules require async initialization. Use initialize() instead.
2556
2568
  */
2557
- initializeSync(config) {
2558
- if (this.initialized) {
2559
- return;
2560
- }
2561
- if (config) {
2562
- this.config = config;
2563
- } else if (this.options.config) {
2564
- this.config = this.options.config;
2565
- } else {
2566
- this.config = loadConfig(this.options.configPath);
2567
- }
2568
- this.module = createModule(this.config.provider);
2569
+ initializeSync(_config) {
2570
+ throw new Error(
2571
+ "initializeSync is not supported. Storage modules require async initialization. Use initialize() instead."
2572
+ );
2569
2573
  }
2570
2574
  /**
2571
2575
  * Check if manager is initialized
@@ -4007,7 +4011,7 @@ var TrackedFileManager = class extends FileManager {
4007
4011
  }
4008
4012
  let buffer;
4009
4013
  if (typeof downloadResult.data === "string") {
4010
- buffer = Buffer.from(downloadResult.data, "utf-8");
4014
+ return null;
4011
4015
  } else if (downloadResult.data instanceof Buffer) {
4012
4016
  buffer = downloadResult.data;
4013
4017
  } else {
@@ -5322,7 +5326,13 @@ var HAZO_FILES_TABLE_SCHEMA = {
5322
5326
  "content_tag"
5323
5327
  ]
5324
5328
  };
5329
+ function validateTableName(tableName) {
5330
+ if (!/^[a-z_][a-z0-9_]*$/i.test(tableName)) {
5331
+ throw new Error(`Invalid table name: ${tableName}`);
5332
+ }
5333
+ }
5325
5334
  function getSchemaForTable(tableName, dbType) {
5335
+ validateTableName(tableName);
5326
5336
  const schema = HAZO_FILES_TABLE_SCHEMA[dbType];
5327
5337
  const defaultName = HAZO_FILES_TABLE_SCHEMA.tableName;
5328
5338
  return {
@@ -5392,6 +5402,7 @@ WHERE file_refs IS NULL OR ref_count IS NULL OR status IS NULL`
5392
5402
  ]
5393
5403
  };
5394
5404
  function getMigrationForTable(tableName, dbType) {
5405
+ validateTableName(tableName);
5395
5406
  const migration = HAZO_FILES_MIGRATION_V2[dbType];
5396
5407
  const defaultName = HAZO_FILES_MIGRATION_V2.tableName;
5397
5408
  return {
@@ -5451,6 +5462,7 @@ var HAZO_FILES_NAMING_TABLE_SCHEMA = {
5451
5462
  ]
5452
5463
  };
5453
5464
  function getNamingSchemaForTable(tableName, dbType) {
5465
+ validateTableName(tableName);
5454
5466
  const schema = HAZO_FILES_NAMING_TABLE_SCHEMA[dbType];
5455
5467
  const defaultName = HAZO_FILES_NAMING_TABLE_SCHEMA.tableName;
5456
5468
  return {
@@ -5487,6 +5499,7 @@ var HAZO_FILES_MIGRATION_V3 = {
5487
5499
  ]
5488
5500
  };
5489
5501
  function getMigrationV3ForTable(tableName, dbType) {
5502
+ validateTableName(tableName);
5490
5503
  const migration = HAZO_FILES_MIGRATION_V3[dbType];
5491
5504
  const defaultName = HAZO_FILES_MIGRATION_V3.tableName;
5492
5505
  return {
package/dist/index.mjs CHANGED
@@ -913,6 +913,9 @@ var LocalStorageModule = class extends BaseStorageModule {
913
913
  if (!stats || stats.isDirectory()) {
914
914
  throw new FileNotFoundError(virtualPath);
915
915
  }
916
+ if (newName.includes("/") || newName.includes("\\") || newName.includes("..")) {
917
+ throw new InvalidPathError(newName, 'Name must not contain path separators or ".."');
918
+ }
916
919
  this.validateExtension(newName);
917
920
  const parentDir = path2.dirname(fullPath);
918
921
  const newFullPath = path2.join(parentDir, newName);
@@ -927,7 +930,7 @@ var LocalStorageModule = class extends BaseStorageModule {
927
930
  const item = await this.statToItem(newFullPath, newStats);
928
931
  return this.successResult(item);
929
932
  } catch (error) {
930
- if (error instanceof FileNotFoundError || error instanceof FileExistsError || error instanceof InvalidExtensionError) {
933
+ if (error instanceof FileNotFoundError || error instanceof FileExistsError || error instanceof InvalidExtensionError || error instanceof InvalidPathError) {
931
934
  return this.errorResult(error.message);
932
935
  }
933
936
  return this.errorResult(`Failed to rename file: ${error.message}`);
@@ -941,6 +944,9 @@ var LocalStorageModule = class extends BaseStorageModule {
941
944
  if (!stats || !stats.isDirectory()) {
942
945
  throw new DirectoryNotFoundError(virtualPath);
943
946
  }
947
+ if (newName.includes("/") || newName.includes("\\") || newName.includes("..")) {
948
+ throw new InvalidPathError(newName, 'Name must not contain path separators or ".."');
949
+ }
944
950
  const parentDir = path2.dirname(fullPath);
945
951
  const newFullPath = path2.join(parentDir, newName);
946
952
  if (!options.overwrite) {
@@ -954,7 +960,7 @@ var LocalStorageModule = class extends BaseStorageModule {
954
960
  const item = await this.statToItem(newFullPath, newStats);
955
961
  return this.successResult(item);
956
962
  } catch (error) {
957
- if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError) {
963
+ if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError || error instanceof InvalidPathError) {
958
964
  return this.errorResult(error.message);
959
965
  }
960
966
  return this.errorResult(`Failed to rename folder: ${error.message}`);
@@ -1096,9 +1102,12 @@ var GoogleDriveAuth = class {
1096
1102
  */
1097
1103
  async exchangeCodeForTokens(code) {
1098
1104
  const { tokens } = await this.oauth2Client.getToken(code);
1105
+ if (!tokens.access_token) {
1106
+ throw new Error("No access token received from Google OAuth");
1107
+ }
1099
1108
  this.tokens = {
1100
1109
  accessToken: tokens.access_token,
1101
- refreshToken: tokens.refresh_token,
1110
+ refreshToken: tokens.refresh_token ?? this.tokens?.refreshToken ?? "",
1102
1111
  expiryDate: tokens.expiry_date || void 0,
1103
1112
  scope: tokens.scope || void 0
1104
1113
  };
@@ -1283,7 +1292,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1283
1292
  const segments = normalized.split("/").filter(Boolean);
1284
1293
  let currentParentId = this.rootFolderId;
1285
1294
  for (const segment of segments) {
1286
- const query = `name='${segment}' and '${currentParentId}' in parents and trashed=false`;
1295
+ const escapedSegment = segment.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1296
+ const query = `name='${escapedSegment}' and '${currentParentId}' in parents and trashed=false`;
1287
1297
  const response = await this.drive.files.list({
1288
1298
  q: query,
1289
1299
  fields: "files(id, name, mimeType)",
@@ -1351,7 +1361,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1351
1361
  if (!parentId) {
1352
1362
  throw new DirectoryNotFoundError(parentPath);
1353
1363
  }
1354
- const existingQuery = `name='${folderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;
1364
+ const escapedFolderName = folderName.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1365
+ const existingQuery = `name='${escapedFolderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;
1355
1366
  const existingResponse = await this.drive.files.list({
1356
1367
  q: existingQuery,
1357
1368
  fields: "files(id)",
@@ -1414,7 +1425,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1414
1425
  throw new DirectoryNotFoundError(parentPath);
1415
1426
  }
1416
1427
  if (!options.overwrite) {
1417
- const existingQuery = `name='${fileName}' and '${parentId}' in parents and trashed=false`;
1428
+ const escapedFileName = fileName.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1429
+ const existingQuery = `name='${escapedFileName}' and '${parentId}' in parents and trashed=false`;
1418
1430
  const existingResponse = await this.drive.files.list({
1419
1431
  q: existingQuery,
1420
1432
  fields: "files(id)",
@@ -2369,20 +2381,12 @@ var FileManager = class {
2369
2381
  this.initialized = true;
2370
2382
  }
2371
2383
  /**
2372
- * Initialize synchronously (uses sync config loading)
2384
+ * @deprecated Storage modules require async initialization. Use initialize() instead.
2373
2385
  */
2374
- initializeSync(config) {
2375
- if (this.initialized) {
2376
- return;
2377
- }
2378
- if (config) {
2379
- this.config = config;
2380
- } else if (this.options.config) {
2381
- this.config = this.options.config;
2382
- } else {
2383
- this.config = loadConfig(this.options.configPath);
2384
- }
2385
- this.module = createModule(this.config.provider);
2386
+ initializeSync(_config) {
2387
+ throw new Error(
2388
+ "initializeSync is not supported. Storage modules require async initialization. Use initialize() instead."
2389
+ );
2386
2390
  }
2387
2391
  /**
2388
2392
  * Check if manager is initialized
@@ -3824,7 +3828,7 @@ var TrackedFileManager = class extends FileManager {
3824
3828
  }
3825
3829
  let buffer;
3826
3830
  if (typeof downloadResult.data === "string") {
3827
- buffer = Buffer.from(downloadResult.data, "utf-8");
3831
+ return null;
3828
3832
  } else if (downloadResult.data instanceof Buffer) {
3829
3833
  buffer = downloadResult.data;
3830
3834
  } else {
@@ -5139,7 +5143,13 @@ var HAZO_FILES_TABLE_SCHEMA = {
5139
5143
  "content_tag"
5140
5144
  ]
5141
5145
  };
5146
+ function validateTableName(tableName) {
5147
+ if (!/^[a-z_][a-z0-9_]*$/i.test(tableName)) {
5148
+ throw new Error(`Invalid table name: ${tableName}`);
5149
+ }
5150
+ }
5142
5151
  function getSchemaForTable(tableName, dbType) {
5152
+ validateTableName(tableName);
5143
5153
  const schema = HAZO_FILES_TABLE_SCHEMA[dbType];
5144
5154
  const defaultName = HAZO_FILES_TABLE_SCHEMA.tableName;
5145
5155
  return {
@@ -5209,6 +5219,7 @@ WHERE file_refs IS NULL OR ref_count IS NULL OR status IS NULL`
5209
5219
  ]
5210
5220
  };
5211
5221
  function getMigrationForTable(tableName, dbType) {
5222
+ validateTableName(tableName);
5212
5223
  const migration = HAZO_FILES_MIGRATION_V2[dbType];
5213
5224
  const defaultName = HAZO_FILES_MIGRATION_V2.tableName;
5214
5225
  return {
@@ -5268,6 +5279,7 @@ var HAZO_FILES_NAMING_TABLE_SCHEMA = {
5268
5279
  ]
5269
5280
  };
5270
5281
  function getNamingSchemaForTable(tableName, dbType) {
5282
+ validateTableName(tableName);
5271
5283
  const schema = HAZO_FILES_NAMING_TABLE_SCHEMA[dbType];
5272
5284
  const defaultName = HAZO_FILES_NAMING_TABLE_SCHEMA.tableName;
5273
5285
  return {
@@ -5304,6 +5316,7 @@ var HAZO_FILES_MIGRATION_V3 = {
5304
5316
  ]
5305
5317
  };
5306
5318
  function getMigrationV3ForTable(tableName, dbType) {
5319
+ validateTableName(tableName);
5307
5320
  const migration = HAZO_FILES_MIGRATION_V3[dbType];
5308
5321
  const defaultName = HAZO_FILES_MIGRATION_V3.tableName;
5309
5322
  return {
@@ -685,9 +685,9 @@ declare class FileManager {
685
685
  */
686
686
  initialize(config?: HazoFilesConfig): Promise<void>;
687
687
  /**
688
- * Initialize synchronously (uses sync config loading)
688
+ * @deprecated Storage modules require async initialization. Use initialize() instead.
689
689
  */
690
- initializeSync(config?: HazoFilesConfig): void;
690
+ initializeSync(_config?: HazoFilesConfig): void;
691
691
  /**
692
692
  * Check if manager is initialized
693
693
  */
@@ -685,9 +685,9 @@ declare class FileManager {
685
685
  */
686
686
  initialize(config?: HazoFilesConfig): Promise<void>;
687
687
  /**
688
- * Initialize synchronously (uses sync config loading)
688
+ * @deprecated Storage modules require async initialization. Use initialize() instead.
689
689
  */
690
- initializeSync(config?: HazoFilesConfig): void;
690
+ initializeSync(_config?: HazoFilesConfig): void;
691
691
  /**
692
692
  * Check if manager is initialized
693
693
  */
@@ -1098,6 +1098,9 @@ var LocalStorageModule = class extends BaseStorageModule {
1098
1098
  if (!stats || stats.isDirectory()) {
1099
1099
  throw new FileNotFoundError(virtualPath);
1100
1100
  }
1101
+ if (newName.includes("/") || newName.includes("\\") || newName.includes("..")) {
1102
+ throw new InvalidPathError(newName, 'Name must not contain path separators or ".."');
1103
+ }
1101
1104
  this.validateExtension(newName);
1102
1105
  const parentDir = path2.dirname(fullPath);
1103
1106
  const newFullPath = path2.join(parentDir, newName);
@@ -1112,7 +1115,7 @@ var LocalStorageModule = class extends BaseStorageModule {
1112
1115
  const item = await this.statToItem(newFullPath, newStats);
1113
1116
  return this.successResult(item);
1114
1117
  } catch (error) {
1115
- if (error instanceof FileNotFoundError || error instanceof FileExistsError || error instanceof InvalidExtensionError) {
1118
+ if (error instanceof FileNotFoundError || error instanceof FileExistsError || error instanceof InvalidExtensionError || error instanceof InvalidPathError) {
1116
1119
  return this.errorResult(error.message);
1117
1120
  }
1118
1121
  return this.errorResult(`Failed to rename file: ${error.message}`);
@@ -1126,6 +1129,9 @@ var LocalStorageModule = class extends BaseStorageModule {
1126
1129
  if (!stats || !stats.isDirectory()) {
1127
1130
  throw new DirectoryNotFoundError(virtualPath);
1128
1131
  }
1132
+ if (newName.includes("/") || newName.includes("\\") || newName.includes("..")) {
1133
+ throw new InvalidPathError(newName, 'Name must not contain path separators or ".."');
1134
+ }
1129
1135
  const parentDir = path2.dirname(fullPath);
1130
1136
  const newFullPath = path2.join(parentDir, newName);
1131
1137
  if (!options.overwrite) {
@@ -1139,7 +1145,7 @@ var LocalStorageModule = class extends BaseStorageModule {
1139
1145
  const item = await this.statToItem(newFullPath, newStats);
1140
1146
  return this.successResult(item);
1141
1147
  } catch (error) {
1142
- if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError) {
1148
+ if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError || error instanceof InvalidPathError) {
1143
1149
  return this.errorResult(error.message);
1144
1150
  }
1145
1151
  return this.errorResult(`Failed to rename folder: ${error.message}`);
@@ -1281,9 +1287,12 @@ var GoogleDriveAuth = class {
1281
1287
  */
1282
1288
  async exchangeCodeForTokens(code) {
1283
1289
  const { tokens } = await this.oauth2Client.getToken(code);
1290
+ if (!tokens.access_token) {
1291
+ throw new Error("No access token received from Google OAuth");
1292
+ }
1284
1293
  this.tokens = {
1285
1294
  accessToken: tokens.access_token,
1286
- refreshToken: tokens.refresh_token,
1295
+ refreshToken: tokens.refresh_token ?? this.tokens?.refreshToken ?? "",
1287
1296
  expiryDate: tokens.expiry_date || void 0,
1288
1297
  scope: tokens.scope || void 0
1289
1298
  };
@@ -1468,7 +1477,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1468
1477
  const segments = normalized.split("/").filter(Boolean);
1469
1478
  let currentParentId = this.rootFolderId;
1470
1479
  for (const segment of segments) {
1471
- const query = `name='${segment}' and '${currentParentId}' in parents and trashed=false`;
1480
+ const escapedSegment = segment.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1481
+ const query = `name='${escapedSegment}' and '${currentParentId}' in parents and trashed=false`;
1472
1482
  const response = await this.drive.files.list({
1473
1483
  q: query,
1474
1484
  fields: "files(id, name, mimeType)",
@@ -1536,7 +1546,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1536
1546
  if (!parentId) {
1537
1547
  throw new DirectoryNotFoundError(parentPath);
1538
1548
  }
1539
- const existingQuery = `name='${folderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;
1549
+ const escapedFolderName = folderName.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1550
+ const existingQuery = `name='${escapedFolderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;
1540
1551
  const existingResponse = await this.drive.files.list({
1541
1552
  q: existingQuery,
1542
1553
  fields: "files(id)",
@@ -1599,7 +1610,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1599
1610
  throw new DirectoryNotFoundError(parentPath);
1600
1611
  }
1601
1612
  if (!options.overwrite) {
1602
- const existingQuery = `name='${fileName}' and '${parentId}' in parents and trashed=false`;
1613
+ const escapedFileName = fileName.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1614
+ const existingQuery = `name='${escapedFileName}' and '${parentId}' in parents and trashed=false`;
1603
1615
  const existingResponse = await this.drive.files.list({
1604
1616
  q: existingQuery,
1605
1617
  fields: "files(id)",
@@ -2554,20 +2566,12 @@ var FileManager = class {
2554
2566
  this.initialized = true;
2555
2567
  }
2556
2568
  /**
2557
- * Initialize synchronously (uses sync config loading)
2569
+ * @deprecated Storage modules require async initialization. Use initialize() instead.
2558
2570
  */
2559
- initializeSync(config) {
2560
- if (this.initialized) {
2561
- return;
2562
- }
2563
- if (config) {
2564
- this.config = config;
2565
- } else if (this.options.config) {
2566
- this.config = this.options.config;
2567
- } else {
2568
- this.config = loadConfig(this.options.configPath);
2569
- }
2570
- this.module = createModule(this.config.provider);
2571
+ initializeSync(_config) {
2572
+ throw new Error(
2573
+ "initializeSync is not supported. Storage modules require async initialization. Use initialize() instead."
2574
+ );
2571
2575
  }
2572
2576
  /**
2573
2577
  * Check if manager is initialized
@@ -4009,7 +4013,7 @@ var TrackedFileManager = class extends FileManager {
4009
4013
  }
4010
4014
  let buffer;
4011
4015
  if (typeof downloadResult.data === "string") {
4012
- buffer = Buffer.from(downloadResult.data, "utf-8");
4016
+ return null;
4013
4017
  } else if (downloadResult.data instanceof Buffer) {
4014
4018
  buffer = downloadResult.data;
4015
4019
  } else {
@@ -5392,7 +5396,13 @@ var HAZO_FILES_TABLE_SCHEMA = {
5392
5396
  "content_tag"
5393
5397
  ]
5394
5398
  };
5399
+ function validateTableName(tableName) {
5400
+ if (!/^[a-z_][a-z0-9_]*$/i.test(tableName)) {
5401
+ throw new Error(`Invalid table name: ${tableName}`);
5402
+ }
5403
+ }
5395
5404
  function getSchemaForTable(tableName, dbType) {
5405
+ validateTableName(tableName);
5396
5406
  const schema = HAZO_FILES_TABLE_SCHEMA[dbType];
5397
5407
  const defaultName = HAZO_FILES_TABLE_SCHEMA.tableName;
5398
5408
  return {
@@ -5462,6 +5472,7 @@ WHERE file_refs IS NULL OR ref_count IS NULL OR status IS NULL`
5462
5472
  ]
5463
5473
  };
5464
5474
  function getMigrationForTable(tableName, dbType) {
5475
+ validateTableName(tableName);
5465
5476
  const migration = HAZO_FILES_MIGRATION_V2[dbType];
5466
5477
  const defaultName = HAZO_FILES_MIGRATION_V2.tableName;
5467
5478
  return {
@@ -5521,6 +5532,7 @@ var HAZO_FILES_NAMING_TABLE_SCHEMA = {
5521
5532
  ]
5522
5533
  };
5523
5534
  function getNamingSchemaForTable(tableName, dbType) {
5535
+ validateTableName(tableName);
5524
5536
  const schema = HAZO_FILES_NAMING_TABLE_SCHEMA[dbType];
5525
5537
  const defaultName = HAZO_FILES_NAMING_TABLE_SCHEMA.tableName;
5526
5538
  return {
@@ -5557,6 +5569,7 @@ var HAZO_FILES_MIGRATION_V3 = {
5557
5569
  ]
5558
5570
  };
5559
5571
  function getMigrationV3ForTable(tableName, dbType) {
5572
+ validateTableName(tableName);
5560
5573
  const migration = HAZO_FILES_MIGRATION_V3[dbType];
5561
5574
  const defaultName = HAZO_FILES_MIGRATION_V3.tableName;
5562
5575
  return {
@@ -5606,6 +5619,9 @@ async function migrateToV3(executor, dbType, tableName) {
5606
5619
  try {
5607
5620
  require("server-only");
5608
5621
  } catch {
5622
+ console.warn(
5623
+ '[hazo_files/server] "server-only" package not installed. Install it to prevent this module from being bundled in client code.'
5624
+ );
5609
5625
  }
5610
5626
  // Annotate the CommonJS export names for ESM import in node:
5611
5627
  0 && (module.exports = {
@@ -920,6 +920,9 @@ var LocalStorageModule = class extends BaseStorageModule {
920
920
  if (!stats || stats.isDirectory()) {
921
921
  throw new FileNotFoundError(virtualPath);
922
922
  }
923
+ if (newName.includes("/") || newName.includes("\\") || newName.includes("..")) {
924
+ throw new InvalidPathError(newName, 'Name must not contain path separators or ".."');
925
+ }
923
926
  this.validateExtension(newName);
924
927
  const parentDir = path2.dirname(fullPath);
925
928
  const newFullPath = path2.join(parentDir, newName);
@@ -934,7 +937,7 @@ var LocalStorageModule = class extends BaseStorageModule {
934
937
  const item = await this.statToItem(newFullPath, newStats);
935
938
  return this.successResult(item);
936
939
  } catch (error) {
937
- if (error instanceof FileNotFoundError || error instanceof FileExistsError || error instanceof InvalidExtensionError) {
940
+ if (error instanceof FileNotFoundError || error instanceof FileExistsError || error instanceof InvalidExtensionError || error instanceof InvalidPathError) {
938
941
  return this.errorResult(error.message);
939
942
  }
940
943
  return this.errorResult(`Failed to rename file: ${error.message}`);
@@ -948,6 +951,9 @@ var LocalStorageModule = class extends BaseStorageModule {
948
951
  if (!stats || !stats.isDirectory()) {
949
952
  throw new DirectoryNotFoundError(virtualPath);
950
953
  }
954
+ if (newName.includes("/") || newName.includes("\\") || newName.includes("..")) {
955
+ throw new InvalidPathError(newName, 'Name must not contain path separators or ".."');
956
+ }
951
957
  const parentDir = path2.dirname(fullPath);
952
958
  const newFullPath = path2.join(parentDir, newName);
953
959
  if (!options.overwrite) {
@@ -961,7 +967,7 @@ var LocalStorageModule = class extends BaseStorageModule {
961
967
  const item = await this.statToItem(newFullPath, newStats);
962
968
  return this.successResult(item);
963
969
  } catch (error) {
964
- if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError) {
970
+ if (error instanceof DirectoryNotFoundError || error instanceof DirectoryExistsError || error instanceof InvalidPathError) {
965
971
  return this.errorResult(error.message);
966
972
  }
967
973
  return this.errorResult(`Failed to rename folder: ${error.message}`);
@@ -1103,9 +1109,12 @@ var GoogleDriveAuth = class {
1103
1109
  */
1104
1110
  async exchangeCodeForTokens(code) {
1105
1111
  const { tokens } = await this.oauth2Client.getToken(code);
1112
+ if (!tokens.access_token) {
1113
+ throw new Error("No access token received from Google OAuth");
1114
+ }
1106
1115
  this.tokens = {
1107
1116
  accessToken: tokens.access_token,
1108
- refreshToken: tokens.refresh_token,
1117
+ refreshToken: tokens.refresh_token ?? this.tokens?.refreshToken ?? "",
1109
1118
  expiryDate: tokens.expiry_date || void 0,
1110
1119
  scope: tokens.scope || void 0
1111
1120
  };
@@ -1290,7 +1299,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1290
1299
  const segments = normalized.split("/").filter(Boolean);
1291
1300
  let currentParentId = this.rootFolderId;
1292
1301
  for (const segment of segments) {
1293
- const query = `name='${segment}' and '${currentParentId}' in parents and trashed=false`;
1302
+ const escapedSegment = segment.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1303
+ const query = `name='${escapedSegment}' and '${currentParentId}' in parents and trashed=false`;
1294
1304
  const response = await this.drive.files.list({
1295
1305
  q: query,
1296
1306
  fields: "files(id, name, mimeType)",
@@ -1358,7 +1368,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1358
1368
  if (!parentId) {
1359
1369
  throw new DirectoryNotFoundError(parentPath);
1360
1370
  }
1361
- const existingQuery = `name='${folderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;
1371
+ const escapedFolderName = folderName.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1372
+ const existingQuery = `name='${escapedFolderName}' and '${parentId}' in parents and mimeType='${FOLDER_MIME_TYPE}' and trashed=false`;
1362
1373
  const existingResponse = await this.drive.files.list({
1363
1374
  q: existingQuery,
1364
1375
  fields: "files(id)",
@@ -1421,7 +1432,8 @@ var GoogleDriveModule = class extends BaseStorageModule {
1421
1432
  throw new DirectoryNotFoundError(parentPath);
1422
1433
  }
1423
1434
  if (!options.overwrite) {
1424
- const existingQuery = `name='${fileName}' and '${parentId}' in parents and trashed=false`;
1435
+ const escapedFileName = fileName.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1436
+ const existingQuery = `name='${escapedFileName}' and '${parentId}' in parents and trashed=false`;
1425
1437
  const existingResponse = await this.drive.files.list({
1426
1438
  q: existingQuery,
1427
1439
  fields: "files(id)",
@@ -2376,20 +2388,12 @@ var FileManager = class {
2376
2388
  this.initialized = true;
2377
2389
  }
2378
2390
  /**
2379
- * Initialize synchronously (uses sync config loading)
2391
+ * @deprecated Storage modules require async initialization. Use initialize() instead.
2380
2392
  */
2381
- initializeSync(config) {
2382
- if (this.initialized) {
2383
- return;
2384
- }
2385
- if (config) {
2386
- this.config = config;
2387
- } else if (this.options.config) {
2388
- this.config = this.options.config;
2389
- } else {
2390
- this.config = loadConfig(this.options.configPath);
2391
- }
2392
- this.module = createModule(this.config.provider);
2393
+ initializeSync(_config) {
2394
+ throw new Error(
2395
+ "initializeSync is not supported. Storage modules require async initialization. Use initialize() instead."
2396
+ );
2393
2397
  }
2394
2398
  /**
2395
2399
  * Check if manager is initialized
@@ -3831,7 +3835,7 @@ var TrackedFileManager = class extends FileManager {
3831
3835
  }
3832
3836
  let buffer;
3833
3837
  if (typeof downloadResult.data === "string") {
3834
- buffer = Buffer.from(downloadResult.data, "utf-8");
3838
+ return null;
3835
3839
  } else if (downloadResult.data instanceof Buffer) {
3836
3840
  buffer = downloadResult.data;
3837
3841
  } else {
@@ -5214,7 +5218,13 @@ var HAZO_FILES_TABLE_SCHEMA = {
5214
5218
  "content_tag"
5215
5219
  ]
5216
5220
  };
5221
+ function validateTableName(tableName) {
5222
+ if (!/^[a-z_][a-z0-9_]*$/i.test(tableName)) {
5223
+ throw new Error(`Invalid table name: ${tableName}`);
5224
+ }
5225
+ }
5217
5226
  function getSchemaForTable(tableName, dbType) {
5227
+ validateTableName(tableName);
5218
5228
  const schema = HAZO_FILES_TABLE_SCHEMA[dbType];
5219
5229
  const defaultName = HAZO_FILES_TABLE_SCHEMA.tableName;
5220
5230
  return {
@@ -5284,6 +5294,7 @@ WHERE file_refs IS NULL OR ref_count IS NULL OR status IS NULL`
5284
5294
  ]
5285
5295
  };
5286
5296
  function getMigrationForTable(tableName, dbType) {
5297
+ validateTableName(tableName);
5287
5298
  const migration = HAZO_FILES_MIGRATION_V2[dbType];
5288
5299
  const defaultName = HAZO_FILES_MIGRATION_V2.tableName;
5289
5300
  return {
@@ -5343,6 +5354,7 @@ var HAZO_FILES_NAMING_TABLE_SCHEMA = {
5343
5354
  ]
5344
5355
  };
5345
5356
  function getNamingSchemaForTable(tableName, dbType) {
5357
+ validateTableName(tableName);
5346
5358
  const schema = HAZO_FILES_NAMING_TABLE_SCHEMA[dbType];
5347
5359
  const defaultName = HAZO_FILES_NAMING_TABLE_SCHEMA.tableName;
5348
5360
  return {
@@ -5379,6 +5391,7 @@ var HAZO_FILES_MIGRATION_V3 = {
5379
5391
  ]
5380
5392
  };
5381
5393
  function getMigrationV3ForTable(tableName, dbType) {
5394
+ validateTableName(tableName);
5382
5395
  const migration = HAZO_FILES_MIGRATION_V3[dbType];
5383
5396
  const defaultName = HAZO_FILES_MIGRATION_V3.tableName;
5384
5397
  return {
@@ -5428,6 +5441,9 @@ async function migrateToV3(executor, dbType, tableName) {
5428
5441
  try {
5429
5442
  __require("server-only");
5430
5443
  } catch {
5444
+ console.warn(
5445
+ '[hazo_files/server] "server-only" package not installed. Install it to prevent this module from being bundled in client code.'
5446
+ );
5431
5447
  }
5432
5448
  export {
5433
5449
  ALL_SYSTEM_VARIABLES,
@@ -0,0 +1,49 @@
1
+ -- hazo_files initial database schema (V1)
2
+ -- Supports both PostgreSQL and SQLite
3
+ --
4
+ -- This creates the main file metadata tracking table.
5
+ -- Use hazo_files HAZO_FILES_TABLE_SCHEMA export for programmatic access.
6
+
7
+ -- ============================================
8
+ -- SQLite version
9
+ -- ============================================
10
+ -- CREATE TABLE IF NOT EXISTS hazo_files (
11
+ -- id TEXT PRIMARY KEY,
12
+ -- filename TEXT NOT NULL,
13
+ -- file_type TEXT NOT NULL,
14
+ -- file_data TEXT DEFAULT '{}',
15
+ -- created_at TEXT NOT NULL,
16
+ -- changed_at TEXT NOT NULL,
17
+ -- file_path TEXT NOT NULL,
18
+ -- storage_type TEXT NOT NULL,
19
+ -- file_hash TEXT,
20
+ -- file_size INTEGER,
21
+ -- file_changed_at TEXT
22
+ -- );
23
+ --
24
+ -- CREATE INDEX IF NOT EXISTS idx_hazo_files_path ON hazo_files (file_path);
25
+ -- CREATE INDEX IF NOT EXISTS idx_hazo_files_storage ON hazo_files (storage_type);
26
+ -- CREATE UNIQUE INDEX IF NOT EXISTS idx_hazo_files_path_storage ON hazo_files (file_path, storage_type);
27
+ -- CREATE INDEX IF NOT EXISTS idx_hazo_files_hash ON hazo_files (file_hash);
28
+
29
+ -- ============================================
30
+ -- PostgreSQL version (active)
31
+ -- ============================================
32
+ CREATE TABLE IF NOT EXISTS hazo_files (
33
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
34
+ filename TEXT NOT NULL,
35
+ file_type TEXT NOT NULL,
36
+ file_data TEXT DEFAULT '{}',
37
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
38
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
39
+ file_path TEXT NOT NULL,
40
+ storage_type TEXT NOT NULL,
41
+ file_hash TEXT,
42
+ file_size BIGINT,
43
+ file_changed_at TIMESTAMP WITH TIME ZONE
44
+ );
45
+
46
+ CREATE INDEX IF NOT EXISTS idx_hazo_files_path ON hazo_files (file_path);
47
+ CREATE INDEX IF NOT EXISTS idx_hazo_files_storage ON hazo_files (storage_type);
48
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_hazo_files_path_storage ON hazo_files (file_path, storage_type);
49
+ CREATE INDEX IF NOT EXISTS idx_hazo_files_hash ON hazo_files (file_hash);
@@ -0,0 +1,51 @@
1
+ -- hazo_files V2 migration - Reference Tracking
2
+ -- Adds columns for file references, soft-delete, scoping, and provenance.
3
+ -- Idempotent - safe to run multiple times.
4
+
5
+ -- ============================================
6
+ -- SQLite version
7
+ -- ============================================
8
+ -- ALTER TABLE hazo_files ADD COLUMN file_refs TEXT DEFAULT '[]';
9
+ -- ALTER TABLE hazo_files ADD COLUMN ref_count INTEGER DEFAULT 0;
10
+ -- ALTER TABLE hazo_files ADD COLUMN status TEXT DEFAULT 'active';
11
+ -- ALTER TABLE hazo_files ADD COLUMN scope_id TEXT;
12
+ -- ALTER TABLE hazo_files ADD COLUMN uploaded_by TEXT;
13
+ -- ALTER TABLE hazo_files ADD COLUMN storage_verified_at TEXT;
14
+ -- ALTER TABLE hazo_files ADD COLUMN deleted_at TEXT;
15
+ -- ALTER TABLE hazo_files ADD COLUMN original_filename TEXT;
16
+ --
17
+ -- CREATE INDEX IF NOT EXISTS idx_hazo_files_status ON hazo_files (status);
18
+ -- CREATE INDEX IF NOT EXISTS idx_hazo_files_scope ON hazo_files (scope_id);
19
+ -- CREATE INDEX IF NOT EXISTS idx_hazo_files_ref_count ON hazo_files (ref_count);
20
+ -- CREATE INDEX IF NOT EXISTS idx_hazo_files_deleted ON hazo_files (deleted_at);
21
+ --
22
+ -- Backfill:
23
+ -- UPDATE hazo_files SET
24
+ -- file_refs = COALESCE(file_refs, '[]'),
25
+ -- ref_count = COALESCE(ref_count, 0),
26
+ -- status = COALESCE(status, 'active')
27
+ -- WHERE file_refs IS NULL OR ref_count IS NULL OR status IS NULL;
28
+
29
+ -- ============================================
30
+ -- PostgreSQL version (active)
31
+ -- ============================================
32
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS file_refs TEXT DEFAULT '[]';
33
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS ref_count INTEGER DEFAULT 0;
34
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS status TEXT DEFAULT 'active';
35
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS scope_id UUID;
36
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS uploaded_by UUID;
37
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS storage_verified_at TIMESTAMP WITH TIME ZONE;
38
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMP WITH TIME ZONE;
39
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS original_filename TEXT;
40
+
41
+ CREATE INDEX IF NOT EXISTS idx_hazo_files_status ON hazo_files (status);
42
+ CREATE INDEX IF NOT EXISTS idx_hazo_files_scope ON hazo_files (scope_id);
43
+ CREATE INDEX IF NOT EXISTS idx_hazo_files_ref_count ON hazo_files (ref_count);
44
+ CREATE INDEX IF NOT EXISTS idx_hazo_files_deleted ON hazo_files (deleted_at);
45
+
46
+ -- Backfill defaults for existing records
47
+ UPDATE hazo_files SET
48
+ file_refs = COALESCE(file_refs, '[]'),
49
+ ref_count = COALESCE(ref_count, 0),
50
+ status = COALESCE(status, 'active')
51
+ WHERE file_refs IS NULL OR ref_count IS NULL OR status IS NULL;
@@ -0,0 +1,15 @@
1
+ -- hazo_files V3 migration - Content Tagging
2
+ -- Adds content_tag column for LLM-based document classification.
3
+ -- Idempotent - safe to run multiple times.
4
+
5
+ -- ============================================
6
+ -- SQLite version
7
+ -- ============================================
8
+ -- ALTER TABLE hazo_files ADD COLUMN content_tag TEXT;
9
+ -- CREATE INDEX IF NOT EXISTS idx_hazo_files_content_tag ON hazo_files (content_tag);
10
+
11
+ -- ============================================
12
+ -- PostgreSQL version (active)
13
+ -- ============================================
14
+ ALTER TABLE hazo_files ADD COLUMN IF NOT EXISTS content_tag TEXT;
15
+ CREATE INDEX IF NOT EXISTS idx_hazo_files_content_tag ON hazo_files (content_tag);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_files",
3
- "version": "1.4.4",
3
+ "version": "1.4.5",
4
4
  "description": "File management including integration to cloud files",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -25,7 +25,8 @@
25
25
  "files": [
26
26
  "dist",
27
27
  "docs",
28
- "hazo_files_config.ini",
28
+ "config",
29
+ "migrations",
29
30
  "README.md",
30
31
  ".env.example"
31
32
  ],
@@ -65,10 +66,7 @@
65
66
  },
66
67
  "homepage": "https://github.com/pub12/hazo_files#readme",
67
68
  "dependencies": {
68
- "dropbox": "^10.34.0",
69
- "googleapis": "^140.0.1",
70
- "ini": "^4.1.3",
71
- "xxhash-wasm": "^1.1.0"
69
+ "ini": "^4.1.3"
72
70
  },
73
71
  "devDependencies": {
74
72
  "@dnd-kit/core": "^6.3.1",
@@ -78,23 +76,29 @@
78
76
  "@types/node": "^20.10.0",
79
77
  "@types/react": "^18.2.45",
80
78
  "@types/react-dom": "^18.2.18",
79
+ "dropbox": "^10.34.0",
80
+ "googleapis": "^140.0.1",
81
81
  "hazo_llm_api": "^1.2.7",
82
82
  "react": "^18.2.0",
83
83
  "react-dom": "^18.2.0",
84
84
  "tsup": "^8.0.1",
85
85
  "typescript": "^5.3.3",
86
- "vitest": "^4.0.15"
86
+ "vitest": "^4.0.15",
87
+ "xxhash-wasm": "^1.1.0"
87
88
  },
88
89
  "peerDependencies": {
89
90
  "@dnd-kit/core": "^6.0.0",
90
91
  "@dnd-kit/sortable": ">=8.0.0",
91
92
  "@dnd-kit/utilities": "^3.0.0",
93
+ "dropbox": "^10.0.0",
94
+ "googleapis": "^140.0.0",
92
95
  "hazo_connect": ">=2.0.0",
93
96
  "hazo_llm_api": ">=1.0.0",
94
97
  "hazo_logs": ">=1.0.0",
95
98
  "react": "^18.0.0",
96
99
  "react-dom": "^18.0.0",
97
- "server-only": ">=0.0.1"
100
+ "server-only": ">=0.0.1",
101
+ "xxhash-wasm": "^1.0.0"
98
102
  },
99
103
  "peerDependenciesMeta": {
100
104
  "@dnd-kit/core": {
@@ -106,6 +110,12 @@
106
110
  "@dnd-kit/utilities": {
107
111
  "optional": true
108
112
  },
113
+ "dropbox": {
114
+ "optional": true
115
+ },
116
+ "googleapis": {
117
+ "optional": true
118
+ },
109
119
  "hazo_connect": {
110
120
  "optional": true
111
121
  },
@@ -117,6 +127,9 @@
117
127
  },
118
128
  "server-only": {
119
129
  "optional": true
130
+ },
131
+ "xxhash-wasm": {
132
+ "optional": true
120
133
  }
121
134
  }
122
135
  }