@rglabs/butterfly 2.0.1

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.
Files changed (117) hide show
  1. package/CLAUDE.md +201 -0
  2. package/README.md +371 -0
  3. package/dist/commands/add.d.ts +23 -0
  4. package/dist/commands/add.js +303 -0
  5. package/dist/commands/code.d.ts +11 -0
  6. package/dist/commands/code.js +72 -0
  7. package/dist/commands/create-object.d.ts +6 -0
  8. package/dist/commands/create-object.js +293 -0
  9. package/dist/commands/create-report.d.ts +6 -0
  10. package/dist/commands/create-report.js +154 -0
  11. package/dist/commands/diff.d.ts +4 -0
  12. package/dist/commands/diff.js +238 -0
  13. package/dist/commands/download.d.ts +4 -0
  14. package/dist/commands/download.js +374 -0
  15. package/dist/commands/layout.d.ts +12 -0
  16. package/dist/commands/layout.js +83 -0
  17. package/dist/commands/record.d.ts +21 -0
  18. package/dist/commands/record.js +483 -0
  19. package/dist/commands/run-poc.d.ts +3 -0
  20. package/dist/commands/run-poc.js +18 -0
  21. package/dist/commands/setup.d.ts +3 -0
  22. package/dist/commands/setup.js +66 -0
  23. package/dist/commands/start-poc.d.ts +3 -0
  24. package/dist/commands/start-poc.js +55 -0
  25. package/dist/commands/sync-docs.d.ts +3 -0
  26. package/dist/commands/sync-docs.js +27 -0
  27. package/dist/commands/translate.d.ts +13 -0
  28. package/dist/commands/translate.js +401 -0
  29. package/dist/commands/upload.d.ts +3 -0
  30. package/dist/commands/upload.js +150 -0
  31. package/dist/commands/workflow-info.d.ts +13 -0
  32. package/dist/commands/workflow-info.js +161 -0
  33. package/dist/components/ConflictResolver.d.ts +12 -0
  34. package/dist/components/ConflictResolver.js +77 -0
  35. package/dist/components/DiffView.d.ts +11 -0
  36. package/dist/components/DiffView.js +101 -0
  37. package/dist/components/DownloadProgress.d.ts +11 -0
  38. package/dist/components/DownloadProgress.js +29 -0
  39. package/dist/components/RecordPreview.d.ts +11 -0
  40. package/dist/components/RecordPreview.js +91 -0
  41. package/dist/components/SetupForm.d.ts +8 -0
  42. package/dist/components/SetupForm.js +56 -0
  43. package/dist/components/UploadProgress.d.ts +13 -0
  44. package/dist/components/UploadProgress.js +42 -0
  45. package/dist/diff/adapters/index.d.ts +8 -0
  46. package/dist/diff/adapters/index.js +18 -0
  47. package/dist/diff/adapters/objectsAdapter.d.ts +13 -0
  48. package/dist/diff/adapters/objectsAdapter.js +177 -0
  49. package/dist/diff/adapters/reportsAdapter.d.ts +14 -0
  50. package/dist/diff/adapters/reportsAdapter.js +212 -0
  51. package/dist/diff/adapters/types.d.ts +19 -0
  52. package/dist/diff/adapters/types.js +2 -0
  53. package/dist/diff/engine.d.ts +19 -0
  54. package/dist/diff/engine.js +57 -0
  55. package/dist/diff/types.d.ts +34 -0
  56. package/dist/diff/types.js +110 -0
  57. package/dist/index.d.ts +3 -0
  58. package/dist/index.js +117 -0
  59. package/dist/types/index.d.ts +18 -0
  60. package/dist/types/index.js +2 -0
  61. package/dist/utils/api.d.ts +85 -0
  62. package/dist/utils/api.js +1031 -0
  63. package/dist/utils/auth.d.ts +4 -0
  64. package/dist/utils/auth.js +22 -0
  65. package/dist/utils/bfySplitter.d.ts +12 -0
  66. package/dist/utils/bfySplitter.js +151 -0
  67. package/dist/utils/docs.d.ts +16 -0
  68. package/dist/utils/docs.js +186 -0
  69. package/dist/utils/errorLogger.d.ts +6 -0
  70. package/dist/utils/errorLogger.js +29 -0
  71. package/dist/utils/files.d.ts +14 -0
  72. package/dist/utils/files.js +772 -0
  73. package/dist/utils/lockManager.d.ts +15 -0
  74. package/dist/utils/lockManager.js +126 -0
  75. package/dist/utils/resourceHandlers.d.ts +50 -0
  76. package/dist/utils/resourceHandlers.js +684 -0
  77. package/dist/utils/resourceMapping.d.ts +32 -0
  78. package/dist/utils/resourceMapping.js +210 -0
  79. package/dist/utils/singleResourceDownload.d.ts +14 -0
  80. package/dist/utils/singleResourceDownload.js +261 -0
  81. package/dist/utils/summaryGenerator.d.ts +2 -0
  82. package/dist/utils/summaryGenerator.js +183 -0
  83. package/dist/utils/uploadHandler.d.ts +31 -0
  84. package/dist/utils/uploadHandler.js +263 -0
  85. package/docs/AI_API.md +93 -0
  86. package/docs/CLAUDE.md +216 -0
  87. package/docs/PROJECT_SPECIFIC.md +1 -0
  88. package/docs/RECORD_COMMAND.md +262 -0
  89. package/docs/WORKFLOW_API.md +480 -0
  90. package/docs/bfy-splitting.md +126 -0
  91. package/docs/cli-commands.md +333 -0
  92. package/docs/examples/README.md +95 -0
  93. package/docs/examples/order-system.md +147 -0
  94. package/docs/examples/product-catalog.md +195 -0
  95. package/docs/examples/reports.md +187 -0
  96. package/docs/excel-export.md +216 -0
  97. package/docs/field-types/README.md +29 -0
  98. package/docs/field-types/calculated.md +147 -0
  99. package/docs/field-types/code-mappings.md +84 -0
  100. package/docs/field-types/custom.md +340 -0
  101. package/docs/object-specs/README.md +136 -0
  102. package/docs/object-specs/code-parameters.md +151 -0
  103. package/docs/object-specs/creating.md +203 -0
  104. package/docs/object-specs/js-code-examples.md +208 -0
  105. package/docs/object-specs/js-field-updates.md +168 -0
  106. package/docs/objects/README.md +89 -0
  107. package/docs/objects/creating.md +127 -0
  108. package/docs/page-layout.md +361 -0
  109. package/docs/permissions.md +260 -0
  110. package/docs/reports.md +197 -0
  111. package/docs/state-machines.md +544 -0
  112. package/docs/tasks/create-object.md +81 -0
  113. package/docs/translations.md +346 -0
  114. package/docs/twig-helpers.md +283 -0
  115. package/docs/webservices.md +159 -0
  116. package/docs/workspaces.md +176 -0
  117. package/package.json +59 -0
@@ -0,0 +1,32 @@
1
+ export interface ResourceConfig {
2
+ downloadType: string;
3
+ displayName: string;
4
+ isCore: true;
5
+ }
6
+ export interface SubEntityConfig {
7
+ parentTable: string;
8
+ foreignKey: string;
9
+ displayName: string;
10
+ isCore: false;
11
+ }
12
+ export type TableConfig = ResourceConfig | SubEntityConfig;
13
+ export declare const CORE_TABLES: Record<string, ResourceConfig>;
14
+ export declare const SUB_ENTITY_TABLES: Record<string, SubEntityConfig>;
15
+ export declare const TABLE_CONFIG: Record<string, TableConfig>;
16
+ export declare function isCoreTable(tableName: string): boolean;
17
+ export declare function isSubEntity(tableName: string): boolean;
18
+ export declare function getTableConfig(tableName: string): TableConfig | undefined;
19
+ export declare function getRootParentInfo(tableName: string): {
20
+ rootTable: string;
21
+ downloadType: string;
22
+ foreignKeyChain: Array<{
23
+ table: string;
24
+ foreignKey: string;
25
+ }>;
26
+ } | null;
27
+ export declare function getParentTable(tableName: string): string | null;
28
+ export declare function getForeignKey(tableName: string): string | null;
29
+ export declare function shouldAutoDownload(tableName: string): boolean;
30
+ export declare function getCoreTableNames(): string[];
31
+ export declare function getSubEntityTableNames(): string[];
32
+ //# sourceMappingURL=resourceMapping.d.ts.map
@@ -0,0 +1,210 @@
1
+ export const CORE_TABLES = {
2
+ 'objects': {
3
+ downloadType: 'objects',
4
+ displayName: 'Objects',
5
+ isCore: true,
6
+ },
7
+ 'cms_reports': {
8
+ downloadType: 'reports',
9
+ displayName: 'Reports',
10
+ isCore: true,
11
+ },
12
+ 'bfy_ai_tasks': {
13
+ downloadType: 'bfy_ai_tasks',
14
+ displayName: 'AI Tasks',
15
+ isCore: true,
16
+ },
17
+ 'bfy_state_machines': {
18
+ downloadType: 'bfy_state_machines',
19
+ displayName: 'State Machines',
20
+ isCore: true,
21
+ },
22
+ 'pages': {
23
+ downloadType: 'pages',
24
+ displayName: 'Pages',
25
+ isCore: true,
26
+ },
27
+ 'bfy_cronjobs': {
28
+ downloadType: 'bfy_cronjobs',
29
+ displayName: 'Cron Jobs',
30
+ isCore: true,
31
+ },
32
+ 'cms_email_templates': {
33
+ downloadType: 'cms_email_templates',
34
+ displayName: 'Email Templates',
35
+ isCore: true,
36
+ },
37
+ 'pdf_templates': {
38
+ downloadType: 'pdf_templates',
39
+ displayName: 'PDF Templates',
40
+ isCore: true,
41
+ },
42
+ 'cms_email_layouts': {
43
+ downloadType: 'cms_email_layouts',
44
+ displayName: 'Email Layouts',
45
+ isCore: true,
46
+ },
47
+ 'bfy_workflows': {
48
+ downloadType: 'bfy_workflows',
49
+ displayName: 'Workflows',
50
+ isCore: true,
51
+ },
52
+ 'webservices': {
53
+ downloadType: 'webservices',
54
+ displayName: 'Webservices',
55
+ isCore: true,
56
+ },
57
+ };
58
+ export const SUB_ENTITY_TABLES = {
59
+ 'object_specs': {
60
+ parentTable: 'objects',
61
+ foreignKey: 'object_id',
62
+ displayName: 'Object Specs',
63
+ isCore: false,
64
+ },
65
+ 'cms_report_specs': {
66
+ parentTable: 'cms_reports',
67
+ foreignKey: 'cms_report_id',
68
+ displayName: 'Report Specs',
69
+ isCore: false,
70
+ },
71
+ 'cms_report_queries': {
72
+ parentTable: 'cms_reports',
73
+ foreignKey: 'cms_report_id',
74
+ displayName: 'Report Queries',
75
+ isCore: false,
76
+ },
77
+ 'cms_report_categories': {
78
+ parentTable: 'cms_reports',
79
+ foreignKey: 'cms_report_id',
80
+ displayName: 'Report Categories',
81
+ isCore: false,
82
+ },
83
+ 'bfy_state_machine_states': {
84
+ parentTable: 'bfy_state_machines',
85
+ foreignKey: 'bfy_state_machine_id',
86
+ displayName: 'State Machine States',
87
+ isCore: false,
88
+ },
89
+ 'bfy_state_machine_roles': {
90
+ parentTable: 'bfy_state_machines',
91
+ foreignKey: 'bfy_state_machine_id',
92
+ displayName: 'State Machine Roles',
93
+ isCore: false,
94
+ },
95
+ 'bfy_state_machine_transitions': {
96
+ parentTable: 'bfy_state_machines',
97
+ foreignKey: 'bfy_state_machine_id',
98
+ displayName: 'State Machine Transitions',
99
+ isCore: false,
100
+ },
101
+ 'bfy_state_machine_transition_specs': {
102
+ parentTable: 'bfy_state_machine_transitions',
103
+ foreignKey: 'bfy_state_machine_transition_id',
104
+ displayName: 'Transition Specs',
105
+ isCore: false,
106
+ },
107
+ 'bfy_sm_actions': {
108
+ parentTable: 'bfy_state_machines',
109
+ foreignKey: 'bfy_state_machine_id',
110
+ displayName: 'State Machine Actions',
111
+ isCore: false,
112
+ },
113
+ 'bfy_sm_action_specs': {
114
+ parentTable: 'bfy_sm_actions',
115
+ foreignKey: 'bfy_sm_action_id',
116
+ displayName: 'Action Specs',
117
+ isCore: false,
118
+ },
119
+ 'bfy_sm_transition_actions': {
120
+ parentTable: 'bfy_state_machine_transitions',
121
+ foreignKey: 'bfy_state_machine_transition_id',
122
+ displayName: 'Transition Actions',
123
+ isCore: false,
124
+ },
125
+ 'bfy_workflow_versions': {
126
+ parentTable: 'bfy_workflows',
127
+ foreignKey: 'bfy_workflow_id',
128
+ displayName: 'Workflow Versions',
129
+ isCore: false,
130
+ },
131
+ 'bfy_workflow_nodes': {
132
+ parentTable: 'bfy_workflow_versions',
133
+ foreignKey: 'bfy_workflow_version_id',
134
+ displayName: 'Workflow Nodes',
135
+ isCore: false,
136
+ },
137
+ 'bfy_workflow_connections': {
138
+ parentTable: 'bfy_workflow_nodes',
139
+ foreignKey: 'source_node_id',
140
+ displayName: 'Workflow Connections',
141
+ isCore: false,
142
+ },
143
+ };
144
+ export const TABLE_CONFIG = {
145
+ ...CORE_TABLES,
146
+ ...SUB_ENTITY_TABLES,
147
+ };
148
+ export function isCoreTable(tableName) {
149
+ return tableName in CORE_TABLES;
150
+ }
151
+ export function isSubEntity(tableName) {
152
+ return tableName in SUB_ENTITY_TABLES;
153
+ }
154
+ export function getTableConfig(tableName) {
155
+ return TABLE_CONFIG[tableName];
156
+ }
157
+ export function getRootParentInfo(tableName) {
158
+ if (isCoreTable(tableName)) {
159
+ const config = CORE_TABLES[tableName];
160
+ return {
161
+ rootTable: tableName,
162
+ downloadType: config.downloadType,
163
+ foreignKeyChain: [],
164
+ };
165
+ }
166
+ if (!isSubEntity(tableName)) {
167
+ return null;
168
+ }
169
+ const chain = [];
170
+ let currentTable = tableName;
171
+ while (isSubEntity(currentTable)) {
172
+ const config = SUB_ENTITY_TABLES[currentTable];
173
+ chain.push({
174
+ table: currentTable,
175
+ foreignKey: config.foreignKey,
176
+ });
177
+ currentTable = config.parentTable;
178
+ }
179
+ if (isCoreTable(currentTable)) {
180
+ const coreConfig = CORE_TABLES[currentTable];
181
+ return {
182
+ rootTable: currentTable,
183
+ downloadType: coreConfig.downloadType,
184
+ foreignKeyChain: chain,
185
+ };
186
+ }
187
+ return null;
188
+ }
189
+ export function getParentTable(tableName) {
190
+ if (isSubEntity(tableName)) {
191
+ return SUB_ENTITY_TABLES[tableName].parentTable;
192
+ }
193
+ return null;
194
+ }
195
+ export function getForeignKey(tableName) {
196
+ if (isSubEntity(tableName)) {
197
+ return SUB_ENTITY_TABLES[tableName].foreignKey;
198
+ }
199
+ return null;
200
+ }
201
+ export function shouldAutoDownload(tableName) {
202
+ return isCoreTable(tableName) || isSubEntity(tableName);
203
+ }
204
+ export function getCoreTableNames() {
205
+ return Object.keys(CORE_TABLES);
206
+ }
207
+ export function getSubEntityTableNames() {
208
+ return Object.keys(SUB_ENTITY_TABLES);
209
+ }
210
+ //# sourceMappingURL=resourceMapping.js.map
@@ -0,0 +1,14 @@
1
+ import { ButterflyAPI } from './api.js';
2
+ interface DownloadResult {
3
+ success: boolean;
4
+ message: string;
5
+ downloadedResource?: {
6
+ type: string;
7
+ id: number;
8
+ name?: string;
9
+ };
10
+ }
11
+ export declare function downloadSingleResource(api: ButterflyAPI, outputPath: string, tableName: string, recordId: number, recordData?: Record<string, any>): Promise<DownloadResult>;
12
+ export declare function shouldTriggerDownload(tableName: string): boolean;
13
+ export {};
14
+ //# sourceMappingURL=singleResourceDownload.d.ts.map
@@ -0,0 +1,261 @@
1
+ import { saveObjectWithSpecs, saveReportData, saveAiTask, saveTableRecord, saveStateMachineData, saveWorkflowData, } from './files.js';
2
+ import { isCoreTable, isSubEntity, getRootParentInfo, SUB_ENTITY_TABLES, CORE_TABLES, } from './resourceMapping.js';
3
+ async function resolveToRootParentId(api, tableName, recordId, recordData) {
4
+ const rootInfo = getRootParentInfo(tableName);
5
+ if (!rootInfo) {
6
+ return null;
7
+ }
8
+ if (isCoreTable(tableName)) {
9
+ return {
10
+ rootTable: tableName,
11
+ rootId: recordId,
12
+ downloadType: rootInfo.downloadType,
13
+ };
14
+ }
15
+ let currentTable = tableName;
16
+ let currentId = recordId;
17
+ let currentData = recordData;
18
+ while (isSubEntity(currentTable)) {
19
+ const subEntityConfig = SUB_ENTITY_TABLES[currentTable];
20
+ const foreignKey = subEntityConfig.foreignKey;
21
+ let parentId;
22
+ if (currentData && currentData[foreignKey]) {
23
+ parentId = currentData[foreignKey];
24
+ }
25
+ else {
26
+ const records = await api.fetchTableAdvanced(currentTable, {
27
+ column: 'id',
28
+ value: String(currentId),
29
+ });
30
+ if (records.length === 0) {
31
+ return null;
32
+ }
33
+ parentId = records[0][foreignKey];
34
+ }
35
+ if (!parentId) {
36
+ return null;
37
+ }
38
+ currentTable = subEntityConfig.parentTable;
39
+ currentId = parentId;
40
+ currentData = undefined;
41
+ }
42
+ if (isCoreTable(currentTable)) {
43
+ return {
44
+ rootTable: currentTable,
45
+ rootId: currentId,
46
+ downloadType: CORE_TABLES[currentTable].downloadType,
47
+ };
48
+ }
49
+ return null;
50
+ }
51
+ async function downloadSingleObject(api, outputPath, objectId) {
52
+ const objects = await api.fetchTableAdvanced('objects', {
53
+ column: 'id',
54
+ value: String(objectId),
55
+ });
56
+ if (objects.length === 0) {
57
+ return { success: false, message: `Object with ID ${objectId} not found` };
58
+ }
59
+ const object = objects[0];
60
+ const specs = await api.fetchTableAdvanced('object_specs', {
61
+ column: 'object_id',
62
+ value: String(objectId),
63
+ });
64
+ await saveObjectWithSpecs(outputPath, object.table_name, object, specs);
65
+ return {
66
+ success: true,
67
+ message: `Downloaded object: ${object.name} (${object.table_name})`,
68
+ downloadedResource: {
69
+ type: 'objects',
70
+ id: objectId,
71
+ name: object.table_name,
72
+ },
73
+ };
74
+ }
75
+ async function downloadSingleReport(api, outputPath, reportId) {
76
+ const reports = await api.fetchTableAdvanced('cms_reports', {
77
+ column: 'id',
78
+ value: String(reportId),
79
+ });
80
+ if (reports.length === 0) {
81
+ return { success: false, message: `Report with ID ${reportId} not found` };
82
+ }
83
+ const report = reports[0];
84
+ const [specs, queries, categories] = await Promise.all([
85
+ api.fetchTableAdvanced('cms_report_specs', {
86
+ column: 'cms_report_id',
87
+ value: String(reportId),
88
+ }),
89
+ api.fetchTableAdvanced('cms_report_queries', {
90
+ column: 'cms_report_id',
91
+ value: String(reportId),
92
+ }),
93
+ api.fetchTable('cms_report_categories'),
94
+ ]);
95
+ await saveReportData(outputPath, report, specs, queries, categories);
96
+ return {
97
+ success: true,
98
+ message: `Downloaded report: ${report.name || report.alias}`,
99
+ downloadedResource: {
100
+ type: 'reports',
101
+ id: reportId,
102
+ name: report.alias || report.name,
103
+ },
104
+ };
105
+ }
106
+ async function downloadSingleStateMachine(api, outputPath, stateMachineId) {
107
+ const [stateMachines, allStates, allRoles, allTransitions, allTransitionSpecs, allActions, allActionSpecs, allTransitionActions,] = await Promise.all([
108
+ api.fetchTableAdvanced('bfy_state_machines', {
109
+ column: 'id',
110
+ value: String(stateMachineId),
111
+ }),
112
+ api.fetchTableAdvanced('bfy_state_machine_states', {
113
+ column: 'bfy_state_machine_id',
114
+ value: String(stateMachineId),
115
+ }),
116
+ api.fetchTableAdvanced('bfy_state_machine_roles', {
117
+ column: 'bfy_state_machine_id',
118
+ value: String(stateMachineId),
119
+ }),
120
+ api.fetchTableAdvanced('bfy_state_machine_transitions', {
121
+ column: 'bfy_state_machine_id',
122
+ value: String(stateMachineId),
123
+ }),
124
+ api.fetchTable('bfy_state_machine_transition_specs'),
125
+ api.fetchTableAdvanced('bfy_sm_actions', {
126
+ column: 'bfy_state_machine_id',
127
+ value: String(stateMachineId),
128
+ }),
129
+ api.fetchTable('bfy_sm_action_specs'),
130
+ api.fetchTable('bfy_sm_transition_actions'),
131
+ ]);
132
+ if (stateMachines.length === 0) {
133
+ return {
134
+ success: false,
135
+ message: `State machine with ID ${stateMachineId} not found`,
136
+ };
137
+ }
138
+ const stateMachine = stateMachines[0];
139
+ const transitionIds = allTransitions.map((t) => t.id);
140
+ const actionIds = allActions.map((a) => a.id);
141
+ const relatedTransitionSpecs = allTransitionSpecs.filter((spec) => transitionIds.includes(spec.bfy_state_machine_transition_id));
142
+ const relatedActionSpecs = allActionSpecs.filter((spec) => actionIds.includes(spec.bfy_sm_action_id));
143
+ const relatedTransitionActions = allTransitionActions.filter((ta) => transitionIds.includes(ta.bfy_state_machine_transition_id) &&
144
+ actionIds.includes(ta.bfy_sm_action_id));
145
+ await saveStateMachineData(outputPath, stateMachine, allStates, allRoles, allTransitions, relatedTransitionSpecs, allActions, relatedActionSpecs, relatedTransitionActions);
146
+ return {
147
+ success: true,
148
+ message: `Downloaded state machine: ${stateMachine.name}`,
149
+ downloadedResource: {
150
+ type: 'bfy_state_machines',
151
+ id: stateMachineId,
152
+ name: stateMachine.name,
153
+ },
154
+ };
155
+ }
156
+ async function downloadSingleWorkflow(api, outputPath, workflowId) {
157
+ const [workflows, allVersions, allNodes, allConnections] = await Promise.all([
158
+ api.fetchTableAdvanced('bfy_workflows', {
159
+ column: 'id',
160
+ value: String(workflowId),
161
+ }),
162
+ api.fetchTableAdvanced('bfy_workflow_versions', {
163
+ column: 'bfy_workflow_id',
164
+ value: String(workflowId),
165
+ }),
166
+ api.fetchTable('bfy_workflow_nodes'),
167
+ api.fetchTable('bfy_workflow_connections'),
168
+ ]);
169
+ if (workflows.length === 0) {
170
+ return { success: false, message: `Workflow with ID ${workflowId} not found` };
171
+ }
172
+ const workflow = workflows[0];
173
+ const versionIds = allVersions.map((v) => v.id);
174
+ const relatedNodes = allNodes.filter((n) => versionIds.includes(n.bfy_workflow_version_id));
175
+ const nodeIds = relatedNodes.map((n) => n.id);
176
+ const relatedConnections = allConnections.filter((c) => nodeIds.includes(c.source_node_id) || nodeIds.includes(c.target_node_id));
177
+ await saveWorkflowData(outputPath, workflow, allVersions, relatedNodes, relatedConnections);
178
+ return {
179
+ success: true,
180
+ message: `Downloaded workflow: ${workflow.name}`,
181
+ downloadedResource: {
182
+ type: 'bfy_workflows',
183
+ id: workflowId,
184
+ name: workflow.name,
185
+ },
186
+ };
187
+ }
188
+ async function downloadSingleTableRecord(api, outputPath, tableName, recordId) {
189
+ const records = await api.fetchTableAdvanced(tableName, {
190
+ column: 'id',
191
+ value: String(recordId),
192
+ });
193
+ if (records.length === 0) {
194
+ return {
195
+ success: false,
196
+ message: `Record with ID ${recordId} not found in ${tableName}`,
197
+ };
198
+ }
199
+ const record = records[0];
200
+ if (tableName === 'bfy_ai_tasks') {
201
+ await saveAiTask(outputPath, record);
202
+ }
203
+ else {
204
+ await saveTableRecord(outputPath, tableName, record);
205
+ }
206
+ const nameField = record.name || record.system_name || record.title || record.alias;
207
+ return {
208
+ success: true,
209
+ message: `Downloaded ${tableName}: ${nameField || `ID ${recordId}`}`,
210
+ downloadedResource: {
211
+ type: tableName,
212
+ id: recordId,
213
+ name: nameField,
214
+ },
215
+ };
216
+ }
217
+ export async function downloadSingleResource(api, outputPath, tableName, recordId, recordData) {
218
+ try {
219
+ const resolved = await resolveToRootParentId(api, tableName, recordId, recordData);
220
+ if (!resolved) {
221
+ return {
222
+ success: true,
223
+ message: `Table ${tableName} is not a tracked resource, skipping download`,
224
+ };
225
+ }
226
+ const { rootTable, rootId, downloadType } = resolved;
227
+ switch (downloadType) {
228
+ case 'objects':
229
+ return await downloadSingleObject(api, outputPath, rootId);
230
+ case 'reports':
231
+ return await downloadSingleReport(api, outputPath, rootId);
232
+ case 'bfy_state_machines':
233
+ return await downloadSingleStateMachine(api, outputPath, rootId);
234
+ case 'bfy_workflows':
235
+ return await downloadSingleWorkflow(api, outputPath, rootId);
236
+ case 'bfy_ai_tasks':
237
+ case 'pages':
238
+ case 'bfy_cronjobs':
239
+ case 'cms_email_templates':
240
+ case 'pdf_templates':
241
+ case 'cms_email_layouts':
242
+ case 'webservices':
243
+ return await downloadSingleTableRecord(api, outputPath, rootTable, rootId);
244
+ default:
245
+ return {
246
+ success: false,
247
+ message: `Unknown download type: ${downloadType}`,
248
+ };
249
+ }
250
+ }
251
+ catch (error) {
252
+ return {
253
+ success: false,
254
+ message: error instanceof Error ? error.message : 'Unknown error during download',
255
+ };
256
+ }
257
+ }
258
+ export function shouldTriggerDownload(tableName) {
259
+ return isCoreTable(tableName) || isSubEntity(tableName);
260
+ }
261
+ //# sourceMappingURL=singleResourceDownload.js.map
@@ -0,0 +1,2 @@
1
+ export declare function generateTableSummary(outputPath: string): Promise<void>;
2
+ //# sourceMappingURL=summaryGenerator.d.ts.map