hazo_files 1.5.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGE_LOG.md +16 -0
- package/README.md +185 -0
- package/SETUP_CHECKLIST.md +96 -0
- package/dist/index.d.mts +223 -10
- package/dist/index.d.ts +223 -10
- package/dist/index.js +406 -169
- package/dist/index.mjs +406 -169
- package/dist/server/index.d.mts +430 -11
- package/dist/server/index.d.ts +430 -11
- package/dist/server/index.js +843 -171
- package/dist/server/index.mjs +832 -171
- package/migrations/004_changed_by.sql +10 -0
- package/migrations/005_source_url.sql +10 -0
- package/migrations/006_quota_tracking.sql +20 -0
- package/package.json +10 -1
package/dist/server/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JobHandler } from 'hazo_jobs';
|
|
1
2
|
import { OAuth2Client } from 'google-auth-library';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -187,6 +188,10 @@ interface FileMetadataInput {
|
|
|
187
188
|
original_filename?: string;
|
|
188
189
|
/** Content tag classifying the document type (V3) */
|
|
189
190
|
content_tag?: string;
|
|
191
|
+
/** Actor UUID who performed this mutation (V4) */
|
|
192
|
+
changed_by?: string;
|
|
193
|
+
/** Source URL when file was imported via importFromUrl (V4) */
|
|
194
|
+
source_url?: string;
|
|
190
195
|
}
|
|
191
196
|
/**
|
|
192
197
|
* Input for updating an existing metadata record
|
|
@@ -433,6 +438,10 @@ interface FileMetadataRecordV2 extends FileMetadataRecord {
|
|
|
433
438
|
deleted_at?: string | null;
|
|
434
439
|
/** Content tag classifying the document type (V3) */
|
|
435
440
|
content_tag?: string | null;
|
|
441
|
+
/** Actor UUID who last mutated this record (V4 — migration 004) */
|
|
442
|
+
changed_by?: string | null;
|
|
443
|
+
/** Source URL when file was imported via importFromUrl (V4 — migration 005) */
|
|
444
|
+
source_url?: string | null;
|
|
436
445
|
}
|
|
437
446
|
/**
|
|
438
447
|
* Options for adding a reference to a file
|
|
@@ -770,8 +779,9 @@ declare class FileMetadataService {
|
|
|
770
779
|
recordAccess(path: string, storageType: StorageProvider): Promise<boolean>;
|
|
771
780
|
/**
|
|
772
781
|
* Record a file deletion
|
|
782
|
+
* changedBy is accepted for API consistency but not written (record is deleted)
|
|
773
783
|
*/
|
|
774
|
-
recordDelete(path: string, storageType: StorageProvider): Promise<boolean>;
|
|
784
|
+
recordDelete(path: string, storageType: StorageProvider, _changedBy?: string): Promise<boolean>;
|
|
775
785
|
/**
|
|
776
786
|
* Record a directory deletion (recursive)
|
|
777
787
|
*/
|
|
@@ -779,11 +789,11 @@ declare class FileMetadataService {
|
|
|
779
789
|
/**
|
|
780
790
|
* Record a file or folder move
|
|
781
791
|
*/
|
|
782
|
-
recordMove(sourcePath: string, destinationPath: string, storageType: StorageProvider): Promise<boolean>;
|
|
792
|
+
recordMove(sourcePath: string, destinationPath: string, storageType: StorageProvider, changedBy?: string): Promise<boolean>;
|
|
783
793
|
/**
|
|
784
794
|
* Record a file or folder rename
|
|
785
795
|
*/
|
|
786
|
-
recordRename(path: string, newName: string, storageType: StorageProvider): Promise<boolean>;
|
|
796
|
+
recordRename(path: string, newName: string, storageType: StorageProvider, changedBy?: string): Promise<boolean>;
|
|
787
797
|
/**
|
|
788
798
|
* Find a record by path and storage type
|
|
789
799
|
*/
|
|
@@ -887,9 +897,9 @@ declare class FileMetadataService {
|
|
|
887
897
|
*/
|
|
888
898
|
softDelete(fileId: string): Promise<boolean>;
|
|
889
899
|
/**
|
|
890
|
-
* Update specific V2 fields on a record
|
|
900
|
+
* Update specific V2/V4 fields on a record
|
|
891
901
|
*/
|
|
892
|
-
updateFields(fileId: string, fields: Partial<Pick<FileMetadataRecordV2, 'scope_id' | 'uploaded_by' | 'original_filename' | 'storage_verified_at' | 'status' | 'content_tag'>>): Promise<boolean>;
|
|
902
|
+
updateFields(fileId: string, fields: Partial<Pick<FileMetadataRecordV2, 'scope_id' | 'uploaded_by' | 'original_filename' | 'storage_verified_at' | 'status' | 'content_tag' | 'changed_by' | 'source_url'>>): Promise<boolean>;
|
|
893
903
|
/**
|
|
894
904
|
* Find orphaned files (zero references)
|
|
895
905
|
*/
|
|
@@ -1053,6 +1063,142 @@ declare function createFileManager(options?: FileManagerOptions): FileManager;
|
|
|
1053
1063
|
*/
|
|
1054
1064
|
declare function createInitializedFileManager(options?: FileManagerOptions): Promise<FileManager>;
|
|
1055
1065
|
|
|
1066
|
+
/**
|
|
1067
|
+
* Quota Service
|
|
1068
|
+
* Per-scope opt-in quota tracking with threshold callbacks.
|
|
1069
|
+
*
|
|
1070
|
+
* A scope without a hazo_file_quotas row has no quota and uploads succeed (fail-open).
|
|
1071
|
+
*/
|
|
1072
|
+
/**
|
|
1073
|
+
* Quota status for a scope
|
|
1074
|
+
*/
|
|
1075
|
+
interface QuotaStatus {
|
|
1076
|
+
scopeId: string;
|
|
1077
|
+
byteLimit: number;
|
|
1078
|
+
byteUsed: number;
|
|
1079
|
+
percentUsed: number;
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Event emitted when usage crosses a configured threshold band
|
|
1083
|
+
*/
|
|
1084
|
+
interface QuotaThresholdEvent {
|
|
1085
|
+
scopeId: string;
|
|
1086
|
+
/** Fractional threshold crossed, e.g. 0.80 or 0.95 */
|
|
1087
|
+
percent: number;
|
|
1088
|
+
bytesUsed: number;
|
|
1089
|
+
byteLimit: number;
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Raw row shape from hazo_file_quotas table
|
|
1093
|
+
*/
|
|
1094
|
+
interface QuotaRow {
|
|
1095
|
+
scope_id: string;
|
|
1096
|
+
byte_limit: number;
|
|
1097
|
+
byte_used: number;
|
|
1098
|
+
updated_at: string;
|
|
1099
|
+
[key: string]: unknown;
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Minimal interface for the quota CRUD service (hazo_connect compatible)
|
|
1103
|
+
*/
|
|
1104
|
+
interface QuotaCrudServiceLike {
|
|
1105
|
+
findBy(criteria: Record<string, unknown>): Promise<QuotaRow[]>;
|
|
1106
|
+
findOneBy(criteria: Record<string, unknown>): Promise<QuotaRow | null>;
|
|
1107
|
+
insert(data: Partial<QuotaRow> | Partial<QuotaRow>[]): Promise<QuotaRow[]>;
|
|
1108
|
+
updateById(id: unknown, patch: Partial<QuotaRow>): Promise<QuotaRow[]>;
|
|
1109
|
+
list(configure?: (qb: unknown) => unknown): Promise<QuotaRow[]>;
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Options for QuotaService
|
|
1113
|
+
*/
|
|
1114
|
+
interface QuotaServiceOptions {
|
|
1115
|
+
/** hazo_connect CRUD service pointed at hazo_file_quotas table */
|
|
1116
|
+
crudService: QuotaCrudServiceLike;
|
|
1117
|
+
/** Callback fired when usage crosses a threshold band */
|
|
1118
|
+
onThreshold?: (event: QuotaThresholdEvent) => void;
|
|
1119
|
+
/** Fractional threshold bands (default: [0.80, 0.95]) */
|
|
1120
|
+
bands?: number[];
|
|
1121
|
+
/** Logger for diagnostics */
|
|
1122
|
+
logger?: {
|
|
1123
|
+
debug?(message: string, data?: Record<string, unknown>): void;
|
|
1124
|
+
warn?(message: string, data?: Record<string, unknown>): void;
|
|
1125
|
+
error?(message: string, data?: Record<string, unknown>): void;
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Per-scope opt-in quota tracking.
|
|
1130
|
+
*
|
|
1131
|
+
* Fail-open: a scope without a quota row has no quota and all uploads succeed.
|
|
1132
|
+
*/
|
|
1133
|
+
declare class QuotaService {
|
|
1134
|
+
private crud;
|
|
1135
|
+
private onThreshold?;
|
|
1136
|
+
private bands;
|
|
1137
|
+
private logger?;
|
|
1138
|
+
constructor(opts: QuotaServiceOptions);
|
|
1139
|
+
/**
|
|
1140
|
+
* Get quota status for a scope.
|
|
1141
|
+
* Returns null if no quota row exists (fail-open = no quota set).
|
|
1142
|
+
*/
|
|
1143
|
+
getQuota(scopeId: string): Promise<QuotaStatus | null>;
|
|
1144
|
+
/**
|
|
1145
|
+
* Set (or update) the byte limit for a scope.
|
|
1146
|
+
* Creates a quota row if one does not exist (with byte_used = 0).
|
|
1147
|
+
* Returns the current stored status after upsert.
|
|
1148
|
+
*
|
|
1149
|
+
* @note This method does NOT auto-reconcile byte_used via a SUM query —
|
|
1150
|
+
* it simply upserts the limit and returns the stored row. To reconcile
|
|
1151
|
+
* byte_used against actual file sizes, call recomputeQuota() separately
|
|
1152
|
+
* after a SUM(file_size) query on hazo_files for the scope.
|
|
1153
|
+
*/
|
|
1154
|
+
setQuotaLimit(scopeId: string, bytes: number): Promise<QuotaStatus>;
|
|
1155
|
+
/**
|
|
1156
|
+
* Recompute byteUsed by reading the current row.
|
|
1157
|
+
* (Full reconciliation against actual file sizes should be done externally
|
|
1158
|
+
* via a SUM query on hazo_files; this method just returns the stored state.)
|
|
1159
|
+
*/
|
|
1160
|
+
recomputeQuota(scopeId: string): Promise<QuotaStatus>;
|
|
1161
|
+
/**
|
|
1162
|
+
* Pre-upload check ONLY — does NOT increment.
|
|
1163
|
+
* Throws QuotaExceededError if the upload would exceed the limit.
|
|
1164
|
+
* If no quota row exists for the scope, succeeds silently (fail-open).
|
|
1165
|
+
*
|
|
1166
|
+
* Use this before the upload, then call incrementUsage after confirmed success.
|
|
1167
|
+
* This prevents quota inflation when an upload fails mid-stream.
|
|
1168
|
+
*/
|
|
1169
|
+
checkQuota(scopeId: string, deltaBytes: number): Promise<void>;
|
|
1170
|
+
/**
|
|
1171
|
+
* Pre-upload check and increment (atomic). Throws QuotaExceededError if the upload
|
|
1172
|
+
* would exceed the limit. If no quota row exists, succeeds silently (fail-open).
|
|
1173
|
+
* Also fires threshold callbacks for any bands crossed by the new usage.
|
|
1174
|
+
*
|
|
1175
|
+
* @deprecated Prefer checkQuota() before upload + incrementUsage() after success.
|
|
1176
|
+
* checkAndIncrement() increments before the upload completes; if the upload
|
|
1177
|
+
* subsequently fails the quota is inflated with no rollback.
|
|
1178
|
+
*/
|
|
1179
|
+
checkAndIncrement(scopeId: string, deltaBytes: number): Promise<void>;
|
|
1180
|
+
/**
|
|
1181
|
+
* Decrement usage (call after soft-delete or hard-delete).
|
|
1182
|
+
* Clamps to zero; no-ops if no quota row.
|
|
1183
|
+
*/
|
|
1184
|
+
decrementUsage(scopeId: string, deltaBytes: number): Promise<void>;
|
|
1185
|
+
/**
|
|
1186
|
+
* Increment usage manually (admin override).
|
|
1187
|
+
* Does NOT throw on exceeded quota — admin is explicitly bypassing.
|
|
1188
|
+
*/
|
|
1189
|
+
incrementUsage(scopeId: string, deltaBytes: number): Promise<void>;
|
|
1190
|
+
/**
|
|
1191
|
+
* Fire threshold callbacks for all bands crossed going from prevUsed → newUsed.
|
|
1192
|
+
* Bands are sorted ascending so callbacks fire in order (80% before 95%).
|
|
1193
|
+
*/
|
|
1194
|
+
private fireThresholdCallbacks;
|
|
1195
|
+
private rowToStatus;
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Create a QuotaService instance
|
|
1199
|
+
*/
|
|
1200
|
+
declare function createQuotaService(opts: QuotaServiceOptions): QuotaService;
|
|
1201
|
+
|
|
1056
1202
|
/**
|
|
1057
1203
|
* Tracked File Manager
|
|
1058
1204
|
* Extends FileManager to add database tracking of file operations
|
|
@@ -1068,6 +1214,10 @@ interface TrackedFileManagerFullOptions extends FileManagerOptions {
|
|
|
1068
1214
|
tracking?: DatabaseTrackingConfig;
|
|
1069
1215
|
/** Logger for structured file operation logging */
|
|
1070
1216
|
logger?: MetadataLogger;
|
|
1217
|
+
/** Optional quota service for per-scope upload limits */
|
|
1218
|
+
quotaService?: QuotaService;
|
|
1219
|
+
/** SSRF allowlist passed to importFromUrl (host strings) */
|
|
1220
|
+
ssrfAllowlist?: string[];
|
|
1071
1221
|
}
|
|
1072
1222
|
/**
|
|
1073
1223
|
* Extended upload options with hash tracking
|
|
@@ -1081,6 +1231,10 @@ interface TrackedUploadOptions extends UploadOptions {
|
|
|
1081
1231
|
* Set to true when you need to immediately query/update the file record.
|
|
1082
1232
|
*/
|
|
1083
1233
|
awaitRecording?: boolean;
|
|
1234
|
+
/** Actor ID (UUID) to record in uploaded_by and changed_by columns */
|
|
1235
|
+
actor_id?: string;
|
|
1236
|
+
/** Scope ID for quota tracking and organizational grouping */
|
|
1237
|
+
scope_id?: string;
|
|
1084
1238
|
}
|
|
1085
1239
|
/**
|
|
1086
1240
|
* TrackedFileManager - File manager with database tracking
|
|
@@ -1091,6 +1245,8 @@ interface TrackedUploadOptions extends UploadOptions {
|
|
|
1091
1245
|
declare class TrackedFileManager extends FileManager {
|
|
1092
1246
|
private metadataService;
|
|
1093
1247
|
private trackingConfig;
|
|
1248
|
+
private quotaService;
|
|
1249
|
+
private ssrfAllowlist;
|
|
1094
1250
|
constructor(options?: TrackedFileManagerFullOptions);
|
|
1095
1251
|
/**
|
|
1096
1252
|
* Check if tracking is enabled and service is available
|
|
@@ -1120,19 +1276,27 @@ declare class TrackedFileManager extends FileManager {
|
|
|
1120
1276
|
/**
|
|
1121
1277
|
* Move a file or folder and update its path in the database
|
|
1122
1278
|
*/
|
|
1123
|
-
moveItem(sourcePath: string, destinationPath: string, options?: MoveOptions
|
|
1279
|
+
moveItem(sourcePath: string, destinationPath: string, options?: MoveOptions & {
|
|
1280
|
+
actor_id?: string;
|
|
1281
|
+
}): Promise<OperationResult<FileSystemItem>>;
|
|
1124
1282
|
/**
|
|
1125
1283
|
* Delete a file and remove its record from the database
|
|
1126
1284
|
*/
|
|
1127
|
-
deleteFile(path: string
|
|
1285
|
+
deleteFile(path: string, opts?: {
|
|
1286
|
+
actor_id?: string;
|
|
1287
|
+
}): Promise<OperationResult>;
|
|
1128
1288
|
/**
|
|
1129
1289
|
* Rename a file and update its record in the database
|
|
1130
1290
|
*/
|
|
1131
|
-
renameFile(path: string, newName: string, options?: RenameOptions
|
|
1291
|
+
renameFile(path: string, newName: string, options?: RenameOptions & {
|
|
1292
|
+
actor_id?: string;
|
|
1293
|
+
}): Promise<OperationResult<FileItem>>;
|
|
1132
1294
|
/**
|
|
1133
1295
|
* Rename a folder and update its record in the database
|
|
1134
1296
|
*/
|
|
1135
|
-
renameFolder(path: string, newName: string, options?: RenameOptions
|
|
1297
|
+
renameFolder(path: string, newName: string, options?: RenameOptions & {
|
|
1298
|
+
actor_id?: string;
|
|
1299
|
+
}): Promise<OperationResult<FolderItem>>;
|
|
1136
1300
|
/**
|
|
1137
1301
|
* Write a file with string content and track it
|
|
1138
1302
|
*/
|
|
@@ -1211,8 +1375,33 @@ declare class TrackedFileManager extends FileManager {
|
|
|
1211
1375
|
getFilesById(fileIds: string[]): Promise<FileWithStatus[]>;
|
|
1212
1376
|
/**
|
|
1213
1377
|
* Soft-delete a file (marks as soft_deleted, does not remove physical file)
|
|
1378
|
+
* Also decrements quota usage if quotaService is configured.
|
|
1379
|
+
*/
|
|
1380
|
+
softDeleteFile(fileId: string, opts?: {
|
|
1381
|
+
actor_id?: string;
|
|
1382
|
+
}): Promise<boolean>;
|
|
1383
|
+
/**
|
|
1384
|
+
* Get quota status for a scope.
|
|
1385
|
+
* Returns null if no quota is configured (fail-open).
|
|
1386
|
+
*/
|
|
1387
|
+
getQuota(scopeId: string): Promise<QuotaStatus | null>;
|
|
1388
|
+
/**
|
|
1389
|
+
* Set or update the byte limit for a scope.
|
|
1390
|
+
* Creates a quota row if one does not exist.
|
|
1391
|
+
*/
|
|
1392
|
+
setQuotaLimit(scopeId: string, bytes: number): Promise<QuotaStatus | null>;
|
|
1393
|
+
/**
|
|
1394
|
+
* Recompute and return the quota status for a scope.
|
|
1395
|
+
*/
|
|
1396
|
+
recomputeQuota(scopeId: string): Promise<QuotaStatus | null>;
|
|
1397
|
+
/**
|
|
1398
|
+
* Increment usage for a scope (admin override — does not throw on exceeded quota).
|
|
1214
1399
|
*/
|
|
1215
|
-
|
|
1400
|
+
incrementQuotaUsage(scopeId: string, deltaBytes: number): Promise<void>;
|
|
1401
|
+
/**
|
|
1402
|
+
* Decrement usage for a scope (e.g. after manual cleanup).
|
|
1403
|
+
*/
|
|
1404
|
+
decrementQuotaUsage(scopeId: string, deltaBytes: number): Promise<void>;
|
|
1216
1405
|
/**
|
|
1217
1406
|
* Find orphaned files (files with zero references)
|
|
1218
1407
|
*/
|
|
@@ -1235,6 +1424,31 @@ declare class TrackedFileManager extends FileManager {
|
|
|
1235
1424
|
file_id?: string;
|
|
1236
1425
|
ref_id?: string;
|
|
1237
1426
|
}>>;
|
|
1427
|
+
/**
|
|
1428
|
+
* Import a file from a URL into virtual storage.
|
|
1429
|
+
*
|
|
1430
|
+
* Uses hazo_secure/fetch for SSRF protection (optional peer dependency).
|
|
1431
|
+
* Streams the response to a temp file, counting bytes live.
|
|
1432
|
+
* On cap exceeded: aborts, deletes temp file, throws ImportSizeCapError.
|
|
1433
|
+
* On success: uploads to virtualPath, sets source_url in DB record.
|
|
1434
|
+
*
|
|
1435
|
+
* @param url - URL to fetch
|
|
1436
|
+
* @param virtualPath - Destination virtual path in storage
|
|
1437
|
+
* @param opts.referrer - Optional Referer header to send
|
|
1438
|
+
* @param opts.maxBytes - Maximum response size in bytes (default: 50MB)
|
|
1439
|
+
* @param opts.actor_id - Actor UUID to record in uploaded_by / changed_by
|
|
1440
|
+
*/
|
|
1441
|
+
importFromUrl(url: string, virtualPath: string, opts?: {
|
|
1442
|
+
referrer?: string;
|
|
1443
|
+
maxBytes?: number;
|
|
1444
|
+
actor_id?: string;
|
|
1445
|
+
/** Scope ID for quota checking and tracking. If provided, quota is checked before upload. */
|
|
1446
|
+
scope_id?: string;
|
|
1447
|
+
}): Promise<OperationResult<{
|
|
1448
|
+
virtualPath: string;
|
|
1449
|
+
size: number;
|
|
1450
|
+
sourceUrl: string;
|
|
1451
|
+
}>>;
|
|
1238
1452
|
}
|
|
1239
1453
|
/**
|
|
1240
1454
|
* Create a new TrackedFileManager instance
|
|
@@ -1804,6 +2018,29 @@ interface HazoFilesServerOptions {
|
|
|
1804
2018
|
* When set, uploads can automatically classify document content.
|
|
1805
2019
|
*/
|
|
1806
2020
|
defaultContentTagConfig?: ContentTagConfig;
|
|
2021
|
+
/**
|
|
2022
|
+
* SSRF protection configuration for importFromUrl.
|
|
2023
|
+
* When provided, only URLs matching the allowlist will be permitted.
|
|
2024
|
+
*/
|
|
2025
|
+
ssrf?: {
|
|
2026
|
+
/** Allowed host strings (e.g. ['example.com', 'cdn.myapp.com']) */
|
|
2027
|
+
allowlist: string[];
|
|
2028
|
+
};
|
|
2029
|
+
/**
|
|
2030
|
+
* CRUD service for the hazo_file_quotas table.
|
|
2031
|
+
* Required if you want to use per-scope quota tracking.
|
|
2032
|
+
*/
|
|
2033
|
+
quotaCrudService?: QuotaCrudServiceLike;
|
|
2034
|
+
/**
|
|
2035
|
+
* Callback fired when a quota threshold band is crossed.
|
|
2036
|
+
* Receives scopeId, percent crossed, bytesUsed, and byteLimit.
|
|
2037
|
+
*/
|
|
2038
|
+
onQuotaThreshold?: (event: QuotaThresholdEvent) => void;
|
|
2039
|
+
/**
|
|
2040
|
+
* Fractional threshold bands that trigger onQuotaThreshold.
|
|
2041
|
+
* Default: [0.80, 0.95]
|
|
2042
|
+
*/
|
|
2043
|
+
quotaBands?: number[];
|
|
1807
2044
|
}
|
|
1808
2045
|
/**
|
|
1809
2046
|
* Result of createHazoFilesServer
|
|
@@ -1881,6 +2118,95 @@ declare function createHazoFilesServer(options?: HazoFilesServerOptions): Promis
|
|
|
1881
2118
|
*/
|
|
1882
2119
|
declare function createBasicFileManager(config: HazoFilesConfig, crudService?: CrudServiceLike<FileMetadataRecord>): Promise<TrackedFileManager>;
|
|
1883
2120
|
|
|
2121
|
+
/**
|
|
2122
|
+
* Purge Job Handlers
|
|
2123
|
+
*
|
|
2124
|
+
* Factory for hazo_jobs-compatible job handlers that perform file lifecycle purge operations.
|
|
2125
|
+
* Uses types-only import from hazo_jobs — no runtime dependency.
|
|
2126
|
+
*
|
|
2127
|
+
* @example
|
|
2128
|
+
* ```typescript
|
|
2129
|
+
* import { createPurgeJobHandlers, HAZO_FILES_JOB_TYPES } from 'hazo_files/server';
|
|
2130
|
+
*
|
|
2131
|
+
* const handlers = createPurgeJobHandlers(fm, {
|
|
2132
|
+
* submitJob: (type, payload) => jobs.submit({ type, payload }),
|
|
2133
|
+
* });
|
|
2134
|
+
*
|
|
2135
|
+
* worker.register(HAZO_FILES_JOB_TYPES.PURGE_PLAN, handlers[HAZO_FILES_JOB_TYPES.PURGE_PLAN]);
|
|
2136
|
+
* worker.register(HAZO_FILES_JOB_TYPES.PURGE_ONE, handlers[HAZO_FILES_JOB_TYPES.PURGE_ONE]);
|
|
2137
|
+
* ```
|
|
2138
|
+
*/
|
|
2139
|
+
|
|
2140
|
+
/**
|
|
2141
|
+
* Job type constants for hazo_files purge operations
|
|
2142
|
+
*/
|
|
2143
|
+
declare const HAZO_FILES_JOB_TYPES: {
|
|
2144
|
+
readonly PURGE_PLAN: "hazo_files.purge_plan";
|
|
2145
|
+
readonly PURGE_ONE: "hazo_files.purge_one";
|
|
2146
|
+
};
|
|
2147
|
+
type HazoFilesJobType = typeof HAZO_FILES_JOB_TYPES[keyof typeof HAZO_FILES_JOB_TYPES];
|
|
2148
|
+
/**
|
|
2149
|
+
* Payload for the purge_plan job.
|
|
2150
|
+
* Finds soft-deleted files older than retentionDays and schedules purge_one jobs.
|
|
2151
|
+
*/
|
|
2152
|
+
interface PurgePlanPayload {
|
|
2153
|
+
/** Number of days after soft-delete before a file is eligible for purge. Default: 30 */
|
|
2154
|
+
retentionDays?: number;
|
|
2155
|
+
/**
|
|
2156
|
+
* Dry-run mode: return wouldPurge list but do not submit any purge_one jobs
|
|
2157
|
+
* and do not delete anything.
|
|
2158
|
+
*/
|
|
2159
|
+
dryRun?: boolean;
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2162
|
+
* Payload for the purge_one job.
|
|
2163
|
+
* Hard-deletes a single soft-deleted file record and its physical storage.
|
|
2164
|
+
*/
|
|
2165
|
+
interface PurgeOnePayload {
|
|
2166
|
+
fileId: string;
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* Result returned by the purge_plan handler
|
|
2170
|
+
*/
|
|
2171
|
+
interface PurgePlanResult {
|
|
2172
|
+
/** Number of files purged (or queued for purge) */
|
|
2173
|
+
purgedCount: number;
|
|
2174
|
+
/**
|
|
2175
|
+
* Populated only when dryRun: true.
|
|
2176
|
+
* Array of fileIds that would be purged.
|
|
2177
|
+
*/
|
|
2178
|
+
wouldPurge?: string[];
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Options for the purge job handler factory
|
|
2182
|
+
*/
|
|
2183
|
+
interface PurgeJobHandlerOptions {
|
|
2184
|
+
/**
|
|
2185
|
+
* Function to submit a child job.
|
|
2186
|
+
* When provided, purge_plan submits individual purge_one jobs via this function.
|
|
2187
|
+
* When omitted, purge_plan returns the fileIds in the result and does not submit jobs.
|
|
2188
|
+
*/
|
|
2189
|
+
submitJob?: (type: string, payload: unknown) => Promise<void>;
|
|
2190
|
+
/** Logger for diagnostics */
|
|
2191
|
+
logger?: {
|
|
2192
|
+
info?(message: string, data?: Record<string, unknown>): void;
|
|
2193
|
+
warn?(message: string, data?: Record<string, unknown>): void;
|
|
2194
|
+
error?(message: string, data?: Record<string, unknown>): void;
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2197
|
+
/**
|
|
2198
|
+
* Create purge job handlers for hazo_files lifecycle management.
|
|
2199
|
+
*
|
|
2200
|
+
* The handlers are compatible with hazo_jobs JobHandler<TPayload, TResult>.
|
|
2201
|
+
*
|
|
2202
|
+
* @param fm - TrackedFileManager instance
|
|
2203
|
+
* @param opts - Optional submitJob function and logger
|
|
2204
|
+
*/
|
|
2205
|
+
declare function createPurgeJobHandlers(fm: TrackedFileManager, opts?: PurgeJobHandlerOptions): {
|
|
2206
|
+
[HAZO_FILES_JOB_TYPES.PURGE_PLAN]: JobHandler<PurgePlanPayload, PurgePlanResult>;
|
|
2207
|
+
[HAZO_FILES_JOB_TYPES.PURGE_ONE]: JobHandler<PurgeOnePayload>;
|
|
2208
|
+
};
|
|
2209
|
+
|
|
1884
2210
|
/**
|
|
1885
2211
|
* Database Schema Exports for hazo_files
|
|
1886
2212
|
*
|
|
@@ -1948,6 +2274,10 @@ interface HazoFilesColumnDefinitions {
|
|
|
1948
2274
|
original_filename: 'TEXT';
|
|
1949
2275
|
/** Content tag classifying the document type (V3) */
|
|
1950
2276
|
content_tag: 'TEXT';
|
|
2277
|
+
/** UUID of the actor who last mutated this record (V4 — migration 004) */
|
|
2278
|
+
changed_by: 'TEXT' | 'UUID';
|
|
2279
|
+
/** Source URL when file was imported via importFromUrl (V4 — migration 005) */
|
|
2280
|
+
source_url: 'TEXT';
|
|
1951
2281
|
}
|
|
1952
2282
|
/**
|
|
1953
2283
|
* Schema definition for a specific database type
|
|
@@ -2170,6 +2500,86 @@ declare const HAZO_FILES_MIGRATION_V3: HazoFilesMigrationV3;
|
|
|
2170
2500
|
* Get V3 migration statements for a custom table name
|
|
2171
2501
|
*/
|
|
2172
2502
|
declare function getMigrationV3ForTable(tableName: string, dbType: 'sqlite' | 'postgres'): MigrationSchemaDefinition;
|
|
2503
|
+
/**
|
|
2504
|
+
* Migration schema for adding V4 actor-tracking and source_url columns.
|
|
2505
|
+
*
|
|
2506
|
+
* @note PostgreSQL ALTER statements use `IF NOT EXISTS` and are idempotent.
|
|
2507
|
+
* SQLite `ALTER TABLE ADD COLUMN` does NOT support `IF NOT EXISTS` —
|
|
2508
|
+
* wrap each statement in a try/catch or check `PRAGMA table_info(hazo_files)`
|
|
2509
|
+
* before running on SQLite to avoid "duplicate column name" errors.
|
|
2510
|
+
*
|
|
2511
|
+
* @example
|
|
2512
|
+
* ```typescript
|
|
2513
|
+
* import { HAZO_FILES_MIGRATION_V4 } from 'hazo_files';
|
|
2514
|
+
*
|
|
2515
|
+
* // SQLite — wrap in try/catch (NOT idempotent)
|
|
2516
|
+
* for (const stmt of HAZO_FILES_MIGRATION_V4.sqlite.alterStatements) {
|
|
2517
|
+
* try { await db.run(stmt); } catch { /* column already exists *\/ }
|
|
2518
|
+
* }
|
|
2519
|
+
*
|
|
2520
|
+
* // PostgreSQL — idempotent (uses IF NOT EXISTS)
|
|
2521
|
+
* for (const stmt of HAZO_FILES_MIGRATION_V4.postgres.alterStatements) {
|
|
2522
|
+
* await client.query(stmt);
|
|
2523
|
+
* }
|
|
2524
|
+
* for (const idx of HAZO_FILES_MIGRATION_V4.postgres.indexes) {
|
|
2525
|
+
* await client.query(idx);
|
|
2526
|
+
* }
|
|
2527
|
+
* ```
|
|
2528
|
+
*/
|
|
2529
|
+
interface HazoFilesMigrationV4 {
|
|
2530
|
+
/** Default table name */
|
|
2531
|
+
tableName: string;
|
|
2532
|
+
/** SQLite migration statements */
|
|
2533
|
+
sqlite: MigrationSchemaDefinition;
|
|
2534
|
+
/** PostgreSQL migration statements */
|
|
2535
|
+
postgres: MigrationSchemaDefinition;
|
|
2536
|
+
/** New column names added in V4 */
|
|
2537
|
+
newColumns: readonly string[];
|
|
2538
|
+
}
|
|
2539
|
+
declare const HAZO_FILES_MIGRATION_V4: HazoFilesMigrationV4;
|
|
2540
|
+
/**
|
|
2541
|
+
* Get V4 migration statements for a custom table name
|
|
2542
|
+
*/
|
|
2543
|
+
declare function getMigrationV4ForTable(tableName: string, dbType: 'sqlite' | 'postgres'): MigrationSchemaDefinition;
|
|
2544
|
+
/**
|
|
2545
|
+
* Default table name for quota tracking
|
|
2546
|
+
*/
|
|
2547
|
+
declare const HAZO_FILE_QUOTAS_DEFAULT_TABLE_NAME = "hazo_file_quotas";
|
|
2548
|
+
/**
|
|
2549
|
+
* Column definitions for the hazo_file_quotas table
|
|
2550
|
+
*/
|
|
2551
|
+
interface HazoFileQuotasColumnDefinitions {
|
|
2552
|
+
/** Scope ID — primary key, links to organizational unit */
|
|
2553
|
+
scope_id: 'TEXT' | 'UUID';
|
|
2554
|
+
/** Maximum allowed bytes for this scope */
|
|
2555
|
+
byte_limit: 'INTEGER' | 'BIGINT';
|
|
2556
|
+
/** Current bytes used (reconciled against actual file records) */
|
|
2557
|
+
byte_used: 'INTEGER' | 'BIGINT';
|
|
2558
|
+
/** ISO timestamp of last update */
|
|
2559
|
+
updated_at: 'TEXT' | 'TIMESTAMP';
|
|
2560
|
+
}
|
|
2561
|
+
/**
|
|
2562
|
+
* Schema definition for hazo_file_quotas table.
|
|
2563
|
+
*
|
|
2564
|
+
* Opt-in per-scope quota. A scope without a row has no quota (fail-open).
|
|
2565
|
+
*
|
|
2566
|
+
* @example
|
|
2567
|
+
* ```typescript
|
|
2568
|
+
* import { HAZO_FILE_QUOTAS_TABLE_SCHEMA } from 'hazo_files';
|
|
2569
|
+
*
|
|
2570
|
+
* // PostgreSQL
|
|
2571
|
+
* await client.query(HAZO_FILE_QUOTAS_TABLE_SCHEMA.postgres.ddl);
|
|
2572
|
+
* for (const idx of HAZO_FILE_QUOTAS_TABLE_SCHEMA.postgres.indexes) {
|
|
2573
|
+
* await client.query(idx);
|
|
2574
|
+
* }
|
|
2575
|
+
* ```
|
|
2576
|
+
*/
|
|
2577
|
+
declare const HAZO_FILE_QUOTAS_TABLE_SCHEMA: {
|
|
2578
|
+
tableName: string;
|
|
2579
|
+
sqlite: DatabaseSchemaDefinition;
|
|
2580
|
+
postgres: DatabaseSchemaDefinition;
|
|
2581
|
+
columns: readonly ["scope_id", "byte_limit", "byte_used", "updated_at"];
|
|
2582
|
+
};
|
|
2173
2583
|
|
|
2174
2584
|
/**
|
|
2175
2585
|
* Migration: Add Reference Tracking (V2)
|
|
@@ -2853,6 +3263,15 @@ declare class ConfigurationError extends HazoFilesError {
|
|
|
2853
3263
|
declare class OperationError extends HazoFilesError {
|
|
2854
3264
|
constructor(operation: string, message: string, details?: Record<string, unknown>);
|
|
2855
3265
|
}
|
|
3266
|
+
declare class QuotaExceededError extends HazoFilesError {
|
|
3267
|
+
constructor(scopeId: string, byteUsed: number, byteLimit: number, deltaBytes: number);
|
|
3268
|
+
}
|
|
3269
|
+
declare class SSRFError extends HazoFilesError {
|
|
3270
|
+
constructor(url: string, reason: string);
|
|
3271
|
+
}
|
|
3272
|
+
declare class ImportSizeCapError extends HazoFilesError {
|
|
3273
|
+
constructor(url: string, capBytes: number);
|
|
3274
|
+
}
|
|
2856
3275
|
|
|
2857
3276
|
/**
|
|
2858
3277
|
* MIME type utilities
|
|
@@ -3225,4 +3644,4 @@ declare function toV2Record(record: FileMetadataRecord): FileMetadataRecordV2;
|
|
|
3225
3644
|
*/
|
|
3226
3645
|
declare function buildFileWithStatus(record: FileMetadataRecord): FileWithStatus;
|
|
3227
3646
|
|
|
3228
|
-
export { ALL_SYSTEM_VARIABLES, type AddExtractionOptions, type AddRefOptions, type AuthCallbacks, AuthenticationError, type CleanupOrphanedOptions, ConfigurationError, type ContentTagConfig, type CreateFolderOptions, type CrudServiceLike, DEFAULT_DATE_FORMATS, type DatabaseSchemaDefinition, type DatabaseTrackingConfig, DirectoryExistsError, DirectoryNotEmptyError, DirectoryNotFoundError, type DownloadOptions, DropboxAuth, type DropboxAuthCallbacks, type DropboxAuthConfig, type DropboxConfig, DropboxModule, type DropboxTokenData, type ExtractionData, type ExtractionOptions, type ExtractionResult, type FileBrowserState, type FileDataStructure, FileExistsError, type FileInfo, type FileItem, FileManager, type FileManagerOptions, type FileMetadataInput, type FileMetadataRecord, type FileMetadataRecordV2, FileMetadataService, type FileMetadataServiceOptions, type FileMetadataUpdate, FileNotFoundError, type FileRef, type FileRefVisibility, type FileStatus, type 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_MIGRATION_V3, HAZO_FILES_NAMING_DEFAULT_TABLE_NAME, HAZO_FILES_NAMING_TABLE_SCHEMA, HAZO_FILES_TABLE_SCHEMA, type HazoFilesColumnDefinitions, type HazoFilesConfig, HazoFilesError, type HazoFilesMigrationV2, type HazoFilesMigrationV3, type HazoFilesNamingColumnDefinitions, type HazoFilesNamingTableSchema, type HazoFilesServerInstance, type HazoFilesServerOptions, type HazoFilesTableSchema, type HazoLLMInstance, type HazoLogger, InvalidExtensionError, InvalidPathError, LLMExtractionService, type LLMFactory, type LLMFactoryConfig, type LLMProvider, type ListNamingConventionsOptions, type ListOptions, type LocalStorageConfig, LocalStorageModule, type MetadataLogger, type MigrationExecutor, type MigrationSchemaDefinition, type MoveOptions, type NameGenerationOptions, type NamingConventionInput, type NamingConventionRecord, NamingConventionService, type NamingConventionServiceOptions, type NamingConventionType, type NamingConventionUpdate, type NamingRuleConfiguratorProps, type NamingRuleHistoryEntry, type NamingRuleSchema, type NamingVariable, OperationError, type OperationResult, type ParsedNamingConvention, type PatternSegment, PermissionDeniedError, type 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, createBasicFileManager, createDropboxAuth, createDropboxModule, createEmptyFileDataStructure, createEmptyNamingRuleSchema, createFileItem, createFileManager, createFileMetadataService, createFileRef, createFolderItem, createGoogleDriveAuth, createGoogleDriveModule, createHazoFilesServer, 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, getMigrationV3ForTable, getMimeType, getNameWithoutExtension, getNamingSchemaForTable, getParentPath, getPathSegments, getRegisteredProviders, getRelativePath, getSchemaForTable, getSystemVariablePreviewValues, hasExtension, hasExtractionStructure, hasFileContentChanged, hashesEqual, hazo_files_generate_file_name, hazo_files_generate_folder_name, isAudio, isChildPath, isCounterVariable, isDateVariable, isDocument, isFile, isFileMetadataVariable, isFolder, isImage, isPreviewable, isProviderRegistered, isText, isVideo, joinPath, loadConfig, loadConfigAsync, migrateToV2, migrateToV3, normalizePath, parseConfig, parseFileData, parseFileRefs, parsePatternString, patternToString, recalculateMergedData, registerModule, removeExtractionById, removeExtractionByIndex, removeRefFromArray, removeRefsByCriteriaFromArray, sanitizeFilename, saveConfig, sortItems, stringifyFileData, stringifyFileRefs, successResult, toV2Record, updateExtractionById, validateExtractionData, validateFileDataStructure, validateNamingRuleSchema, validatePath };
|
|
3647
|
+
export { ALL_SYSTEM_VARIABLES, type AddExtractionOptions, type AddRefOptions, type AuthCallbacks, AuthenticationError, type CleanupOrphanedOptions, ConfigurationError, type ContentTagConfig, type CreateFolderOptions, type CrudServiceLike, DEFAULT_DATE_FORMATS, type DatabaseSchemaDefinition, type DatabaseTrackingConfig, DirectoryExistsError, DirectoryNotEmptyError, DirectoryNotFoundError, type DownloadOptions, DropboxAuth, type DropboxAuthCallbacks, type DropboxAuthConfig, type DropboxConfig, DropboxModule, type DropboxTokenData, type ExtractionData, type ExtractionOptions, type ExtractionResult, type FileBrowserState, type FileDataStructure, FileExistsError, type FileInfo, type FileItem, FileManager, type FileManagerOptions, type FileMetadataInput, type FileMetadataRecord, type FileMetadataRecordV2, FileMetadataService, type FileMetadataServiceOptions, type FileMetadataUpdate, FileNotFoundError, type FileRef, type FileRefVisibility, type FileStatus, type FileSystemItem, FileTooLargeError, type FileWithStatus, type FindOrphanedOptions, type FolderItem, type GeneratedNameResult, type GoogleAuthConfig, GoogleDriveAuth, type GoogleDriveConfig, GoogleDriveModule, HAZO_FILES_DEFAULT_TABLE_NAME, HAZO_FILES_JOB_TYPES, HAZO_FILES_MIGRATION_V2, HAZO_FILES_MIGRATION_V3, HAZO_FILES_MIGRATION_V4, HAZO_FILES_NAMING_DEFAULT_TABLE_NAME, HAZO_FILES_NAMING_TABLE_SCHEMA, HAZO_FILES_TABLE_SCHEMA, HAZO_FILE_QUOTAS_DEFAULT_TABLE_NAME, HAZO_FILE_QUOTAS_TABLE_SCHEMA, type HazoFileQuotasColumnDefinitions, type HazoFilesColumnDefinitions, type HazoFilesConfig, HazoFilesError, type HazoFilesJobType, type HazoFilesMigrationV2, type HazoFilesMigrationV3, type HazoFilesMigrationV4, type HazoFilesNamingColumnDefinitions, type HazoFilesNamingTableSchema, type HazoFilesServerInstance, type HazoFilesServerOptions, type HazoFilesTableSchema, type HazoLLMInstance, type HazoLogger, ImportSizeCapError, InvalidExtensionError, InvalidPathError, LLMExtractionService, type LLMFactory, type LLMFactoryConfig, type LLMProvider, type ListNamingConventionsOptions, type ListOptions, type LocalStorageConfig, LocalStorageModule, type MetadataLogger, type MigrationExecutor, type MigrationSchemaDefinition, type MoveOptions, type NameGenerationOptions, type NamingConventionInput, type NamingConventionRecord, NamingConventionService, type NamingConventionServiceOptions, type NamingConventionType, type NamingConventionUpdate, type NamingRuleConfiguratorProps, type NamingRuleHistoryEntry, type NamingRuleSchema, type NamingVariable, OperationError, type OperationResult, type ParsedNamingConvention, type PatternSegment, PermissionDeniedError, type ProgressCallback, type PurgeJobHandlerOptions, type PurgeOnePayload, type PurgePlanPayload, type PurgePlanResult, type QuotaCrudServiceLike, QuotaExceededError, QuotaService, type QuotaServiceOptions, type QuotaStatus, type QuotaThresholdEvent, type RemoveExtractionOptions, type RemoveRefsCriteria, type RenameOptions, SSRFError, SYSTEM_COUNTER_VARIABLES, SYSTEM_DATE_VARIABLES, SYSTEM_FILE_VARIABLES, type 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, createBasicFileManager, createDropboxAuth, createDropboxModule, createEmptyFileDataStructure, createEmptyNamingRuleSchema, createFileItem, createFileManager, createFileMetadataService, createFileRef, createFolderItem, createGoogleDriveAuth, createGoogleDriveModule, createHazoFilesServer, createInitializedFileManager, createInitializedTrackedFileManager, createLLMExtractionService, createLiteralSegment, createLocalModule, createModule, createNamingConventionService, createPurgeJobHandlers, createQuotaService, createTrackedFileManager, createUploadExtractService, createVariableSegment, deepMerge, errorResult, filterItems, formatBytes, formatCounter, formatDateToken, generateExtractionId, generateId, generatePreviewName, generateRefId, generateSampleConfig, generateSegmentId, getBaseName, getBreadcrumbs, getDirName, getExtension, getExtensionFromMime, getExtractionById, getExtractionCount, getExtractions, getFileCategory, getFileMetadataValues, getMergedData, getMigrationForTable, getMigrationV3ForTable, getMigrationV4ForTable, getMimeType, getNameWithoutExtension, getNamingSchemaForTable, getParentPath, getPathSegments, getRegisteredProviders, getRelativePath, getSchemaForTable, getSystemVariablePreviewValues, hasExtension, hasExtractionStructure, hasFileContentChanged, hashesEqual, hazo_files_generate_file_name, hazo_files_generate_folder_name, isAudio, isChildPath, isCounterVariable, isDateVariable, isDocument, isFile, isFileMetadataVariable, isFolder, isImage, isPreviewable, isProviderRegistered, isText, isVideo, joinPath, loadConfig, loadConfigAsync, migrateToV2, migrateToV3, normalizePath, parseConfig, parseFileData, parseFileRefs, parsePatternString, patternToString, recalculateMergedData, registerModule, removeExtractionById, removeExtractionByIndex, removeRefFromArray, removeRefsByCriteriaFromArray, sanitizeFilename, saveConfig, sortItems, stringifyFileData, stringifyFileRefs, successResult, toV2Record, updateExtractionById, validateExtractionData, validateFileDataStructure, validateNamingRuleSchema, validatePath };
|