hazo_files 2.0.1 → 3.0.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 CHANGED
@@ -5,6 +5,45 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 3.0.0 — 2026-05-29
9
+
10
+ ### Breaking changes (Wave 2 standardisation)
11
+
12
+ - **Required peer dep:** `hazo_core ^1.0.0`. Provides `HazoError` hierarchy, structured logger, and `withContext()` correlation propagation.
13
+ - **Cross-hazo peer-dep major bumps:** `hazo_connect ^3.0.0` (was `^2.7.3`), `hazo_llm_api ^2.0.0` (was `^1.3.0`). Consumers using these alongside `hazo_files` must upgrade them together.
14
+ - **Error API surface:** the 12 `HazoFilesError` subclasses (`FileNotFoundError`, `FileTooLargeError`, etc.) now extend `HazoError` from `hazo_core` and carry `HAZO_FILES_*` codes. Catch sites that used `instanceof HazoFilesError` continue to work; catch sites that matched `error.message` text should switch to `.code`.
15
+
16
+ ### Internal changes
17
+
18
+ - Default logger resolves to `createLogger('hazo_files')` from `hazo_core` (delegates to `hazo_logs`).
19
+ - Google Drive adapter outbound API calls and `LLMExtractionService` provider calls use `fetchWithRequestId()` so `x-request-id` propagates.
20
+ - `TrackedFileManager` operations run inside `withContext({ correlationId })` per call so DB writes and storage writes share the same correlation ID.
21
+
22
+ ### Migration
23
+
24
+ 1. `npm install hazo_core@^1.0.0`.
25
+ 2. Upgrade `hazo_connect` to `^3.0.0` and `hazo_llm_api` to `^2.0.0` if you depend on them.
26
+ 3. No public API method signatures changed — `FileManager` and `TrackedFileManager` methods keep their existing call shape.
27
+
28
+ ## 2.1.1 — 2026-05-24
29
+
30
+ **Docs + housekeeping** — no API changes.
31
+
32
+ - README: added documentation for `NamingTemplate`, `writeWithCollisionRetry`, and the pure `addRef`/`removeRef`/`countRefs` helpers introduced in 2.1.0.
33
+ - `.gitignore`: untracked test-app runtime artifacts (`data/`, `logs/`, `tsconfig.tsbuildinfo`, `*.tgz`).
34
+
35
+ ## 2.1.0 — 2026-05-24
36
+
37
+ **Additive** — no breaking changes from 2.0.x.
38
+
39
+ - `NamingTemplate` DSL with formatters (`slug`, `pad:N`, `upper`, `lower`, `truncate:N`, `date:FMT`). 200-char cap; sanitises `/\:*?"<>|` → `_`; throws on missing variable; dotted-path resolution. Formatters `pad` and `truncate` throw on missing/NaN arg; `date` throws on empty value.
40
+ - `writeWithCollisionRetry` helper with 999-attempt cap; throws `StorageCollisionExhausted`. Renders the `{index}` variable per attempt.
41
+ - Reference tracking helpers: `addRef` / `removeRef` / `countRefs` over `{ file_refs, ref_count }`. Idempotent on same `ref_id`; soft-tombstone via `removed_at`.
42
+
43
+ ### Migration from 2.0.x
44
+
45
+ No required changes. Existing imports continue to work. Use the new helpers to compute filenames and track usage references.
46
+
8
47
  ## 2.0.1 (2026-05-23)
9
48
 
10
49
  ### Added
package/README.md CHANGED
@@ -1564,6 +1564,117 @@ import type {
1564
1564
  } from 'hazo_files';
1565
1565
  ```
1566
1566
 
1567
+ ### Pure Reference Helpers (v2.1.0)
1568
+
1569
+ Functional helpers for manipulating `{ file_refs, ref_count }` objects without a database. Useful for in-memory state management or building your own persistence layer.
1570
+
1571
+ ```typescript
1572
+ import { addRef, removeRef, countRefs } from 'hazo_files';
1573
+ import type { FileWithRefs, FileRef } from 'hazo_files';
1574
+
1575
+ // addRef — idempotent on same ref_id; returns updated object
1576
+ const updated = addRef(file, {
1577
+ ref_id: 'ref-123',
1578
+ ref_type: 'form_field',
1579
+ ref_source: 'form-abc',
1580
+ created_at: new Date().toISOString(),
1581
+ });
1582
+ // updated.ref_count === countRefs(updated)
1583
+
1584
+ // removeRef — soft-tombstones by setting removed_at; returns updated object
1585
+ const released = removeRef(file, 'ref-123', new Date().toISOString());
1586
+ // released.ref_count decremented; original ref_id still present with removed_at set
1587
+
1588
+ // countRefs — count active (non-tombstoned) references
1589
+ const active = countRefs(file); // number
1590
+ ```
1591
+
1592
+ These helpers are **pure functions** — they never write to a database. Pair them with `TrackedFileManager.addRef` / `removeRef` when you need DB persistence.
1593
+
1594
+ ## Naming Templates (v2.1.0)
1595
+
1596
+ `NamingTemplate` is a lightweight DSL for generating filenames and folder paths from string templates with variable substitution and pipe formatters.
1597
+
1598
+ ### Basic Usage
1599
+
1600
+ ```typescript
1601
+ import { NamingTemplate } from 'hazo_files';
1602
+
1603
+ const name = NamingTemplate.render(
1604
+ '{client_name|slug}_{date|date:YYYY-MM-DD}_{index|pad:3}.pdf',
1605
+ { client_name: 'Acme Corp', date: '2026-05-24T00:00:00Z', index: 7 }
1606
+ );
1607
+ // → "acme-corp_2026-05-24_007.pdf"
1608
+ ```
1609
+
1610
+ ### Template Syntax
1611
+
1612
+ - **`{variable}`** — substitutes `variable` from the vars object
1613
+ - **`{variable|formatter}`** — applies a formatter after substitution
1614
+ - **`{variable|formatter:arg}`** — formatter with argument
1615
+ - **`{obj.nested.key}`** — dotted-path resolution into nested objects
1616
+ - Output is capped at **200 characters**; `/\:*?"<>|` are sanitised to `_`
1617
+
1618
+ ### Formatters
1619
+
1620
+ | Formatter | Example | Description |
1621
+ |---|---|---|
1622
+ | `slug` | `{name\|slug}` | Lowercase, replace non-alphanumeric with `-`, strip leading/trailing `-` |
1623
+ | `upper` | `{code\|upper}` | Uppercase |
1624
+ | `lower` | `{code\|lower}` | Lowercase |
1625
+ | `pad:N` | `{index\|pad:3}` | Zero-pad to N digits (7 → `007`) |
1626
+ | `truncate:N` | `{title\|truncate:20}` | Trim to N characters |
1627
+ | `date:FMT` | `{ts\|date:YYYY-MM-DD}` | Format ISO date string; tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss` |
1628
+
1629
+ ### Error Conditions
1630
+
1631
+ - Missing variable → throws `Error: missing variable: <name>`
1632
+ - `pad` / `truncate` without numeric arg → throws
1633
+ - `date` formatter on empty/invalid value → throws
1634
+ - Unknown formatter → throws
1635
+
1636
+ ## Collision-Safe Writes (v2.1.0)
1637
+
1638
+ `writeWithCollisionRetry` writes a file to any `FileStorageProvider`, automatically incrementing an `{index}` variable in the template until a free path is found.
1639
+
1640
+ ### Usage
1641
+
1642
+ ```typescript
1643
+ import { writeWithCollisionRetry, StorageCollisionExhausted } from 'hazo_files';
1644
+
1645
+ try {
1646
+ const result = await writeWithCollisionRetry({
1647
+ provider, // FileStorageProvider
1648
+ template: '{client|slug}_{date|date:YYYY-MM-DD}_{index|pad:3}.pdf',
1649
+ vars: { client: 'Acme Corp', date: new Date().toISOString() },
1650
+ body: pdfBuffer,
1651
+ path_prefix: 'uploads/forms', // optional — prepended to rendered name
1652
+ max_attempts: 999, // optional, default 999
1653
+ put_opts: { metadata: { ... } } // optional extra PutOpts (ifNotExists always set)
1654
+ });
1655
+
1656
+ console.log(result.logical_path);
1657
+ // → "uploads/forms/acme-corp_2026-05-24_001.pdf"
1658
+ // (or _002, _003, … if earlier slots were taken)
1659
+ } catch (err) {
1660
+ if (err instanceof StorageCollisionExhausted) {
1661
+ // All 999 attempts collided
1662
+ console.error(`Could not write after ${err.attempts} attempts`);
1663
+ }
1664
+ throw err;
1665
+ }
1666
+ ```
1667
+
1668
+ ### How It Works
1669
+
1670
+ 1. Renders the template with `{ ...vars, index: 1 }` for the first attempt
1671
+ 2. Calls `provider.put(path, body, { ifNotExists: true })`
1672
+ 3. If the file exists, increments `index` and retries
1673
+ 4. Returns `PutResult & { logical_path: string }` on the first successful write
1674
+ 5. Throws `StorageCollisionExhausted` if all attempts are exhausted
1675
+
1676
+ The `{index}` variable is **automatically injected** — you don't need to supply it in `vars`.
1677
+
1567
1678
  ## File Change Detection
1568
1679
 
1569
1680
  Detect file content changes using fast xxHash hashing.
@@ -42,3 +42,14 @@ root_path =
42
42
  ; Comma-separated list of supported date format tokens for naming rules
43
43
  ; Available: YYYY, YY, MM, M, DD, D, MMM, MMMM, YYYY-MM-DD, YYYY-MMM-DD, DD-MM-YYYY, MM-DD-YYYY
44
44
  date_formats = YYYY,YY,MM,M,DD,D,MMM,MMMM,YYYY-MM-DD,YYYY-MMM-DD,DD-MM-YYYY,MM-DD-YYYY
45
+
46
+ [log.overrides]
47
+ ; Override log levels per namespace. Format: namespace = TRACE|DEBUG|INFO|WARN|ERROR
48
+ ; Example:
49
+ ; hazo_files.metadata = DEBUG
50
+ ; hazo_files.naming = WARN
51
+
52
+ [env]
53
+ ; Set HAZO_ENV to control which overlay config file is loaded
54
+ ; e.g. HAZO_ENV=production loads hazo_files_config.production.ini as an overlay
55
+ ; hazo_env = production
@@ -57,6 +57,7 @@ var TypedEventEmitter = class {
57
57
  };
58
58
 
59
59
  // src/background_upload/core/job.ts
60
+ var import_hazo_core = require("hazo_core");
60
61
  var Job = class {
61
62
  constructor(init) {
62
63
  this.status = "queued";
@@ -64,7 +65,7 @@ var Job = class {
64
65
  this.error = null;
65
66
  this.confirmation_payload = null;
66
67
  this.confirmation_resolve = null;
67
- this.job_id = crypto.randomUUID();
68
+ this.job_id = (0, import_hazo_core.generateRequestId)().slice(4);
68
69
  this.batch_id = init.batch_id;
69
70
  this.created_at = Date.now();
70
71
  this.updated_at = this.created_at;
@@ -183,6 +184,7 @@ var PipelineExecutor = class {
183
184
  };
184
185
 
185
186
  // src/background_upload/core/upload-manager.ts
187
+ var import_hazo_core2 = require("hazo_core");
186
188
  var UploadManager = class {
187
189
  constructor(config) {
188
190
  this.jobs = /* @__PURE__ */ new Map();
@@ -204,7 +206,7 @@ var UploadManager = class {
204
206
  }
205
207
  submit_batch(options) {
206
208
  if (this.destroyed) throw new Error("UploadManager is destroyed");
207
- const batch_id = crypto.randomUUID();
209
+ const batch_id = (0, import_hazo_core2.generateRequestId)().slice(4);
208
210
  const job_ids = [];
209
211
  const pipeline_steps = options.pipeline_steps ?? this.config.default_pipeline_steps;
210
212
  for (const file of options.files) {
@@ -28,6 +28,7 @@ var TypedEventEmitter = class {
28
28
  };
29
29
 
30
30
  // src/background_upload/core/job.ts
31
+ import { generateRequestId } from "hazo_core";
31
32
  var Job = class {
32
33
  constructor(init) {
33
34
  this.status = "queued";
@@ -35,7 +36,7 @@ var Job = class {
35
36
  this.error = null;
36
37
  this.confirmation_payload = null;
37
38
  this.confirmation_resolve = null;
38
- this.job_id = crypto.randomUUID();
39
+ this.job_id = generateRequestId().slice(4);
39
40
  this.batch_id = init.batch_id;
40
41
  this.created_at = Date.now();
41
42
  this.updated_at = this.created_at;
@@ -154,6 +155,7 @@ var PipelineExecutor = class {
154
155
  };
155
156
 
156
157
  // src/background_upload/core/upload-manager.ts
158
+ import { generateRequestId as generateRequestId2 } from "hazo_core";
157
159
  var UploadManager = class {
158
160
  constructor(config) {
159
161
  this.jobs = /* @__PURE__ */ new Map();
@@ -175,7 +177,7 @@ var UploadManager = class {
175
177
  }
176
178
  submit_batch(options) {
177
179
  if (this.destroyed) throw new Error("UploadManager is destroyed");
178
- const batch_id = crypto.randomUUID();
180
+ const batch_id = generateRequestId2().slice(4);
179
181
  const job_ids = [];
180
182
  const pipeline_steps = options.pipeline_steps ?? this.config.default_pipeline_steps;
181
183
  for (const file of options.files) {
@@ -41,7 +41,11 @@ module.exports = __toCommonJS(index_exports);
41
41
  // src/background_upload/react/provider.tsx
42
42
  var import_react3 = require("react");
43
43
 
44
+ // src/background_upload/core/upload-manager.ts
45
+ var import_hazo_core2 = require("hazo_core");
46
+
44
47
  // src/background_upload/core/job.ts
48
+ var import_hazo_core = require("hazo_core");
45
49
  var Job = class {
46
50
  constructor(init) {
47
51
  this.status = "queued";
@@ -49,7 +53,7 @@ var Job = class {
49
53
  this.error = null;
50
54
  this.confirmation_payload = null;
51
55
  this.confirmation_resolve = null;
52
- this.job_id = crypto.randomUUID();
56
+ this.job_id = (0, import_hazo_core.generateRequestId)().slice(4);
53
57
  this.batch_id = init.batch_id;
54
58
  this.created_at = Date.now();
55
59
  this.updated_at = this.created_at;
@@ -218,7 +222,7 @@ var UploadManager = class {
218
222
  }
219
223
  submit_batch(options) {
220
224
  if (this.destroyed) throw new Error("UploadManager is destroyed");
221
- const batch_id = crypto.randomUUID();
225
+ const batch_id = (0, import_hazo_core2.generateRequestId)().slice(4);
222
226
  const job_ids = [];
223
227
  const pipeline_steps = options.pipeline_steps ?? this.config.default_pipeline_steps;
224
228
  for (const file of options.files) {
@@ -1,7 +1,11 @@
1
1
  // src/background_upload/react/provider.tsx
2
2
  import { useRef, useEffect as useEffect2 } from "react";
3
3
 
4
+ // src/background_upload/core/upload-manager.ts
5
+ import { generateRequestId as generateRequestId2 } from "hazo_core";
6
+
4
7
  // src/background_upload/core/job.ts
8
+ import { generateRequestId } from "hazo_core";
5
9
  var Job = class {
6
10
  constructor(init) {
7
11
  this.status = "queued";
@@ -9,7 +13,7 @@ var Job = class {
9
13
  this.error = null;
10
14
  this.confirmation_payload = null;
11
15
  this.confirmation_resolve = null;
12
- this.job_id = crypto.randomUUID();
16
+ this.job_id = generateRequestId().slice(4);
13
17
  this.batch_id = init.batch_id;
14
18
  this.created_at = Date.now();
15
19
  this.updated_at = this.created_at;
@@ -178,7 +182,7 @@ var UploadManager = class {
178
182
  }
179
183
  submit_batch(options) {
180
184
  if (this.destroyed) throw new Error("UploadManager is destroyed");
181
- const batch_id = crypto.randomUUID();
185
+ const batch_id = generateRequestId2().slice(4);
182
186
  const job_ids = [];
183
187
  const pipeline_steps = options.pipeline_steps ?? this.config.default_pipeline_steps;
184
188
  for (const file of options.files) {
package/dist/index.d.mts CHANGED
@@ -1,3 +1,6 @@
1
+ import { HazoAuthError, HazoConfigError, HazoConflictError, HazoNotFoundError, HazoValidationError, HazoExternalError } from 'hazo_core';
2
+ export { HazoError as HazoFilesError } from 'hazo_core';
3
+ import { Readable } from 'node:stream';
1
4
  import { OAuth2Client } from 'google-auth-library';
2
5
 
3
6
  /**
@@ -396,7 +399,7 @@ type FileRefVisibility = 'public' | 'private' | 'internal';
396
399
  * A reference from an entity to a file.
397
400
  * Multiple entities can reference the same file.
398
401
  */
399
- interface FileRef {
402
+ interface FileRef$1 {
400
403
  /** Unique ID for this reference */
401
404
  ref_id: string;
402
405
  /** Type of entity referencing the file (e.g., 'form_field', 'chat_message') */
@@ -480,7 +483,7 @@ interface FileWithStatus {
480
483
  /** Full metadata record (V2) */
481
484
  record: FileMetadataRecordV2;
482
485
  /** Parsed file references */
483
- refs: FileRef[];
486
+ refs: FileRef$1[];
484
487
  /** Whether the file has zero references */
485
488
  is_orphaned: boolean;
486
489
  }
@@ -878,7 +881,7 @@ declare class FileMetadataService {
878
881
  /**
879
882
  * Get all references for a file
880
883
  */
881
- getRefs(fileId: string): Promise<FileRef[] | null>;
884
+ getRefs(fileId: string): Promise<FileRef$1[] | null>;
882
885
  /**
883
886
  * Get a file with its status and parsed refs
884
887
  */
@@ -2870,46 +2873,43 @@ declare function registerModule(provider: StorageProvider, factory: ModuleFactor
2870
2873
 
2871
2874
  /**
2872
2875
  * Custom error classes for hazo_files
2876
+ * All errors extend the appropriate hazo_core subclass.
2873
2877
  */
2874
- declare class HazoFilesError extends Error {
2875
- code: string;
2876
- details?: Record<string, unknown> | undefined;
2877
- constructor(message: string, code: string, details?: Record<string, unknown> | undefined);
2878
- }
2879
- declare class FileNotFoundError extends HazoFilesError {
2878
+
2879
+ declare class FileNotFoundError extends HazoNotFoundError {
2880
2880
  constructor(path: string);
2881
2881
  }
2882
- declare class DirectoryNotFoundError extends HazoFilesError {
2882
+ declare class DirectoryNotFoundError extends HazoNotFoundError {
2883
2883
  constructor(path: string);
2884
2884
  }
2885
- declare class FileExistsError extends HazoFilesError {
2885
+ declare class FileExistsError extends HazoConflictError {
2886
2886
  constructor(path: string);
2887
2887
  }
2888
- declare class DirectoryExistsError extends HazoFilesError {
2888
+ declare class DirectoryExistsError extends HazoConflictError {
2889
2889
  constructor(path: string);
2890
2890
  }
2891
- declare class DirectoryNotEmptyError extends HazoFilesError {
2891
+ declare class DirectoryNotEmptyError extends HazoConflictError {
2892
2892
  constructor(path: string);
2893
2893
  }
2894
- declare class PermissionDeniedError extends HazoFilesError {
2894
+ declare class PermissionDeniedError extends HazoAuthError {
2895
2895
  constructor(path: string, operation: string);
2896
2896
  }
2897
- declare class InvalidPathError extends HazoFilesError {
2897
+ declare class InvalidPathError extends HazoValidationError {
2898
2898
  constructor(path: string, reason: string);
2899
2899
  }
2900
- declare class FileTooLargeError extends HazoFilesError {
2900
+ declare class FileTooLargeError extends HazoValidationError {
2901
2901
  constructor(path: string, size: number, maxSize: number);
2902
2902
  }
2903
- declare class InvalidExtensionError extends HazoFilesError {
2903
+ declare class InvalidExtensionError extends HazoValidationError {
2904
2904
  constructor(path: string, extension: string, allowedExtensions: string[]);
2905
2905
  }
2906
- declare class AuthenticationError extends HazoFilesError {
2906
+ declare class AuthenticationError extends HazoAuthError {
2907
2907
  constructor(provider: string, message: string);
2908
2908
  }
2909
- declare class ConfigurationError extends HazoFilesError {
2909
+ declare class ConfigurationError extends HazoConfigError {
2910
2910
  constructor(message: string);
2911
2911
  }
2912
- declare class OperationError extends HazoFilesError {
2912
+ declare class OperationError extends HazoExternalError {
2913
2913
  constructor(operation: string, message: string, details?: Record<string, unknown>);
2914
2914
  }
2915
2915
 
@@ -3256,24 +3256,24 @@ declare function generateRefId(): string;
3256
3256
  * Parse a JSON string into FileRef array.
3257
3257
  * Returns empty array on invalid input.
3258
3258
  */
3259
- declare function parseFileRefs(json: string | null | undefined): FileRef[];
3259
+ declare function parseFileRefs(json: string | null | undefined): FileRef$1[];
3260
3260
  /**
3261
3261
  * Serialize FileRef array to JSON string
3262
3262
  */
3263
- declare function stringifyFileRefs(refs: FileRef[]): string;
3263
+ declare function stringifyFileRefs(refs: FileRef$1[]): string;
3264
3264
  /**
3265
3265
  * Create a FileRef from AddRefOptions
3266
3266
  */
3267
- declare function createFileRef(options: AddRefOptions): FileRef;
3267
+ declare function createFileRef(options: AddRefOptions): FileRef$1;
3268
3268
  /**
3269
3269
  * Remove a ref by ref_id (immutable)
3270
3270
  */
3271
- declare function removeRefFromArray(refs: FileRef[], refId: string): FileRef[];
3271
+ declare function removeRefFromArray(refs: FileRef$1[], refId: string): FileRef$1[];
3272
3272
  /**
3273
3273
  * Remove refs matching criteria from array (immutable).
3274
3274
  * All specified criteria fields must match (AND semantics).
3275
3275
  */
3276
- declare function removeRefsByCriteriaFromArray(refs: FileRef[], criteria: Omit<RemoveRefsCriteria, 'file_id' | 'scope_id'>): FileRef[];
3276
+ declare function removeRefsByCriteriaFromArray(refs: FileRef$1[], criteria: Omit<RemoveRefsCriteria, 'file_id' | 'scope_id'>): FileRef$1[];
3277
3277
  /**
3278
3278
  * Safely cast a FileMetadataRecord to FileMetadataRecordV2.
3279
3279
  * Missing V2 fields are defaulted.
@@ -3284,4 +3284,90 @@ declare function toV2Record(record: FileMetadataRecord): FileMetadataRecordV2;
3284
3284
  */
3285
3285
  declare function buildFileWithStatus(record: FileMetadataRecord): FileWithStatus;
3286
3286
 
3287
- 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 HazoFilesTableSchema, type HazoLLMInstance, 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, createDropboxAuth, createDropboxModule, 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, 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 };
3287
+ declare class NamingTemplate {
3288
+ static render(template: string, vars: Record<string, unknown>): string;
3289
+ }
3290
+
3291
+ type StoragePath = string;
3292
+ interface PutOpts {
3293
+ /** Reject if the target path already exists (atomic). */
3294
+ ifNotExists?: boolean;
3295
+ /** Hint for content-type; provider may sniff if absent. */
3296
+ contentType?: string;
3297
+ /** Free-form key/value metadata persisted with the file when supported. */
3298
+ metadata?: Record<string, string>;
3299
+ }
3300
+ interface PutResult {
3301
+ /** Provider tag — `"app_file_server"`, `"gdrive"`, `"in_memory"`. */
3302
+ provider: string;
3303
+ /** Provider-native identifier (path for app-server; file ID for GDrive). */
3304
+ native_id: string;
3305
+ /** Size in bytes of the persisted body. */
3306
+ size: number;
3307
+ }
3308
+ interface SignedUrlOpts {
3309
+ /** Seconds the URL is valid for. */
3310
+ ttl_seconds?: number;
3311
+ /** Suggested download filename (Content-Disposition). */
3312
+ filename_hint?: string;
3313
+ }
3314
+ interface ProbeResult {
3315
+ ok: boolean;
3316
+ /** Machine-readable error tag when ok=false. */
3317
+ error?: "drive_not_shared" | "write_denied" | "invalid_id" | "transient" | "config_missing";
3318
+ /** Free-form detail for logging. */
3319
+ message?: string;
3320
+ }
3321
+ /**
3322
+ * Storage provider abstraction. Every method MUST be idempotent at the
3323
+ * data-content level — re-invoking put with identical body is allowed.
3324
+ *
3325
+ * Paths are logical; providers translate to native identifiers internally.
3326
+ */
3327
+ interface FileStorageProvider {
3328
+ put(path: StoragePath, body: Buffer | Readable, opts?: PutOpts): Promise<PutResult>;
3329
+ get(path: StoragePath): Promise<Buffer | Readable>;
3330
+ delete(path: StoragePath): Promise<void>;
3331
+ exists(path: StoragePath): Promise<boolean>;
3332
+ getSignedUrl(path: StoragePath, opts?: SignedUrlOpts): Promise<string>;
3333
+ /** Used by validation cron + onboarding step 2. */
3334
+ probe(): Promise<ProbeResult>;
3335
+ }
3336
+
3337
+ interface WriteWithCollisionOpts {
3338
+ provider: FileStorageProvider;
3339
+ template: string;
3340
+ vars: Record<string, unknown>;
3341
+ body: Buffer;
3342
+ /** Prefix to mount the rendered filename under, e.g. `"folders/abc123"`. */
3343
+ path_prefix?: string;
3344
+ /** Max attempts. Default 999. */
3345
+ max_attempts?: number;
3346
+ /** Extra opts passed to provider.put (ifNotExists is always forced true). */
3347
+ put_opts?: Omit<PutOpts, "ifNotExists">;
3348
+ }
3349
+ declare function writeWithCollisionRetry(opts: WriteWithCollisionOpts): Promise<PutResult & {
3350
+ logical_path: string;
3351
+ }>;
3352
+
3353
+ interface FileRef {
3354
+ ref_id: string;
3355
+ ref_type: string;
3356
+ ref_source: string;
3357
+ form_id?: string;
3358
+ field_id?: string;
3359
+ message_id?: string;
3360
+ document_id?: string;
3361
+ created_at: string;
3362
+ removed_at?: string;
3363
+ }
3364
+ interface FileWithRefs {
3365
+ file_refs: FileRef[];
3366
+ ref_count: number;
3367
+ }
3368
+
3369
+ declare function addRef<T extends FileWithRefs>(file: T, ref: FileRef): T;
3370
+ declare function removeRef<T extends FileWithRefs>(file: T, ref_id: string, removed_at: string): T;
3371
+ declare function countRefs(file: Pick<FileWithRefs, "file_refs">): number;
3372
+
3373
+ 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$1 as FileRef, type FileRefVisibility, type FileStatus, type FileSystemItem, FileTooLargeError, type FileWithRefs, 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, type HazoFilesMigrationV2, type HazoFilesMigrationV3, type HazoFilesNamingColumnDefinitions, type HazoFilesNamingTableSchema, type HazoFilesTableSchema, type HazoLLMInstance, 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, NamingTemplate, 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, type WriteWithCollisionOpts, addExtractionToFileData, addRef, backfillV2Defaults, buildFileWithStatus, clearExtractions, clonePattern, computeFileHash, computeFileHashFromStream, computeFileHashSync, computeFileInfo, countRefs, createAndInitializeModule, createDropboxAuth, createDropboxModule, 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, 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, removeRef, removeRefFromArray, removeRefsByCriteriaFromArray, sanitizeFilename, saveConfig, sortItems, stringifyFileData, stringifyFileRefs, successResult, toV2Record, updateExtractionById, validateExtractionData, validateFileDataStructure, validateNamingRuleSchema, validatePath, writeWithCollisionRetry };