From 8af8f835018d7716573a35aaf6ebb5292ac835de Mon Sep 17 00:00:00 2001 From: mayor Date: Wed, 21 Jan 2026 16:03:44 -0600 Subject: [PATCH] feat(errors): add operation context to all error handlers Enhances error handling by adding operation context to all catchError calls in extract and load modules. This provides better debugging information when errors occur. Changes: - Added {context: {operation: 'function_name'}, fatal: true} to all catchError calls in extract-*.ts and load-*.ts files - Individual file errors (e.g., file downloads) use fatal: false to allow batch operations to continue This enables better error tracking and debugging in production by identifying exactly which operation failed. --- src/lib/extract/extract-access.ts | 5 ++++- src/lib/extract/extract-assets.ts | 10 ++++++++-- src/lib/extract/extract-collections.ts | 5 ++++- src/lib/extract/extract-content.ts | 10 ++++++++-- src/lib/extract/extract-dashboards.ts | 10 ++++++++-- src/lib/extract/extract-extensions.ts | 5 ++++- src/lib/extract/extract-fields.ts | 5 ++++- src/lib/extract/extract-files.ts | 5 ++++- src/lib/extract/extract-flows.ts | 10 ++++++++-- src/lib/extract/extract-folders.ts | 5 ++++- src/lib/extract/extract-permissions.ts | 5 ++++- src/lib/extract/extract-policies.ts | 5 ++++- src/lib/extract/extract-presets.ts | 5 ++++- src/lib/extract/extract-relations.ts | 5 ++++- src/lib/extract/extract-roles.ts | 5 ++++- src/lib/extract/extract-schema.ts | 5 ++++- src/lib/extract/extract-settings.ts | 5 ++++- src/lib/extract/extract-translations.ts | 5 ++++- src/lib/extract/extract-users.ts | 5 ++++- src/lib/load/load-collections.ts | 20 ++++++++++++++++---- src/lib/load/load-dashboards.ts | 10 ++++++++-- src/lib/load/load-data.ts | 15 ++++++++++++--- src/lib/load/load-extensions.ts | 5 ++++- src/lib/load/load-files.ts | 10 ++++++++-- src/lib/load/load-flows.ts | 10 ++++++++-- src/lib/load/load-folders.ts | 10 ++++++++-- src/lib/load/load-permissions.ts | 5 ++++- src/lib/load/load-policies.ts | 5 ++++- src/lib/load/load-presets.ts | 5 ++++- src/lib/load/load-relations.ts | 5 ++++- src/lib/load/load-roles.ts | 10 ++++++++-- src/lib/load/load-settings.ts | 5 ++++- src/lib/load/load-translations.ts | 5 ++++- src/lib/load/load-users.ts | 5 ++++- 34 files changed, 192 insertions(+), 48 deletions(-) diff --git a/src/lib/extract/extract-access.ts b/src/lib/extract/extract-access.ts index 3bb4c971..5021e409 100644 --- a/src/lib/extract/extract-access.ts +++ b/src/lib/extract/extract-access.ts @@ -28,7 +28,10 @@ export default async function extractAccess(dir: string) { await writeToFile('access', response, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_access'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-assets.ts b/src/lib/extract/extract-assets.ts index 06897a4e..04d88b62 100644 --- a/src/lib/extract/extract-assets.ts +++ b/src/lib/extract/extract-assets.ts @@ -36,10 +36,16 @@ export async function downloadAllFiles(dir: string) { const fileList = await getAssetList() await Promise.all(fileList.map(file => downloadFile(file, dir).catch(error => { - catchError(`Error downloading ${file.filename_disk}: ${error.message}`) + catchError(`Error downloading ${file.filename_disk}: ${error.message}`, { + context: {fileId: file.id, filename: file.filename_disk, operation: 'downloadFile'}, + fatal: false, + }) }))) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_assets'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-collections.ts b/src/lib/extract/extract-collections.ts index 54ab6d46..f951536e 100644 --- a/src/lib/extract/extract-collections.ts +++ b/src/lib/extract/extract-collections.ts @@ -19,7 +19,10 @@ export default async function extractCollections(dir: string) { ) await writeToFile('collections', collections, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_collections'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-content.ts b/src/lib/extract/extract-content.ts index b334de37..71e71579 100644 --- a/src/lib/extract/extract-content.ts +++ b/src/lib/extract/extract-content.ts @@ -19,7 +19,10 @@ async function getDataFromCollection(collection: string, dir: string) { const response = await api.client.request(readItems(collection as never, {limit: -1})) await writeToFile(`${collection}`, response, `${dir}/content/`) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_content'}, + fatal: true, + }) } } @@ -29,7 +32,10 @@ export async function extractContent(dir: string) { const collections = await getCollections() await Promise.all(collections.map(collection => getDataFromCollection(collection, dir))) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_content'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-dashboards.ts b/src/lib/extract/extract-dashboards.ts index b1b979bc..73278c2b 100644 --- a/src/lib/extract/extract-dashboards.ts +++ b/src/lib/extract/extract-dashboards.ts @@ -19,7 +19,10 @@ export async function extractDashboards(dir: string) { const dashboards = filterFields(response, directusDashboardFields) await writeToFile('dashboards', dashboards, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_dashboards'}, + fatal: true, + }) } ux.action.stop() @@ -36,7 +39,10 @@ export async function extractPanels(dir: string) { const panels = filterFields(response, directusPanelFields) await writeToFile('panels', panels, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_dashboards'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-extensions.ts b/src/lib/extract/extract-extensions.ts index 1d2965f6..346fe1e2 100644 --- a/src/lib/extract/extract-extensions.ts +++ b/src/lib/extract/extract-extensions.ts @@ -16,7 +16,10 @@ export default async function extractExtensions(dir: string) { const response = await api.client.request(readExtensions()) await writeToFile('extensions', response, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_extensions'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-fields.ts b/src/lib/extract/extract-fields.ts index 53022037..0e6697ef 100644 --- a/src/lib/extract/extract-fields.ts +++ b/src/lib/extract/extract-fields.ts @@ -34,7 +34,10 @@ export default async function extractFields(dir: string) { await writeToFile('fields', fields, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_fields'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-files.ts b/src/lib/extract/extract-files.ts index 67808a1d..f9de8710 100644 --- a/src/lib/extract/extract-files.ts +++ b/src/lib/extract/extract-files.ts @@ -19,7 +19,10 @@ export default async function extractFiles(dir: string) { const files = filterFields(response, directusFileFields) await writeToFile('files', files, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_files'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-flows.ts b/src/lib/extract/extract-flows.ts index f46f1243..60d58148 100644 --- a/src/lib/extract/extract-flows.ts +++ b/src/lib/extract/extract-flows.ts @@ -19,7 +19,10 @@ export async function extractFlows(dir: string) { const flows = filterFields(response, directusFlowFields) await writeToFile('flows', flows, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_flows'}, + fatal: true, + }) } ux.action.stop() @@ -36,7 +39,10 @@ export async function extractOperations(dir: string) { const operations = filterFields(response, directusOperationFields) await writeToFile('operations', operations, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_flows'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-folders.ts b/src/lib/extract/extract-folders.ts index 2bd3d68c..d1118e9b 100644 --- a/src/lib/extract/extract-folders.ts +++ b/src/lib/extract/extract-folders.ts @@ -19,7 +19,10 @@ export default async function extractFolders(dir: string) { const folders = filterFields(response, directusFolderFields) await writeToFile('folders', folders, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_folders'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-permissions.ts b/src/lib/extract/extract-permissions.ts index 59fbd108..ab4932b7 100644 --- a/src/lib/extract/extract-permissions.ts +++ b/src/lib/extract/extract-permissions.ts @@ -27,7 +27,10 @@ export default async function extractPermissions(dir: string) { }) await writeToFile('permissions', response, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_permissions'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-policies.ts b/src/lib/extract/extract-policies.ts index 1923c922..58ebd55c 100644 --- a/src/lib/extract/extract-policies.ts +++ b/src/lib/extract/extract-policies.ts @@ -24,7 +24,10 @@ export default async function extractPolicies(dir: string) { await writeToFile('policies', response, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_policies'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-presets.ts b/src/lib/extract/extract-presets.ts index 792e5b02..41ce2cce 100644 --- a/src/lib/extract/extract-presets.ts +++ b/src/lib/extract/extract-presets.ts @@ -30,7 +30,10 @@ export default async function extractPresets(dir: string) { }) await writeToFile('presets', presets, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_presets'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-relations.ts b/src/lib/extract/extract-relations.ts index 52cf51dd..73c8f551 100644 --- a/src/lib/extract/extract-relations.ts +++ b/src/lib/extract/extract-relations.ts @@ -40,7 +40,10 @@ export default async function extractRelations(dir: string) { await writeToFile('relations', relations, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_relations'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-roles.ts b/src/lib/extract/extract-roles.ts index 41f88e58..f1946368 100644 --- a/src/lib/extract/extract-roles.ts +++ b/src/lib/extract/extract-roles.ts @@ -19,7 +19,10 @@ export default async function extractRoles(dir: string) { const roles = filterFields(response, directusRoleFields) await writeToFile('roles', roles, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_roles'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-schema.ts b/src/lib/extract/extract-schema.ts index d55dcd4b..206f99e4 100644 --- a/src/lib/extract/extract-schema.ts +++ b/src/lib/extract/extract-schema.ts @@ -19,7 +19,10 @@ export default async function extractSchema(dir: string) { const schema = await api.client.request(schemaSnapshot()) await writeToFile('schema/snapshot', schema, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_schema'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-settings.ts b/src/lib/extract/extract-settings.ts index 9c397cbe..99b745d2 100644 --- a/src/lib/extract/extract-settings.ts +++ b/src/lib/extract/extract-settings.ts @@ -16,7 +16,10 @@ export default async function extractSettings(dir: string) { const settings = await api.client.request(readSettings({limit: -1})) await writeToFile('settings', settings, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_settings'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-translations.ts b/src/lib/extract/extract-translations.ts index 8ce5d64f..3f41c4c1 100644 --- a/src/lib/extract/extract-translations.ts +++ b/src/lib/extract/extract-translations.ts @@ -16,7 +16,10 @@ export default async function extractTranslations(dir: string) { const translations = await api.client.request(readTranslations({limit: -1})) await writeToFile('translations', translations, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_translations'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/extract/extract-users.ts b/src/lib/extract/extract-users.ts index f9be1b2c..515dd825 100644 --- a/src/lib/extract/extract-users.ts +++ b/src/lib/extract/extract-users.ts @@ -19,7 +19,10 @@ export default async function extractUsers(dir: string) { const users = filterFields(response, directusUserFields) await writeToFile('users', users, dir) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'extract_users'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/load/load-collections.ts b/src/lib/load/load-collections.ts index f5ef0652..62d4fbd9 100644 --- a/src/lib/load/load-collections.ts +++ b/src/lib/load/load-collections.ts @@ -38,7 +38,10 @@ async function processCollections(collectionsToAdd: any[], fieldsToAdd: any[]) { await (existingCollection ? addNewFieldsToExistingCollection(collection.collection, fieldsToAdd, existingFields) : addNewCollectionWithFields(collection, fieldsToAdd)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_collections'}, + fatal: true, + }) } } } @@ -85,7 +88,10 @@ async function addNewFieldsToExistingCollection(collectionName: string, fieldsTo // @ts-ignore - ignore await api.client.request(createField(collectionName, field)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_collections'}, + fatal: true, + }) } } } @@ -103,7 +109,10 @@ async function updateCollections(collections: any[]) { await api.client.request(updateCollection(collection.collection, pl)) } } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_collections'}, + fatal: true, + }) } } } @@ -126,7 +135,10 @@ async function addCustomFieldsOnSystemCollections(fields: any[]) { await api.client.request(createField(field.collection, field)) } } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_collections'}, + fatal: true, + }) } } } diff --git a/src/lib/load/load-dashboards.ts b/src/lib/load/load-dashboards.ts index 6ca623ce..3c49fcbd 100644 --- a/src/lib/load/load-dashboards.ts +++ b/src/lib/load/load-dashboards.ts @@ -33,7 +33,10 @@ export default async function loadDashboards(dir: string) { try { await api.client.request(createDashboard(dashboard)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_dashboards'}, + fatal: true, + }) } })) @@ -64,7 +67,10 @@ export async function loadPanels(dir: string) { try { await api.client.request(createPanel(panel)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_dashboards'}, + fatal: true, + }) } })) } diff --git a/src/lib/load/load-data.ts b/src/lib/load/load-data.ts index 848faf27..d2bc9b48 100644 --- a/src/lib/load/load-data.ts +++ b/src/lib/load/load-data.ts @@ -79,7 +79,10 @@ async function getExistingPrimaryKeys(collection: string, primaryKeyField: strin if (response.length < limit) break page++ } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_data'}, + fatal: true, + }) break } } @@ -91,7 +94,10 @@ async function uploadBatch(collection: string, batch: any[], method: Function) { try { await api.client.request(method(collection, batch)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_data'}, + fatal: true, + }) } } @@ -134,7 +140,10 @@ async function loadSingletons(dir:string) { await api.client.request(updateSingleton(name, cleanedData)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_data'}, + fatal: true, + }) } })) diff --git a/src/lib/load/load-extensions.ts b/src/lib/load/load-extensions.ts index 7c956529..ee9bd871 100644 --- a/src/lib/load/load-extensions.ts +++ b/src/lib/load/load-extensions.ts @@ -52,7 +52,10 @@ export default async function loadExtensions(dir: string): Promise { }) return `-- Installed ${ext.schema?.name}` } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_extensions'}, + fatal: true, + }) return `-- Failed to install ${ext.schema?.name}` } })) diff --git a/src/lib/load/load-files.ts b/src/lib/load/load-files.ts index 7d6c4760..eb5c2719 100644 --- a/src/lib/load/load-files.ts +++ b/src/lib/load/load-files.ts @@ -54,11 +54,17 @@ export default async function loadFiles(dir: string) { try { await api.client.request(uploadFiles(form as any)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_files'}, + fatal: true, + }) } })) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_files'}, + fatal: true, + }) } } diff --git a/src/lib/load/load-flows.ts b/src/lib/load/load-flows.ts index d4817897..0172e984 100644 --- a/src/lib/load/load-flows.ts +++ b/src/lib/load/load-flows.ts @@ -39,7 +39,10 @@ export default async function loadFlows(dir: string) { await loadOperations(newOperations) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_flows'}, + fatal: true, + }) } finally { ux.action.stop() } @@ -72,6 +75,9 @@ export async function loadOperations(operations: any[]) { } } } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_flows'}, + fatal: true, + }) } } diff --git a/src/lib/load/load-folders.ts b/src/lib/load/load-folders.ts index 87fb2525..9917e503 100644 --- a/src/lib/load/load-folders.ts +++ b/src/lib/load/load-folders.ts @@ -38,14 +38,20 @@ export default async function loadFolders(dir: string) { try { await api.client.request(updateFolder(id, rest)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_folders'}, + fatal: true, + }) } })) } else { // ux.stdout('-- No new folders to create') } } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_folders'}, + fatal: true, + }) } } diff --git a/src/lib/load/load-permissions.ts b/src/lib/load/load-permissions.ts index 905c0cbc..23c891da 100644 --- a/src/lib/load/load-permissions.ts +++ b/src/lib/load/load-permissions.ts @@ -30,7 +30,10 @@ export default async function loadPermissions( await api.client.request(createPermissions(newPermissions)) } } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_permissions'}, + fatal: true, + }) } } diff --git a/src/lib/load/load-policies.ts b/src/lib/load/load-policies.ts index 52b7883b..72c5e91b 100644 --- a/src/lib/load/load-policies.ts +++ b/src/lib/load/load-policies.ts @@ -32,7 +32,10 @@ export default async function loadPolicies(dir: string) { // Add the new policy ID to our set of existing policies existingPolicyIds.add(policy.id) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_policies'}, + fatal: true, + }) } } } diff --git a/src/lib/load/load-presets.ts b/src/lib/load/load-presets.ts index 4e0be901..71876166 100644 --- a/src/lib/load/load-presets.ts +++ b/src/lib/load/load-presets.ts @@ -33,7 +33,10 @@ export default async function loadPresets(dir: string) { try { await api.client.request(createPresets(presetsToAdd)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_presets'}, + fatal: true, + }) } } else { // ux.stdout('-- No new presets to create') diff --git a/src/lib/load/load-relations.ts b/src/lib/load/load-relations.ts index 97fe40e5..dca67182 100644 --- a/src/lib/load/load-relations.ts +++ b/src/lib/load/load-relations.ts @@ -46,7 +46,10 @@ async function addRelations(relations: any[]) { try { await api.client.request(createRelation(relation)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_relations'}, + fatal: true, + }) } } } diff --git a/src/lib/load/load-roles.ts b/src/lib/load/load-roles.ts index 201b8b90..16bb326e 100644 --- a/src/lib/load/load-roles.ts +++ b/src/lib/load/load-roles.ts @@ -43,7 +43,10 @@ export default async function loadRoles(dir: string) { existingRoleIds.add(role.id) existingRoleNames.add(role.name.toLowerCase()) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_roles'}, + fatal: true, + }) } } @@ -59,7 +62,10 @@ export default async function loadRoles(dir: string) { const simplifiedRole = {parent: role.parent} await api.client.request(updateRole(role.id, simplifiedRole)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_roles'}, + fatal: true, + }) } } } diff --git a/src/lib/load/load-settings.ts b/src/lib/load/load-settings.ts index 78601de1..bd03ff7b 100644 --- a/src/lib/load/load-settings.ts +++ b/src/lib/load/load-settings.ts @@ -61,7 +61,10 @@ export default async function loadSettings(dir: string) { const mergedSettings = customDefu(currentSettings as any, settings) as DirectusSettings await api.client.request(updateSettings(mergedSettings)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_settings'}, + fatal: true, + }) } ux.action.stop() diff --git a/src/lib/load/load-translations.ts b/src/lib/load/load-translations.ts index 35ca4a2a..c115aff5 100644 --- a/src/lib/load/load-translations.ts +++ b/src/lib/load/load-translations.ts @@ -30,7 +30,10 @@ export default async function loadTranslations(dir: string) { try { await api.client.request(createTranslations(newTranslations)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_translations'}, + fatal: true, + }) } } else { // ux.stdout('-- No new translations to create') diff --git a/src/lib/load/load-users.ts b/src/lib/load/load-users.ts index 80032281..54e686a0 100644 --- a/src/lib/load/load-users.ts +++ b/src/lib/load/load-users.ts @@ -61,7 +61,10 @@ export default async function loadUsers( try { await api.client.request(createUser(user)) } catch (error) { - catchError(error) + catchError(error, { + context: {operation: 'load_users'}, + fatal: true, + }) } } }