@relayfile/adapter-linear 0.2.3 → 0.2.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/dist/__tests__/emit-auxiliary-files.test.d.ts +2 -0
- package/dist/__tests__/emit-auxiliary-files.test.d.ts.map +1 -0
- package/dist/__tests__/emit-auxiliary-files.test.js +596 -0
- package/dist/__tests__/emit-auxiliary-files.test.js.map +1 -0
- package/dist/__tests__/path-mapper.test.js +62 -1
- package/dist/__tests__/path-mapper.test.js.map +1 -1
- package/dist/emit-auxiliary-files.d.ts +111 -0
- package/dist/emit-auxiliary-files.d.ts.map +1 -0
- package/dist/emit-auxiliary-files.js +482 -0
- package/dist/emit-auxiliary-files.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/layout-prompt.d.ts +1 -1
- package/dist/layout-prompt.d.ts.map +1 -1
- package/dist/layout-prompt.js +2 -0
- package/dist/layout-prompt.js.map +1 -1
- package/dist/path-mapper.d.ts +11 -0
- package/dist/path-mapper.d.ts.map +1 -1
- package/dist/path-mapper.js +13 -0
- package/dist/path-mapper.js.map +1 -1
- package/dist/summary.d.ts +4 -0
- package/dist/summary.d.ts.map +1 -0
- package/dist/summary.js +163 -0
- package/dist/summary.js.map +1 -0
- package/dist/summary.test.d.ts +2 -0
- package/dist/summary.test.d.ts.map +1 -0
- package/dist/summary.test.js +65 -0
- package/dist/summary.test.js.map +1 -0
- package/dist/thread.d.ts +58 -0
- package/dist/thread.d.ts.map +1 -0
- package/dist/thread.js +226 -0
- package/dist/thread.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter-owned auxiliary-file emission for Linear.
|
|
3
|
+
*
|
|
4
|
+
* Phase 2 port of the `emitAuxiliaryFiles` contract introduced by
|
|
5
|
+
* `@relayfile/adapter-core` and exercised by `@relayfile/adapter-confluence`
|
|
6
|
+
* in PR #78. Generalizes the Linear branch of cloud's
|
|
7
|
+
* `record-writer.ts::writeLinearAuxiliaryFiles` (plus
|
|
8
|
+
* `readLinearIssueAliasContext`) so cloud's Phase-3 dispatcher can collapse
|
|
9
|
+
* to a per-provider switch.
|
|
10
|
+
*
|
|
11
|
+
* Per-resource emission:
|
|
12
|
+
*
|
|
13
|
+
* * **issue** — canonical `/linear/issues/<identifier-or-title-slug>__<id>.json`,
|
|
14
|
+
* plus a by-uuid alias keyed on the Linear UUID (always emitted — the
|
|
15
|
+
* stable reconciliation anchor), a by-id alias keyed on the Linear
|
|
16
|
+
* `TEAM-123` identifier when present (human-readable lookup), a by-title
|
|
17
|
+
* alias when the title slugs to non-empty, and a by-state alias when both
|
|
18
|
+
* `state.name` and `identifier` are present. Index row carries
|
|
19
|
+
* `{ id, title, updated, identifier, state }`.
|
|
20
|
+
*
|
|
21
|
+
* * **comment** — canonical `/linear/comments/<slug>__<id>.json`, no
|
|
22
|
+
* subtree aliases (current cloud + adapter shape only writes the
|
|
23
|
+
* canonical record and the index row). Index row
|
|
24
|
+
* `{ id, title, updated }`.
|
|
25
|
+
*
|
|
26
|
+
* * **user**, **team** — canonical `/linear/users/<id>.json` /
|
|
27
|
+
* `/linear/teams/<id>.json`, index row `{ id, title, updated }`.
|
|
28
|
+
*
|
|
29
|
+
* * **project** — canonical `/linear/projects/<id>.json`. No index file
|
|
30
|
+
* today; the helper exists in the path-mapper but no `_index.json`
|
|
31
|
+
* emitter is wired in. We still emit the canonical file so cloud's
|
|
32
|
+
* existing project sync surfaces survive the port.
|
|
33
|
+
*
|
|
34
|
+
* * **cycle**, **milestone**, **roadmap** — canonical paths only. Same
|
|
35
|
+
* rationale as projects.
|
|
36
|
+
*
|
|
37
|
+
* Reconciliation: every issue write reads the prior by-uuid alias (the
|
|
38
|
+
* stable anchor keyed on `issue.id`, always emitted) to recover the
|
|
39
|
+
* previous identifier / title / state, then deletes whichever alias and
|
|
40
|
+
* canonical paths no longer apply. User/team writes reconcile against the
|
|
41
|
+
* prior index row. Reads degrade to "no reconciliation" when the client
|
|
42
|
+
* lacks `readFile` — same back-compat we shipped in #78.
|
|
43
|
+
*
|
|
44
|
+
* Delete tombstones: `{ id, _deleted: true }`. For issues we read the
|
|
45
|
+
* prior by-uuid alias to recover the identifier, title, and state — the
|
|
46
|
+
* UUID is always present on a tombstone (it's the only field), so the
|
|
47
|
+
* lookup key is guaranteed even when the original write predated the
|
|
48
|
+
* identifier. For all resource types, `IndexFileReconciler.remove(id)` is
|
|
49
|
+
* called on the delete branch so `_index.json` doesn't accumulate ghost
|
|
50
|
+
* rows (the Devin regression on #78 — see
|
|
51
|
+
* `packages/confluence/src/emit-auxiliary-files.ts`).
|
|
52
|
+
*/
|
|
53
|
+
import { PriorAliasReader, IndexFileReconciler, runEmitBatch, EMIT_AUXILIARY_JSON_CONTENT_TYPE, } from '@relayfile/adapter-core';
|
|
54
|
+
import { slugifyAlias } from './alias-slug.js';
|
|
55
|
+
import { LINEAR_PATH_ROOT, linearByIdAliasPath, linearByTitleAliasPath, linearByUuidAliasPath, linearCommentPath, linearCommentsIndexPath, linearCyclePath, linearIssueByStatePath, linearIssuePath, linearIssuesIndexPath, linearMilestonePath, linearProjectPath, linearRoadmapPath, linearTeamPath, linearTeamsIndexPath, linearUserPath, linearUsersIndexPath, } from './path-mapper.js';
|
|
56
|
+
import { linearCommentIndexRow, linearIssueIndexRow, linearTeamIndexRow, linearUserIndexRow, } from './queries.js';
|
|
57
|
+
const LINEAR_PROVIDER_NAME = 'linear';
|
|
58
|
+
const JSON_CONTENT_TYPE = EMIT_AUXILIARY_JSON_CONTENT_TYPE;
|
|
59
|
+
const ISSUES_SCOPE = `${LINEAR_PATH_ROOT}/issues`;
|
|
60
|
+
/**
|
|
61
|
+
* Phase-2 entry point. Cloud's Phase-3 dispatcher iterates
|
|
62
|
+
* `(provider, records)` and calls this with a shimmed
|
|
63
|
+
* `AuxiliaryEmitterClient`.
|
|
64
|
+
*/
|
|
65
|
+
export async function emitLinearAuxiliaryFiles(client, input) {
|
|
66
|
+
const workspaceId = input.workspaceId;
|
|
67
|
+
const aggregate = { written: 0, deleted: 0, errors: [] };
|
|
68
|
+
const issues = input.issues ?? [];
|
|
69
|
+
const comments = input.comments ?? [];
|
|
70
|
+
const users = input.users ?? [];
|
|
71
|
+
const teams = input.teams ?? [];
|
|
72
|
+
const projects = input.projects ?? [];
|
|
73
|
+
const cycles = input.cycles ?? [];
|
|
74
|
+
const milestones = input.milestones ?? [];
|
|
75
|
+
const roadmaps = input.roadmaps ?? [];
|
|
76
|
+
if (issues.length === 0 &&
|
|
77
|
+
comments.length === 0 &&
|
|
78
|
+
users.length === 0 &&
|
|
79
|
+
teams.length === 0 &&
|
|
80
|
+
projects.length === 0 &&
|
|
81
|
+
cycles.length === 0 &&
|
|
82
|
+
milestones.length === 0 &&
|
|
83
|
+
roadmaps.length === 0) {
|
|
84
|
+
return aggregate;
|
|
85
|
+
}
|
|
86
|
+
if (issues.length > 0) {
|
|
87
|
+
accumulate(aggregate, await emitIssues(client, workspaceId, issues, input.connectionId));
|
|
88
|
+
}
|
|
89
|
+
if (comments.length > 0) {
|
|
90
|
+
accumulate(aggregate, await emitComments(client, workspaceId, comments, input.connectionId));
|
|
91
|
+
}
|
|
92
|
+
if (users.length > 0) {
|
|
93
|
+
accumulate(aggregate, await emitUsers(client, workspaceId, users, input.connectionId));
|
|
94
|
+
}
|
|
95
|
+
if (teams.length > 0) {
|
|
96
|
+
accumulate(aggregate, await emitTeams(client, workspaceId, teams, input.connectionId));
|
|
97
|
+
}
|
|
98
|
+
if (projects.length > 0) {
|
|
99
|
+
accumulate(aggregate, await emitProjects(client, workspaceId, projects, input.connectionId));
|
|
100
|
+
}
|
|
101
|
+
if (cycles.length > 0) {
|
|
102
|
+
accumulate(aggregate, await emitCycles(client, workspaceId, cycles, input.connectionId));
|
|
103
|
+
}
|
|
104
|
+
if (milestones.length > 0) {
|
|
105
|
+
accumulate(aggregate, await emitMilestones(client, workspaceId, milestones, input.connectionId));
|
|
106
|
+
}
|
|
107
|
+
if (roadmaps.length > 0) {
|
|
108
|
+
accumulate(aggregate, await emitRoadmaps(client, workspaceId, roadmaps, input.connectionId));
|
|
109
|
+
}
|
|
110
|
+
return aggregate;
|
|
111
|
+
}
|
|
112
|
+
// -- issues -----------------------------------------------------------------
|
|
113
|
+
async function emitIssues(client, workspaceId, records, connectionId) {
|
|
114
|
+
const indexReconciler = new IndexFileReconciler({
|
|
115
|
+
client,
|
|
116
|
+
workspaceId,
|
|
117
|
+
path: linearIssuesIndexPath(),
|
|
118
|
+
builder: (rows) => ({
|
|
119
|
+
path: linearIssuesIndexPath(),
|
|
120
|
+
content: `${JSON.stringify([...rows].sort(compareIndexRows))}\n`,
|
|
121
|
+
contentType: JSON_CONTENT_TYPE,
|
|
122
|
+
}),
|
|
123
|
+
});
|
|
124
|
+
const priorReader = new PriorAliasReader(client, workspaceId);
|
|
125
|
+
const fanOut = await runEmitBatch(client, workspaceId, records, async (record) => {
|
|
126
|
+
if (isDeleteRecord(record)) {
|
|
127
|
+
return planIssueDelete(record.id, priorReader, indexReconciler);
|
|
128
|
+
}
|
|
129
|
+
return planIssueWrite(record, priorReader, indexReconciler, connectionId);
|
|
130
|
+
});
|
|
131
|
+
const indexResult = await indexReconciler.flush();
|
|
132
|
+
fanOut.written += indexResult.written;
|
|
133
|
+
fanOut.errors.push(...indexResult.errors);
|
|
134
|
+
return fanOut;
|
|
135
|
+
}
|
|
136
|
+
async function planIssueWrite(issue, priorReader, indexReconciler, connectionId) {
|
|
137
|
+
const id = readNonEmptyString(issue.id);
|
|
138
|
+
if (!id) {
|
|
139
|
+
return {};
|
|
140
|
+
}
|
|
141
|
+
const identifier = readNonEmptyString(issue.identifier);
|
|
142
|
+
const title = readNonEmptyString(issue.title);
|
|
143
|
+
const stateName = readIssueStateName(issue);
|
|
144
|
+
const content = renderContent('issue', issue, connectionId, false);
|
|
145
|
+
const newPaths = issuePathsFor({ id, identifier, title, stateName });
|
|
146
|
+
// Reconciliation: the by-uuid alias is the stable anchor — it's always
|
|
147
|
+
// emitted (keyed on the UUID, which is always present) so a prior write
|
|
148
|
+
// is guaranteed to have produced it. This resolves the
|
|
149
|
+
// identifier-transition gap CodeRabbit caught: an issue going from
|
|
150
|
+
// identifier-less to identifier-bearing previously left a stale
|
|
151
|
+
// UUID-keyed by-id alias behind because the fallback in this lookup
|
|
152
|
+
// recomputed the new identifier-keyed path.
|
|
153
|
+
const prior = await priorReader.read(linearByUuidAliasPath(ISSUES_SCOPE, id), extractPriorIssueState);
|
|
154
|
+
const stalePaths = prior
|
|
155
|
+
? diffPaths(issuePathsFor({
|
|
156
|
+
id,
|
|
157
|
+
// IMPORTANT: do NOT fall back to the current identifier here. If
|
|
158
|
+
// the prior payload had no identifier, the prior by-id alias was
|
|
159
|
+
// never written (we only emit by-id when identifier is present),
|
|
160
|
+
// so there's nothing stale to clean up on that path. Passing the
|
|
161
|
+
// current identifier would synthesize a phantom prior path.
|
|
162
|
+
identifier: prior.identifier,
|
|
163
|
+
title: prior.title,
|
|
164
|
+
stateName: prior.stateName,
|
|
165
|
+
}), newPaths)
|
|
166
|
+
: [];
|
|
167
|
+
const writes = newPaths.map((path) => ({
|
|
168
|
+
path,
|
|
169
|
+
content,
|
|
170
|
+
contentType: JSON_CONTENT_TYPE,
|
|
171
|
+
}));
|
|
172
|
+
const deletes = stalePaths.map((path) => ({ path }));
|
|
173
|
+
indexReconciler.upsert(linearIssueIndexRow(toIssueNode(issue)));
|
|
174
|
+
return { writes, deletes };
|
|
175
|
+
}
|
|
176
|
+
async function planIssueDelete(id, priorReader, indexReconciler) {
|
|
177
|
+
// Bare tombstones carry only the UUID, so we read the by-uuid alias —
|
|
178
|
+
// the stable anchor keyed on `issue.id`, always written alongside every
|
|
179
|
+
// prior issue emit. This is the fix for the Devin finding: the previous
|
|
180
|
+
// implementation read `linearByIdAliasPath(scope, id)` (UUID), but
|
|
181
|
+
// `issuePathsFor` writes by-id keyed on the identifier (e.g. AGE-8),
|
|
182
|
+
// not the UUID, so the lookup never matched and no alias paths got
|
|
183
|
+
// computed → none of the 4 stale files got deleted on tombstone.
|
|
184
|
+
const prior = (await priorReader.read(linearByUuidAliasPath(ISSUES_SCOPE, id), extractPriorIssueState)) ?? null;
|
|
185
|
+
const paths = issuePathsFor({
|
|
186
|
+
id,
|
|
187
|
+
identifier: prior?.identifier,
|
|
188
|
+
title: prior?.title,
|
|
189
|
+
stateName: prior?.stateName,
|
|
190
|
+
});
|
|
191
|
+
// See planPageDelete in the confluence port — index row must drop too.
|
|
192
|
+
indexReconciler.remove(id);
|
|
193
|
+
return { deletes: paths.map((path) => ({ path })) };
|
|
194
|
+
}
|
|
195
|
+
function extractPriorIssueState(parsed) {
|
|
196
|
+
const payload = pickPayload(parsed);
|
|
197
|
+
if (!payload)
|
|
198
|
+
return null;
|
|
199
|
+
return {
|
|
200
|
+
identifier: readNonEmptyString(payload.identifier),
|
|
201
|
+
title: readNonEmptyString(payload.title),
|
|
202
|
+
stateName: readPriorStateName(payload),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function readPriorStateName(payload) {
|
|
206
|
+
const stateRecord = isRecord(payload.state) ? payload.state : undefined;
|
|
207
|
+
return (readNonEmptyString(stateRecord?.name) ??
|
|
208
|
+
readNonEmptyString(payload.state_name) ??
|
|
209
|
+
readNonEmptyString(payload.state_type));
|
|
210
|
+
}
|
|
211
|
+
function issuePathsFor(args) {
|
|
212
|
+
const { id, identifier, title, stateName } = args;
|
|
213
|
+
const humanReadable = identifier ?? title;
|
|
214
|
+
const paths = [];
|
|
215
|
+
// Canonical path.
|
|
216
|
+
paths.push(linearIssuePath(id, humanReadable));
|
|
217
|
+
// by-uuid alias — the stable reconciliation anchor, always emitted.
|
|
218
|
+
// Keyed on the Linear UUID (`issue.id`), which is always present even on
|
|
219
|
+
// bare delete tombstones. Subsequent emits read prior state from this
|
|
220
|
+
// path to discover the previous identifier/title/state.
|
|
221
|
+
paths.push(linearByUuidAliasPath(ISSUES_SCOPE, id));
|
|
222
|
+
// by-id alias — human-readable lookup keyed on the Linear identifier
|
|
223
|
+
// (e.g. `TEAM-123`). Only emitted when the identifier is present, so we
|
|
224
|
+
// don't pollute `/linear/issues/by-id/` with UUID-keyed entries that
|
|
225
|
+
// duplicate the by-uuid subtree.
|
|
226
|
+
if (identifier) {
|
|
227
|
+
paths.push(linearByIdAliasPath(ISSUES_SCOPE, identifier));
|
|
228
|
+
}
|
|
229
|
+
// by-title alias — skip when title slugs to empty (`slugifyAlias` returns
|
|
230
|
+
// the literal `'untitled'` sentinel in that case).
|
|
231
|
+
if (title && slugifies(title)) {
|
|
232
|
+
paths.push(linearByTitleAliasPath(ISSUES_SCOPE, title, id));
|
|
233
|
+
}
|
|
234
|
+
// by-state alias — only when both state and identifier are present, since
|
|
235
|
+
// the alias filename is the identifier (Linear's `slugifyStateName`
|
|
236
|
+
// helper throws on empty input).
|
|
237
|
+
if (stateName && identifier) {
|
|
238
|
+
paths.push(linearIssueByStatePath(stateName, identifier));
|
|
239
|
+
}
|
|
240
|
+
return paths;
|
|
241
|
+
}
|
|
242
|
+
function readIssueStateName(issue) {
|
|
243
|
+
return readNonEmptyString(issue.state?.name);
|
|
244
|
+
}
|
|
245
|
+
function toIssueNode(issue) {
|
|
246
|
+
return {
|
|
247
|
+
id: issue.id,
|
|
248
|
+
identifier: issue.identifier ?? null,
|
|
249
|
+
title: issue.title ?? null,
|
|
250
|
+
state: issue.state
|
|
251
|
+
? { name: issue.state.name ?? null, type: issue.state.type ?? null }
|
|
252
|
+
: null,
|
|
253
|
+
updatedAt: issue.updatedAt ?? null,
|
|
254
|
+
createdAt: issue.createdAt ?? null,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
// -- comments ---------------------------------------------------------------
|
|
258
|
+
async function emitComments(client, workspaceId, records, connectionId) {
|
|
259
|
+
const indexReconciler = new IndexFileReconciler({
|
|
260
|
+
client,
|
|
261
|
+
workspaceId,
|
|
262
|
+
path: linearCommentsIndexPath(),
|
|
263
|
+
builder: (rows) => ({
|
|
264
|
+
path: linearCommentsIndexPath(),
|
|
265
|
+
content: `${JSON.stringify([...rows].sort(compareIndexRows))}\n`,
|
|
266
|
+
contentType: JSON_CONTENT_TYPE,
|
|
267
|
+
}),
|
|
268
|
+
});
|
|
269
|
+
const fanOut = await runEmitBatch(client, workspaceId, records, async (record) => {
|
|
270
|
+
if (isDeleteRecord(record)) {
|
|
271
|
+
indexReconciler.remove(record.id);
|
|
272
|
+
return { deletes: [{ path: linearCommentPath(record.id) }] };
|
|
273
|
+
}
|
|
274
|
+
const id = readNonEmptyString(record.id);
|
|
275
|
+
if (!id)
|
|
276
|
+
return {};
|
|
277
|
+
const humanReadable = readNonEmptyString(record.issue?.identifier) ?? readNonEmptyString(record.body ?? undefined);
|
|
278
|
+
const path = linearCommentPath(id, humanReadable);
|
|
279
|
+
indexReconciler.upsert(linearCommentIndexRow(toCommentNode(record)));
|
|
280
|
+
return {
|
|
281
|
+
writes: [
|
|
282
|
+
{
|
|
283
|
+
path,
|
|
284
|
+
content: renderContent('comment', record, connectionId, false),
|
|
285
|
+
contentType: JSON_CONTENT_TYPE,
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
};
|
|
289
|
+
});
|
|
290
|
+
const indexResult = await indexReconciler.flush();
|
|
291
|
+
fanOut.written += indexResult.written;
|
|
292
|
+
fanOut.errors.push(...indexResult.errors);
|
|
293
|
+
return fanOut;
|
|
294
|
+
}
|
|
295
|
+
function toCommentNode(comment) {
|
|
296
|
+
return {
|
|
297
|
+
id: comment.id,
|
|
298
|
+
body: comment.body ?? null,
|
|
299
|
+
issue: comment.issue
|
|
300
|
+
? {
|
|
301
|
+
id: comment.issue.id ?? null,
|
|
302
|
+
identifier: comment.issue.identifier ?? null,
|
|
303
|
+
title: comment.issue.title ?? null,
|
|
304
|
+
url: comment.issue.url ?? null,
|
|
305
|
+
}
|
|
306
|
+
: null,
|
|
307
|
+
updatedAt: comment.updatedAt ?? null,
|
|
308
|
+
createdAt: comment.createdAt ?? null,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
// -- users / teams / projects / cycles / milestones / roadmaps -------------
|
|
312
|
+
async function emitUsers(client, workspaceId, records, connectionId) {
|
|
313
|
+
return emitFlatResource(client, workspaceId, records, {
|
|
314
|
+
indexPath: linearUsersIndexPath(),
|
|
315
|
+
canonicalPath: (id) => linearUserPath(id),
|
|
316
|
+
indexRow: (record) => linearUserIndexRow(record),
|
|
317
|
+
objectType: 'user',
|
|
318
|
+
connectionId,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
async function emitTeams(client, workspaceId, records, connectionId) {
|
|
322
|
+
return emitFlatResource(client, workspaceId, records, {
|
|
323
|
+
indexPath: linearTeamsIndexPath(),
|
|
324
|
+
canonicalPath: (id) => linearTeamPath(id),
|
|
325
|
+
indexRow: (record) => linearTeamIndexRow(record),
|
|
326
|
+
objectType: 'team',
|
|
327
|
+
connectionId,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
async function emitProjects(client, workspaceId, records, connectionId) {
|
|
331
|
+
// Projects don't ship an `_index.json` in the current adapter (no
|
|
332
|
+
// index-emitter bucket), so we only emit the canonical record.
|
|
333
|
+
return emitCanonicalOnlyResource(client, workspaceId, records, {
|
|
334
|
+
canonicalPath: (id) => linearProjectPath(id),
|
|
335
|
+
objectType: 'project',
|
|
336
|
+
connectionId,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
async function emitCycles(client, workspaceId, records, connectionId) {
|
|
340
|
+
return emitCanonicalOnlyResource(client, workspaceId, records, {
|
|
341
|
+
canonicalPath: (id) => linearCyclePath(id),
|
|
342
|
+
objectType: 'cycle',
|
|
343
|
+
connectionId,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
async function emitMilestones(client, workspaceId, records, connectionId) {
|
|
347
|
+
return emitCanonicalOnlyResource(client, workspaceId, records, {
|
|
348
|
+
canonicalPath: (id) => linearMilestonePath(id),
|
|
349
|
+
objectType: 'milestone',
|
|
350
|
+
connectionId,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
async function emitRoadmaps(client, workspaceId, records, connectionId) {
|
|
354
|
+
return emitCanonicalOnlyResource(client, workspaceId, records, {
|
|
355
|
+
canonicalPath: (id) => linearRoadmapPath(id),
|
|
356
|
+
objectType: 'roadmap',
|
|
357
|
+
connectionId,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
async function emitFlatResource(client, workspaceId, records, opts) {
|
|
361
|
+
const indexReconciler = new IndexFileReconciler({
|
|
362
|
+
client,
|
|
363
|
+
workspaceId,
|
|
364
|
+
path: opts.indexPath,
|
|
365
|
+
builder: (rows) => ({
|
|
366
|
+
path: opts.indexPath,
|
|
367
|
+
content: `${JSON.stringify([...rows].sort(compareIndexRows))}\n`,
|
|
368
|
+
contentType: JSON_CONTENT_TYPE,
|
|
369
|
+
}),
|
|
370
|
+
});
|
|
371
|
+
const fanOut = await runEmitBatch(client, workspaceId, records, async (record) => {
|
|
372
|
+
if (isDeleteRecord(record)) {
|
|
373
|
+
indexReconciler.remove(record.id);
|
|
374
|
+
return { deletes: [{ path: opts.canonicalPath(record.id) }] };
|
|
375
|
+
}
|
|
376
|
+
const id = readNonEmptyString(record.id);
|
|
377
|
+
if (!id)
|
|
378
|
+
return {};
|
|
379
|
+
indexReconciler.upsert(opts.indexRow(record));
|
|
380
|
+
return {
|
|
381
|
+
writes: [
|
|
382
|
+
{
|
|
383
|
+
path: opts.canonicalPath(id),
|
|
384
|
+
content: renderContent(opts.objectType, record, opts.connectionId, false),
|
|
385
|
+
contentType: JSON_CONTENT_TYPE,
|
|
386
|
+
},
|
|
387
|
+
],
|
|
388
|
+
};
|
|
389
|
+
});
|
|
390
|
+
const indexResult = await indexReconciler.flush();
|
|
391
|
+
fanOut.written += indexResult.written;
|
|
392
|
+
fanOut.errors.push(...indexResult.errors);
|
|
393
|
+
return fanOut;
|
|
394
|
+
}
|
|
395
|
+
async function emitCanonicalOnlyResource(client, workspaceId, records, opts) {
|
|
396
|
+
return runEmitBatch(client, workspaceId, records, async (record) => {
|
|
397
|
+
if (isDeleteRecord(record)) {
|
|
398
|
+
return { deletes: [{ path: opts.canonicalPath(record.id) }] };
|
|
399
|
+
}
|
|
400
|
+
const id = readNonEmptyString(record.id);
|
|
401
|
+
if (!id)
|
|
402
|
+
return {};
|
|
403
|
+
return {
|
|
404
|
+
writes: [
|
|
405
|
+
{
|
|
406
|
+
path: opts.canonicalPath(id),
|
|
407
|
+
content: renderContent(opts.objectType, record, opts.connectionId, false),
|
|
408
|
+
contentType: JSON_CONTENT_TYPE,
|
|
409
|
+
},
|
|
410
|
+
],
|
|
411
|
+
};
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
// -- shared helpers ---------------------------------------------------------
|
|
415
|
+
function renderContent(objectType, payload, connectionId, deleted) {
|
|
416
|
+
return JSON.stringify({
|
|
417
|
+
provider: LINEAR_PROVIDER_NAME,
|
|
418
|
+
objectType,
|
|
419
|
+
objectId: payload.id,
|
|
420
|
+
deleted,
|
|
421
|
+
payload,
|
|
422
|
+
...(connectionId ? { connectionId } : {}),
|
|
423
|
+
}, null, 2);
|
|
424
|
+
}
|
|
425
|
+
function compareIndexRows(left, right) {
|
|
426
|
+
if (left.updated !== right.updated) {
|
|
427
|
+
return right.updated.localeCompare(left.updated);
|
|
428
|
+
}
|
|
429
|
+
return left.id.localeCompare(right.id);
|
|
430
|
+
}
|
|
431
|
+
function diffPaths(prior, next) {
|
|
432
|
+
const nextSet = new Set(next);
|
|
433
|
+
const seen = new Set();
|
|
434
|
+
const stale = [];
|
|
435
|
+
for (const p of prior) {
|
|
436
|
+
if (!nextSet.has(p) && !seen.has(p)) {
|
|
437
|
+
seen.add(p);
|
|
438
|
+
stale.push(p);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return stale;
|
|
442
|
+
}
|
|
443
|
+
function pickPayload(parsed) {
|
|
444
|
+
const wrapped = parsed.payload;
|
|
445
|
+
if (isRecord(wrapped)) {
|
|
446
|
+
return wrapped;
|
|
447
|
+
}
|
|
448
|
+
return parsed;
|
|
449
|
+
}
|
|
450
|
+
function isDeleteRecord(record) {
|
|
451
|
+
return (isRecord(record) &&
|
|
452
|
+
record._deleted === true &&
|
|
453
|
+
typeof record.id === 'string');
|
|
454
|
+
}
|
|
455
|
+
function readNonEmptyString(value) {
|
|
456
|
+
if (typeof value !== 'string')
|
|
457
|
+
return undefined;
|
|
458
|
+
const trimmed = value.trim();
|
|
459
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
460
|
+
}
|
|
461
|
+
function isRecord(value) {
|
|
462
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Skip by-title aliases for titles that slug to nothing (emoji-only /
|
|
466
|
+
* punctuation-only). The by-id alias still resolves those records.
|
|
467
|
+
*
|
|
468
|
+
* Delegates to the shared `slugifyAlias` per AGENTS.md "NEVER write a
|
|
469
|
+
* new slugifier" rule. `slugifyAlias` returns the literal string
|
|
470
|
+
* `'untitled'` as its empty-slug sentinel.
|
|
471
|
+
*/
|
|
472
|
+
function slugifies(value) {
|
|
473
|
+
return slugifyAlias(value) !== 'untitled';
|
|
474
|
+
}
|
|
475
|
+
function accumulate(aggregate, partial) {
|
|
476
|
+
aggregate.written += partial.written;
|
|
477
|
+
aggregate.deleted += partial.deleted;
|
|
478
|
+
if (partial.errors.length > 0) {
|
|
479
|
+
aggregate.errors.push(...partial.errors);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
//# sourceMappingURL=emit-auxiliary-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-auxiliary-files.js","sourceRoot":"","sources":["../src/emit-auxiliary-files.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,12 @@ export * from './linear-adapter.js';
|
|
|
2
2
|
export * from './index-emitter.js';
|
|
3
3
|
export * from './layout-prompt.js';
|
|
4
4
|
export * from './path-mapper.js';
|
|
5
|
+
export * from './summary.js';
|
|
6
|
+
export * from './thread.js';
|
|
5
7
|
export * from './webhook-normalizer.js';
|
|
6
8
|
export * from './types.js';
|
|
7
9
|
export * from './queries.js';
|
|
8
10
|
export * from './writeback.js';
|
|
11
|
+
export * from './emit-auxiliary-files.js';
|
|
9
12
|
export * from './resources.js';
|
|
10
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAE1C,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,12 @@ export * from './linear-adapter.js';
|
|
|
3
3
|
export * from './index-emitter.js';
|
|
4
4
|
export * from './layout-prompt.js';
|
|
5
5
|
export * from './path-mapper.js';
|
|
6
|
+
export * from './summary.js';
|
|
7
|
+
export * from './thread.js';
|
|
6
8
|
export * from './webhook-normalizer.js';
|
|
7
9
|
export * from './types.js';
|
|
8
10
|
export * from './queries.js';
|
|
9
11
|
export * from './writeback.js';
|
|
12
|
+
export * from './emit-auxiliary-files.js';
|
|
10
13
|
export * from './resources.js';
|
|
11
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAE1C,cAAc,gBAAgB,CAAC"}
|
package/dist/layout-prompt.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const LINEAR_LAYOUT_PROMPT = "# Linear Mount Layout\n\nAlways run `ls` before constructing a path. PR 0 standardizes human-readable leaf names to `<sanitized-name>__<id>`, so consumers should inspect the live directory instead of guessing a filename.\n\n## Tree\n\n`/linear/LAYOUT.md` is this guide.\n`/linear/issues/`, `/linear/comments/`, `/linear/users/`, and `/linear/teams/` each own their canonical JSON records plus a sibling `_index.json`.\nOther integration-owned trees include `/linear/projects/`, `/linear/cycles/`, `/linear/milestones/`, and `/linear/roadmaps/`.\n\n## Indexes\n\n`/linear/issues/_index.json` rows use:\n\n```json\n{ \"id\": \"<id>\", \"title\": \"<human-readable>\", \"updated\": \"<iso8601>\", \"identifier\": \"<TEAM-123>\", \"state\": \"<state name>\" }\n```\n\n`/linear/comments/_index.json`, `/linear/users/_index.json`, and `/linear/teams/_index.json` use:\n\n```json\n{ \"id\": \"<id>\", \"title\": \"<human-readable>\", \"updated\": \"<iso8601>\" }\n```\n\n## JSONL And Querying\n\nLinear does not emit JSONL in this adapter today. Comments are individual `.json` records rather than `comments.jsonl`.\n\nExamples:\n\n```bash\nls /linear/issues\njq '.[0]' /linear/issues/_index.json\njq '.[] | {identifier, state, title}' /linear/issues/_index.json\ngrep -R \"ENG-\" /linear/comments\n```\n";
|
|
1
|
+
export declare const LINEAR_LAYOUT_PROMPT = "# Linear Mount Layout\n\nAlways run `ls` before constructing a path. PR 0 standardizes human-readable leaf names to `<sanitized-name>__<id>`, so consumers should inspect the live directory instead of guessing a filename.\n\n## Tree\n\n`/linear/LAYOUT.md` is this guide.\n`/linear/issues/`, `/linear/comments/`, `/linear/users/`, and `/linear/teams/` each own their canonical JSON records plus a sibling `_index.json`.\nOther integration-owned trees include `/linear/projects/`, `/linear/cycles/`, `/linear/milestones/`, and `/linear/roadmaps/`.\n\nIssue lookups: `/linear/issues/by-uuid/<uuid>.json` is the stable anchor (always emitted, keyed on the Linear UUID). `/linear/issues/by-id/<TEAM-123>.json` is the human-readable lookup keyed on the Linear identifier (only emitted when the issue has one). `/linear/issues/by-title/<slug>.json` and `/linear/issues/by-state/<state>/<TEAM-123>.json` are additional lookups.\n\n## Indexes\n\n`/linear/issues/_index.json` rows use:\n\n```json\n{ \"id\": \"<id>\", \"title\": \"<human-readable>\", \"updated\": \"<iso8601>\", \"identifier\": \"<TEAM-123>\", \"state\": \"<state name>\" }\n```\n\n`/linear/comments/_index.json`, `/linear/users/_index.json`, and `/linear/teams/_index.json` use:\n\n```json\n{ \"id\": \"<id>\", \"title\": \"<human-readable>\", \"updated\": \"<iso8601>\" }\n```\n\n## JSONL And Querying\n\nLinear does not emit JSONL in this adapter today. Comments are individual `.json` records rather than `comments.jsonl`.\n\nExamples:\n\n```bash\nls /linear/issues\njq '.[0]' /linear/issues/_index.json\njq '.[] | {identifier, state, title}' /linear/issues/_index.json\ngrep -R \"ENG-\" /linear/comments\n```\n";
|
|
2
2
|
export declare function linearLayoutPromptFile(): {
|
|
3
3
|
path: string;
|
|
4
4
|
contentType: "text/markdown; charset=utf-8";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-prompt.d.ts","sourceRoot":"","sources":["../src/layout-prompt.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"layout-prompt.d.ts","sourceRoot":"","sources":["../src/layout-prompt.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,4oDAsChC,CAAC;AAEF,wBAAgB,sBAAsB;;;;EAMrC"}
|
package/dist/layout-prompt.js
CHANGED
|
@@ -8,6 +8,8 @@ Always run \`ls\` before constructing a path. PR 0 standardizes human-readable l
|
|
|
8
8
|
\`/linear/issues/\`, \`/linear/comments/\`, \`/linear/users/\`, and \`/linear/teams/\` each own their canonical JSON records plus a sibling \`_index.json\`.
|
|
9
9
|
Other integration-owned trees include \`/linear/projects/\`, \`/linear/cycles/\`, \`/linear/milestones/\`, and \`/linear/roadmaps/\`.
|
|
10
10
|
|
|
11
|
+
Issue lookups: \`/linear/issues/by-uuid/<uuid>.json\` is the stable anchor (always emitted, keyed on the Linear UUID). \`/linear/issues/by-id/<TEAM-123>.json\` is the human-readable lookup keyed on the Linear identifier (only emitted when the issue has one). \`/linear/issues/by-title/<slug>.json\` and \`/linear/issues/by-state/<state>/<TEAM-123>.json\` are additional lookups.
|
|
12
|
+
|
|
11
13
|
## Indexes
|
|
12
14
|
|
|
13
15
|
\`/linear/issues/_index.json\` rows use:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-prompt.js","sourceRoot":"","sources":["../src/layout-prompt.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG
|
|
1
|
+
{"version":3,"file":"layout-prompt.js","sourceRoot":"","sources":["../src/layout-prompt.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCnC,CAAC;AAEF,MAAM,UAAU,sBAAsB;IACpC,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,8BAAuC;QACpD,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,oBAAoB,IAAI;KAClG,CAAC;AACJ,CAAC"}
|
package/dist/path-mapper.d.ts
CHANGED
|
@@ -32,5 +32,16 @@ export declare function linearMilestonePath(milestoneId: string): string;
|
|
|
32
32
|
export declare function linearRoadmapPath(roadmapId: string): string;
|
|
33
33
|
export declare function linearByTitleAliasPath(scope: string, title: string, id: string, colliding?: boolean): string;
|
|
34
34
|
export declare function linearByIdAliasPath(scope: string, identifier: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Stable UUID-keyed alias for Linear records. Used as the reconciliation
|
|
37
|
+
* anchor when computing prior state, because the Linear UUID (`issue.id`)
|
|
38
|
+
* is always present even on bare delete tombstones, whereas the human-readable
|
|
39
|
+
* `identifier` (e.g. `TEAM-123`) may be missing on partial payloads or on
|
|
40
|
+
* issues that were created without one. The existing `linearByIdAliasPath`
|
|
41
|
+
* remains the human-readable lookup alias keyed on `identifier` when
|
|
42
|
+
* available — both are emitted side-by-side for issues so consumers can
|
|
43
|
+
* resolve a record by either key.
|
|
44
|
+
*/
|
|
45
|
+
export declare function linearByUuidAliasPath(scope: string, uuid: string): string;
|
|
35
46
|
export declare function computeLinearPath(objectType: string, objectId: string, humanReadable?: string): string;
|
|
36
47
|
//# sourceMappingURL=path-mapper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-mapper.d.ts","sourceRoot":"","sources":["../src/path-mapper.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAC1C,eAAO,MAAM,uBAAuB,iEAAkE,CAAC;AAEvG,eAAO,MAAM,mBAAmB,2FAStB,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AAID,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAmED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAuCD,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAa9G;AAGD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAmBvE;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAmC1D;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,CAOlF;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAMjG;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAI7E;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,yBAAyB,CAAC,EAAE,MAAM,EAClC,KAAK,CAAC,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,iBAAiB,GACvB,MAAM,CAGR;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEpF;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAE7G;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,MAAM,CAS1G;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAsBtG"}
|
|
1
|
+
{"version":3,"file":"path-mapper.d.ts","sourceRoot":"","sources":["../src/path-mapper.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAC1C,eAAO,MAAM,uBAAuB,iEAAkE,CAAC;AAEvG,eAAO,MAAM,mBAAmB,2FAStB,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AAID,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAmED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAuCD,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,MAAM,CAa9G;AAGD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAmBvE;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAmC1D;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,CAOlF;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAMjG;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAI7E;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,yBAAyB,CAAC,EAAE,MAAM,EAClC,KAAK,CAAC,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,iBAAiB,GACvB,MAAM,CAGR;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEpF;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAE7G;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,MAAM,CAS1G;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAsBtG"}
|
package/dist/path-mapper.js
CHANGED
|
@@ -243,6 +243,19 @@ export function linearByTitleAliasPath(scope, title, id, colliding = false) {
|
|
|
243
243
|
export function linearByIdAliasPath(scope, identifier) {
|
|
244
244
|
return `${scope}/by-id/${encodeLinearPathSegment(identifier)}.json`;
|
|
245
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Stable UUID-keyed alias for Linear records. Used as the reconciliation
|
|
248
|
+
* anchor when computing prior state, because the Linear UUID (`issue.id`)
|
|
249
|
+
* is always present even on bare delete tombstones, whereas the human-readable
|
|
250
|
+
* `identifier` (e.g. `TEAM-123`) may be missing on partial payloads or on
|
|
251
|
+
* issues that were created without one. The existing `linearByIdAliasPath`
|
|
252
|
+
* remains the human-readable lookup alias keyed on `identifier` when
|
|
253
|
+
* available — both are emitted side-by-side for issues so consumers can
|
|
254
|
+
* resolve a record by either key.
|
|
255
|
+
*/
|
|
256
|
+
export function linearByUuidAliasPath(scope, uuid) {
|
|
257
|
+
return `${scope}/by-uuid/${encodeLinearPathSegment(uuid)}.json`;
|
|
258
|
+
}
|
|
246
259
|
export function computeLinearPath(objectType, objectId, humanReadable) {
|
|
247
260
|
const normalizedType = normalizeLinearObjectType(objectType);
|
|
248
261
|
const normalizedId = assertNonEmptySegment(objectId, 'object id');
|