@proletariat/cli 0.3.58 → 0.3.60
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/dist/commands/{spec → dashboard}/index.d.ts +4 -4
- package/dist/commands/dashboard/index.js +117 -0
- package/dist/commands/dashboard/index.js.map +1 -0
- package/dist/commands/execution/config.js +5 -4
- package/dist/commands/execution/config.js.map +1 -1
- package/dist/commands/execution/stop.js +4 -2
- package/dist/commands/execution/stop.js.map +1 -1
- package/dist/commands/execution/view.js +3 -0
- package/dist/commands/execution/view.js.map +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +40 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp-server.js +1 -2
- package/dist/commands/mcp-server.js.map +1 -1
- package/dist/commands/{spec/link/index.d.ts → session/exec.d.ts} +5 -3
- package/dist/commands/session/exec.js +205 -0
- package/dist/commands/session/exec.js.map +1 -0
- package/dist/commands/session/index.js +12 -0
- package/dist/commands/session/index.js.map +1 -1
- package/dist/commands/{spec/delete.d.ts → session/inspect.d.ts} +3 -3
- package/dist/commands/session/inspect.js +316 -0
- package/dist/commands/session/inspect.js.map +1 -0
- package/dist/commands/session/peek.d.ts +15 -0
- package/dist/commands/session/peek.js +141 -8
- package/dist/commands/session/peek.js.map +1 -1
- package/dist/commands/session/poke.d.ts +4 -1
- package/dist/commands/session/poke.js +175 -20
- package/dist/commands/session/poke.js.map +1 -1
- package/dist/commands/{spec/link/depends.d.ts → session/restart.d.ts} +6 -4
- package/dist/commands/session/restart.js +320 -0
- package/dist/commands/session/restart.js.map +1 -0
- package/dist/commands/ticket/list.d.ts +10 -0
- package/dist/commands/ticket/list.js +126 -1
- package/dist/commands/ticket/list.js.map +1 -1
- package/dist/commands/tools/add.d.ts +20 -0
- package/dist/commands/tools/add.js +129 -0
- package/dist/commands/tools/add.js.map +1 -0
- package/dist/commands/tools/check.d.ts +10 -0
- package/dist/commands/tools/check.js +75 -0
- package/dist/commands/tools/check.js.map +1 -0
- package/dist/commands/tools/detect.d.ts +11 -0
- package/dist/commands/tools/detect.js +107 -0
- package/dist/commands/tools/detect.js.map +1 -0
- package/dist/commands/tools/index.d.ts +11 -0
- package/dist/commands/tools/index.js +87 -0
- package/dist/commands/tools/index.js.map +1 -0
- package/dist/commands/tools/remove.d.ts +13 -0
- package/dist/commands/tools/remove.js +55 -0
- package/dist/commands/tools/remove.js.map +1 -0
- package/dist/commands/{spec/view.d.ts → trello/configure.d.ts} +6 -6
- package/dist/commands/trello/configure.js +259 -0
- package/dist/commands/trello/configure.js.map +1 -0
- package/dist/commands/{spec/plan.d.ts → trello/import.d.ts} +3 -5
- package/dist/commands/trello/import.js +241 -0
- package/dist/commands/trello/import.js.map +1 -0
- package/dist/commands/{spec/ticket.d.ts → trello/sync.d.ts} +5 -6
- package/dist/commands/trello/sync.js +190 -0
- package/dist/commands/trello/sync.js.map +1 -0
- package/dist/commands/work/start.d.ts +1 -0
- package/dist/commands/work/start.js +17 -39
- package/dist/commands/work/start.js.map +1 -1
- package/dist/lib/dashboard/data.d.ts +64 -0
- package/dist/lib/dashboard/data.js +259 -0
- package/dist/lib/dashboard/data.js.map +1 -0
- package/dist/lib/dashboard/html.d.ts +7 -0
- package/dist/lib/dashboard/html.js +682 -0
- package/dist/lib/dashboard/html.js.map +1 -0
- package/dist/lib/dashboard/server.d.ts +20 -0
- package/dist/lib/dashboard/server.js +114 -0
- package/dist/lib/dashboard/server.js.map +1 -0
- package/dist/lib/events/events.d.ts +26 -2
- package/dist/lib/events/events.js +3 -2
- package/dist/lib/events/events.js.map +1 -1
- package/dist/lib/execution/config.d.ts +8 -0
- package/dist/lib/execution/config.js +83 -4
- package/dist/lib/execution/config.js.map +1 -1
- package/dist/lib/execution/runners.d.ts +36 -3
- package/dist/lib/execution/runners.js +216 -35
- package/dist/lib/execution/runners.js.map +1 -1
- package/dist/lib/execution/spawner.d.ts +2 -0
- package/dist/lib/execution/spawner.js +22 -31
- package/dist/lib/execution/spawner.js.map +1 -1
- package/dist/lib/execution/types.d.ts +26 -5
- package/dist/lib/execution/types.js +24 -0
- package/dist/lib/execution/types.js.map +1 -1
- package/dist/lib/external-issues/adapters.d.ts +17 -0
- package/dist/lib/external-issues/adapters.js +88 -0
- package/dist/lib/external-issues/adapters.js.map +1 -1
- package/dist/lib/external-issues/index.d.ts +1 -0
- package/dist/lib/external-issues/index.js +2 -0
- package/dist/lib/external-issues/index.js.map +1 -1
- package/dist/lib/external-issues/mapping-store.js +1 -1
- package/dist/lib/external-issues/outbound-sync.d.ts +79 -0
- package/dist/lib/external-issues/outbound-sync.js +296 -0
- package/dist/lib/external-issues/outbound-sync.js.map +1 -0
- package/dist/lib/external-issues/trello.d.ts +80 -0
- package/dist/lib/external-issues/trello.js +266 -0
- package/dist/lib/external-issues/trello.js.map +1 -0
- package/dist/lib/external-issues/types.d.ts +3 -3
- package/dist/lib/external-issues/types.js +1 -1
- package/dist/lib/external-issues/types.js.map +1 -1
- package/dist/lib/linear/client.d.ts +4 -3
- package/dist/lib/linear/client.js +185 -122
- package/dist/lib/linear/client.js.map +1 -1
- package/dist/lib/mcp/tools/cli-passthrough.js +77 -0
- package/dist/lib/mcp/tools/cli-passthrough.js.map +1 -1
- package/dist/lib/mcp/tools/index.d.ts +0 -1
- package/dist/lib/mcp/tools/index.js +0 -1
- package/dist/lib/mcp/tools/index.js.map +1 -1
- package/dist/lib/onboarding/detect-tools.d.ts +15 -0
- package/dist/lib/onboarding/detect-tools.js +44 -0
- package/dist/lib/onboarding/detect-tools.js.map +1 -0
- package/dist/lib/onboarding/index.d.ts +2 -0
- package/dist/lib/onboarding/index.js +3 -0
- package/dist/lib/onboarding/index.js.map +1 -0
- package/dist/lib/onboarding/wizard.d.ts +25 -0
- package/dist/lib/onboarding/wizard.js +156 -0
- package/dist/lib/onboarding/wizard.js.map +1 -0
- package/dist/lib/pmo/schema.d.ts +2 -1
- package/dist/lib/pmo/schema.js +3 -1
- package/dist/lib/pmo/schema.js.map +1 -1
- package/dist/lib/pmo/storage/tickets.d.ts +8 -0
- package/dist/lib/pmo/storage/tickets.js +56 -2
- package/dist/lib/pmo/storage/tickets.js.map +1 -1
- package/dist/lib/pmo/sync-manager.js +3 -0
- package/dist/lib/pmo/sync-manager.js.map +1 -1
- package/dist/lib/runners/claude-code-runner.js +6 -0
- package/dist/lib/runners/claude-code-runner.js.map +1 -1
- package/dist/lib/tool-registry/detect.d.ts +20 -0
- package/dist/lib/tool-registry/detect.js +95 -0
- package/dist/lib/tool-registry/detect.js.map +1 -0
- package/dist/lib/tool-registry/index.d.ts +10 -0
- package/dist/lib/tool-registry/index.js +13 -0
- package/dist/lib/tool-registry/index.js.map +1 -0
- package/dist/lib/tool-registry/policy.d.ts +32 -0
- package/dist/lib/tool-registry/policy.js +97 -0
- package/dist/lib/tool-registry/policy.js.map +1 -0
- package/dist/lib/tool-registry/registry.d.ts +42 -0
- package/dist/lib/tool-registry/registry.js +120 -0
- package/dist/lib/tool-registry/registry.js.map +1 -0
- package/dist/lib/tool-registry/spawn.d.ts +50 -0
- package/dist/lib/tool-registry/spawn.js +103 -0
- package/dist/lib/tool-registry/spawn.js.map +1 -0
- package/dist/lib/tool-registry/types.d.ts +56 -0
- package/dist/lib/tool-registry/types.js +109 -0
- package/dist/lib/tool-registry/types.js.map +1 -0
- package/dist/lib/trello/client.d.ts +23 -0
- package/dist/lib/trello/client.js +114 -0
- package/dist/lib/trello/client.js.map +1 -0
- package/dist/lib/trello/config.d.ts +55 -0
- package/dist/lib/trello/config.js +127 -0
- package/dist/lib/trello/config.js.map +1 -0
- package/dist/lib/trello/index.d.ts +5 -0
- package/dist/lib/trello/index.js +5 -0
- package/dist/lib/trello/index.js.map +1 -0
- package/dist/lib/trello/mapper.d.ts +13 -0
- package/dist/lib/trello/mapper.js +71 -0
- package/dist/lib/trello/mapper.js.map +1 -0
- package/dist/lib/trello/sync.d.ts +13 -0
- package/dist/lib/trello/sync.js +38 -0
- package/dist/lib/trello/sync.js.map +1 -0
- package/dist/lib/trello/types.d.ts +53 -0
- package/dist/lib/trello/types.js +2 -0
- package/dist/lib/trello/types.js.map +1 -0
- package/dist/lib/work-source/client.js +17 -0
- package/dist/lib/work-source/client.js.map +1 -1
- package/dist/lib/work-source/config.d.ts +1 -1
- package/dist/lib/work-source/config.js +23 -1
- package/dist/lib/work-source/config.js.map +1 -1
- package/dist/lib/work-source/index.d.ts +1 -0
- package/dist/lib/work-source/index.js +1 -0
- package/dist/lib/work-source/index.js.map +1 -1
- package/dist/lib/work-source/provider-sources.d.ts +113 -0
- package/dist/lib/work-source/provider-sources.js +227 -0
- package/dist/lib/work-source/provider-sources.js.map +1 -0
- package/oclif.manifest.json +4368 -4364
- package/package.json +6 -2
- package/dist/commands/spec/create.d.ts +0 -20
- package/dist/commands/spec/create.js +0 -171
- package/dist/commands/spec/create.js.map +0 -1
- package/dist/commands/spec/delete.js +0 -112
- package/dist/commands/spec/delete.js.map +0 -1
- package/dist/commands/spec/edit.d.ts +0 -23
- package/dist/commands/spec/edit.js +0 -262
- package/dist/commands/spec/edit.js.map +0 -1
- package/dist/commands/spec/index.js +0 -88
- package/dist/commands/spec/index.js.map +0 -1
- package/dist/commands/spec/link/depends.js +0 -87
- package/dist/commands/spec/link/depends.js.map +0 -1
- package/dist/commands/spec/link/index.js +0 -93
- package/dist/commands/spec/link/index.js.map +0 -1
- package/dist/commands/spec/link/remove.d.ts +0 -18
- package/dist/commands/spec/link/remove.js +0 -91
- package/dist/commands/spec/link/remove.js.map +0 -1
- package/dist/commands/spec/list.d.ts +0 -14
- package/dist/commands/spec/list.js +0 -101
- package/dist/commands/spec/list.js.map +0 -1
- package/dist/commands/spec/plan.js +0 -102
- package/dist/commands/spec/plan.js.map +0 -1
- package/dist/commands/spec/ticket.js +0 -144
- package/dist/commands/spec/ticket.js.map +0 -1
- package/dist/commands/spec/view.js +0 -202
- package/dist/commands/spec/view.js.map +0 -1
- package/dist/lib/mcp/tools/spec.d.ts +0 -6
- package/dist/lib/mcp/tools/spec.js +0 -197
- package/dist/lib/mcp/tools/spec.js.map +0 -1
- package/dist/lib/pmo/spec-parser.d.ts +0 -25
- package/dist/lib/pmo/spec-parser.js +0 -206
- package/dist/lib/pmo/spec-parser.js.map +0 -1
- package/dist/lib/pmo/spec-types.d.ts +0 -43
- package/dist/lib/pmo/spec-types.js +0 -8
- package/dist/lib/pmo/spec-types.js.map +0 -1
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outbound Sync Handler
|
|
3
|
+
*
|
|
4
|
+
* Listens for ticket state changes on the EventBus and pushes them
|
|
5
|
+
* to external issue trackers (Linear, Shortcut, etc.) via their
|
|
6
|
+
* respective adapters.
|
|
7
|
+
*
|
|
8
|
+
* The handler is provider-agnostic: it resolves which external provider
|
|
9
|
+
* a ticket is mapped to, then dispatches to the correct sync implementation.
|
|
10
|
+
*/
|
|
11
|
+
import { getEventBus } from '../events/event-bus.js';
|
|
12
|
+
import { LinearClient } from '../linear/client.js';
|
|
13
|
+
import { LinearMapper } from '../linear/mapper.js';
|
|
14
|
+
import { LinearSync } from '../linear/sync.js';
|
|
15
|
+
import { loadLinearConfig, isLinearConfigured } from '../linear/config.js';
|
|
16
|
+
import { ExternalExecutionMappingStore } from './mapping-store.js';
|
|
17
|
+
/**
|
|
18
|
+
* OutboundSyncHandler subscribes to ticket events and pushes changes
|
|
19
|
+
* to mapped external providers. It is fire-and-forget: sync failures
|
|
20
|
+
* are logged but never block the caller.
|
|
21
|
+
*/
|
|
22
|
+
export class OutboundSyncHandler {
|
|
23
|
+
unsubscribers = [];
|
|
24
|
+
db;
|
|
25
|
+
mappingStore;
|
|
26
|
+
constructor(db) {
|
|
27
|
+
this.db = db;
|
|
28
|
+
this.mappingStore = new ExternalExecutionMappingStore(db);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Start listening for ticket events on the global EventBus.
|
|
32
|
+
* Call `stop()` to unsubscribe.
|
|
33
|
+
*/
|
|
34
|
+
start() {
|
|
35
|
+
const bus = getEventBus();
|
|
36
|
+
this.unsubscribers.push(bus.on('ticket:status_changed', (event) => {
|
|
37
|
+
void this.handleStatusChanged(event);
|
|
38
|
+
}));
|
|
39
|
+
this.unsubscribers.push(bus.on('ticket:pr_linked', (event) => {
|
|
40
|
+
void this.handlePRLinked(event);
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Stop listening for events and clean up.
|
|
45
|
+
*/
|
|
46
|
+
stop() {
|
|
47
|
+
for (const unsub of this.unsubscribers) {
|
|
48
|
+
unsub();
|
|
49
|
+
}
|
|
50
|
+
this.unsubscribers = [];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Handle a ticket status change by syncing to all mapped external providers.
|
|
54
|
+
*/
|
|
55
|
+
async handleStatusChanged(event) {
|
|
56
|
+
const results = [];
|
|
57
|
+
// Try Linear sync (via Linear-specific mapping table)
|
|
58
|
+
try {
|
|
59
|
+
const linearResult = await this.syncStatusToLinear(event);
|
|
60
|
+
if (linearResult) {
|
|
61
|
+
results.push(linearResult);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Sync errors are non-fatal
|
|
66
|
+
}
|
|
67
|
+
// Try provider-agnostic sync via external_execution_map
|
|
68
|
+
try {
|
|
69
|
+
const genericResults = await this.syncStatusToMappedProviders(event);
|
|
70
|
+
results.push(...genericResults);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Sync errors are non-fatal
|
|
74
|
+
}
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Handle a PR link by syncing to all mapped external providers.
|
|
79
|
+
*/
|
|
80
|
+
async handlePRLinked(event) {
|
|
81
|
+
const results = [];
|
|
82
|
+
// Try Linear sync
|
|
83
|
+
try {
|
|
84
|
+
const linearResult = await this.syncPRToLinear(event);
|
|
85
|
+
if (linearResult) {
|
|
86
|
+
results.push(linearResult);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Sync errors are non-fatal
|
|
91
|
+
}
|
|
92
|
+
// Update provider-agnostic mapping with PR URL
|
|
93
|
+
try {
|
|
94
|
+
this.recordPRInMappings(event);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Non-fatal
|
|
98
|
+
}
|
|
99
|
+
return results;
|
|
100
|
+
}
|
|
101
|
+
// ===========================================================================
|
|
102
|
+
// Linear Sync
|
|
103
|
+
// ===========================================================================
|
|
104
|
+
/**
|
|
105
|
+
* Sync a status change to Linear if the ticket has a Linear mapping.
|
|
106
|
+
*/
|
|
107
|
+
async syncStatusToLinear(event) {
|
|
108
|
+
if (!isLinearConfigured(this.db))
|
|
109
|
+
return null;
|
|
110
|
+
const config = loadLinearConfig(this.db);
|
|
111
|
+
if (!config)
|
|
112
|
+
return null;
|
|
113
|
+
const mapper = new LinearMapper(this.db);
|
|
114
|
+
const mapping = mapper.getByTicketId(event.ticketId);
|
|
115
|
+
if (!mapping)
|
|
116
|
+
return null;
|
|
117
|
+
// Only sync outbound or bidirectional mappings
|
|
118
|
+
if (mapping.syncDirection === 'inbound')
|
|
119
|
+
return null;
|
|
120
|
+
const category = event.newStatusCategory;
|
|
121
|
+
if (!category) {
|
|
122
|
+
return { provider: 'linear', success: false, error: 'No status category on ticket' };
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const client = new LinearClient(config.apiKey);
|
|
126
|
+
// Get Linear team's workflow states
|
|
127
|
+
const team = await client.getTeamByKey(mapping.linearTeamKey);
|
|
128
|
+
if (!team) {
|
|
129
|
+
return { provider: 'linear', success: false, error: `Team not found: ${mapping.linearTeamKey}` };
|
|
130
|
+
}
|
|
131
|
+
const states = await client.listStates(team.id);
|
|
132
|
+
const matchingState = states.find((s) => s.type === category);
|
|
133
|
+
if (!matchingState) {
|
|
134
|
+
return { provider: 'linear', success: false, error: `No Linear state for category: ${category}` };
|
|
135
|
+
}
|
|
136
|
+
await client.updateIssueState(mapping.linearIssueId, matchingState.id);
|
|
137
|
+
// Post a comment about the status change
|
|
138
|
+
if (event.newStatusName) {
|
|
139
|
+
await client.addComment(mapping.linearIssueId, `Status updated to **${event.newStatusName}** (via prlt)`);
|
|
140
|
+
}
|
|
141
|
+
mapper.updateSyncTimestamp(event.ticketId);
|
|
142
|
+
return { provider: 'linear', success: true };
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
return {
|
|
146
|
+
provider: 'linear',
|
|
147
|
+
success: false,
|
|
148
|
+
error: err instanceof Error ? err.message : String(err),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Sync a PR link to Linear if the ticket has a Linear mapping.
|
|
154
|
+
*/
|
|
155
|
+
async syncPRToLinear(event) {
|
|
156
|
+
if (!isLinearConfigured(this.db))
|
|
157
|
+
return null;
|
|
158
|
+
const config = loadLinearConfig(this.db);
|
|
159
|
+
if (!config)
|
|
160
|
+
return null;
|
|
161
|
+
const mapper = new LinearMapper(this.db);
|
|
162
|
+
const mapping = mapper.getByTicketId(event.ticketId);
|
|
163
|
+
if (!mapping)
|
|
164
|
+
return null;
|
|
165
|
+
// Only sync outbound or bidirectional mappings
|
|
166
|
+
if (mapping.syncDirection === 'inbound')
|
|
167
|
+
return null;
|
|
168
|
+
try {
|
|
169
|
+
const client = new LinearClient(config.apiKey);
|
|
170
|
+
const sync = new LinearSync(client, mapper);
|
|
171
|
+
const success = await sync.syncPRLink(event.ticketId, event.prUrl, event.prTitle ?? 'Pull Request');
|
|
172
|
+
return { provider: 'linear', success };
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
return {
|
|
176
|
+
provider: 'linear',
|
|
177
|
+
success: false,
|
|
178
|
+
error: err instanceof Error ? err.message : String(err),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// ===========================================================================
|
|
183
|
+
// Provider-Agnostic Sync
|
|
184
|
+
// ===========================================================================
|
|
185
|
+
/**
|
|
186
|
+
* Sync status changes to providers tracked via the external_execution_map table.
|
|
187
|
+
* Updates the state snapshot so that future inbound syncs can detect drift.
|
|
188
|
+
*/
|
|
189
|
+
async syncStatusToMappedProviders(event) {
|
|
190
|
+
const results = [];
|
|
191
|
+
// Find all external mappings that reference this ticket via execution links
|
|
192
|
+
// or via the latest_state_snapshot containing the ticketId
|
|
193
|
+
const mappings = this.findMappingsForTicket(event.ticketId);
|
|
194
|
+
for (const mapping of mappings) {
|
|
195
|
+
// Skip Linear here (handled separately above with its full API integration)
|
|
196
|
+
if (mapping.provider === 'linear')
|
|
197
|
+
continue;
|
|
198
|
+
try {
|
|
199
|
+
// Update the state snapshot to reflect the new status
|
|
200
|
+
this.mappingStore.upsertMapping({
|
|
201
|
+
provider: mapping.provider,
|
|
202
|
+
externalId: mapping.externalId,
|
|
203
|
+
latestStateSnapshot: {
|
|
204
|
+
...(mapping.latestStateSnapshot ?? {}),
|
|
205
|
+
ticketStatus: event.newStatusName,
|
|
206
|
+
ticketCategory: event.newStatusCategory,
|
|
207
|
+
lastOutboundSync: new Date().toISOString(),
|
|
208
|
+
},
|
|
209
|
+
lastSyncedAt: new Date(),
|
|
210
|
+
});
|
|
211
|
+
results.push({ provider: mapping.provider, success: true });
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
results.push({
|
|
215
|
+
provider: mapping.provider,
|
|
216
|
+
success: false,
|
|
217
|
+
error: err instanceof Error ? err.message : String(err),
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return results;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Record a PR URL in all external mappings for a ticket.
|
|
225
|
+
*/
|
|
226
|
+
recordPRInMappings(event) {
|
|
227
|
+
const mappings = this.findMappingsForTicket(event.ticketId);
|
|
228
|
+
for (const mapping of mappings) {
|
|
229
|
+
try {
|
|
230
|
+
this.mappingStore.upsertMapping({
|
|
231
|
+
provider: mapping.provider,
|
|
232
|
+
externalId: mapping.externalId,
|
|
233
|
+
prUrl: event.prUrl,
|
|
234
|
+
lastSyncedAt: new Date(),
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// Non-fatal
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Find external execution mappings associated with a ticket.
|
|
244
|
+
* Checks the latest_state_snapshot for pmoTicketId references.
|
|
245
|
+
*/
|
|
246
|
+
findMappingsForTicket(ticketId) {
|
|
247
|
+
// Query external_execution_map where latest_state_snapshot contains the ticketId
|
|
248
|
+
const rows = this.db.prepare(`
|
|
249
|
+
SELECT provider, external_id, latest_state_snapshot
|
|
250
|
+
FROM pmo_external_execution_map
|
|
251
|
+
WHERE latest_state_snapshot LIKE ?
|
|
252
|
+
`).all(`%${ticketId}%`);
|
|
253
|
+
return rows.map((row) => ({
|
|
254
|
+
provider: row.provider,
|
|
255
|
+
externalId: row.external_id,
|
|
256
|
+
latestStateSnapshot: row.latest_state_snapshot ? parseSnapshot(row.latest_state_snapshot) : null,
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function parseSnapshot(value) {
|
|
261
|
+
try {
|
|
262
|
+
const parsed = JSON.parse(value);
|
|
263
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
264
|
+
return parsed;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
// ignore
|
|
269
|
+
}
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
// =============================================================================
|
|
273
|
+
// Singleton
|
|
274
|
+
// =============================================================================
|
|
275
|
+
let _handler;
|
|
276
|
+
/**
|
|
277
|
+
* Initialize and start the outbound sync handler.
|
|
278
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
279
|
+
*/
|
|
280
|
+
export function initOutboundSync(db) {
|
|
281
|
+
if (!_handler) {
|
|
282
|
+
_handler = new OutboundSyncHandler(db);
|
|
283
|
+
_handler.start();
|
|
284
|
+
}
|
|
285
|
+
return _handler;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Stop the outbound sync handler (primarily for testing).
|
|
289
|
+
*/
|
|
290
|
+
export function stopOutboundSync() {
|
|
291
|
+
if (_handler) {
|
|
292
|
+
_handler.stop();
|
|
293
|
+
_handler = undefined;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=outbound-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbound-sync.js","sourceRoot":"","sources":["../../../src/lib/external-issues/outbound-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type IssueEnvelope, type NormalizedIssueEnvelope } from './types.js';
|
|
2
|
+
export interface TrelloAdapterConfig {
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
apiToken?: string;
|
|
5
|
+
boardId?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Normalize a raw Trello API card into a canonical IssueEnvelope.
|
|
9
|
+
*/
|
|
10
|
+
export declare function normalizeTrelloCard(rawCard: unknown, listName?: string): IssueEnvelope;
|
|
11
|
+
/**
|
|
12
|
+
* Normalize a raw Trello card into a PMO-ready NormalizedIssueEnvelope.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeTrelloCardToEnvelope(rawCard: unknown, listName?: string): NormalizedIssueEnvelope;
|
|
15
|
+
/**
|
|
16
|
+
* Build a PMO ticket description from a NormalizedIssueEnvelope.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildTrelloTicketDescription(envelope: NormalizedIssueEnvelope): string;
|
|
19
|
+
/**
|
|
20
|
+
* Build ticket metadata from a NormalizedIssueEnvelope for traceability.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildTrelloMetadata(envelope: NormalizedIssueEnvelope): Record<string, string>;
|
|
23
|
+
/**
|
|
24
|
+
* Build a spawn context message from a NormalizedIssueEnvelope.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildTrelloSpawnContextMessage(envelope: NormalizedIssueEnvelope, additionalMessage?: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Build a CLI command string for selecting a specific Trello card.
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildTrelloCardChoiceCommand(cardId: string, projectId?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Fetch a single Trello card by its ID and normalize it.
|
|
33
|
+
*/
|
|
34
|
+
export declare function getTrelloCardById(configInput: TrelloAdapterConfig, cardId: string, options?: {
|
|
35
|
+
fetchImpl?: typeof fetch;
|
|
36
|
+
}): Promise<NormalizedIssueEnvelope | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if Trello is configured via environment variables.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isTrelloConfiguredFromEnv(config?: TrelloAdapterConfig): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Fetch and normalize Trello cards from a board into NormalizedIssueEnvelopes.
|
|
43
|
+
*/
|
|
44
|
+
export declare function listTrelloCards(configInput: TrelloAdapterConfig, options?: {
|
|
45
|
+
limit?: number;
|
|
46
|
+
query?: string;
|
|
47
|
+
fetchImpl?: typeof fetch;
|
|
48
|
+
}): Promise<NormalizedIssueEnvelope[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Import a Trello card into PMO as a linked ticket.
|
|
51
|
+
*/
|
|
52
|
+
export declare function importTrelloCardToPmo(storage: {
|
|
53
|
+
listTickets(projectId: string): Promise<Array<{
|
|
54
|
+
id: string;
|
|
55
|
+
metadata?: Record<string, string>;
|
|
56
|
+
}>>;
|
|
57
|
+
createTicket(projectId: string, input: {
|
|
58
|
+
title: string;
|
|
59
|
+
description: string;
|
|
60
|
+
priority?: string;
|
|
61
|
+
category?: string;
|
|
62
|
+
labels: string[];
|
|
63
|
+
metadata: Record<string, string>;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
id: string;
|
|
66
|
+
}>;
|
|
67
|
+
updateTicket(ticketId: string, input: {
|
|
68
|
+
title: string;
|
|
69
|
+
description: string;
|
|
70
|
+
priority?: string;
|
|
71
|
+
category?: string;
|
|
72
|
+
labels: string[];
|
|
73
|
+
metadata: Record<string, string>;
|
|
74
|
+
}): Promise<{
|
|
75
|
+
id: string;
|
|
76
|
+
}>;
|
|
77
|
+
}, projectId: string, envelope: NormalizedIssueEnvelope): Promise<{
|
|
78
|
+
ticketId: string;
|
|
79
|
+
created: boolean;
|
|
80
|
+
}>;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { ExternalIssueAdapterError, toNormalizedEnvelope, } from './types.js';
|
|
2
|
+
function ensureTrelloConfig(config) {
|
|
3
|
+
const apiKey = config.apiKey || process.env.PRLT_TRELLO_API_KEY || process.env.TRELLO_API_KEY;
|
|
4
|
+
const apiToken = config.apiToken || process.env.PRLT_TRELLO_API_TOKEN || process.env.TRELLO_API_TOKEN;
|
|
5
|
+
const boardId = config.boardId || process.env.PRLT_TRELLO_BOARD_ID;
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
throw new ExternalIssueAdapterError('MISSING_CONFIG', 'Missing Trello API key. Set TRELLO_API_KEY or PRLT_TRELLO_API_KEY, or run "prlt trello configure".');
|
|
8
|
+
}
|
|
9
|
+
if (!apiToken) {
|
|
10
|
+
throw new ExternalIssueAdapterError('MISSING_CONFIG', 'Missing Trello API token. Set TRELLO_API_TOKEN or PRLT_TRELLO_API_TOKEN, or run "prlt trello configure".');
|
|
11
|
+
}
|
|
12
|
+
return { apiKey, apiToken, boardId: boardId || undefined };
|
|
13
|
+
}
|
|
14
|
+
function ensureCardShape(card) {
|
|
15
|
+
if (!card.id || !card.name || !card.url) {
|
|
16
|
+
throw new ExternalIssueAdapterError('BAD_PAYLOAD', 'Trello card payload is missing required fields (id, name, url).', card);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function deriveTrelloLabels(card) {
|
|
20
|
+
if (!Array.isArray(card.labels)) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
return card.labels
|
|
24
|
+
.map(label => label.name?.trim())
|
|
25
|
+
.filter((name) => Boolean(name));
|
|
26
|
+
}
|
|
27
|
+
function deriveTrelloPriority(labels) {
|
|
28
|
+
const priorityLabel = labels.find(l => /^P[0-3]$/i.test(l));
|
|
29
|
+
return priorityLabel ? priorityLabel.toUpperCase() : null;
|
|
30
|
+
}
|
|
31
|
+
function deriveTrelloAssignee(card) {
|
|
32
|
+
const members = card.members;
|
|
33
|
+
if (Array.isArray(members) && members.length > 0) {
|
|
34
|
+
return members[0]?.fullName || members[0]?.username || null;
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function deriveCategory(_card) {
|
|
39
|
+
return 'feature';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Normalize a raw Trello API card into a canonical IssueEnvelope.
|
|
43
|
+
*/
|
|
44
|
+
export function normalizeTrelloCard(rawCard, listName) {
|
|
45
|
+
if (!rawCard || typeof rawCard !== 'object') {
|
|
46
|
+
throw new ExternalIssueAdapterError('BAD_PAYLOAD', 'Trello card payload is invalid.', rawCard);
|
|
47
|
+
}
|
|
48
|
+
const card = rawCard;
|
|
49
|
+
ensureCardShape(card);
|
|
50
|
+
const labels = deriveTrelloLabels(card);
|
|
51
|
+
return {
|
|
52
|
+
source: 'trello',
|
|
53
|
+
external_id: card.id,
|
|
54
|
+
external_key: card.id,
|
|
55
|
+
title: card.name,
|
|
56
|
+
description: card.desc || '',
|
|
57
|
+
labels,
|
|
58
|
+
priority: deriveTrelloPriority(labels),
|
|
59
|
+
status: listName ?? (card.closed ? 'Closed' : 'Open'),
|
|
60
|
+
url: card.url,
|
|
61
|
+
project_key: card.idBoard || 'DEFAULT',
|
|
62
|
+
assignee: deriveTrelloAssignee(card),
|
|
63
|
+
item_type: 'card',
|
|
64
|
+
raw: rawCard,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Normalize a raw Trello card into a PMO-ready NormalizedIssueEnvelope.
|
|
69
|
+
*/
|
|
70
|
+
export function normalizeTrelloCardToEnvelope(rawCard, listName) {
|
|
71
|
+
const envelope = normalizeTrelloCard(rawCard, listName);
|
|
72
|
+
const card = rawCard;
|
|
73
|
+
return toNormalizedEnvelope(envelope, deriveCategory(card));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build a PMO ticket description from a NormalizedIssueEnvelope.
|
|
77
|
+
*/
|
|
78
|
+
export function buildTrelloTicketDescription(envelope) {
|
|
79
|
+
const body = envelope.description.trim();
|
|
80
|
+
const metadataLines = [
|
|
81
|
+
`- Source: ${envelope.source.name}`,
|
|
82
|
+
`- External key: ${envelope.source.externalKey}`,
|
|
83
|
+
`- External id: ${envelope.source.externalId}`,
|
|
84
|
+
`- URL: ${envelope.source.url}`,
|
|
85
|
+
`- Status: ${envelope.status}`,
|
|
86
|
+
`- Priority: ${envelope.priority || 'Unset'}`,
|
|
87
|
+
`- Labels: ${envelope.labels.length > 0 ? envelope.labels.join(', ') : 'None'}`,
|
|
88
|
+
];
|
|
89
|
+
const parts = [
|
|
90
|
+
body,
|
|
91
|
+
'## External Issue Context',
|
|
92
|
+
metadataLines.join('\n'),
|
|
93
|
+
].filter(Boolean);
|
|
94
|
+
return parts.join('\n\n');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Build ticket metadata from a NormalizedIssueEnvelope for traceability.
|
|
98
|
+
*/
|
|
99
|
+
export function buildTrelloMetadata(envelope) {
|
|
100
|
+
return {
|
|
101
|
+
external_source: envelope.source.name,
|
|
102
|
+
external_key: envelope.source.externalKey,
|
|
103
|
+
external_id: envelope.source.externalId,
|
|
104
|
+
external_url: envelope.source.url,
|
|
105
|
+
external_raw: JSON.stringify(envelope.source.raw),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Build a spawn context message from a NormalizedIssueEnvelope.
|
|
110
|
+
*/
|
|
111
|
+
export function buildTrelloSpawnContextMessage(envelope, additionalMessage) {
|
|
112
|
+
const lines = [
|
|
113
|
+
`External issue source: ${envelope.source.name}`,
|
|
114
|
+
`External issue key: ${envelope.source.externalKey}`,
|
|
115
|
+
`External issue id: ${envelope.source.externalId}`,
|
|
116
|
+
`External issue URL: ${envelope.source.url}`,
|
|
117
|
+
];
|
|
118
|
+
if (additionalMessage?.trim()) {
|
|
119
|
+
lines.push('', additionalMessage.trim());
|
|
120
|
+
}
|
|
121
|
+
return lines.join('\n');
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Build a CLI command string for selecting a specific Trello card.
|
|
125
|
+
*/
|
|
126
|
+
export function buildTrelloCardChoiceCommand(cardId, projectId) {
|
|
127
|
+
let command = `prlt work start --from trello:${cardId} --json`;
|
|
128
|
+
if (projectId) {
|
|
129
|
+
command += ` -P ${projectId}`;
|
|
130
|
+
}
|
|
131
|
+
return command;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Fetch the list name for a card's idList.
|
|
135
|
+
*/
|
|
136
|
+
async function fetchListName(config, listId, options) {
|
|
137
|
+
const fetchImpl = options?.fetchImpl || fetch;
|
|
138
|
+
try {
|
|
139
|
+
const url = `https://api.trello.com/1/lists/${listId}?key=${encodeURIComponent(config.apiKey)}&token=${encodeURIComponent(config.apiToken)}&fields=name`;
|
|
140
|
+
const response = await fetchImpl(url);
|
|
141
|
+
if (!response.ok)
|
|
142
|
+
return undefined;
|
|
143
|
+
const list = await response.json();
|
|
144
|
+
return list.name ?? undefined;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Fetch a single Trello card by its ID and normalize it.
|
|
152
|
+
*/
|
|
153
|
+
export async function getTrelloCardById(configInput, cardId, options) {
|
|
154
|
+
const config = ensureTrelloConfig(configInput);
|
|
155
|
+
const fetchImpl = options?.fetchImpl || fetch;
|
|
156
|
+
const url = `https://api.trello.com/1/cards/${encodeURIComponent(cardId)}?key=${encodeURIComponent(config.apiKey)}&token=${encodeURIComponent(config.apiToken)}&fields=id,name,desc,url,shortUrl,idBoard,idList,idMembers,closed,due,dueComplete&members=true&member_fields=fullName,username&labels=all`;
|
|
157
|
+
const response = await fetchImpl(url);
|
|
158
|
+
if (response.status === 401 || response.status === 403) {
|
|
159
|
+
throw new ExternalIssueAdapterError('AUTH_FAILED', 'Trello authentication failed. Verify your API key and token.');
|
|
160
|
+
}
|
|
161
|
+
if (response.status === 429) {
|
|
162
|
+
throw new ExternalIssueAdapterError('RATE_LIMITED', 'Trello API rate limit exceeded. Wait a moment and try again.');
|
|
163
|
+
}
|
|
164
|
+
if (response.status === 404) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
throw new ExternalIssueAdapterError('REQUEST_FAILED', `Trello request failed with status ${response.status}.`);
|
|
169
|
+
}
|
|
170
|
+
const payload = await response.json();
|
|
171
|
+
// Resolve list name for status
|
|
172
|
+
const listName = payload.idList
|
|
173
|
+
? await fetchListName(config, payload.idList, { fetchImpl })
|
|
174
|
+
: undefined;
|
|
175
|
+
return normalizeTrelloCardToEnvelope(payload, listName);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Check if Trello is configured via environment variables.
|
|
179
|
+
*/
|
|
180
|
+
export function isTrelloConfiguredFromEnv(config) {
|
|
181
|
+
const apiKey = config?.apiKey
|
|
182
|
+
|| process.env.PRLT_TRELLO_API_KEY
|
|
183
|
+
|| process.env.TRELLO_API_KEY;
|
|
184
|
+
const apiToken = config?.apiToken
|
|
185
|
+
|| process.env.PRLT_TRELLO_API_TOKEN
|
|
186
|
+
|| process.env.TRELLO_API_TOKEN;
|
|
187
|
+
return Boolean(apiKey && apiToken);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Fetch and normalize Trello cards from a board into NormalizedIssueEnvelopes.
|
|
191
|
+
*/
|
|
192
|
+
export async function listTrelloCards(configInput, options) {
|
|
193
|
+
const config = ensureTrelloConfig(configInput);
|
|
194
|
+
const fetchImpl = options?.fetchImpl || fetch;
|
|
195
|
+
const limit = Math.max(1, Math.min(options?.limit ?? 20, 100));
|
|
196
|
+
if (!config.boardId && !options?.query) {
|
|
197
|
+
throw new ExternalIssueAdapterError('MISSING_CONFIG', 'Missing Trello board ID. Run "prlt trello configure" and select a board, or set PRLT_TRELLO_BOARD_ID.');
|
|
198
|
+
}
|
|
199
|
+
// If query, use search endpoint
|
|
200
|
+
if (options?.query) {
|
|
201
|
+
const url = `https://api.trello.com/1/search?key=${encodeURIComponent(config.apiKey)}&token=${encodeURIComponent(config.apiToken)}&query=${encodeURIComponent(options.query)}&modelTypes=cards&cards_limit=${limit}&card_fields=id,name,desc,url,shortUrl,idBoard,idList,idMembers,closed,due,dueComplete&card_members=true&card_member_fields=fullName,username&card_labels=all`;
|
|
202
|
+
const response = await fetchImpl(url);
|
|
203
|
+
if (response.status === 401 || response.status === 403) {
|
|
204
|
+
throw new ExternalIssueAdapterError('AUTH_FAILED', 'Trello authentication failed. Verify your API key and token.');
|
|
205
|
+
}
|
|
206
|
+
if (!response.ok) {
|
|
207
|
+
throw new ExternalIssueAdapterError('REQUEST_FAILED', `Trello request failed with status ${response.status}.`);
|
|
208
|
+
}
|
|
209
|
+
const payload = await response.json();
|
|
210
|
+
const cards = payload.cards ?? [];
|
|
211
|
+
return cards.slice(0, limit).map(card => normalizeTrelloCardToEnvelope(card));
|
|
212
|
+
}
|
|
213
|
+
// Otherwise, list from board
|
|
214
|
+
const url = `https://api.trello.com/1/boards/${encodeURIComponent(config.boardId)}/cards/open?key=${encodeURIComponent(config.apiKey)}&token=${encodeURIComponent(config.apiToken)}&fields=id,name,desc,url,shortUrl,idBoard,idList,idMembers,closed,due,dueComplete&members=true&member_fields=fullName,username&labels=all`;
|
|
215
|
+
const response = await fetchImpl(url);
|
|
216
|
+
if (response.status === 401 || response.status === 403) {
|
|
217
|
+
throw new ExternalIssueAdapterError('AUTH_FAILED', 'Trello authentication failed. Verify your API key and token.');
|
|
218
|
+
}
|
|
219
|
+
if (!response.ok) {
|
|
220
|
+
throw new ExternalIssueAdapterError('REQUEST_FAILED', `Trello request failed with status ${response.status}.`);
|
|
221
|
+
}
|
|
222
|
+
const cards = await response.json();
|
|
223
|
+
if (!Array.isArray(cards)) {
|
|
224
|
+
throw new ExternalIssueAdapterError('BAD_PAYLOAD', 'Trello response payload was missing cards array.', cards);
|
|
225
|
+
}
|
|
226
|
+
return cards.slice(0, limit).map(card => normalizeTrelloCardToEnvelope(card));
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Import a Trello card into PMO as a linked ticket.
|
|
230
|
+
*/
|
|
231
|
+
export async function importTrelloCardToPmo(storage, projectId, envelope) {
|
|
232
|
+
const tickets = await storage.listTickets(projectId);
|
|
233
|
+
const existing = tickets.find((ticket) => {
|
|
234
|
+
const source = ticket.metadata?.external_source;
|
|
235
|
+
const key = ticket.metadata?.external_key;
|
|
236
|
+
const id = ticket.metadata?.external_id;
|
|
237
|
+
return source === 'trello'
|
|
238
|
+
&& (key === envelope.source.externalKey || id === envelope.source.externalId);
|
|
239
|
+
});
|
|
240
|
+
const description = buildTrelloTicketDescription(envelope);
|
|
241
|
+
const metadata = buildTrelloMetadata(envelope);
|
|
242
|
+
if (existing) {
|
|
243
|
+
await storage.updateTicket(existing.id, {
|
|
244
|
+
title: envelope.title,
|
|
245
|
+
description,
|
|
246
|
+
priority: envelope.priority ?? undefined,
|
|
247
|
+
category: envelope.category ?? undefined,
|
|
248
|
+
labels: envelope.labels,
|
|
249
|
+
metadata: {
|
|
250
|
+
...existing.metadata,
|
|
251
|
+
...metadata,
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
return { ticketId: existing.id, created: false };
|
|
255
|
+
}
|
|
256
|
+
const ticket = await storage.createTicket(projectId, {
|
|
257
|
+
title: envelope.title,
|
|
258
|
+
description,
|
|
259
|
+
priority: envelope.priority ?? undefined,
|
|
260
|
+
category: envelope.category ?? undefined,
|
|
261
|
+
labels: envelope.labels,
|
|
262
|
+
metadata,
|
|
263
|
+
});
|
|
264
|
+
return { ticketId: ticket.id, created: true };
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=trello.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trello.js","sourceRoot":"","sources":["../../../src/lib/external-issues/trello.ts"],"names":[],"mappings":"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"}
|