hazo_files 1.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/TECHDOC.md ADDED
@@ -0,0 +1,325 @@
1
+ # hazo_files - Technical Documentation
2
+
3
+ Comprehensive technical reference describing system architecture, components, data flows, and integration patterns.
4
+
5
+ ## System Architecture
6
+
7
+ The hazo_files package is built on a layered architecture with pluggable storage modules.
8
+
9
+ ### Architecture Diagram
10
+
11
+ ```
12
+ Client Layer (React)
13
+ └── FileBrowser Component
14
+ └── HTTP API Calls
15
+
16
+ Server Layer (Node.js)
17
+ └── API Routes (Next.js/Express)
18
+ └── FileManager Service
19
+ ├── LocalStorageModule → fs
20
+ └── GoogleDriveModule → Google Drive API
21
+ ```
22
+
23
+ ## Core Components
24
+
25
+ ### FileManager
26
+ Main service providing unified API across storage providers.
27
+ - Location: `src/services/file-manager.ts`
28
+ - Methods: createDirectory, uploadFile, downloadFile, listDirectory, etc.
29
+ - Delegates operations to active storage module
30
+
31
+ ### Storage Modules
32
+ Implement `StorageModule` interface with all file operations.
33
+ - LocalStorageModule: Direct filesystem access
34
+ - GoogleDriveModule: Google Drive API v3 with OAuth
35
+
36
+ ### Naming System
37
+ Pattern-based file/folder name generation system.
38
+ - Location: `src/common/naming-utils.ts`, `src/types/naming.ts`
39
+ - Components: Schema definition, pattern parsing, variable substitution
40
+ - Functions: hazo_files_generate_file_name, hazo_files_generate_folder_name
41
+ - System variables: Date formats, file metadata, counter
42
+
43
+ ### UI Components
44
+ React components for file management and configuration:
45
+ - **File Browser**: FileBrowser, FolderTree, FileList, FilePreview, PathBreadcrumb
46
+ - **Naming Configurator**: NamingRuleConfigurator, VariableList, PatternBuilder, PatternPreview
47
+ - **Dialogs**: Create/rename/delete/upload dialogs
48
+ - **Hooks**: useFileBrowser, useFileOperations, useNamingRule
49
+
50
+ ## Storage Modules
51
+
52
+ ### LocalStorageModule
53
+ **Path Mapping**: Virtual paths (`/docs/file.pdf`) map to filesystem (`{basePath}/docs/file.pdf`)
54
+ **Features**: Extension filtering, size limits, progress tracking
55
+ **Performance**: <10ms for most operations
56
+
57
+ ### GoogleDriveModule
58
+ **Path Resolution**: Recursive API queries to resolve paths to Drive file IDs
59
+ **Authentication**: OAuth 2.0 with token refresh
60
+ **Performance**: 200-1000ms per operation (network latency)
61
+
62
+ ## API Endpoints
63
+
64
+ ### GET /api/files
65
+ - Query params: action (list|tree|exists|get), path, provider
66
+ - Returns: OperationResult<T>
67
+
68
+ ### POST /api/files
69
+ - Body: action, path, provider, operation-specific params
70
+ - Returns: OperationResult<T>
71
+
72
+ ### POST /api/files/upload
73
+ - Content-Type: multipart/form-data
74
+ - Fields: file, path, provider
75
+ - Returns: OperationResult<FileItem>
76
+
77
+ ### GET /api/files/download
78
+ - Query: path, provider
79
+ - Returns: Binary file stream
80
+
81
+ ## Database Schema
82
+
83
+ ### Token Storage (PostgreSQL)
84
+
85
+ ```sql
86
+ CREATE TABLE google_drive_tokens (
87
+ id SERIAL PRIMARY KEY,
88
+ user_id VARCHAR(255) UNIQUE NOT NULL,
89
+ access_token TEXT NOT NULL,
90
+ refresh_token TEXT NOT NULL,
91
+ expiry_date BIGINT,
92
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
93
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
94
+ );
95
+
96
+ CREATE INDEX idx_tokens_user_id ON google_drive_tokens(user_id);
97
+
98
+ GRANT ALL PRIVILEGES ON DATABASE your_database TO your_user;
99
+ GRANT ALL PRIVILEGES ON TABLE google_drive_tokens TO your_user;
100
+ GRANT USAGE, SELECT ON SEQUENCE google_drive_tokens_id_seq TO your_user;
101
+ ```
102
+
103
+ ### Token Storage (SQLite)
104
+
105
+ ```sql
106
+ CREATE TABLE google_drive_tokens (
107
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
108
+ user_id TEXT UNIQUE NOT NULL,
109
+ access_token TEXT NOT NULL,
110
+ refresh_token TEXT NOT NULL,
111
+ expiry_date INTEGER,
112
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
113
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
114
+ );
115
+
116
+ CREATE INDEX idx_tokens_user_id ON google_drive_tokens(user_id);
117
+ ```
118
+
119
+ ## Security
120
+
121
+ ### Authentication
122
+ - Local: Server-side access control required
123
+ - Google Drive: OAuth 2.0 with token refresh
124
+
125
+ ### Input Validation
126
+ - Path validation prevents directory traversal
127
+ - Filename sanitization removes dangerous characters
128
+ - Extension whitelist via allowedExtensions
129
+ - Size limits via maxFileSize
130
+
131
+ ### Best Practices
132
+ - Store tokens in database, never expose to client
133
+ - Use CSRF protection on POST endpoints
134
+ - Implement rate limiting
135
+ - Validate all user inputs
136
+
137
+ ## Performance
138
+
139
+ ### Benchmarks
140
+
141
+ **Local Storage**:
142
+ - Upload 1MB: 5-10ms
143
+ - Download 1MB: 3-8ms
144
+ - List 100 files: 2-5ms
145
+
146
+ **Google Drive**:
147
+ - Upload 1MB: 500-1000ms
148
+ - Download 1MB: 300-700ms
149
+ - List 100 files: 400-800ms
150
+
151
+ ### Optimization Strategies
152
+ 1. Path caching for Google Drive
153
+ 2. Batch API requests
154
+ 3. Virtual scrolling for large lists
155
+ 4. React Query for client-side caching
156
+
157
+ ## Error Handling
158
+
159
+ ### Error Types
160
+ - FileNotFoundError, DirectoryNotFoundError
161
+ - FileExistsError, DirectoryExistsError
162
+ - InvalidPathError, FileTooLargeError
163
+ - InvalidExtensionError, AuthenticationError
164
+
165
+ ### Error Flow
166
+ ```
167
+ Module → Catch error → Return OperationResult with error
168
+ API → Return OperationResult as JSON
169
+ Client → Check result.success, handle error
170
+ ```
171
+
172
+ ## Naming System Architecture
173
+
174
+ ### Pattern Structure
175
+
176
+ ```
177
+ NamingRuleSchema
178
+ ├── version: number
179
+ ├── filePattern: PatternSegment[]
180
+ │ ├── { id, type: 'variable', value: 'client_id' }
181
+ │ ├── { id, type: 'literal', value: '_' }
182
+ │ └── { id, type: 'variable', value: 'YYYY-MM-DD' }
183
+ ├── folderPattern: PatternSegment[]
184
+ └── metadata: { name?, description?, createdAt?, updatedAt? }
185
+ ```
186
+
187
+ ### Name Generation Flow
188
+
189
+ ```
190
+ User provides:
191
+ - NamingRuleSchema (pattern definition)
192
+ - Variable values (user-defined variables)
193
+ - Options (date, counter, etc.)
194
+
195
+
196
+
197
+ Pattern segments iteration:
198
+ For each segment:
199
+ - If literal → Use value directly
200
+ - If variable → Lookup value:
201
+ - Check date variables (YYYY, MM, DD, etc.)
202
+ - Check file metadata (original_name, extension)
203
+ - Check counter variable
204
+ - Check user variables
205
+ - If missing → Return error
206
+
207
+
208
+
209
+ Post-processing:
210
+ - Join all segments
211
+ - Sanitize filename (remove unsafe chars)
212
+ - Preserve extension (if file pattern)
213
+
214
+
215
+
216
+ Return GeneratedNameResult:
217
+ { success: true, name: "ACME_2024-12-09_001.pdf" }
218
+ ```
219
+
220
+ ### Variable Resolution Order
221
+
222
+ 1. **Date variables**: Checked first using formatDateToken()
223
+ 2. **File metadata**: From original filename (if provided)
224
+ 3. **Counter**: Formatted with zero padding
225
+ 4. **User variables**: From provided variables object
226
+ 5. **Error**: If none match, return error result
227
+
228
+ ### Configurator State Management
229
+
230
+ ```
231
+ useNamingRule Hook
232
+ ├── State:
233
+ │ ├── filePattern: PatternSegment[]
234
+ │ ├── folderPattern: PatternSegment[]
235
+ │ ├── history: NamingRuleHistoryEntry[]
236
+ │ └── historyIndex: number
237
+
238
+ ├── Actions:
239
+ │ ├── Pattern manipulation (add, remove, update, reorder, clear)
240
+ │ ├── Undo/Redo (Ctrl+Z, Ctrl+Y)
241
+ │ └── Schema import/export
242
+
243
+ └── Effects:
244
+ ├── onChange callback on pattern change
245
+ ├── Keyboard event listeners
246
+ └── History recording
247
+ ```
248
+
249
+ ### Drag-and-Drop System
250
+
251
+ **Architecture**: Single top-level DndContext pattern
252
+
253
+ ```
254
+ NamingRuleConfigurator (DndContext)
255
+ ├── Sensors:
256
+ │ └── PointerSensor (8px activation distance)
257
+
258
+ ├── Collision Detection: closestCenter
259
+
260
+ ├── Event Handlers:
261
+ │ ├── onDragStart → setActiveVariable (for DragOverlay)
262
+ │ └── onDragEnd → handleDragEnd:
263
+ │ ├── Case 1: New variable drop (draggable-* ID)
264
+ │ │ ├── Detect drop target (file-pattern-drop / folder-pattern-drop)
265
+ │ │ └── Call addToFilePattern / addToFolderPattern
266
+ │ └── Case 2: Segment reordering (segment ID)
267
+ │ ├── Find indices in filePattern / folderPattern
268
+ │ └── Call reorderFilePattern / reorderFolderPattern
269
+
270
+ ├── DragOverlay:
271
+ │ └── Shows activeVariable during drag
272
+
273
+ ├── Children:
274
+ ├── VariableList
275
+ │ └── DraggableVariable (useDraggable)
276
+ │ └── Data: { type: 'variable', variable: NamingVariable }
277
+
278
+ └── PatternBuilder (NO DndContext - CRITICAL)
279
+ ├── SortableContext (for segment reordering)
280
+ ├── useDroppable (for drop zone detection)
281
+ └── PatternSegmentItem (useSortable)
282
+ ```
283
+
284
+ **Critical Design Decision**: PatternBuilder does NOT have its own DndContext. It relies entirely on the parent NamingRuleConfigurator's DndContext. This is essential because:
285
+
286
+ 1. Nested DndContext blocks drag events from parent
287
+ 2. @dnd-kit prevents event bubbling between contexts
288
+ 3. All drag logic must be in a single handleDragEnd handler
289
+
290
+ **Common Mistake**: Adding DndContext to child components causes drag-and-drop to break. Always use SortableContext and useDroppable/useSortable hooks in children, reserve DndContext for top-level component only.
291
+
292
+ ### System Variable Evaluation
293
+
294
+ **Date Variables** (evaluated at generation time):
295
+ - Uses provided `date` option or `new Date()`
296
+ - Formatted via `formatDateToken()` with switch statement
297
+ - Supports 12+ date formats
298
+
299
+ **File Variables** (from original filename):
300
+ - `original_name`: Extracted via getNameWithoutExtension()
301
+ - `extension`: Extracted via getExtension() (includes dot)
302
+ - `ext`: Extension without dot
303
+
304
+ **Counter Variable**:
305
+ - Provided via `counterValue` option (default: 1)
306
+ - Formatted with `counterDigits` padding (default: 3)
307
+ - Example: 1 → "001", 42 → "042"
308
+
309
+ ### Performance Characteristics
310
+
311
+ **Name Generation**:
312
+ - Time complexity: O(n) where n = number of segments
313
+ - Memory: O(n) for segment array and result string
314
+ - No I/O operations, pure computation
315
+ - Typical execution: <1ms for patterns with <50 segments
316
+
317
+ **Configurator UI**:
318
+ - Pattern updates: Re-renders affected components only
319
+ - History operations: O(1) for undo/redo
320
+ - Drag operations: Handled by @dnd-kit (optimized)
321
+ - Preview generation: Runs on every pattern change (debounce recommended for production)
322
+
323
+ ---
324
+
325
+ **Version**: 1.0.0