team-toon-tack 1.0.4 → 1.0.5
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/package.json +1 -1
- package/scripts/init.ts +1 -11
- package/scripts/sync.ts +15 -23
- package/scripts/utils.ts +23 -5
- package/scripts/work-on.ts +4 -4
package/package.json
CHANGED
package/scripts/init.ts
CHANGED
|
@@ -277,17 +277,7 @@ async function init() {
|
|
|
277
277
|
complete: 'Done',
|
|
278
278
|
need_review: 'In Review'
|
|
279
279
|
},
|
|
280
|
-
|
|
281
|
-
id: currentCycle.id,
|
|
282
|
-
name: currentCycle.name || 'Cycle',
|
|
283
|
-
start_date: currentCycle.startsAt?.toISOString().split('T')[0] || '',
|
|
284
|
-
end_date: currentCycle.endsAt?.toISOString().split('T')[0] || ''
|
|
285
|
-
} : {
|
|
286
|
-
id: '',
|
|
287
|
-
name: 'No active cycle',
|
|
288
|
-
start_date: '',
|
|
289
|
-
end_date: ''
|
|
290
|
-
}
|
|
280
|
+
priority_order: ['urgent', 'high', 'medium', 'low', 'none']
|
|
291
281
|
};
|
|
292
282
|
|
|
293
283
|
// Find current user key
|
package/scripts/sync.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getLinearClient, loadConfig, loadLocalConfig,
|
|
1
|
+
import { getLinearClient, loadConfig, loadLocalConfig, loadCycleData, saveCycleData, getTeamId, getPrioritySortIndex, CycleData, Task, Attachment, Comment } from './utils';
|
|
2
2
|
|
|
3
3
|
async function sync() {
|
|
4
4
|
const args = process.argv.slice(2);
|
|
@@ -47,24 +47,17 @@ Examples:
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
const activeCycle = cycles.nodes[0];
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
start_date: activeCycle.startsAt?.toISOString().split('T')[0] ?? '',
|
|
58
|
-
end_date: activeCycle.endsAt?.toISOString().split('T')[0] ?? ''
|
|
59
|
-
};
|
|
60
|
-
await saveConfig(config);
|
|
61
|
-
console.log('Config updated with new cycle.');
|
|
50
|
+
const cycleId = activeCycle.id;
|
|
51
|
+
const cycleName = activeCycle.name ?? 'Cycle';
|
|
52
|
+
|
|
53
|
+
// Check if cycle changed by comparing with existing cycle.toon
|
|
54
|
+
const existingData = await loadCycleData();
|
|
55
|
+
if (existingData && existingData.cycleId !== cycleId) {
|
|
56
|
+
console.log(`Cycle changed: ${existingData.cycleName} → ${cycleName}`);
|
|
62
57
|
} else {
|
|
63
|
-
console.log(`Current cycle: ${
|
|
58
|
+
console.log(`Current cycle: ${cycleName}`);
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
const cycleId = config.current_cycle.id;
|
|
67
|
-
|
|
68
61
|
// Phase 2: Fetch workflow states
|
|
69
62
|
const workflowStates = await client.workflowStates({
|
|
70
63
|
filter: { team: { id: { eq: teamId } } }
|
|
@@ -72,8 +65,7 @@ Examples:
|
|
|
72
65
|
const stateMap = new Map(workflowStates.nodes.map(s => [s.name, s.id]));
|
|
73
66
|
const testingStateId = stateMap.get('Testing');
|
|
74
67
|
|
|
75
|
-
// Phase 3:
|
|
76
|
-
const existingData = await loadCycleData();
|
|
68
|
+
// Phase 3: Build existing tasks map for preserving local status
|
|
77
69
|
const existingTasksMap = new Map(existingData?.tasks.map(t => [t.id, t]));
|
|
78
70
|
|
|
79
71
|
// Phase 4: Fetch current issues with full content
|
|
@@ -168,22 +160,22 @@ Examples:
|
|
|
168
160
|
tasks.push(task);
|
|
169
161
|
}
|
|
170
162
|
|
|
171
|
-
// Sort by priority
|
|
163
|
+
// Sort by priority using config order
|
|
172
164
|
tasks.sort((a, b) => {
|
|
173
|
-
const pa = a.priority
|
|
174
|
-
const pb = b.priority
|
|
165
|
+
const pa = getPrioritySortIndex(a.priority, config.priority_order);
|
|
166
|
+
const pb = getPrioritySortIndex(b.priority, config.priority_order);
|
|
175
167
|
return pa - pb;
|
|
176
168
|
});
|
|
177
169
|
|
|
178
170
|
const newData: CycleData = {
|
|
179
171
|
cycleId: cycleId,
|
|
180
|
-
cycleName:
|
|
172
|
+
cycleName: cycleName,
|
|
181
173
|
updatedAt: new Date().toISOString(),
|
|
182
174
|
tasks: tasks
|
|
183
175
|
};
|
|
184
176
|
|
|
185
177
|
await saveCycleData(newData);
|
|
186
|
-
console.log(`\n✅ Synced ${tasks.length} tasks for ${
|
|
178
|
+
console.log(`\n✅ Synced ${tasks.length} tasks for ${cycleName}.`);
|
|
187
179
|
if (updatedCount > 0) {
|
|
188
180
|
console.log(` Updated ${updatedCount} issues to Testing in Linear.`);
|
|
189
181
|
}
|
package/scripts/utils.ts
CHANGED
|
@@ -55,11 +55,29 @@ export interface LabelConfig {
|
|
|
55
55
|
export interface Config {
|
|
56
56
|
teams: Record<string, TeamConfig>;
|
|
57
57
|
users: Record<string, UserConfig>;
|
|
58
|
-
labels
|
|
59
|
-
priorities
|
|
60
|
-
statuses
|
|
61
|
-
status_transitions
|
|
62
|
-
|
|
58
|
+
labels?: Record<string, LabelConfig>;
|
|
59
|
+
priorities?: Record<string, { value: number; name: string }>;
|
|
60
|
+
statuses?: Record<string, { name: string; type: string }>;
|
|
61
|
+
status_transitions?: Record<string, string>;
|
|
62
|
+
priority_order?: string[]; // e.g., ['urgent', 'high', 'medium', 'low', 'none']
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Linear priority value to name mapping (fixed by Linear API)
|
|
66
|
+
export const PRIORITY_NAMES: Record<number, string> = {
|
|
67
|
+
0: 'none',
|
|
68
|
+
1: 'urgent',
|
|
69
|
+
2: 'high',
|
|
70
|
+
3: 'medium',
|
|
71
|
+
4: 'low'
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const DEFAULT_PRIORITY_ORDER = ['urgent', 'high', 'medium', 'low', 'none'];
|
|
75
|
+
|
|
76
|
+
export function getPrioritySortIndex(priority: number, priorityOrder?: string[]): number {
|
|
77
|
+
const order = priorityOrder ?? DEFAULT_PRIORITY_ORDER;
|
|
78
|
+
const name = PRIORITY_NAMES[priority] ?? 'none';
|
|
79
|
+
const index = order.indexOf(name);
|
|
80
|
+
return index === -1 ? order.length : index;
|
|
63
81
|
}
|
|
64
82
|
|
|
65
83
|
export interface Attachment {
|
package/scripts/work-on.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import prompts from 'prompts';
|
|
2
|
-
import { getLinearClient, loadConfig, loadLocalConfig, loadCycleData, saveCycleData, getUserEmail, getTeamId } from './utils';
|
|
2
|
+
import { getLinearClient, loadConfig, loadLocalConfig, loadCycleData, saveCycleData, getUserEmail, getTeamId, getPrioritySortIndex } from './utils';
|
|
3
3
|
|
|
4
4
|
const PRIORITY_LABELS: Record<number, string> = {
|
|
5
|
-
0: '⚪',
|
|
5
|
+
0: '⚪ None',
|
|
6
6
|
1: '🔴 Urgent',
|
|
7
7
|
2: '🟠 High',
|
|
8
8
|
3: '🟡 Medium',
|
|
@@ -53,8 +53,8 @@ Examples:
|
|
|
53
53
|
!excludedEmails.has(t.assignee ?? '')
|
|
54
54
|
)
|
|
55
55
|
.sort((a, b) => {
|
|
56
|
-
const pa = a.priority
|
|
57
|
-
const pb = b.priority
|
|
56
|
+
const pa = getPrioritySortIndex(a.priority, config.priority_order);
|
|
57
|
+
const pb = getPrioritySortIndex(b.priority, config.priority_order);
|
|
58
58
|
return pa - pb;
|
|
59
59
|
});
|
|
60
60
|
|