@stoneforge/quarry 1.12.0 → 1.14.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/README.md +2 -0
- package/dist/api/quarry-api.d.ts +9 -1
- package/dist/api/quarry-api.d.ts.map +1 -1
- package/dist/api/quarry-api.js +21 -2
- package/dist/api/quarry-api.js.map +1 -1
- package/dist/api/types.d.ts +8 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/api/types.js.map +1 -1
- package/dist/cli/commands/auto-link-helper.d.ts +33 -0
- package/dist/cli/commands/auto-link-helper.d.ts.map +1 -0
- package/dist/cli/commands/auto-link-helper.js +74 -0
- package/dist/cli/commands/auto-link-helper.js.map +1 -0
- package/dist/cli/commands/crud.d.ts +3 -0
- package/dist/cli/commands/crud.d.ts.map +1 -1
- package/dist/cli/commands/crud.js +144 -15
- package/dist/cli/commands/crud.js.map +1 -1
- package/dist/cli/commands/docs.js +2 -2
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/document.js +1 -1
- package/dist/cli/commands/document.js.map +1 -1
- package/dist/cli/commands/entity.js +1 -1
- package/dist/cli/commands/entity.js.map +1 -1
- package/dist/cli/commands/external-sync.d.ts +18 -0
- package/dist/cli/commands/external-sync.d.ts.map +1 -0
- package/dist/cli/commands/external-sync.js +2499 -0
- package/dist/cli/commands/external-sync.js.map +1 -0
- package/dist/cli/commands/library.js +1 -1
- package/dist/cli/commands/library.js.map +1 -1
- package/dist/cli/commands/message.js +2 -2
- package/dist/cli/commands/message.js.map +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/serve.js +2 -0
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/task.d.ts.map +1 -1
- package/dist/cli/commands/task.js +7 -4
- package/dist/cli/commands/task.js.map +1 -1
- package/dist/cli/commands/team.js +1 -1
- package/dist/cli/commands/team.js.map +1 -1
- package/dist/cli/commands/workflow.js +1 -1
- package/dist/cli/commands/workflow.js.map +1 -1
- package/dist/cli/runner.d.ts.map +1 -1
- package/dist/cli/runner.js +3 -0
- package/dist/cli/runner.js.map +1 -1
- package/dist/cli/utils/progress.d.ts +30 -0
- package/dist/cli/utils/progress.d.ts.map +1 -0
- package/dist/cli/utils/progress.js +47 -0
- package/dist/cli/utils/progress.js.map +1 -0
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +34 -0
- package/dist/config/config.js.map +1 -1
- package/dist/config/defaults.d.ts +13 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +22 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/file.d.ts.map +1 -1
- package/dist/config/file.js +71 -0
- package/dist/config/file.js.map +1 -1
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +2 -2
- package/dist/config/index.js.map +1 -1
- package/dist/config/merge.d.ts.map +1 -1
- package/dist/config/merge.js +52 -1
- package/dist/config/merge.js.map +1 -1
- package/dist/config/types.d.ts +68 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +33 -0
- package/dist/config/types.js.map +1 -1
- package/dist/config/validation.d.ts.map +1 -1
- package/dist/config/validation.js +64 -1
- package/dist/config/validation.js.map +1 -1
- package/dist/external-sync/adapters/document-sync-adapter.d.ts +150 -0
- package/dist/external-sync/adapters/document-sync-adapter.d.ts.map +1 -0
- package/dist/external-sync/adapters/document-sync-adapter.js +325 -0
- package/dist/external-sync/adapters/document-sync-adapter.js.map +1 -0
- package/dist/external-sync/adapters/task-sync-adapter.d.ts +177 -0
- package/dist/external-sync/adapters/task-sync-adapter.d.ts.map +1 -0
- package/dist/external-sync/adapters/task-sync-adapter.js +353 -0
- package/dist/external-sync/adapters/task-sync-adapter.js.map +1 -0
- package/dist/external-sync/auto-link.d.ts +66 -0
- package/dist/external-sync/auto-link.d.ts.map +1 -0
- package/dist/external-sync/auto-link.js +98 -0
- package/dist/external-sync/auto-link.js.map +1 -0
- package/dist/external-sync/conflict-resolver.d.ts +170 -0
- package/dist/external-sync/conflict-resolver.d.ts.map +1 -0
- package/dist/external-sync/conflict-resolver.js +580 -0
- package/dist/external-sync/conflict-resolver.js.map +1 -0
- package/dist/external-sync/index.d.ts +23 -0
- package/dist/external-sync/index.d.ts.map +1 -0
- package/dist/external-sync/index.js +24 -0
- package/dist/external-sync/index.js.map +1 -0
- package/dist/external-sync/provider-registry.d.ts +113 -0
- package/dist/external-sync/provider-registry.d.ts.map +1 -0
- package/dist/external-sync/provider-registry.js +205 -0
- package/dist/external-sync/provider-registry.js.map +1 -0
- package/dist/external-sync/providers/folder/folder-document-adapter.d.ts +97 -0
- package/dist/external-sync/providers/folder/folder-document-adapter.d.ts.map +1 -0
- package/dist/external-sync/providers/folder/folder-document-adapter.js +261 -0
- package/dist/external-sync/providers/folder/folder-document-adapter.js.map +1 -0
- package/dist/external-sync/providers/folder/folder-fs.d.ts +146 -0
- package/dist/external-sync/providers/folder/folder-fs.d.ts.map +1 -0
- package/dist/external-sync/providers/folder/folder-fs.js +300 -0
- package/dist/external-sync/providers/folder/folder-fs.js.map +1 -0
- package/dist/external-sync/providers/folder/folder-provider.d.ts +28 -0
- package/dist/external-sync/providers/folder/folder-provider.d.ts.map +1 -0
- package/dist/external-sync/providers/folder/folder-provider.js +87 -0
- package/dist/external-sync/providers/folder/folder-provider.js.map +1 -0
- package/dist/external-sync/providers/folder/index.d.ts +11 -0
- package/dist/external-sync/providers/folder/index.d.ts.map +1 -0
- package/dist/external-sync/providers/folder/index.js +13 -0
- package/dist/external-sync/providers/folder/index.js.map +1 -0
- package/dist/external-sync/providers/github/github-api.d.ts +271 -0
- package/dist/external-sync/providers/github/github-api.d.ts.map +1 -0
- package/dist/external-sync/providers/github/github-api.js +366 -0
- package/dist/external-sync/providers/github/github-api.js.map +1 -0
- package/dist/external-sync/providers/github/github-field-map.d.ts +76 -0
- package/dist/external-sync/providers/github/github-field-map.d.ts.map +1 -0
- package/dist/external-sync/providers/github/github-field-map.js +157 -0
- package/dist/external-sync/providers/github/github-field-map.js.map +1 -0
- package/dist/external-sync/providers/github/github-provider.d.ts +36 -0
- package/dist/external-sync/providers/github/github-provider.d.ts.map +1 -0
- package/dist/external-sync/providers/github/github-provider.js +212 -0
- package/dist/external-sync/providers/github/github-provider.js.map +1 -0
- package/dist/external-sync/providers/github/github-task-adapter.d.ts +135 -0
- package/dist/external-sync/providers/github/github-task-adapter.d.ts.map +1 -0
- package/dist/external-sync/providers/github/github-task-adapter.js +374 -0
- package/dist/external-sync/providers/github/github-task-adapter.js.map +1 -0
- package/dist/external-sync/providers/github/index.d.ts +12 -0
- package/dist/external-sync/providers/github/index.d.ts.map +1 -0
- package/dist/external-sync/providers/github/index.js +15 -0
- package/dist/external-sync/providers/github/index.js.map +1 -0
- package/dist/external-sync/providers/index.d.ts +13 -0
- package/dist/external-sync/providers/index.d.ts.map +1 -0
- package/dist/external-sync/providers/index.js +15 -0
- package/dist/external-sync/providers/index.js.map +1 -0
- package/dist/external-sync/providers/linear/index.d.ts +19 -0
- package/dist/external-sync/providers/linear/index.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/index.js +19 -0
- package/dist/external-sync/providers/linear/index.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-api.d.ts +252 -0
- package/dist/external-sync/providers/linear/linear-api.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-api.js +522 -0
- package/dist/external-sync/providers/linear/linear-api.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-field-map.d.ts +135 -0
- package/dist/external-sync/providers/linear/linear-field-map.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-field-map.js +338 -0
- package/dist/external-sync/providers/linear/linear-field-map.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-provider.d.ts +52 -0
- package/dist/external-sync/providers/linear/linear-provider.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-provider.js +169 -0
- package/dist/external-sync/providers/linear/linear-provider.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-task-adapter.d.ts +190 -0
- package/dist/external-sync/providers/linear/linear-task-adapter.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-task-adapter.js +521 -0
- package/dist/external-sync/providers/linear/linear-task-adapter.js.map +1 -0
- package/dist/external-sync/providers/linear/linear-types.d.ts +114 -0
- package/dist/external-sync/providers/linear/linear-types.d.ts.map +1 -0
- package/dist/external-sync/providers/linear/linear-types.js +10 -0
- package/dist/external-sync/providers/linear/linear-types.js.map +1 -0
- package/dist/external-sync/providers/notion/index.d.ts +19 -0
- package/dist/external-sync/providers/notion/index.d.ts.map +1 -0
- package/dist/external-sync/providers/notion/index.js +20 -0
- package/dist/external-sync/providers/notion/index.js.map +1 -0
- package/dist/external-sync/providers/notion/notion-api.d.ts +253 -0
- package/dist/external-sync/providers/notion/notion-api.d.ts.map +1 -0
- package/dist/external-sync/providers/notion/notion-api.js +492 -0
- package/dist/external-sync/providers/notion/notion-api.js.map +1 -0
- package/dist/external-sync/providers/notion/notion-blocks.d.ts +93 -0
- package/dist/external-sync/providers/notion/notion-blocks.d.ts.map +1 -0
- package/dist/external-sync/providers/notion/notion-blocks.js +773 -0
- package/dist/external-sync/providers/notion/notion-blocks.js.map +1 -0
- package/dist/external-sync/providers/notion/notion-document-adapter.d.ts +176 -0
- package/dist/external-sync/providers/notion/notion-document-adapter.d.ts.map +1 -0
- package/dist/external-sync/providers/notion/notion-document-adapter.js +413 -0
- package/dist/external-sync/providers/notion/notion-document-adapter.js.map +1 -0
- package/dist/external-sync/providers/notion/notion-provider.d.ts +57 -0
- package/dist/external-sync/providers/notion/notion-provider.d.ts.map +1 -0
- package/dist/external-sync/providers/notion/notion-provider.js +159 -0
- package/dist/external-sync/providers/notion/notion-provider.js.map +1 -0
- package/dist/external-sync/providers/notion/notion-types.d.ts +388 -0
- package/dist/external-sync/providers/notion/notion-types.d.ts.map +1 -0
- package/dist/external-sync/providers/notion/notion-types.js +47 -0
- package/dist/external-sync/providers/notion/notion-types.js.map +1 -0
- package/dist/external-sync/sync-engine.d.ts +364 -0
- package/dist/external-sync/sync-engine.d.ts.map +1 -0
- package/dist/external-sync/sync-engine.js +1154 -0
- package/dist/external-sync/sync-engine.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/server/index.js +8 -8
- package/dist/server/index.js.map +1 -1
- package/dist/services/inbox.js +1 -1
- package/dist/sync/hash.d.ts +5 -0
- package/dist/sync/hash.d.ts.map +1 -1
- package/dist/sync/hash.js +21 -2
- package/dist/sync/hash.js.map +1 -1
- package/package.json +10 -12
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conflict Detection and Resolution Module
|
|
3
|
+
*
|
|
4
|
+
* Detects conflicts during external sync (both local and remote changed since
|
|
5
|
+
* last sync) and resolves them using configurable strategies:
|
|
6
|
+
*
|
|
7
|
+
* - last_write_wins: Compare updatedAt timestamps, most recent wins
|
|
8
|
+
* - local_wins: Stoneforge version always wins
|
|
9
|
+
* - remote_wins: External version always wins
|
|
10
|
+
* - manual: Tag element with sync-conflict for human resolution
|
|
11
|
+
*
|
|
12
|
+
* Supports field-level merge: when different fields changed on each side,
|
|
13
|
+
* both changes are applied automatically. Only same-field changes are conflicts.
|
|
14
|
+
*
|
|
15
|
+
* @module conflict-resolver
|
|
16
|
+
*/
|
|
17
|
+
import { createHash } from 'crypto';
|
|
18
|
+
import { computeContentHashSync } from '../sync/hash.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Conflict Detection
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Detect whether a conflict exists between a local element and a remote item.
|
|
24
|
+
*
|
|
25
|
+
* A conflict exists when BOTH of these are true:
|
|
26
|
+
* - Local changed: current element content hash differs from lastPushedHash
|
|
27
|
+
* - Remote changed: current external item hash differs from lastPulledHash
|
|
28
|
+
*
|
|
29
|
+
* If a fieldMapConfig is provided along with baselines, performs field-level
|
|
30
|
+
* analysis to determine which specific fields conflict.
|
|
31
|
+
*
|
|
32
|
+
* @param localElement - The current local element
|
|
33
|
+
* @param remoteItem - The current external item
|
|
34
|
+
* @param syncState - The element's external sync state (from metadata._externalSync)
|
|
35
|
+
* @param options - Optional field-level detection options
|
|
36
|
+
* @returns ConflictInfo if both sides changed, or null if no conflict
|
|
37
|
+
*/
|
|
38
|
+
export function detectConflict(localElement, remoteItem, syncState, options) {
|
|
39
|
+
// Check if local changed: current hash differs from lastPushedHash
|
|
40
|
+
const localChanged = hasLocalChanged(localElement, syncState);
|
|
41
|
+
// Check if remote changed: compute a hash of the remote item's relevant fields
|
|
42
|
+
// and compare against lastPulledHash
|
|
43
|
+
const remoteChanged = hasRemoteChanged(remoteItem, syncState);
|
|
44
|
+
// No conflict if only one side (or neither) changed
|
|
45
|
+
if (!localChanged || !remoteChanged) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
// Both sides changed — we have a conflict
|
|
49
|
+
// Perform field-level analysis if possible
|
|
50
|
+
const fieldAnalysis = analyzeFieldChanges(localElement, remoteItem, options);
|
|
51
|
+
return {
|
|
52
|
+
elementId: localElement.id,
|
|
53
|
+
externalId: remoteItem.externalId,
|
|
54
|
+
provider: syncState.provider,
|
|
55
|
+
project: syncState.project,
|
|
56
|
+
localUpdatedAt: localElement.updatedAt,
|
|
57
|
+
remoteUpdatedAt: remoteItem.updatedAt,
|
|
58
|
+
localChangedFields: fieldAnalysis.localChangedFields,
|
|
59
|
+
remoteChangedFields: fieldAnalysis.remoteChangedFields,
|
|
60
|
+
conflictingFields: fieldAnalysis.conflictingFields,
|
|
61
|
+
canFieldMerge: fieldAnalysis.canFieldMerge,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check whether the local element has changed since last push.
|
|
66
|
+
* Compares current content hash against the stored lastPushedHash.
|
|
67
|
+
*/
|
|
68
|
+
function hasLocalChanged(localElement, syncState) {
|
|
69
|
+
if (!syncState.lastPushedHash) {
|
|
70
|
+
// Never pushed — consider it changed
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
const currentHash = computeContentHashSync(localElement);
|
|
74
|
+
return currentHash.hash !== syncState.lastPushedHash;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check whether the remote item has changed since last pull.
|
|
78
|
+
* Computes a content hash of the remote item's normalized fields
|
|
79
|
+
* and compares against the stored lastPulledHash.
|
|
80
|
+
*/
|
|
81
|
+
function hasRemoteChanged(remoteItem, syncState) {
|
|
82
|
+
if (!syncState.lastPulledHash) {
|
|
83
|
+
// Never pulled — consider it changed
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
const currentHash = computeExternalItemHash(remoteItem);
|
|
87
|
+
return currentHash !== syncState.lastPulledHash;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Compute a deterministic hash for an external item's content fields.
|
|
91
|
+
* Used for change detection on the remote side.
|
|
92
|
+
*
|
|
93
|
+
* Normalizes the item to a consistent shape for hashing:
|
|
94
|
+
* sorted keys, JSON stringified, SHA256.
|
|
95
|
+
*/
|
|
96
|
+
export function computeExternalItemHash(item) {
|
|
97
|
+
// Extract the content-relevant fields (exclude volatile fields like raw)
|
|
98
|
+
const hashableFields = {
|
|
99
|
+
title: item.title,
|
|
100
|
+
body: item.body ?? '',
|
|
101
|
+
state: item.state,
|
|
102
|
+
labels: [...item.labels].sort(),
|
|
103
|
+
assignees: [...item.assignees].sort(),
|
|
104
|
+
};
|
|
105
|
+
// Sort keys for determinism and hash
|
|
106
|
+
const sortedKeys = Object.keys(hashableFields).sort();
|
|
107
|
+
const sorted = {};
|
|
108
|
+
for (const key of sortedKeys) {
|
|
109
|
+
sorted[key] = hashableFields[key];
|
|
110
|
+
}
|
|
111
|
+
const input = `external:${JSON.stringify(sorted)}`;
|
|
112
|
+
return hashString(input);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Analyze which fields changed on each side.
|
|
116
|
+
*
|
|
117
|
+
* When baselines and field map config are provided, performs precise
|
|
118
|
+
* field-level diffing. Otherwise, falls back to reporting the entire
|
|
119
|
+
* change as a single conflict.
|
|
120
|
+
*/
|
|
121
|
+
function analyzeFieldChanges(localElement, remoteItem, options) {
|
|
122
|
+
const fieldMapConfig = options?.fieldMapConfig;
|
|
123
|
+
const localBaseline = options?.localBaseline;
|
|
124
|
+
const remoteBaseline = options?.remoteBaseline;
|
|
125
|
+
// Without field map config or baselines, we can't do field-level analysis
|
|
126
|
+
if (!fieldMapConfig || !localBaseline || !remoteBaseline) {
|
|
127
|
+
return {
|
|
128
|
+
localChangedFields: ['*'],
|
|
129
|
+
remoteChangedFields: ['*'],
|
|
130
|
+
conflictingFields: ['*'],
|
|
131
|
+
canFieldMerge: false,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const localChangedFields = [];
|
|
135
|
+
const remoteChangedFields = [];
|
|
136
|
+
// Check each mapped field for changes
|
|
137
|
+
for (const mapping of fieldMapConfig.fields) {
|
|
138
|
+
const localField = mapping.localField;
|
|
139
|
+
const externalField = mapping.externalField;
|
|
140
|
+
// Check if local changed for this field
|
|
141
|
+
const localCurrent = getFieldValue(localElement, localField);
|
|
142
|
+
const localBaselineValue = localBaseline[localField];
|
|
143
|
+
if (!deepEqual(localCurrent, localBaselineValue)) {
|
|
144
|
+
localChangedFields.push(localField);
|
|
145
|
+
}
|
|
146
|
+
// Check if remote changed for this field
|
|
147
|
+
const remoteCurrent = getExternalFieldValue(remoteItem, externalField);
|
|
148
|
+
const remoteBaselineValue = remoteBaseline[externalField];
|
|
149
|
+
if (!deepEqual(remoteCurrent, remoteBaselineValue)) {
|
|
150
|
+
remoteChangedFields.push(externalField);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Find conflicting fields — fields that changed on BOTH sides
|
|
154
|
+
// We need to map between local and external field names
|
|
155
|
+
const conflictingFields = findConflictingFields(localChangedFields, remoteChangedFields, fieldMapConfig.fields);
|
|
156
|
+
return {
|
|
157
|
+
localChangedFields,
|
|
158
|
+
remoteChangedFields,
|
|
159
|
+
conflictingFields,
|
|
160
|
+
// Can field-merge if at least some fields don't conflict
|
|
161
|
+
canFieldMerge: conflictingFields.length < localChangedFields.length ||
|
|
162
|
+
conflictingFields.length < remoteChangedFields.length,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Find fields that changed on BOTH sides by cross-referencing the
|
|
167
|
+
* field mapping to identify overlapping changes.
|
|
168
|
+
*/
|
|
169
|
+
function findConflictingFields(localChangedFields, remoteChangedFields, mappings) {
|
|
170
|
+
const conflicting = [];
|
|
171
|
+
for (const mapping of mappings) {
|
|
172
|
+
const localChanged = localChangedFields.includes(mapping.localField);
|
|
173
|
+
const remoteChanged = remoteChangedFields.includes(mapping.externalField);
|
|
174
|
+
if (localChanged && remoteChanged) {
|
|
175
|
+
// Same mapped field changed on both sides — conflict
|
|
176
|
+
conflicting.push(mapping.localField);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return conflicting;
|
|
180
|
+
}
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// Conflict Resolution
|
|
183
|
+
// ============================================================================
|
|
184
|
+
/**
|
|
185
|
+
* Resolve a conflict using the specified strategy.
|
|
186
|
+
*
|
|
187
|
+
* Strategies:
|
|
188
|
+
* - last_write_wins: Compare updatedAt timestamps, most recent wins
|
|
189
|
+
* - local_wins: Stoneforge version always takes precedence
|
|
190
|
+
* - remote_wins: External version always takes precedence
|
|
191
|
+
* - manual: Mark for human resolution
|
|
192
|
+
*
|
|
193
|
+
* When field-level merge is possible (different fields changed on each side),
|
|
194
|
+
* non-conflicting fields are merged automatically regardless of strategy.
|
|
195
|
+
* The strategy only applies to fields that actually conflict (same field
|
|
196
|
+
* changed on both sides).
|
|
197
|
+
*
|
|
198
|
+
* @param conflict - The detected conflict info
|
|
199
|
+
* @param strategy - The resolution strategy to apply
|
|
200
|
+
* @param localElement - Current local element
|
|
201
|
+
* @param remoteItem - Current remote item
|
|
202
|
+
* @param options - Optional field map config for field-level merge
|
|
203
|
+
* @returns ResolvedChanges describing what to apply
|
|
204
|
+
*/
|
|
205
|
+
export function resolveConflict(conflict, strategy, localElement, remoteItem, options) {
|
|
206
|
+
// If we can do field-level merge and have the elements, try it
|
|
207
|
+
if (conflict.canFieldMerge &&
|
|
208
|
+
localElement &&
|
|
209
|
+
remoteItem &&
|
|
210
|
+
options?.fieldMapConfig) {
|
|
211
|
+
return resolveWithFieldMerge(conflict, strategy, localElement, remoteItem, options.fieldMapConfig);
|
|
212
|
+
}
|
|
213
|
+
// Full-element resolution (no field-level merge)
|
|
214
|
+
switch (strategy) {
|
|
215
|
+
case 'last_write_wins':
|
|
216
|
+
return resolveLastWriteWins(conflict, localElement, remoteItem);
|
|
217
|
+
case 'local_wins':
|
|
218
|
+
return resolveLocalWins(conflict);
|
|
219
|
+
case 'remote_wins':
|
|
220
|
+
return resolveRemoteWins(conflict, remoteItem);
|
|
221
|
+
case 'manual':
|
|
222
|
+
return resolveManual(conflict, localElement, remoteItem);
|
|
223
|
+
default:
|
|
224
|
+
// Exhaustive check
|
|
225
|
+
return resolveManual(conflict, localElement, remoteItem);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Resolve a conflict using last-write-wins strategy.
|
|
230
|
+
* Compares updatedAt timestamps; the most recent wins.
|
|
231
|
+
*/
|
|
232
|
+
function resolveLastWriteWins(conflict, localElement, remoteItem) {
|
|
233
|
+
const localTime = new Date(conflict.localUpdatedAt).getTime();
|
|
234
|
+
const remoteTime = new Date(conflict.remoteUpdatedAt).getTime();
|
|
235
|
+
if (localTime >= remoteTime) {
|
|
236
|
+
// Local is newer or same time — local wins
|
|
237
|
+
return {
|
|
238
|
+
conflict,
|
|
239
|
+
strategy: 'last_write_wins',
|
|
240
|
+
resolved: true,
|
|
241
|
+
winner: 'local',
|
|
242
|
+
// No local updates needed; remote should be updated from local
|
|
243
|
+
remoteUpdates: localElement ? extractPushableFields(localElement) : undefined,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
// Remote is newer — remote wins
|
|
248
|
+
return {
|
|
249
|
+
conflict,
|
|
250
|
+
strategy: 'last_write_wins',
|
|
251
|
+
resolved: true,
|
|
252
|
+
winner: 'remote',
|
|
253
|
+
localUpdates: remoteItem ? extractPullableFields(remoteItem) : undefined,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Resolve a conflict with local-wins strategy.
|
|
259
|
+
* Stoneforge version always takes precedence.
|
|
260
|
+
*/
|
|
261
|
+
function resolveLocalWins(conflict) {
|
|
262
|
+
return {
|
|
263
|
+
conflict,
|
|
264
|
+
strategy: 'local_wins',
|
|
265
|
+
resolved: true,
|
|
266
|
+
winner: 'local',
|
|
267
|
+
// Remote needs to be updated with local values; caller handles the push
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Resolve a conflict with remote-wins strategy.
|
|
272
|
+
* External version always takes precedence.
|
|
273
|
+
*/
|
|
274
|
+
function resolveRemoteWins(conflict, remoteItem) {
|
|
275
|
+
return {
|
|
276
|
+
conflict,
|
|
277
|
+
strategy: 'remote_wins',
|
|
278
|
+
resolved: true,
|
|
279
|
+
winner: 'remote',
|
|
280
|
+
localUpdates: remoteItem ? extractPullableFields(remoteItem) : undefined,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Mark a conflict for manual resolution.
|
|
285
|
+
* Stores both versions so a human can choose.
|
|
286
|
+
*/
|
|
287
|
+
function resolveManual(conflict, localElement, remoteItem) {
|
|
288
|
+
return {
|
|
289
|
+
conflict,
|
|
290
|
+
strategy: 'manual',
|
|
291
|
+
resolved: false,
|
|
292
|
+
manualConflict: {
|
|
293
|
+
local: localElement ? extractPushableFields(localElement) : {},
|
|
294
|
+
remote: remoteItem ? extractPullableFields(remoteItem) : {},
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Resolve with field-level merge.
|
|
300
|
+
*
|
|
301
|
+
* Non-conflicting fields are merged automatically:
|
|
302
|
+
* - Fields only changed locally → keep local, push to remote
|
|
303
|
+
* - Fields only changed remotely → pull remote, apply locally
|
|
304
|
+
*
|
|
305
|
+
* For conflicting fields (same field changed on both sides),
|
|
306
|
+
* the strategy determines the winner.
|
|
307
|
+
*/
|
|
308
|
+
function resolveWithFieldMerge(conflict, strategy, localElement, remoteItem, fieldMapConfig) {
|
|
309
|
+
const localUpdates = {};
|
|
310
|
+
const remoteUpdates = {};
|
|
311
|
+
// Build lookup sets for quick membership checks
|
|
312
|
+
const localChangedSet = new Set(conflict.localChangedFields);
|
|
313
|
+
const remoteChangedSet = new Set(conflict.remoteChangedFields);
|
|
314
|
+
const conflictingSet = new Set(conflict.conflictingFields);
|
|
315
|
+
for (const mapping of fieldMapConfig.fields) {
|
|
316
|
+
const localField = mapping.localField;
|
|
317
|
+
const externalField = mapping.externalField;
|
|
318
|
+
const localChanged = localChangedSet.has(localField);
|
|
319
|
+
const remoteChanged = remoteChangedSet.has(externalField);
|
|
320
|
+
if (localChanged && !remoteChanged) {
|
|
321
|
+
// Only local changed — push local value to remote
|
|
322
|
+
const localValue = getFieldValue(localElement, localField);
|
|
323
|
+
remoteUpdates[externalField] = localValue;
|
|
324
|
+
}
|
|
325
|
+
else if (remoteChanged && !localChanged) {
|
|
326
|
+
// Only remote changed — pull remote value to local
|
|
327
|
+
const remoteValue = getExternalFieldValue(remoteItem, externalField);
|
|
328
|
+
localUpdates[localField] = remoteValue;
|
|
329
|
+
}
|
|
330
|
+
else if (conflictingSet.has(localField)) {
|
|
331
|
+
// Both changed this field — apply strategy
|
|
332
|
+
resolveFieldConflict(strategy, conflict, mapping, localElement, remoteItem, localUpdates, remoteUpdates);
|
|
333
|
+
}
|
|
334
|
+
// If neither changed, no action needed
|
|
335
|
+
}
|
|
336
|
+
// If strategy is manual and there are conflicting fields, mark as unresolved
|
|
337
|
+
if (strategy === 'manual' && conflict.conflictingFields.length > 0) {
|
|
338
|
+
const localConflictValues = {};
|
|
339
|
+
const remoteConflictValues = {};
|
|
340
|
+
for (const field of conflict.conflictingFields) {
|
|
341
|
+
localConflictValues[field] = getFieldValue(localElement, field);
|
|
342
|
+
// Find corresponding external field
|
|
343
|
+
const mapping = fieldMapConfig.fields.find((m) => m.localField === field);
|
|
344
|
+
if (mapping) {
|
|
345
|
+
remoteConflictValues[mapping.externalField] = getExternalFieldValue(remoteItem, mapping.externalField);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
conflict,
|
|
350
|
+
strategy,
|
|
351
|
+
resolved: false,
|
|
352
|
+
winner: 'merged',
|
|
353
|
+
localUpdates: Object.keys(localUpdates).length > 0 ? localUpdates : undefined,
|
|
354
|
+
remoteUpdates: Object.keys(remoteUpdates).length > 0 ? remoteUpdates : undefined,
|
|
355
|
+
manualConflict: {
|
|
356
|
+
local: localConflictValues,
|
|
357
|
+
remote: remoteConflictValues,
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
conflict,
|
|
363
|
+
strategy,
|
|
364
|
+
resolved: true,
|
|
365
|
+
winner: 'merged',
|
|
366
|
+
localUpdates: Object.keys(localUpdates).length > 0 ? localUpdates : undefined,
|
|
367
|
+
remoteUpdates: Object.keys(remoteUpdates).length > 0 ? remoteUpdates : undefined,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Resolve a single field conflict using the given strategy.
|
|
372
|
+
*/
|
|
373
|
+
function resolveFieldConflict(strategy, conflict, mapping, localElement, remoteItem, localUpdates, remoteUpdates) {
|
|
374
|
+
const localValue = getFieldValue(localElement, mapping.localField);
|
|
375
|
+
const remoteValue = getExternalFieldValue(remoteItem, mapping.externalField);
|
|
376
|
+
switch (strategy) {
|
|
377
|
+
case 'last_write_wins': {
|
|
378
|
+
const localTime = new Date(conflict.localUpdatedAt).getTime();
|
|
379
|
+
const remoteTime = new Date(conflict.remoteUpdatedAt).getTime();
|
|
380
|
+
if (localTime >= remoteTime) {
|
|
381
|
+
remoteUpdates[mapping.externalField] = localValue;
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
localUpdates[mapping.localField] = remoteValue;
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
case 'local_wins':
|
|
389
|
+
remoteUpdates[mapping.externalField] = localValue;
|
|
390
|
+
break;
|
|
391
|
+
case 'remote_wins':
|
|
392
|
+
localUpdates[mapping.localField] = remoteValue;
|
|
393
|
+
break;
|
|
394
|
+
case 'manual':
|
|
395
|
+
// Don't auto-resolve — handled by the caller
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// Manual Conflict Resolution
|
|
401
|
+
// ============================================================================
|
|
402
|
+
/** Tag applied to elements with unresolved sync conflicts */
|
|
403
|
+
export const SYNC_CONFLICT_TAG = 'sync-conflict';
|
|
404
|
+
/**
|
|
405
|
+
* Apply manual conflict resolution metadata to an element.
|
|
406
|
+
* Tags the element with 'sync-conflict' and stores both versions
|
|
407
|
+
* in metadata._externalSync.conflict.
|
|
408
|
+
*
|
|
409
|
+
* @param element - The element to mark as conflicted
|
|
410
|
+
* @param conflict - The conflict info
|
|
411
|
+
* @param localValues - Local field values at time of conflict
|
|
412
|
+
* @param remoteValues - Remote field values at time of conflict
|
|
413
|
+
* @returns Updated metadata and tags to apply to the element
|
|
414
|
+
*/
|
|
415
|
+
export function applyManualConflict(element, conflict, localValues, remoteValues) {
|
|
416
|
+
// Add sync-conflict tag if not already present
|
|
417
|
+
const tags = element.tags.includes(SYNC_CONFLICT_TAG)
|
|
418
|
+
? [...element.tags]
|
|
419
|
+
: [...element.tags, SYNC_CONFLICT_TAG];
|
|
420
|
+
// Store both versions in metadata._externalSync.conflict
|
|
421
|
+
const existingSyncState = element.metadata._externalSync;
|
|
422
|
+
const metadata = {
|
|
423
|
+
...element.metadata,
|
|
424
|
+
_externalSync: {
|
|
425
|
+
...existingSyncState,
|
|
426
|
+
conflict: {
|
|
427
|
+
local: localValues,
|
|
428
|
+
remote: remoteValues,
|
|
429
|
+
detectedAt: new Date().toISOString(),
|
|
430
|
+
elementId: conflict.elementId,
|
|
431
|
+
externalId: conflict.externalId,
|
|
432
|
+
provider: conflict.provider,
|
|
433
|
+
project: conflict.project,
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
return { metadata, tags };
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Resolve a manual conflict by choosing a side.
|
|
441
|
+
* Clears the sync-conflict tag and conflict metadata.
|
|
442
|
+
*
|
|
443
|
+
* Returns the updates to apply to the element. The caller is
|
|
444
|
+
* responsible for applying these and pushing/pulling as needed.
|
|
445
|
+
*
|
|
446
|
+
* @param element - The element with the conflict
|
|
447
|
+
* @param keep - Which side to keep: 'local' or 'remote'
|
|
448
|
+
* @returns Updated metadata, tags, and field values from the chosen side
|
|
449
|
+
*/
|
|
450
|
+
export function resolveManualConflict(element, keep) {
|
|
451
|
+
// Extract the stored conflict data
|
|
452
|
+
const syncState = element.metadata._externalSync;
|
|
453
|
+
const conflictData = syncState?.conflict;
|
|
454
|
+
// Get field values from the chosen side
|
|
455
|
+
const fieldValues = conflictData
|
|
456
|
+
? keep === 'local'
|
|
457
|
+
? { ...conflictData.local }
|
|
458
|
+
: { ...conflictData.remote }
|
|
459
|
+
: {};
|
|
460
|
+
// Remove sync-conflict tag
|
|
461
|
+
const tags = element.tags.filter((t) => t !== SYNC_CONFLICT_TAG);
|
|
462
|
+
// Remove conflict metadata, keep the rest of _externalSync
|
|
463
|
+
const cleanedSyncState = { ...syncState };
|
|
464
|
+
delete cleanedSyncState.conflict;
|
|
465
|
+
const metadata = {
|
|
466
|
+
...element.metadata,
|
|
467
|
+
_externalSync: cleanedSyncState,
|
|
468
|
+
};
|
|
469
|
+
return { metadata, tags, fieldValues };
|
|
470
|
+
}
|
|
471
|
+
// ============================================================================
|
|
472
|
+
// Conversion to ExternalSyncConflict
|
|
473
|
+
// ============================================================================
|
|
474
|
+
/**
|
|
475
|
+
* Convert a ConflictInfo and ResolvedChanges into an ExternalSyncConflict
|
|
476
|
+
* suitable for inclusion in sync result reports.
|
|
477
|
+
*
|
|
478
|
+
* @param conflict - The detected conflict info
|
|
479
|
+
* @param resolved - The resolution result
|
|
480
|
+
* @returns ExternalSyncConflict for reporting
|
|
481
|
+
*/
|
|
482
|
+
export function toExternalSyncConflict(conflict, resolved) {
|
|
483
|
+
return {
|
|
484
|
+
elementId: conflict.elementId,
|
|
485
|
+
externalId: conflict.externalId,
|
|
486
|
+
provider: conflict.provider,
|
|
487
|
+
project: conflict.project,
|
|
488
|
+
localUpdatedAt: conflict.localUpdatedAt,
|
|
489
|
+
remoteUpdatedAt: conflict.remoteUpdatedAt,
|
|
490
|
+
strategy: resolved.strategy,
|
|
491
|
+
resolved: resolved.resolved,
|
|
492
|
+
winner: resolved.winner === 'merged' ? 'local' : resolved.winner,
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
// ============================================================================
|
|
496
|
+
// Helper Functions
|
|
497
|
+
// ============================================================================
|
|
498
|
+
/**
|
|
499
|
+
* Extract pushable fields from a local element (fields relevant to external sync).
|
|
500
|
+
*/
|
|
501
|
+
function extractPushableFields(element) {
|
|
502
|
+
const fields = {};
|
|
503
|
+
// Extract common sync-relevant fields
|
|
504
|
+
if ('title' in element)
|
|
505
|
+
fields.title = element.title;
|
|
506
|
+
if ('status' in element)
|
|
507
|
+
fields.status = element.status;
|
|
508
|
+
if ('tags' in element)
|
|
509
|
+
fields.tags = element.tags;
|
|
510
|
+
if ('priority' in element)
|
|
511
|
+
fields.priority = element.priority;
|
|
512
|
+
if ('taskType' in element)
|
|
513
|
+
fields.taskType = element.taskType;
|
|
514
|
+
if ('assignee' in element)
|
|
515
|
+
fields.assignee = element.assignee;
|
|
516
|
+
return fields;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Extract pullable fields from a remote item (fields relevant to local update).
|
|
520
|
+
*/
|
|
521
|
+
function extractPullableFields(item) {
|
|
522
|
+
return {
|
|
523
|
+
title: item.title,
|
|
524
|
+
body: item.body,
|
|
525
|
+
state: item.state,
|
|
526
|
+
labels: [...item.labels],
|
|
527
|
+
assignees: [...item.assignees],
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Get a field value from a local element by field name.
|
|
532
|
+
*/
|
|
533
|
+
function getFieldValue(element, field) {
|
|
534
|
+
return element[field];
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Get a field value from an external item by field name.
|
|
538
|
+
*/
|
|
539
|
+
function getExternalFieldValue(item, field) {
|
|
540
|
+
return item[field];
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Deep equality comparison for field values.
|
|
544
|
+
* Handles primitives, arrays, and plain objects.
|
|
545
|
+
*/
|
|
546
|
+
function deepEqual(a, b) {
|
|
547
|
+
if (a === b)
|
|
548
|
+
return true;
|
|
549
|
+
if (a === null || b === null)
|
|
550
|
+
return a === b;
|
|
551
|
+
if (a === undefined || b === undefined)
|
|
552
|
+
return a === b;
|
|
553
|
+
if (typeof a !== typeof b)
|
|
554
|
+
return false;
|
|
555
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
556
|
+
if (a.length !== b.length)
|
|
557
|
+
return false;
|
|
558
|
+
return a.every((item, index) => deepEqual(item, b[index]));
|
|
559
|
+
}
|
|
560
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
561
|
+
const aObj = a;
|
|
562
|
+
const bObj = b;
|
|
563
|
+
const aKeys = Object.keys(aObj).sort();
|
|
564
|
+
const bKeys = Object.keys(bObj).sort();
|
|
565
|
+
if (aKeys.length !== bKeys.length)
|
|
566
|
+
return false;
|
|
567
|
+
return aKeys.every((key, i) => key === bKeys[i] && deepEqual(aObj[key], bObj[key]));
|
|
568
|
+
}
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Compute a simple hash of a string using SHA-256 (synchronous via crypto).
|
|
573
|
+
* Uses the same approach as computeContentHashSync in the sync module.
|
|
574
|
+
*/
|
|
575
|
+
function hashString(input) {
|
|
576
|
+
const hash = createHash('sha256');
|
|
577
|
+
hash.update(input);
|
|
578
|
+
return hash.digest('hex');
|
|
579
|
+
}
|
|
580
|
+
//# sourceMappingURL=conflict-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict-resolver.js","sourceRoot":"","sources":["../../src/external-sync/conflict-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External Sync — public exports
|
|
3
|
+
*
|
|
4
|
+
* Central module for external service synchronization (GitHub, Linear, etc.).
|
|
5
|
+
* Re-exports the provider registry, sync engine, provider implementations,
|
|
6
|
+
* and future conflict resolver modules.
|
|
7
|
+
*/
|
|
8
|
+
export { ProviderRegistry, createProviderRegistry, createDefaultProviderRegistry, createConfiguredProviderRegistry, } from './provider-registry.js';
|
|
9
|
+
export type { ProviderAdapterEntry } from './provider-registry.js';
|
|
10
|
+
export { detectConflict, resolveConflict, resolveManualConflict, applyManualConflict, toExternalSyncConflict, computeExternalItemHash, SYNC_CONFLICT_TAG, } from './conflict-resolver.js';
|
|
11
|
+
export type { ConflictInfo, ResolvedChanges, DetectConflictOptions, } from './conflict-resolver.js';
|
|
12
|
+
export { SyncEngine, createSyncEngine } from './sync-engine.js';
|
|
13
|
+
export type { SyncOptions, SyncEngineAPI, SyncEngineSettings, SyncConflictResolver, ConflictResolution, SyncEngineConfig, } from './sync-engine.js';
|
|
14
|
+
export { createGitHubProvider, createGitHubPlaceholderProvider, GitHubTaskAdapter, GITHUB_FIELD_MAP_CONFIG, GITHUB_PRIORITY_LABELS, GITHUB_TASK_TYPE_LABELS, GITHUB_SYNC_LABEL_PREFIX, statusToGitHubState, gitHubStateToStatus, GitHubApiClient, GitHubApiError, isGitHubApiError, } from './providers/github/index.js';
|
|
15
|
+
export type { GitHubIssue, GitHubLabel, GitHubUser, GitHubApiClientOptions, ListIssuesOptions, CreateIssueInput, UpdateIssueInput, RateLimitInfo, } from './providers/github/index.js';
|
|
16
|
+
export { autoLinkTask } from './auto-link.js';
|
|
17
|
+
export type { AutoLinkTaskParams, AutoLinkTaskResult } from './auto-link.js';
|
|
18
|
+
export { createLinearProvider, createLinearPlaceholderProvider, } from './providers/linear/index.js';
|
|
19
|
+
export type { CreateLinearProviderOptions } from './providers/linear/index.js';
|
|
20
|
+
export { createNotionProvider, createNotionPlaceholderProvider, NotionDocumentAdapter, createNotionDocumentAdapter, extractTitleFromProperties, buildPageProperties, markdownToNotionBlocks, notionBlocksToMarkdown, NotionApiClient, NotionApiError, isNotionApiError, } from './providers/notion/index.js';
|
|
21
|
+
export type { CreateNotionProviderOptions, NotionApiClientOptions, RateLimitState as NotionRateLimitState, NotionPage, NotionBlock, NotionBlockInput, NotionRichText, NotionAnnotations, NotionProperty, NotionDatabase, NotionDatabaseProperty, NotionDatabaseSchema, NotionUpdateDatabaseInput, } from './providers/notion/index.js';
|
|
22
|
+
export { createFolderProvider, FolderDocumentAdapter, createFolderDocumentAdapter, slugify, } from './providers/folder/index.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/external-sync/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAChE,YAAY,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,GACd,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG7E,OAAO,EACL,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAG/E,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,cAAc,IAAI,oBAAoB,EACtC,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,2BAA2B,EAC3B,OAAO,GACR,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External Sync — public exports
|
|
3
|
+
*
|
|
4
|
+
* Central module for external service synchronization (GitHub, Linear, etc.).
|
|
5
|
+
* Re-exports the provider registry, sync engine, provider implementations,
|
|
6
|
+
* and future conflict resolver modules.
|
|
7
|
+
*/
|
|
8
|
+
// Provider registry
|
|
9
|
+
export { ProviderRegistry, createProviderRegistry, createDefaultProviderRegistry, createConfiguredProviderRegistry, } from './provider-registry.js';
|
|
10
|
+
// Conflict resolver
|
|
11
|
+
export { detectConflict, resolveConflict, resolveManualConflict, applyManualConflict, toExternalSyncConflict, computeExternalItemHash, SYNC_CONFLICT_TAG, } from './conflict-resolver.js';
|
|
12
|
+
// Sync engine
|
|
13
|
+
export { SyncEngine, createSyncEngine } from './sync-engine.js';
|
|
14
|
+
// GitHub provider
|
|
15
|
+
export { createGitHubProvider, createGitHubPlaceholderProvider, GitHubTaskAdapter, GITHUB_FIELD_MAP_CONFIG, GITHUB_PRIORITY_LABELS, GITHUB_TASK_TYPE_LABELS, GITHUB_SYNC_LABEL_PREFIX, statusToGitHubState, gitHubStateToStatus, GitHubApiClient, GitHubApiError, isGitHubApiError, } from './providers/github/index.js';
|
|
16
|
+
// Auto-link utility
|
|
17
|
+
export { autoLinkTask } from './auto-link.js';
|
|
18
|
+
// Linear provider
|
|
19
|
+
export { createLinearProvider, createLinearPlaceholderProvider, } from './providers/linear/index.js';
|
|
20
|
+
// Notion provider
|
|
21
|
+
export { createNotionProvider, createNotionPlaceholderProvider, NotionDocumentAdapter, createNotionDocumentAdapter, extractTitleFromProperties, buildPageProperties, markdownToNotionBlocks, notionBlocksToMarkdown, NotionApiClient, NotionApiError, isNotionApiError, } from './providers/notion/index.js';
|
|
22
|
+
// Folder provider
|
|
23
|
+
export { createFolderProvider, FolderDocumentAdapter, createFolderDocumentAdapter, slugify, } from './providers/folder/index.js';
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/external-sync/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,oBAAoB;AACpB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,wBAAwB,CAAC;AAGhC,oBAAoB;AACpB,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAOhC,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAUhE,kBAAkB;AAClB,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAYrC,oBAAoB;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,kBAAkB;AAClB,OAAO,EACL,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,6BAA6B,CAAC;AAGrC,kBAAkB;AAClB,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAiBrC,kBAAkB;AAClB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,2BAA2B,EAC3B,OAAO,GACR,MAAM,6BAA6B,CAAC"}
|