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 +114 -0
- package/dist/index.d.mts +392 -1
- package/dist/index.d.ts +392 -1
- package/dist/index.js +598 -8
- package/dist/index.mjs +586 -8
- package/dist/server/index.d.mts +392 -1
- package/dist/server/index.d.ts +392 -1
- package/dist/server/index.js +598 -8
- package/dist/server/index.mjs +586 -8
- package/package.json +1 -1
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
|
-
|
|
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 };
|