@flowdot.ai/daemon 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/LICENSE +45 -0
- package/README.md +51 -0
- package/dist/goals/DependencyResolver.d.ts +54 -0
- package/dist/goals/DependencyResolver.js +329 -0
- package/dist/goals/ErrorRecovery.d.ts +133 -0
- package/dist/goals/ErrorRecovery.js +489 -0
- package/dist/goals/GoalApiClient.d.ts +81 -0
- package/dist/goals/GoalApiClient.js +743 -0
- package/dist/goals/GoalCache.d.ts +65 -0
- package/dist/goals/GoalCache.js +243 -0
- package/dist/goals/GoalCommsHandler.d.ts +150 -0
- package/dist/goals/GoalCommsHandler.js +378 -0
- package/dist/goals/GoalExporter.d.ts +164 -0
- package/dist/goals/GoalExporter.js +318 -0
- package/dist/goals/GoalImporter.d.ts +107 -0
- package/dist/goals/GoalImporter.js +345 -0
- package/dist/goals/GoalManager.d.ts +110 -0
- package/dist/goals/GoalManager.js +535 -0
- package/dist/goals/GoalReporter.d.ts +105 -0
- package/dist/goals/GoalReporter.js +534 -0
- package/dist/goals/GoalScheduler.d.ts +102 -0
- package/dist/goals/GoalScheduler.js +209 -0
- package/dist/goals/GoalValidator.d.ts +72 -0
- package/dist/goals/GoalValidator.js +657 -0
- package/dist/goals/MetaGoalEnforcer.d.ts +111 -0
- package/dist/goals/MetaGoalEnforcer.js +536 -0
- package/dist/goals/MilestoneBreaker.d.ts +74 -0
- package/dist/goals/MilestoneBreaker.js +348 -0
- package/dist/goals/PermissionBridge.d.ts +109 -0
- package/dist/goals/PermissionBridge.js +326 -0
- package/dist/goals/ProgressTracker.d.ts +113 -0
- package/dist/goals/ProgressTracker.js +324 -0
- package/dist/goals/ReviewScheduler.d.ts +106 -0
- package/dist/goals/ReviewScheduler.js +360 -0
- package/dist/goals/TaskExecutor.d.ts +116 -0
- package/dist/goals/TaskExecutor.js +370 -0
- package/dist/goals/TaskFeedback.d.ts +126 -0
- package/dist/goals/TaskFeedback.js +402 -0
- package/dist/goals/TaskGenerator.d.ts +75 -0
- package/dist/goals/TaskGenerator.js +329 -0
- package/dist/goals/TaskQueue.d.ts +84 -0
- package/dist/goals/TaskQueue.js +331 -0
- package/dist/goals/TaskSanitizer.d.ts +61 -0
- package/dist/goals/TaskSanitizer.js +464 -0
- package/dist/goals/errors.d.ts +116 -0
- package/dist/goals/errors.js +299 -0
- package/dist/goals/index.d.ts +24 -0
- package/dist/goals/index.js +23 -0
- package/dist/goals/types.d.ts +395 -0
- package/dist/goals/types.js +230 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/loop/DaemonIPC.d.ts +67 -0
- package/dist/loop/DaemonIPC.js +358 -0
- package/dist/loop/IntervalParser.d.ts +39 -0
- package/dist/loop/IntervalParser.js +217 -0
- package/dist/loop/LoopDaemon.d.ts +123 -0
- package/dist/loop/LoopDaemon.js +1821 -0
- package/dist/loop/LoopExecutor.d.ts +93 -0
- package/dist/loop/LoopExecutor.js +326 -0
- package/dist/loop/LoopManager.d.ts +79 -0
- package/dist/loop/LoopManager.js +476 -0
- package/dist/loop/LoopScheduler.d.ts +69 -0
- package/dist/loop/LoopScheduler.js +329 -0
- package/dist/loop/LoopStore.d.ts +57 -0
- package/dist/loop/LoopStore.js +406 -0
- package/dist/loop/LoopValidator.d.ts +55 -0
- package/dist/loop/LoopValidator.js +603 -0
- package/dist/loop/errors.d.ts +115 -0
- package/dist/loop/errors.js +312 -0
- package/dist/loop/index.d.ts +11 -0
- package/dist/loop/index.js +10 -0
- package/dist/loop/notifications/Notifier.d.ts +28 -0
- package/dist/loop/notifications/Notifier.js +78 -0
- package/dist/loop/notifications/SlackNotifier.d.ts +28 -0
- package/dist/loop/notifications/SlackNotifier.js +203 -0
- package/dist/loop/notifications/TerminalNotifier.d.ts +18 -0
- package/dist/loop/notifications/TerminalNotifier.js +72 -0
- package/dist/loop/notifications/WebhookNotifier.d.ts +24 -0
- package/dist/loop/notifications/WebhookNotifier.js +123 -0
- package/dist/loop/notifications/index.d.ts +24 -0
- package/dist/loop/notifications/index.js +109 -0
- package/dist/loop/types.d.ts +280 -0
- package/dist/loop/types.js +222 -0
- package/package.json +92 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export const EXPORT_FORMAT_VERSION = '1.0.0';
|
|
3
|
+
export class GoalExporter extends EventEmitter {
|
|
4
|
+
logger;
|
|
5
|
+
defaultOptions;
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
super();
|
|
8
|
+
this.logger = options.logger ?? console;
|
|
9
|
+
this.defaultOptions = options.defaultOptions ?? {
|
|
10
|
+
type: 'full',
|
|
11
|
+
includeProgress: true,
|
|
12
|
+
includeSnapshots: false,
|
|
13
|
+
includeFeedback: false,
|
|
14
|
+
includeMetaGoals: true,
|
|
15
|
+
stripUserData: false,
|
|
16
|
+
compress: false,
|
|
17
|
+
prettyPrint: true,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async exportGoal(goalHash, dataProvider, options) {
|
|
21
|
+
return this.exportGoals([goalHash], dataProvider, options);
|
|
22
|
+
}
|
|
23
|
+
async exportGoals(goalHashes, dataProvider, options) {
|
|
24
|
+
const opts = { ...this.defaultOptions, ...options };
|
|
25
|
+
const errors = [];
|
|
26
|
+
const warnings = [];
|
|
27
|
+
this.emit('export:started', goalHashes.length);
|
|
28
|
+
try {
|
|
29
|
+
const goals = await dataProvider.getGoals(goalHashes);
|
|
30
|
+
if (goals.length === 0) {
|
|
31
|
+
return {
|
|
32
|
+
success: false,
|
|
33
|
+
errors: ['No goals found to export'],
|
|
34
|
+
warnings: [],
|
|
35
|
+
statistics: this.emptyStatistics(),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (goals.length !== goalHashes.length) {
|
|
39
|
+
warnings.push(`Requested ${goalHashes.length} goals but found ${goals.length}`);
|
|
40
|
+
this.emit('warning', warnings[warnings.length - 1]);
|
|
41
|
+
}
|
|
42
|
+
const exportedGoals = [];
|
|
43
|
+
let totalMilestones = 0;
|
|
44
|
+
let totalTasks = 0;
|
|
45
|
+
let totalMemories = 0;
|
|
46
|
+
for (let i = 0; i < goals.length; i++) {
|
|
47
|
+
const goal = goals[i];
|
|
48
|
+
this.emit('export:progress', i + 1, goals.length);
|
|
49
|
+
try {
|
|
50
|
+
const exported = await this.exportSingleGoal(goal, dataProvider, opts);
|
|
51
|
+
exportedGoals.push(exported);
|
|
52
|
+
totalMilestones += exported.milestones.length;
|
|
53
|
+
totalTasks += exported.tasks.length;
|
|
54
|
+
totalMemories += exported.memories.length;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
errors.push(`Failed to export goal ${goal.hash}: ${error instanceof Error ? error.message : String(error)}`);
|
|
58
|
+
this.emit('warning', errors[errors.length - 1]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
let exportedMetaGoals;
|
|
62
|
+
if (opts.includeMetaGoals && dataProvider.getMetaGoals) {
|
|
63
|
+
try {
|
|
64
|
+
const metaGoals = await dataProvider.getMetaGoals();
|
|
65
|
+
exportedMetaGoals = metaGoals.map((mg) => this.exportMetaGoal(mg, opts.stripUserData ?? false));
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
warnings.push(`Failed to export meta-goals: ${error instanceof Error ? error.message : String(error)}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const manifest = {
|
|
72
|
+
version: EXPORT_FORMAT_VERSION,
|
|
73
|
+
exportType: opts.type ?? 'full',
|
|
74
|
+
exportedAt: new Date().toISOString(),
|
|
75
|
+
goalCount: exportedGoals.length,
|
|
76
|
+
metaGoalCount: exportedMetaGoals?.length ?? 0,
|
|
77
|
+
totalMilestones,
|
|
78
|
+
totalTasks,
|
|
79
|
+
totalMemories,
|
|
80
|
+
options: opts,
|
|
81
|
+
};
|
|
82
|
+
const exportPackage = {
|
|
83
|
+
manifest,
|
|
84
|
+
goals: exportedGoals,
|
|
85
|
+
metaGoals: exportedMetaGoals,
|
|
86
|
+
};
|
|
87
|
+
const serialized = this.serialize(exportPackage, opts);
|
|
88
|
+
const result = {
|
|
89
|
+
success: errors.length === 0,
|
|
90
|
+
package: exportPackage,
|
|
91
|
+
serialized,
|
|
92
|
+
errors,
|
|
93
|
+
warnings,
|
|
94
|
+
statistics: {
|
|
95
|
+
goalsExported: exportedGoals.length,
|
|
96
|
+
milestonesExported: totalMilestones,
|
|
97
|
+
tasksExported: totalTasks,
|
|
98
|
+
memoriesExported: totalMemories,
|
|
99
|
+
metaGoalsExported: exportedMetaGoals?.length ?? 0,
|
|
100
|
+
exportSize: serialized.length,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
this.emit('export:completed', result);
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
108
|
+
this.emit('export:error', err);
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
errors: [err.message],
|
|
112
|
+
warnings,
|
|
113
|
+
statistics: this.emptyStatistics(),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async exportAll(dataProvider, options) {
|
|
118
|
+
const goals = await dataProvider.getGoals();
|
|
119
|
+
const hashes = goals.map((g) => g.hash);
|
|
120
|
+
return this.exportGoals(hashes, dataProvider, options);
|
|
121
|
+
}
|
|
122
|
+
async createTemplate(goalHash, dataProvider, _templateName) {
|
|
123
|
+
return this.exportGoal(goalHash, dataProvider, {
|
|
124
|
+
type: 'template',
|
|
125
|
+
stripUserData: true,
|
|
126
|
+
includeProgress: false,
|
|
127
|
+
includeSnapshots: false,
|
|
128
|
+
includeFeedback: false,
|
|
129
|
+
includeMetaGoals: false,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
validateExport(data) {
|
|
133
|
+
const errors = [];
|
|
134
|
+
const warnings = [];
|
|
135
|
+
try {
|
|
136
|
+
const pkg = typeof data === 'string'
|
|
137
|
+
? JSON.parse(data)
|
|
138
|
+
: data;
|
|
139
|
+
if (!pkg.manifest) {
|
|
140
|
+
errors.push('Missing manifest');
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
if (!pkg.manifest.version) {
|
|
144
|
+
errors.push('Missing version in manifest');
|
|
145
|
+
}
|
|
146
|
+
if (!pkg.manifest.exportedAt) {
|
|
147
|
+
errors.push('Missing exportedAt in manifest');
|
|
148
|
+
}
|
|
149
|
+
if (pkg.manifest.version !== EXPORT_FORMAT_VERSION) {
|
|
150
|
+
warnings.push(`Version mismatch: export is ${pkg.manifest.version}, current is ${EXPORT_FORMAT_VERSION}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (!Array.isArray(pkg.goals)) {
|
|
154
|
+
errors.push('Goals must be an array');
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
for (let i = 0; i < pkg.goals.length; i++) {
|
|
158
|
+
const goal = pkg.goals[i];
|
|
159
|
+
if (!goal.hash) {
|
|
160
|
+
errors.push(`Goal ${i} missing hash`);
|
|
161
|
+
}
|
|
162
|
+
if (!goal.title) {
|
|
163
|
+
errors.push(`Goal ${i} missing title`);
|
|
164
|
+
}
|
|
165
|
+
if (!goal.status) {
|
|
166
|
+
errors.push(`Goal ${i} missing status`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (pkg.manifest?.checksum) {
|
|
171
|
+
const computed = this.computeChecksum(pkg.goals);
|
|
172
|
+
if (computed !== pkg.manifest.checksum) {
|
|
173
|
+
errors.push('Checksum mismatch - data may be corrupted');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
errors.push(`Parse error: ${error instanceof Error ? error.message : String(error)}`);
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
valid: errors.length === 0,
|
|
182
|
+
errors,
|
|
183
|
+
warnings,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
async exportSingleGoal(goal, dataProvider, options) {
|
|
187
|
+
const [milestones, tasks, memories] = await Promise.all([
|
|
188
|
+
dataProvider.getMilestones(goal.hash),
|
|
189
|
+
dataProvider.getTasks(goal.hash),
|
|
190
|
+
dataProvider.getMemories(goal.hash),
|
|
191
|
+
]);
|
|
192
|
+
const progress = options.includeProgress && dataProvider.getProgress
|
|
193
|
+
? dataProvider.getProgress(goal.hash)
|
|
194
|
+
: undefined;
|
|
195
|
+
const snapshots = options.includeSnapshots && dataProvider.getSnapshots
|
|
196
|
+
? dataProvider.getSnapshots(goal.hash)
|
|
197
|
+
: undefined;
|
|
198
|
+
const feedback = options.includeFeedback && dataProvider.getFeedback
|
|
199
|
+
? dataProvider.getFeedback(goal.hash)
|
|
200
|
+
: undefined;
|
|
201
|
+
const stripUserData = options.stripUserData ?? false;
|
|
202
|
+
return {
|
|
203
|
+
hash: stripUserData ? this.anonymizeHash(goal.hash) : goal.hash,
|
|
204
|
+
title: goal.name,
|
|
205
|
+
description: goal.description ?? undefined,
|
|
206
|
+
status: options.type === 'template' ? 'draft' : goal.status,
|
|
207
|
+
priority: goal.priority,
|
|
208
|
+
deadline: goal.deadline?.toISOString(),
|
|
209
|
+
approvalMode: goal.approvalMode,
|
|
210
|
+
parentHash: String(goal.parentId)
|
|
211
|
+
? stripUserData
|
|
212
|
+
? this.anonymizeHash(String(goal.parentId))
|
|
213
|
+
: String(goal.parentId)
|
|
214
|
+
: undefined,
|
|
215
|
+
dependencyHashes: goal.dependsOn?.map((h) => stripUserData ? this.anonymizeHash(h) : h),
|
|
216
|
+
tags: [],
|
|
217
|
+
createdAt: goal.createdAt.toISOString(),
|
|
218
|
+
updatedAt: goal.updatedAt.toISOString(),
|
|
219
|
+
milestones: milestones.map((m) => this.exportMilestone(m, stripUserData)),
|
|
220
|
+
tasks: tasks.map((t) => this.exportTask(t, stripUserData, options.type)),
|
|
221
|
+
memories: stripUserData
|
|
222
|
+
? []
|
|
223
|
+
: memories.map((m) => this.exportMemory(m)),
|
|
224
|
+
progress: stripUserData ? undefined : progress,
|
|
225
|
+
snapshots: stripUserData ? undefined : snapshots,
|
|
226
|
+
feedback: stripUserData ? undefined : feedback,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
exportMilestone(milestone, stripUserData) {
|
|
230
|
+
return {
|
|
231
|
+
id: milestone.id,
|
|
232
|
+
title: milestone.title,
|
|
233
|
+
description: milestone.description ?? undefined,
|
|
234
|
+
status: stripUserData ? 'pending' : (milestone.isComplete ? 'completed' : 'pending'),
|
|
235
|
+
order: milestone.id,
|
|
236
|
+
deadline: stripUserData ? undefined : milestone.targetDate?.toISOString(),
|
|
237
|
+
createdAt: milestone.createdAt.toISOString(),
|
|
238
|
+
updatedAt: milestone.updatedAt.toISOString(),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
exportTask(task, stripUserData, exportType) {
|
|
242
|
+
return {
|
|
243
|
+
id: task.id,
|
|
244
|
+
milestoneId: task.milestoneId ?? undefined,
|
|
245
|
+
title: task.title,
|
|
246
|
+
description: task.description ?? undefined,
|
|
247
|
+
type: task.taskType,
|
|
248
|
+
status: exportType === 'template' || stripUserData ? 'pending' : task.status,
|
|
249
|
+
priority: task.priority ? { "high": 1, "medium": 2, "low": 3 }[task.priority] ?? 2 : 2,
|
|
250
|
+
params: stripUserData ? undefined : task.params,
|
|
251
|
+
requiresApproval: task.requiresApproval ?? false,
|
|
252
|
+
deadline: stripUserData ? undefined : task.deadline?.toISOString(),
|
|
253
|
+
completedAt: stripUserData ? undefined : task.completedAt?.toISOString(),
|
|
254
|
+
createdAt: task.createdAt.toISOString(),
|
|
255
|
+
updatedAt: task.updatedAt.toISOString(),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
exportMemory(memory) {
|
|
259
|
+
return {
|
|
260
|
+
id: memory.id,
|
|
261
|
+
category: memory.memoryType,
|
|
262
|
+
content: memory.content,
|
|
263
|
+
source: memory.source,
|
|
264
|
+
confidence: undefined,
|
|
265
|
+
expiresAt: undefined,
|
|
266
|
+
createdAt: memory.createdAt.toISOString(),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
exportMetaGoal(metaGoal, stripUserData) {
|
|
270
|
+
return {
|
|
271
|
+
id: metaGoal.id,
|
|
272
|
+
name: metaGoal.description,
|
|
273
|
+
description: metaGoal.description,
|
|
274
|
+
scope: metaGoal.scope === 'all' ? 'all' : 'specific',
|
|
275
|
+
appliesTo: metaGoal.scope === 'all' ? undefined : (stripUserData ? undefined : metaGoal.scope),
|
|
276
|
+
constraints: [],
|
|
277
|
+
priority: metaGoal.priority,
|
|
278
|
+
isActive: metaGoal.isActive,
|
|
279
|
+
createdAt: metaGoal.createdAt.toISOString(),
|
|
280
|
+
updatedAt: metaGoal.updatedAt.toISOString(),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
anonymizeHash(hash) {
|
|
284
|
+
const base = hash.substring(0, 4);
|
|
285
|
+
return `anon_${base}_${Date.now().toString(36)}`;
|
|
286
|
+
}
|
|
287
|
+
serialize(pkg, options) {
|
|
288
|
+
const indent = options.prettyPrint ? 2 : undefined;
|
|
289
|
+
let serialized = JSON.stringify(pkg, null, indent);
|
|
290
|
+
if (options.compress) {
|
|
291
|
+
serialized = Buffer.from(serialized).toString('base64');
|
|
292
|
+
}
|
|
293
|
+
return serialized;
|
|
294
|
+
}
|
|
295
|
+
computeChecksum(goals) {
|
|
296
|
+
const data = JSON.stringify(goals.map((g) => g.hash).sort());
|
|
297
|
+
let hash = 0;
|
|
298
|
+
for (let i = 0; i < data.length; i++) {
|
|
299
|
+
const char = data.charCodeAt(i);
|
|
300
|
+
hash = (hash << 5) - hash + char;
|
|
301
|
+
hash = hash & hash;
|
|
302
|
+
}
|
|
303
|
+
return Math.abs(hash).toString(16);
|
|
304
|
+
}
|
|
305
|
+
emptyStatistics() {
|
|
306
|
+
return {
|
|
307
|
+
goalsExported: 0,
|
|
308
|
+
milestonesExported: 0,
|
|
309
|
+
tasksExported: 0,
|
|
310
|
+
memoriesExported: 0,
|
|
311
|
+
metaGoalsExported: 0,
|
|
312
|
+
exportSize: 0,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
export function createGoalExporter(options) {
|
|
317
|
+
return new GoalExporter(options);
|
|
318
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import type { Goal, GoalHash, CreateGoalInput, CreateMilestoneInput, CreateTaskInput, CreateMemoryInput, CreateMetaGoalInput, Logger } from './types.js';
|
|
3
|
+
import { type ExportPackage } from './GoalExporter.js';
|
|
4
|
+
export type ImportMode = 'create' | 'merge' | 'replace' | 'template';
|
|
5
|
+
export type ConflictResolution = 'skip' | 'overwrite' | 'rename' | 'ask';
|
|
6
|
+
export interface ImportOptions {
|
|
7
|
+
readonly mode?: ImportMode;
|
|
8
|
+
readonly conflictResolution?: ConflictResolution;
|
|
9
|
+
readonly dryRun?: boolean;
|
|
10
|
+
readonly validateOnly?: boolean;
|
|
11
|
+
readonly importMilestones?: boolean;
|
|
12
|
+
readonly importTasks?: boolean;
|
|
13
|
+
readonly importMemories?: boolean;
|
|
14
|
+
readonly importMetaGoals?: boolean;
|
|
15
|
+
readonly resetStatus?: boolean;
|
|
16
|
+
readonly assignToUser?: number;
|
|
17
|
+
readonly prefixTitle?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ImportConflict {
|
|
20
|
+
readonly type: 'goal' | 'meta_goal';
|
|
21
|
+
readonly existingHash?: GoalHash;
|
|
22
|
+
readonly importedTitle: string;
|
|
23
|
+
readonly resolution?: ConflictResolution;
|
|
24
|
+
}
|
|
25
|
+
export interface ImportValidation {
|
|
26
|
+
readonly valid: boolean;
|
|
27
|
+
readonly errors: string[];
|
|
28
|
+
readonly warnings: string[];
|
|
29
|
+
readonly conflicts: ImportConflict[];
|
|
30
|
+
readonly statistics: {
|
|
31
|
+
goalsToImport: number;
|
|
32
|
+
milestonesToImport: number;
|
|
33
|
+
tasksToImport: number;
|
|
34
|
+
memoriesToImport: number;
|
|
35
|
+
metaGoalsToImport: number;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export interface ImportMapping {
|
|
39
|
+
readonly originalHash: GoalHash;
|
|
40
|
+
readonly newHash: GoalHash;
|
|
41
|
+
readonly milestoneMapping: Map<number, number>;
|
|
42
|
+
readonly taskMapping: Map<number, number>;
|
|
43
|
+
readonly memoryMapping: Map<number, number>;
|
|
44
|
+
}
|
|
45
|
+
export interface ImportResult {
|
|
46
|
+
readonly success: boolean;
|
|
47
|
+
readonly dryRun: boolean;
|
|
48
|
+
readonly imported: ImportMapping[];
|
|
49
|
+
readonly skipped: string[];
|
|
50
|
+
readonly errors: string[];
|
|
51
|
+
readonly warnings: string[];
|
|
52
|
+
readonly statistics: {
|
|
53
|
+
goalsImported: number;
|
|
54
|
+
milestonesImported: number;
|
|
55
|
+
tasksImported: number;
|
|
56
|
+
memoriesImported: number;
|
|
57
|
+
metaGoalsImported: number;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export interface ImportDataWriter {
|
|
61
|
+
createGoal(input: CreateGoalInput): Promise<Goal>;
|
|
62
|
+
createMilestone(goalHash: GoalHash, input: CreateMilestoneInput): Promise<{
|
|
63
|
+
id: number;
|
|
64
|
+
}>;
|
|
65
|
+
createTask(goalHash: GoalHash, input: CreateTaskInput): Promise<{
|
|
66
|
+
id: number;
|
|
67
|
+
}>;
|
|
68
|
+
createMemory(goalHash: GoalHash, input: CreateMemoryInput): Promise<{
|
|
69
|
+
id: number;
|
|
70
|
+
}>;
|
|
71
|
+
createMetaGoal?(input: CreateMetaGoalInput): Promise<{
|
|
72
|
+
id: number;
|
|
73
|
+
}>;
|
|
74
|
+
goalExists?(hash: GoalHash): Promise<boolean>;
|
|
75
|
+
findGoalByTitle?(title: string): Promise<Goal | null>;
|
|
76
|
+
}
|
|
77
|
+
export interface GoalImporterOptions {
|
|
78
|
+
readonly logger?: Logger;
|
|
79
|
+
readonly defaultOptions?: ImportOptions;
|
|
80
|
+
}
|
|
81
|
+
export interface GoalImporterEvents {
|
|
82
|
+
'import:started': [goalCount: number];
|
|
83
|
+
'import:progress': [current: number, total: number, goalTitle: string];
|
|
84
|
+
'import:conflict': [conflict: ImportConflict];
|
|
85
|
+
'import:completed': [result: ImportResult];
|
|
86
|
+
'import:error': [error: Error];
|
|
87
|
+
'validation:completed': [validation: ImportValidation];
|
|
88
|
+
warning: [message: string];
|
|
89
|
+
}
|
|
90
|
+
export declare class GoalImporter extends EventEmitter<GoalImporterEvents> {
|
|
91
|
+
private readonly logger;
|
|
92
|
+
private readonly defaultOptions;
|
|
93
|
+
constructor(options?: GoalImporterOptions);
|
|
94
|
+
parse(data: string): ExportPackage;
|
|
95
|
+
validate(data: string | ExportPackage, dataWriter: ImportDataWriter, options?: ImportOptions): Promise<ImportValidation>;
|
|
96
|
+
import(data: string | ExportPackage, dataWriter: ImportDataWriter, options?: ImportOptions): Promise<ImportResult>;
|
|
97
|
+
importTemplate(data: string | ExportPackage, dataWriter: ImportDataWriter, templateOptions?: {
|
|
98
|
+
newTitle?: string;
|
|
99
|
+
newDeadline?: string;
|
|
100
|
+
}): Promise<ImportResult>;
|
|
101
|
+
private validateGoal;
|
|
102
|
+
private importGoal;
|
|
103
|
+
private importMetaGoal;
|
|
104
|
+
private emptyValidationStatistics;
|
|
105
|
+
private emptyStatistics;
|
|
106
|
+
}
|
|
107
|
+
export declare function createGoalImporter(options?: GoalImporterOptions): GoalImporter;
|