filemayor 2.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.
@@ -0,0 +1,235 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ═══════════════════════════════════════════════════════════════════
5
+ * FILEMAYOR CORE — CATEGORIES
6
+ * Extension → Category mapping with configurable overrides
7
+ * ═══════════════════════════════════════════════════════════════════
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ // ─── Default Category Definitions ─────────────────────────────────
13
+ const DEFAULT_CATEGORIES = {
14
+ documents: {
15
+ label: 'Documents',
16
+ extensions: [
17
+ '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
18
+ '.odt', '.ods', '.odp', '.rtf', '.txt', '.csv', '.tsv',
19
+ '.md', '.tex', '.epub', '.mobi', '.pages', '.numbers', '.key'
20
+ ],
21
+ color: '#d4af37',
22
+ icon: 'FileText'
23
+ },
24
+ images: {
25
+ label: 'Images',
26
+ extensions: [
27
+ '.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp', '.bmp',
28
+ '.tiff', '.tif', '.ico', '.heic', '.heif', '.raw', '.cr2',
29
+ '.nef', '.arw', '.dng', '.psd', '.ai', '.eps', '.xcf'
30
+ ],
31
+ color: '#f472b6',
32
+ icon: 'Image'
33
+ },
34
+ audio: {
35
+ label: 'Audio',
36
+ extensions: [
37
+ '.mp3', '.wav', '.flac', '.aac', '.ogg', '.m4a', '.wma',
38
+ '.aiff', '.alac', '.opus', '.mid', '.midi', '.pcm'
39
+ ],
40
+ color: '#38bdf8',
41
+ icon: 'Music'
42
+ },
43
+ video: {
44
+ label: 'Video',
45
+ extensions: [
46
+ '.mp4', '.mkv', '.avi', '.mov', '.wmv', '.webm', '.flv',
47
+ '.m4v', '.mpg', '.mpeg', '.3gp', '.ts', '.vob', '.ogv'
48
+ ],
49
+ color: '#a78bfa',
50
+ icon: 'Video'
51
+ },
52
+ archives: {
53
+ label: 'Archives',
54
+ extensions: [
55
+ '.zip', '.rar', '.7z', '.tar', '.gz', '.bz2', '.xz',
56
+ '.tgz', '.tbz2', '.lz', '.lzma', '.cab', '.iso', '.dmg',
57
+ '.img', '.zst', '.br'
58
+ ],
59
+ color: '#34d399',
60
+ icon: 'Archive'
61
+ },
62
+ code: {
63
+ label: 'Code',
64
+ extensions: [
65
+ '.js', '.ts', '.jsx', '.tsx', '.py', '.java', '.cpp', '.c',
66
+ '.cs', '.go', '.rs', '.rb', '.php', '.swift', '.kt', '.scala',
67
+ '.lua', '.r', '.m', '.h', '.hpp', '.vue', '.svelte', '.astro',
68
+ '.sh', '.bash', '.zsh', '.fish', '.ps1', '.bat', '.cmd',
69
+ '.sql', '.graphql', '.proto', '.wasm'
70
+ ],
71
+ color: '#fb923c',
72
+ icon: 'Code'
73
+ },
74
+ config: {
75
+ label: 'Config',
76
+ extensions: [
77
+ '.json', '.yaml', '.yml', '.toml', '.ini', '.cfg', '.conf',
78
+ '.env', '.properties', '.xml', '.plist', '.reg'
79
+ ],
80
+ color: '#94a3b8',
81
+ icon: 'Settings'
82
+ },
83
+ fonts: {
84
+ label: 'Fonts',
85
+ extensions: [
86
+ '.ttf', '.otf', '.woff', '.woff2', '.eot', '.fon'
87
+ ],
88
+ color: '#e879f9',
89
+ icon: 'Type'
90
+ },
91
+ data: {
92
+ label: 'Data',
93
+ extensions: [
94
+ '.db', '.sqlite', '.sqlite3', '.mdb', '.accdb', '.dbf',
95
+ '.parquet', '.avro', '.arrow', '.ndjson', '.jsonl',
96
+ '.hdf5', '.h5', '.nc', '.fits'
97
+ ],
98
+ color: '#22d3ee',
99
+ icon: 'Database'
100
+ },
101
+ executables: {
102
+ label: 'Executables',
103
+ extensions: [
104
+ '.exe', '.msi', '.app', '.apk', '.deb', '.rpm', '.snap',
105
+ '.flatpak', '.appimage', '.pkg', '.bin', '.run',
106
+ '.dll', '.so', '.dylib'
107
+ ],
108
+ color: '#ef4444',
109
+ icon: 'Cpu'
110
+ },
111
+ design: {
112
+ label: 'Design',
113
+ extensions: [
114
+ '.fig', '.sketch', '.xd', '.indd', '.blend', '.3ds',
115
+ '.obj', '.fbx', '.stl', '.gltf', '.glb', '.usdz',
116
+ '.dwg', '.dxf', '.step', '.stp'
117
+ ],
118
+ color: '#c084fc',
119
+ icon: 'Palette'
120
+ },
121
+ books: {
122
+ label: 'Books',
123
+ extensions: [
124
+ '.epub', '.mobi', '.azw', '.azw3', '.djvu', '.cbz', '.cbr'
125
+ ],
126
+ color: '#fbbf24',
127
+ icon: 'BookOpen'
128
+ }
129
+ };
130
+
131
+ // ─── Extension Cache ──────────────────────────────────────────────
132
+ let _extensionMap = null;
133
+
134
+ /**
135
+ * Build a flat map of extension → category for O(1) lookups
136
+ * @param {Object} categories - Category definitions
137
+ * @returns {Map<string, string>} Extension to category name map
138
+ */
139
+ function buildExtensionMap(categories = DEFAULT_CATEGORIES) {
140
+ const map = new Map();
141
+ for (const [categoryName, def] of Object.entries(categories)) {
142
+ for (const ext of def.extensions) {
143
+ map.set(ext.toLowerCase(), categoryName);
144
+ }
145
+ }
146
+ return map;
147
+ }
148
+
149
+ /**
150
+ * Get the category for a file extension
151
+ * @param {string} ext - File extension (with dot, e.g. '.pdf')
152
+ * @param {Object} customCategories - Optional custom categories
153
+ * @returns {string} Category name or 'other'
154
+ */
155
+ function categorize(ext, customCategories = null) {
156
+ if (!ext) return 'other';
157
+ const normalized = ext.toLowerCase();
158
+
159
+ if (customCategories) {
160
+ const customMap = buildExtensionMap(customCategories);
161
+ return customMap.get(normalized) || 'other';
162
+ }
163
+
164
+ // Use cached map for default categories
165
+ if (!_extensionMap) {
166
+ _extensionMap = buildExtensionMap(DEFAULT_CATEGORIES);
167
+ }
168
+ return _extensionMap.get(normalized) || 'other';
169
+ }
170
+
171
+ /**
172
+ * Get all registered categories with metadata
173
+ * @param {Object} customCategories - Optional overrides
174
+ * @returns {Object} Merged categories
175
+ */
176
+ function getCategories(customCategories = null) {
177
+ if (!customCategories) return { ...DEFAULT_CATEGORIES };
178
+ return { ...DEFAULT_CATEGORIES, ...customCategories };
179
+ }
180
+
181
+ /**
182
+ * Get all extensions registered across all categories
183
+ * @returns {string[]} List of all known extensions
184
+ */
185
+ function getAllExtensions() {
186
+ const all = [];
187
+ for (const def of Object.values(DEFAULT_CATEGORIES)) {
188
+ all.push(...def.extensions);
189
+ }
190
+ return all;
191
+ }
192
+
193
+ /**
194
+ * Merge user-defined categories with defaults
195
+ * @param {Object} userCategories - User category overrides
196
+ * @returns {Object} Merged category map
197
+ */
198
+ function mergeCategories(userCategories) {
199
+ const merged = { ...DEFAULT_CATEGORIES };
200
+ for (const [name, def] of Object.entries(userCategories)) {
201
+ if (merged[name]) {
202
+ // Merge extensions (deduplicate)
203
+ const existingExts = new Set(merged[name].extensions);
204
+ for (const ext of (def.extensions || [])) {
205
+ existingExts.add(ext.toLowerCase());
206
+ }
207
+ merged[name] = {
208
+ ...merged[name],
209
+ ...def,
210
+ extensions: [...existingExts]
211
+ };
212
+ } else {
213
+ // New category
214
+ merged[name] = {
215
+ label: def.label || name,
216
+ extensions: (def.extensions || []).map(e => e.toLowerCase()),
217
+ color: def.color || '#6b7280',
218
+ icon: def.icon || 'File'
219
+ };
220
+ }
221
+ }
222
+
223
+ // Rebuild cache
224
+ _extensionMap = buildExtensionMap(merged);
225
+ return merged;
226
+ }
227
+
228
+ module.exports = {
229
+ DEFAULT_CATEGORIES,
230
+ categorize,
231
+ getCategories,
232
+ getAllExtensions,
233
+ mergeCategories,
234
+ buildExtensionMap
235
+ };