hazo_files 1.4.0 → 1.4.2

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
@@ -16,7 +16,9 @@ A powerful, modular file management package for Node.js and React applications w
16
16
  - **Extraction Data Management**: Track and manage LLM-extracted metadata with merge strategies
17
17
  - **LLM Integration**: Built-in support for hazo_llm_api document/image extraction
18
18
  - **Upload + Extract Workflow**: Combined service for uploading files with automatic LLM extraction and naming
19
+ - **File Reference Tracking**: Multi-entity file references with orphan detection, soft delete, and lifecycle management
19
20
  - **File Change Detection**: xxHash-based content hashing for efficient change detection
21
+ - **Schema Migrations**: Built-in V2 migration utilities for adding reference tracking to existing databases
20
22
  - **TypeScript**: Full type safety and IntelliSense support
21
23
  - **OAuth Integration**: Built-in Google Drive OAuth authentication
22
24
  - **Progress Tracking**: Upload/download progress callbacks
@@ -50,6 +52,23 @@ npm install server-only # Server-side safety (recommended)
50
52
  # Note: xxhash-wasm is included automatically as a dependency
51
53
  ```
52
54
 
55
+ ### Tailwind CSS v4 Setup (Required for UI Components)
56
+
57
+ If you're using Tailwind CSS v4 with the UI components, you must add a `@source` directive to your CSS file to ensure Tailwind scans the package's files for utility classes.
58
+
59
+ Add this to your `globals.css` or main CSS file AFTER the tailwindcss import:
60
+
61
+ ```css
62
+ @import "tailwindcss";
63
+
64
+ /* Required: Enable Tailwind to scan hazo_files package for utility classes */
65
+ @source "../node_modules/hazo_files/dist/ui";
66
+ ```
67
+
68
+ Without this directive, Tailwind v4's JIT compiler will not generate CSS for the utility classes used in hazo_files components (like `hover:bg-gray-100`, `text-sm`, `rounded-md`, etc.), resulting in broken styling.
69
+
70
+ **Note**: This is only required for Tailwind v4. Earlier versions of Tailwind automatically scan `node_modules` and do not need this configuration.
71
+
53
72
  ## Quick Start
54
73
 
55
74
  ### Basic Usage (Server-side)
@@ -1175,6 +1194,101 @@ const autoResult = await extractionService.extract(
1175
1194
  );
1176
1195
  ```
1177
1196
 
1197
+ ## File Reference Tracking
1198
+
1199
+ Track which entities (form fields, chat messages, etc.) reference each file. Multiple entities can reference the same file, enabling shared files without duplication.
1200
+
1201
+ ### Adding and Removing References
1202
+
1203
+ ```typescript
1204
+ import { TrackedFileManager } from 'hazo_files';
1205
+
1206
+ // Upload a file with an initial reference
1207
+ const result = await trackedManager.uploadFileWithRef(buffer, '/docs/report.pdf', {
1208
+ scope_id: 'workspace-123',
1209
+ uploaded_by: 'user-456',
1210
+ ref: {
1211
+ entity_type: 'form_field',
1212
+ entity_id: 'field-789',
1213
+ created_by: 'user-456',
1214
+ },
1215
+ });
1216
+ // result.data.file_id, result.data.ref_id
1217
+
1218
+ // Add another reference to the same file
1219
+ await trackedManager.addRef(fileId, {
1220
+ entity_type: 'chat_message',
1221
+ entity_id: 'msg-abc',
1222
+ });
1223
+
1224
+ // Remove a specific reference
1225
+ const { remaining_refs } = await trackedManager.removeRef(fileId, refId);
1226
+
1227
+ // Get file with status info
1228
+ const fileStatus = await trackedManager.getFileById(fileId);
1229
+ // { record, refs: FileRef[], is_orphaned: boolean }
1230
+ ```
1231
+
1232
+ ### Orphan Detection and Cleanup
1233
+
1234
+ ```typescript
1235
+ // Find files with zero references
1236
+ const orphans = await trackedManager.findOrphanedFiles({
1237
+ olderThanMs: 7 * 24 * 60 * 60 * 1000, // 7 days old
1238
+ scope_id: 'workspace-123',
1239
+ });
1240
+
1241
+ // Clean up orphaned files (delete physical files + DB records)
1242
+ const { cleaned, errors } = await trackedManager.cleanupOrphanedFiles({
1243
+ olderThanMs: 30 * 24 * 60 * 60 * 1000,
1244
+ softDeleteOnly: false, // true to only mark as soft_deleted
1245
+ });
1246
+
1247
+ // Soft-delete a specific file
1248
+ await trackedManager.softDeleteFile(fileId);
1249
+
1250
+ // Verify physical file existence
1251
+ const exists = await trackedManager.verifyFileExistence(fileId);
1252
+ ```
1253
+
1254
+ ### Database Migration (Existing Databases)
1255
+
1256
+ If you have an existing `hazo_files` table, run the V2 migration to add reference tracking columns:
1257
+
1258
+ ```typescript
1259
+ import { migrateToV2, backfillV2Defaults, HAZO_FILES_MIGRATION_V2 } from 'hazo_files';
1260
+
1261
+ // Using the migration helper
1262
+ await migrateToV2(
1263
+ { run: (sql) => db.exec(sql) }, // SQLite
1264
+ 'sqlite'
1265
+ );
1266
+ await backfillV2Defaults({ run: (sql) => db.exec(sql) }, 'sqlite');
1267
+
1268
+ // Or run statements manually
1269
+ for (const stmt of HAZO_FILES_MIGRATION_V2.sqlite.alterStatements) {
1270
+ try { await db.run(stmt); } catch { /* column exists */ }
1271
+ }
1272
+ for (const idx of HAZO_FILES_MIGRATION_V2.sqlite.indexes) {
1273
+ await db.run(idx);
1274
+ }
1275
+ ```
1276
+
1277
+ New tables created with `HAZO_FILES_TABLE_SCHEMA` already include V2 columns.
1278
+
1279
+ ### Reference Tracking Types
1280
+
1281
+ ```typescript
1282
+ import type {
1283
+ FileRef, // Individual reference from entity to file
1284
+ FileMetadataRecordV2, // Extended record with refs, status, scope
1285
+ FileWithStatus, // Rich view: record + parsed refs + is_orphaned
1286
+ FileStatus, // 'active' | 'orphaned' | 'soft_deleted' | 'missing'
1287
+ AddRefOptions, // Options for adding a reference
1288
+ RemoveRefsCriteria, // Criteria for bulk ref removal
1289
+ } from 'hazo_files';
1290
+ ```
1291
+
1178
1292
  ## File Change Detection
1179
1293
 
1180
1294
  Detect file content changes using fast xxHash hashing.
package/dist/index.d.mts CHANGED
@@ -179,6 +179,12 @@ interface FileMetadataInput {
179
179
  file_hash?: string;
180
180
  /** File size in bytes */
181
181
  file_size?: number;
182
+ /** Scope ID for organizational grouping (V2) */
183
+ scope_id?: string;
184
+ /** User who uploaded the file (V2) */
185
+ uploaded_by?: string;
186
+ /** Original filename at upload time (V2) */
187
+ original_filename?: string;
182
188
  }
183
189
  /**
184
190
  * Input for updating an existing metadata record
@@ -354,6 +360,135 @@ interface ListNamingConventionsOptions {
354
360
  includeGlobal?: boolean;
355
361
  }
356
362
 
363
+ /**
364
+ * Reference Tracking Types for hazo_files
365
+ * Supports multi-entity file references with lifecycle management
366
+ */
367
+
368
+ /** Status of a file in the system */
369
+ type FileStatus = 'active' | 'orphaned' | 'soft_deleted' | 'missing';
370
+ /** Visibility level for a file reference */
371
+ type FileRefVisibility = 'public' | 'private' | 'internal';
372
+ /**
373
+ * A reference from an entity to a file.
374
+ * Multiple entities can reference the same file.
375
+ */
376
+ interface FileRef {
377
+ /** Unique ID for this reference */
378
+ ref_id: string;
379
+ /** Type of entity referencing the file (e.g., 'form_field', 'chat_message') */
380
+ entity_type: string;
381
+ /** ID of the entity referencing the file */
382
+ entity_id: string;
383
+ /** ISO timestamp when reference was created */
384
+ created_at: string;
385
+ /** User or system that created this reference */
386
+ created_by?: string;
387
+ /** Visibility of this reference */
388
+ visibility?: FileRefVisibility;
389
+ /** Optional label for the reference */
390
+ label?: string;
391
+ /** Optional metadata for the reference */
392
+ metadata?: Record<string, unknown>;
393
+ }
394
+ /**
395
+ * Extended metadata record with reference tracking fields.
396
+ * Extends FileMetadataRecord with V2 columns.
397
+ */
398
+ interface FileMetadataRecordV2 extends FileMetadataRecord {
399
+ /** JSON string of FileRef[] - parsed by service methods */
400
+ file_refs: string;
401
+ /** Number of active references (denormalized for queries) */
402
+ ref_count: number;
403
+ /** Current file status */
404
+ status: FileStatus;
405
+ /** Scope ID for organizational grouping (e.g., workspace, tenant) */
406
+ scope_id?: string | null;
407
+ /** User who uploaded the file */
408
+ uploaded_by?: string | null;
409
+ /** Original filename at upload time */
410
+ original_filename?: string | null;
411
+ /** ISO timestamp when storage was last verified */
412
+ storage_verified_at?: string | null;
413
+ /** ISO timestamp when file was soft-deleted */
414
+ deleted_at?: string | null;
415
+ }
416
+ /**
417
+ * Options for adding a reference to a file
418
+ */
419
+ interface AddRefOptions {
420
+ /** Type of entity referencing the file */
421
+ entity_type: string;
422
+ /** ID of the entity referencing the file */
423
+ entity_id: string;
424
+ /** User creating the reference */
425
+ created_by?: string;
426
+ /** Visibility of the reference */
427
+ visibility?: FileRefVisibility;
428
+ /** Optional label */
429
+ label?: string;
430
+ /** Optional metadata */
431
+ metadata?: Record<string, unknown>;
432
+ }
433
+ /**
434
+ * Criteria for removing references.
435
+ * All specified fields must match (AND semantics).
436
+ */
437
+ interface RemoveRefsCriteria {
438
+ /** Match by entity type */
439
+ entity_type?: string;
440
+ /** Match by entity ID */
441
+ entity_id?: string;
442
+ /** Match by scope ID on the file record */
443
+ scope_id?: string;
444
+ /** Match by specific file ID */
445
+ file_id?: string;
446
+ }
447
+ /**
448
+ * Rich status view of a file with parsed references
449
+ */
450
+ interface FileWithStatus {
451
+ /** Full metadata record (V2) */
452
+ record: FileMetadataRecordV2;
453
+ /** Parsed file references */
454
+ refs: FileRef[];
455
+ /** Whether the file has zero references */
456
+ is_orphaned: boolean;
457
+ }
458
+ /**
459
+ * Options for finding orphaned files
460
+ */
461
+ interface FindOrphanedOptions {
462
+ /** Only find orphans older than this duration (ISO 8601 duration or ms) */
463
+ olderThanMs?: number;
464
+ /** Filter by scope */
465
+ scope_id?: string;
466
+ /** Filter by storage type */
467
+ storage_type?: StorageProvider;
468
+ /** Maximum number of results */
469
+ limit?: number;
470
+ }
471
+ /**
472
+ * Options for cleaning up orphaned files
473
+ */
474
+ interface CleanupOrphanedOptions extends FindOrphanedOptions {
475
+ /** If true, only soft-delete rather than permanently removing (default: false) */
476
+ softDeleteOnly?: boolean;
477
+ /** If true, also delete physical files (default: true) */
478
+ deletePhysicalFiles?: boolean;
479
+ }
480
+ /**
481
+ * Options for uploading a file with an initial reference
482
+ */
483
+ interface UploadWithRefOptions {
484
+ /** Reference to add after upload */
485
+ ref?: AddRefOptions;
486
+ /** Scope ID for the file */
487
+ scope_id?: string;
488
+ /** User performing the upload */
489
+ uploaded_by?: string;
490
+ }
491
+
357
492
  /**
358
493
  * Core types for the hazo_files package
359
494
  */
@@ -813,6 +948,67 @@ declare class FileMetadataService {
813
948
  * Clear all extractions for a file
814
949
  */
815
950
  clearExtractions(path: string, storageType: StorageProvider): Promise<boolean>;
951
+ /**
952
+ * Find a record by ID
953
+ */
954
+ findById(id: string): Promise<FileMetadataRecord | null>;
955
+ /**
956
+ * Find multiple records by IDs
957
+ */
958
+ findByIds(ids: string[]): Promise<FileMetadataRecord[]>;
959
+ /**
960
+ * Add a reference to a file
961
+ * @returns The new ref_id, or null on failure
962
+ */
963
+ addRef(fileId: string, options: AddRefOptions): Promise<{
964
+ ref_id: string;
965
+ } | null>;
966
+ /**
967
+ * Remove a specific reference from a file
968
+ * @returns Remaining ref count, or null on failure
969
+ */
970
+ removeRef(fileId: string, refId: string): Promise<{
971
+ remaining_refs: number;
972
+ } | null>;
973
+ /**
974
+ * Remove references matching criteria across all records.
975
+ * Scans all records and removes matching refs (AND semantics).
976
+ */
977
+ removeRefsByCriteria(criteria: RemoveRefsCriteria): Promise<{
978
+ removed_count: number;
979
+ }>;
980
+ /**
981
+ * Helper: remove matching refs from a single record
982
+ */
983
+ private removeRefsFromRecord;
984
+ /**
985
+ * Get all references for a file
986
+ */
987
+ getRefs(fileId: string): Promise<FileRef[] | null>;
988
+ /**
989
+ * Get a file with its status and parsed refs
990
+ */
991
+ getFileWithStatus(fileId: string): Promise<FileWithStatus | null>;
992
+ /**
993
+ * Get multiple files with status
994
+ */
995
+ getFilesWithStatus(fileIds: string[]): Promise<FileWithStatus[]>;
996
+ /**
997
+ * Update the status of a file
998
+ */
999
+ updateStatus(fileId: string, status: FileStatus): Promise<boolean>;
1000
+ /**
1001
+ * Soft-delete a file (set status to soft_deleted, record deleted_at)
1002
+ */
1003
+ softDelete(fileId: string): Promise<boolean>;
1004
+ /**
1005
+ * Update specific V2 fields on a record
1006
+ */
1007
+ updateFields(fileId: string, fields: Partial<Pick<FileMetadataRecordV2, 'scope_id' | 'uploaded_by' | 'original_filename' | 'storage_verified_at' | 'status'>>): Promise<boolean>;
1008
+ /**
1009
+ * Find orphaned files (zero references)
1010
+ */
1011
+ findOrphaned(options?: FindOrphanedOptions): Promise<FileWithStatus[]>;
816
1012
  }
817
1013
  /**
818
1014
  * Create a FileMetadataService instance
@@ -953,6 +1149,52 @@ declare class TrackedFileManager extends FileManager {
953
1149
  * @returns Stored size in bytes or null if not found/not tracked
954
1150
  */
955
1151
  getStoredSize(path: string): Promise<number | null>;
1152
+ /**
1153
+ * Add a reference to a file
1154
+ */
1155
+ addRef(fileId: string, options: AddRefOptions): Promise<{
1156
+ ref_id: string;
1157
+ } | null>;
1158
+ /**
1159
+ * Remove a reference from a file
1160
+ */
1161
+ removeRef(fileId: string, refId: string): Promise<{
1162
+ remaining_refs: number;
1163
+ } | null>;
1164
+ /**
1165
+ * Get a file by its database ID with status information
1166
+ */
1167
+ getFileById(fileId: string): Promise<FileWithStatus | null>;
1168
+ /**
1169
+ * Get multiple files by their database IDs with status information
1170
+ */
1171
+ getFilesById(fileIds: string[]): Promise<FileWithStatus[]>;
1172
+ /**
1173
+ * Soft-delete a file (marks as soft_deleted, does not remove physical file)
1174
+ */
1175
+ softDeleteFile(fileId: string): Promise<boolean>;
1176
+ /**
1177
+ * Find orphaned files (files with zero references)
1178
+ */
1179
+ findOrphanedFiles(options?: FindOrphanedOptions): Promise<FileWithStatus[]>;
1180
+ /**
1181
+ * Cleanup orphaned files — removes physical files and/or DB records
1182
+ */
1183
+ cleanupOrphanedFiles(options?: CleanupOrphanedOptions): Promise<{
1184
+ cleaned: number;
1185
+ errors: string[];
1186
+ }>;
1187
+ /**
1188
+ * Verify that a file's physical storage exists and update its status
1189
+ */
1190
+ verifyFileExistence(fileId: string): Promise<boolean | null>;
1191
+ /**
1192
+ * Upload a file and optionally add an initial reference
1193
+ */
1194
+ uploadFileWithRef(source: string | Buffer | ReadableStream, remotePath: string, options?: TrackedUploadOptions & UploadWithRefOptions): Promise<OperationResult<FileItem & {
1195
+ file_id?: string;
1196
+ ref_id?: string;
1197
+ }>>;
956
1198
  }
957
1199
  /**
958
1200
  * Create a new TrackedFileManager instance
@@ -1485,6 +1727,22 @@ interface HazoFilesColumnDefinitions {
1485
1727
  file_size: 'INTEGER' | 'BIGINT';
1486
1728
  /** ISO timestamp when file content last changed */
1487
1729
  file_changed_at: 'TEXT' | 'TIMESTAMP';
1730
+ /** JSON string of FileRef[] - reference tracking (V2) */
1731
+ file_refs: 'TEXT';
1732
+ /** Number of active references (V2) */
1733
+ ref_count: 'INTEGER';
1734
+ /** File status: active, orphaned, soft_deleted, missing (V2) */
1735
+ status: 'TEXT';
1736
+ /** Scope ID for organizational grouping (V2) */
1737
+ scope_id: 'TEXT' | 'UUID';
1738
+ /** User who uploaded the file (V2) */
1739
+ uploaded_by: 'TEXT' | 'UUID';
1740
+ /** ISO timestamp when storage was last verified (V2) */
1741
+ storage_verified_at: 'TEXT' | 'TIMESTAMP';
1742
+ /** ISO timestamp when file was soft-deleted (V2) */
1743
+ deleted_at: 'TEXT' | 'TIMESTAMP';
1744
+ /** Original filename at upload time (V2) */
1745
+ original_filename: 'TEXT';
1488
1746
  }
1489
1747
  /**
1490
1748
  * Schema definition for a specific database type
@@ -1547,6 +1805,57 @@ declare const HAZO_FILES_TABLE_SCHEMA: HazoFilesTableSchema;
1547
1805
  * @returns DDL and index statements with the custom table name
1548
1806
  */
1549
1807
  declare function getSchemaForTable(tableName: string, dbType: 'sqlite' | 'postgres'): DatabaseSchemaDefinition;
1808
+ /**
1809
+ * Migration schema for adding V2 reference tracking columns to existing tables.
1810
+ * Idempotent — safe to run multiple times (uses IF NOT EXISTS for indexes,
1811
+ * and ALTER TABLE ADD COLUMN is ignored if column exists in SQLite).
1812
+ *
1813
+ * For PostgreSQL, columns are added with IF NOT EXISTS (PG 9.6+).
1814
+ *
1815
+ * @example
1816
+ * ```typescript
1817
+ * import { HAZO_FILES_MIGRATION_V2 } from 'hazo_files';
1818
+ *
1819
+ * // SQLite
1820
+ * for (const stmt of HAZO_FILES_MIGRATION_V2.sqlite.alterStatements) {
1821
+ * try { await db.run(stmt); } catch { /* column already exists *\/ }
1822
+ * }
1823
+ * for (const idx of HAZO_FILES_MIGRATION_V2.sqlite.indexes) {
1824
+ * await db.run(idx);
1825
+ * }
1826
+ *
1827
+ * // PostgreSQL
1828
+ * for (const stmt of HAZO_FILES_MIGRATION_V2.postgres.alterStatements) {
1829
+ * await client.query(stmt);
1830
+ * }
1831
+ * for (const idx of HAZO_FILES_MIGRATION_V2.postgres.indexes) {
1832
+ * await client.query(idx);
1833
+ * }
1834
+ * ```
1835
+ */
1836
+ interface MigrationSchemaDefinition {
1837
+ /** ALTER TABLE statements to add new columns */
1838
+ alterStatements: string[];
1839
+ /** CREATE INDEX statements for new columns */
1840
+ indexes: string[];
1841
+ /** UPDATE statement to backfill defaults for existing records */
1842
+ backfill: string;
1843
+ }
1844
+ interface HazoFilesMigrationV2 {
1845
+ /** Default table name */
1846
+ tableName: string;
1847
+ /** SQLite migration statements */
1848
+ sqlite: MigrationSchemaDefinition;
1849
+ /** PostgreSQL migration statements */
1850
+ postgres: MigrationSchemaDefinition;
1851
+ /** New column names added in V2 */
1852
+ newColumns: readonly string[];
1853
+ }
1854
+ declare const HAZO_FILES_MIGRATION_V2: HazoFilesMigrationV2;
1855
+ /**
1856
+ * Get migration statements for a custom table name
1857
+ */
1858
+ declare function getMigrationForTable(tableName: string, dbType: 'sqlite' | 'postgres'): MigrationSchemaDefinition;
1550
1859
  /**
1551
1860
  * Default table name for naming conventions
1552
1861
  */
@@ -1617,6 +1926,47 @@ declare const HAZO_FILES_NAMING_TABLE_SCHEMA: HazoFilesNamingTableSchema;
1617
1926
  */
1618
1927
  declare function getNamingSchemaForTable(tableName: string, dbType: 'sqlite' | 'postgres'): DatabaseSchemaDefinition;
1619
1928
 
1929
+ /**
1930
+ * Migration: Add Reference Tracking (V2)
1931
+ *
1932
+ * Adds reference tracking columns to an existing hazo_files table.
1933
+ * Idempotent — safe to run multiple times.
1934
+ */
1935
+ /**
1936
+ * Executor interface for running SQL statements.
1937
+ * Compatible with common database adapters (better-sqlite3, pg, hazo_connect).
1938
+ */
1939
+ interface MigrationExecutor {
1940
+ run(sql: string): Promise<void> | void;
1941
+ }
1942
+ /**
1943
+ * Run the V2 migration: add reference tracking columns and indexes.
1944
+ *
1945
+ * @param executor - Object with a `run(sql)` method
1946
+ * @param dbType - Database type ('sqlite' | 'postgres')
1947
+ * @param tableName - Custom table name (defaults to 'hazo_files')
1948
+ *
1949
+ * @example
1950
+ * ```typescript
1951
+ * import { migrateToV2 } from 'hazo_files';
1952
+ *
1953
+ * // SQLite with better-sqlite3
1954
+ * await migrateToV2({ run: (sql) => db.exec(sql) }, 'sqlite');
1955
+ *
1956
+ * // PostgreSQL with pg
1957
+ * await migrateToV2({ run: (sql) => client.query(sql) }, 'postgres');
1958
+ * ```
1959
+ */
1960
+ declare function migrateToV2(executor: MigrationExecutor, dbType: 'sqlite' | 'postgres', tableName?: string): Promise<void>;
1961
+ /**
1962
+ * Backfill V2 defaults for existing records that have NULL V2 columns.
1963
+ *
1964
+ * @param executor - Object with a `run(sql)` method
1965
+ * @param dbType - Database type ('sqlite' | 'postgres')
1966
+ * @param tableName - Custom table name (defaults to 'hazo_files')
1967
+ */
1968
+ declare function backfillV2Defaults(executor: MigrationExecutor, dbType: 'sqlite' | 'postgres', tableName?: string): Promise<void>;
1969
+
1620
1970
  /**
1621
1971
  * Common utility functions
1622
1972
  */
@@ -2391,4 +2741,45 @@ declare function hashesEqual(hash1: string | null | undefined, hash2: string | n
2391
2741
  */
2392
2742
  declare function hasFileContentChanged(oldHash: string | null | undefined, newBuffer: Buffer): Promise<boolean>;
2393
2743
 
2394
- export { ALL_SYSTEM_VARIABLES, type AddExtractionOptions, type AuthCallbacks, AuthenticationError, ConfigurationError, type CreateFolderOptions, type CrudServiceLike, DEFAULT_DATE_FORMATS, type DatabaseSchemaDefinition, type DatabaseTrackingConfig, DirectoryExistsError, DirectoryNotEmptyError, DirectoryNotFoundError, type DownloadOptions, type ExtractionData, type ExtractionOptions, type ExtractionResult, type FileBrowserState, type FileDataStructure, FileExistsError, type FileInfo, type FileItem, FileManager, type FileManagerOptions, type FileMetadataInput, type FileMetadataRecord, FileMetadataService, type FileMetadataServiceOptions, type FileMetadataUpdate, FileNotFoundError, type FileSystemItem, FileTooLargeError, type FolderItem, type GeneratedNameResult, type GoogleAuthConfig, GoogleDriveAuth, type GoogleDriveConfig, GoogleDriveModule, HAZO_FILES_DEFAULT_TABLE_NAME, HAZO_FILES_NAMING_DEFAULT_TABLE_NAME, HAZO_FILES_NAMING_TABLE_SCHEMA, HAZO_FILES_TABLE_SCHEMA, type HazoFilesColumnDefinitions, type HazoFilesConfig, HazoFilesError, type HazoFilesNamingColumnDefinitions, type HazoFilesNamingTableSchema, type HazoFilesTableSchema, type HazoLLMInstance, InvalidExtensionError, InvalidPathError, LLMExtractionService, type LLMFactory, type LLMProvider, type ListNamingConventionsOptions, type ListOptions, type LocalStorageConfig, LocalStorageModule, type MetadataLogger, 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 ProgressCallback, type RemoveExtractionOptions, type RenameOptions, SYSTEM_COUNTER_VARIABLES, SYSTEM_DATE_VARIABLES, SYSTEM_FILE_VARIABLES, type StorageModule, type StorageProvider, type TokenData, TrackedFileManager, type TrackedFileManagerFullOptions, type TrackedFileManagerOptions, type TrackedUploadOptions, type TreeNode, type UploadExtractOptions, type UploadExtractResult, UploadExtractService, type UploadOptions, type UseNamingRuleActions, type UseNamingRuleReturn, type UseNamingRuleState, type VariableCategory, addExtractionToFileData, clearExtractions, clonePattern, computeFileHash, computeFileHashFromStream, computeFileHashSync, computeFileInfo, createAndInitializeModule, createEmptyFileDataStructure, createEmptyNamingRuleSchema, createFileItem, createFileManager, createFileMetadataService, createFolderItem, createGoogleDriveAuth, createGoogleDriveModule, createInitializedFileManager, createInitializedTrackedFileManager, createLLMExtractionService, createLiteralSegment, createLocalModule, createModule, createNamingConventionService, createTrackedFileManager, createUploadExtractService, createVariableSegment, deepMerge, errorResult, filterItems, formatBytes, formatCounter, formatDateToken, generateExtractionId, generateId, generatePreviewName, generateSampleConfig, generateSegmentId, getBaseName, getBreadcrumbs, getDirName, getExtension, getExtensionFromMime, getExtractionById, getExtractionCount, getExtractions, getFileCategory, getFileMetadataValues, getMergedData, 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, normalizePath, parseConfig, parseFileData, parsePatternString, patternToString, recalculateMergedData, registerModule, removeExtractionById, removeExtractionByIndex, sanitizeFilename, saveConfig, sortItems, stringifyFileData, successResult, updateExtractionById, validateExtractionData, validateFileDataStructure, validateNamingRuleSchema, validatePath };
2744
+ /**
2745
+ * Reference Tracking Utilities
2746
+ * Pure functions for managing file references within the file_refs JSON field
2747
+ */
2748
+
2749
+ /**
2750
+ * Generate a unique reference ID
2751
+ */
2752
+ declare function generateRefId(): string;
2753
+ /**
2754
+ * Parse a JSON string into FileRef array.
2755
+ * Returns empty array on invalid input.
2756
+ */
2757
+ declare function parseFileRefs(json: string | null | undefined): FileRef[];
2758
+ /**
2759
+ * Serialize FileRef array to JSON string
2760
+ */
2761
+ declare function stringifyFileRefs(refs: FileRef[]): string;
2762
+ /**
2763
+ * Create a FileRef from AddRefOptions
2764
+ */
2765
+ declare function createFileRef(options: AddRefOptions): FileRef;
2766
+ /**
2767
+ * Remove a ref by ref_id (immutable)
2768
+ */
2769
+ declare function removeRefFromArray(refs: FileRef[], refId: string): FileRef[];
2770
+ /**
2771
+ * Remove refs matching criteria from array (immutable).
2772
+ * All specified criteria fields must match (AND semantics).
2773
+ */
2774
+ declare function removeRefsByCriteriaFromArray(refs: FileRef[], criteria: Omit<RemoveRefsCriteria, 'file_id' | 'scope_id'>): FileRef[];
2775
+ /**
2776
+ * Safely cast a FileMetadataRecord to FileMetadataRecordV2.
2777
+ * Missing V2 fields are defaulted.
2778
+ */
2779
+ declare function toV2Record(record: FileMetadataRecord): FileMetadataRecordV2;
2780
+ /**
2781
+ * Build a FileWithStatus view from a record
2782
+ */
2783
+ declare function buildFileWithStatus(record: FileMetadataRecord): FileWithStatus;
2784
+
2785
+ export { ALL_SYSTEM_VARIABLES, type AddExtractionOptions, type AddRefOptions, type AuthCallbacks, AuthenticationError, type CleanupOrphanedOptions, ConfigurationError, type CreateFolderOptions, type CrudServiceLike, DEFAULT_DATE_FORMATS, type DatabaseSchemaDefinition, type DatabaseTrackingConfig, DirectoryExistsError, DirectoryNotEmptyError, DirectoryNotFoundError, type DownloadOptions, 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 FileSystemItem, FileTooLargeError, type FileWithStatus, type FindOrphanedOptions, type FolderItem, type GeneratedNameResult, type GoogleAuthConfig, GoogleDriveAuth, type GoogleDriveConfig, GoogleDriveModule, HAZO_FILES_DEFAULT_TABLE_NAME, HAZO_FILES_MIGRATION_V2, HAZO_FILES_NAMING_DEFAULT_TABLE_NAME, HAZO_FILES_NAMING_TABLE_SCHEMA, HAZO_FILES_TABLE_SCHEMA, type HazoFilesColumnDefinitions, type HazoFilesConfig, HazoFilesError, type HazoFilesMigrationV2, type HazoFilesNamingColumnDefinitions, type HazoFilesNamingTableSchema, type HazoFilesTableSchema, type HazoLLMInstance, InvalidExtensionError, InvalidPathError, LLMExtractionService, type LLMFactory, 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 ProgressCallback, type RemoveExtractionOptions, type RemoveRefsCriteria, type RenameOptions, SYSTEM_COUNTER_VARIABLES, SYSTEM_DATE_VARIABLES, SYSTEM_FILE_VARIABLES, type StorageModule, type StorageProvider, 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, createEmptyFileDataStructure, createEmptyNamingRuleSchema, createFileItem, createFileManager, createFileMetadataService, createFileRef, createFolderItem, createGoogleDriveAuth, createGoogleDriveModule, createInitializedFileManager, createInitializedTrackedFileManager, createLLMExtractionService, createLiteralSegment, createLocalModule, createModule, createNamingConventionService, 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, 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, normalizePath, parseConfig, parseFileData, parseFileRefs, parsePatternString, patternToString, recalculateMergedData, registerModule, removeExtractionById, removeExtractionByIndex, removeRefFromArray, removeRefsByCriteriaFromArray, sanitizeFilename, saveConfig, sortItems, stringifyFileData, stringifyFileRefs, successResult, toV2Record, updateExtractionById, validateExtractionData, validateFileDataStructure, validateNamingRuleSchema, validatePath };