team-toon-tack 3.7.2 → 3.7.3

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.
@@ -86,51 +86,49 @@ Examples:
86
86
  }
87
87
  // Build excluded labels set
88
88
  const excludedLabels = new Set(localConfig.exclude_labels ?? []);
89
- // Phase 1: Fetch active cycle directly from team
89
+ // Phase 1: Fetch active cycle directly from team (if the team uses cycles)
90
90
  console.log("Fetching latest cycle...");
91
91
  const team = await client.team(teamId);
92
92
  const activeCycle = await team.activeCycle;
93
- if (!activeCycle) {
94
- console.error("No active cycle found.");
95
- process.exit(1);
96
- }
97
- const cycleId = activeCycle.id;
98
- const cycleName = activeCycle.name ?? `Cycle #${activeCycle.number}`;
99
- const newCycleInfo = {
100
- id: cycleId,
101
- name: cycleName,
102
- start_date: activeCycle.startsAt?.toISOString().split("T")[0] ?? "",
103
- end_date: activeCycle.endsAt?.toISOString().split("T")[0] ?? "",
104
- };
105
- // Check if cycle changed and update config with history
93
+ let cycleId;
94
+ let cycleName;
106
95
  const existingData = await loadCycleData();
107
- const oldCycleId = config.current_cycle?.id ?? existingData?.cycleId;
108
- if (oldCycleId && oldCycleId !== cycleId) {
109
- const oldCycleName = config.current_cycle?.name ?? existingData?.cycleName ?? "Unknown";
110
- console.log(`Cycle changed: ${oldCycleName} → ${cycleName}`);
111
- // Move old cycle to history (avoid duplicates)
112
- if (config.current_cycle) {
113
- config.cycle_history = config.cycle_history ?? [];
114
- // Remove if already exists in history
115
- config.cycle_history = config.cycle_history.filter((c) => c.id !== config.current_cycle?.id);
116
- config.cycle_history.unshift(config.current_cycle);
117
- // Keep only last 10 cycles
118
- if (config.cycle_history.length > 10) {
119
- config.cycle_history = config.cycle_history.slice(0, 10);
96
+ if (activeCycle) {
97
+ cycleId = activeCycle.id;
98
+ cycleName = activeCycle.name ?? `Cycle #${activeCycle.number}`;
99
+ const newCycleInfo = {
100
+ id: cycleId,
101
+ name: cycleName,
102
+ start_date: activeCycle.startsAt?.toISOString().split("T")[0] ?? "",
103
+ end_date: activeCycle.endsAt?.toISOString().split("T")[0] ?? "",
104
+ };
105
+ const oldCycleId = config.current_cycle?.id ?? existingData?.cycleId;
106
+ if (oldCycleId && oldCycleId !== cycleId) {
107
+ const oldCycleName = config.current_cycle?.name ?? existingData?.cycleName ?? "Unknown";
108
+ console.log(`Cycle changed: ${oldCycleName} → ${cycleName}`);
109
+ if (config.current_cycle) {
110
+ config.cycle_history = config.cycle_history ?? [];
111
+ config.cycle_history = config.cycle_history.filter((c) => c.id !== config.current_cycle?.id);
112
+ config.cycle_history.unshift(config.current_cycle);
113
+ if (config.cycle_history.length > 10) {
114
+ config.cycle_history = config.cycle_history.slice(0, 10);
115
+ }
120
116
  }
121
- }
122
- // Update current cycle
123
- config.current_cycle = newCycleInfo;
124
- await saveConfig(config);
125
- console.log("Config updated with new cycle (old cycle saved to history).");
126
- }
127
- else {
128
- // Update current cycle info even if ID unchanged (dates might change)
129
- if (!config.current_cycle || config.current_cycle.id !== cycleId) {
130
117
  config.current_cycle = newCycleInfo;
131
118
  await saveConfig(config);
119
+ console.log("Config updated with new cycle (old cycle saved to history).");
120
+ }
121
+ else {
122
+ if (!config.current_cycle || config.current_cycle.id !== cycleId) {
123
+ config.current_cycle = newCycleInfo;
124
+ await saveConfig(config);
125
+ }
126
+ console.log(`Current cycle: ${cycleName}`);
132
127
  }
133
- console.log(`Current cycle: ${cycleName}`);
128
+ }
129
+ else {
130
+ cycleName = "No Cycle";
131
+ console.log("No active cycle on this team — syncing without cycle filter.");
134
132
  }
135
133
  // Phase 2: Fetch workflow states and get status mappings
136
134
  const workflowStates = await client.workflowStates({
@@ -222,12 +220,14 @@ Examples:
222
220
  ? "all statuses"
223
221
  : `${syncStatuses.join("/")} status`;
224
222
  console.log(`Fetching issues (${statusDesc})${labelDesc}...`);
225
- // Build filter - label is optional
223
+ // Build filter - label is optional; cycle is skipped if team has no
224
+ // active cycle (Linear lets teams disable cycles entirely).
226
225
  const issueFilter = {
227
226
  team: { id: { eq: teamId } },
228
- cycle: { id: { eq: cycleId } },
229
227
  };
230
- // Only filter by status if not syncing all
228
+ if (cycleId) {
229
+ issueFilter.cycle = { id: { eq: cycleId } };
230
+ }
231
231
  if (!syncAll) {
232
232
  issueFilter.state = { name: { in: syncStatuses } };
233
233
  }
@@ -372,7 +372,7 @@ Examples:
372
372
  finalTasks = tasks;
373
373
  }
374
374
  const newData = {
375
- cycleId: cycleId,
375
+ cycleId: cycleId ?? `team:${teamId}`,
376
376
  cycleName: cycleName,
377
377
  updatedAt: new Date().toISOString(),
378
378
  tasks: finalTasks,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-toon-tack",
3
- "version": "3.7.2",
3
+ "version": "3.7.3",
4
4
  "description": "Linear & Trello task sync & management CLI with TOON format",
5
5
  "type": "module",
6
6
  "bin": {