@relayfile/adapter-linear 0.2.3 → 0.2.4

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.
@@ -1,6 +1,6 @@
1
1
  import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { computeLinearPath, linearByIdAliasPath, linearByTitleAliasPath, normalizeLinearObjectType, normalizeNangoLinearModel, tryNormalizeLinearObjectType, } from '../path-mapper.js';
3
+ import { computeLinearPath, linearByIdAliasPath, linearByTitleAliasPath, linearByUuidAliasPath, normalizeLinearObjectType, normalizeNangoLinearModel, tryNormalizeLinearObjectType, } from '../path-mapper.js';
4
4
  describe('linear path-mapper', () => {
5
5
  describe('normalizeLinearObjectType', () => {
6
6
  it('accepts canonical types', () => {
@@ -61,5 +61,66 @@ describe('linear path-mapper', () => {
61
61
  assert.equal(linearByIdAliasPath('/linear/issues', 'AGE-8'), '/linear/issues/by-id/AGE-8.json');
62
62
  });
63
63
  });
64
+ // The reconciliation anchor introduced in bcb45996: keyed on the stable
65
+ // Linear UUID rather than the (possibly-absent) `TEAM-123` identifier.
66
+ // Per AGENTS.md every path-mapper helper needs round-trip coverage, and
67
+ // `by-uuid` is now load-bearing for delete tombstones — without these
68
+ // tests the next regression on the anchor would slip through CI.
69
+ describe('linearByUuidAliasPath', () => {
70
+ it('composes a stable by-uuid alias path under any scope', () => {
71
+ assert.equal(linearByUuidAliasPath('/linear/issues', '8a3c9b50-22f0-4d2c-a07d-7e02d2cf6f9e'), '/linear/issues/by-uuid/8a3c9b50-22f0-4d2c-a07d-7e02d2cf6f9e.json');
72
+ // Also works for project scope so future adapters reusing the helper
73
+ // don't accidentally hardcode the issues path.
74
+ assert.equal(linearByUuidAliasPath('/linear/projects', 'proj-uuid-1'), '/linear/projects/by-uuid/proj-uuid-1.json');
75
+ });
76
+ it('round-trips: the leaf segment decodes back to the source UUID', () => {
77
+ const uuid = '8a3c9b50-22f0-4d2c-a07d-7e02d2cf6f9e';
78
+ const composed = linearByUuidAliasPath('/linear/issues', uuid);
79
+ const leaf = composed.split('/').pop().replace(/\.json$/u, '');
80
+ assert.equal(decodeURIComponent(leaf), uuid);
81
+ });
82
+ it('percent-encodes UUIDs containing characters that need escaping', () => {
83
+ // Linear UUIDs are well-formed today, but the helper must defend
84
+ // against operator-supplied scope+id pairs that include reserved
85
+ // URI characters — otherwise `by-uuid` becomes a foot-gun the day
86
+ // someone calls it with a slug-like input.
87
+ const messyId = 'team/id with spaces';
88
+ const composed = linearByUuidAliasPath('/linear/issues', messyId);
89
+ const leaf = composed.split('/').pop().replace(/\.json$/u, '');
90
+ assert.equal(decodeURIComponent(leaf), messyId);
91
+ });
92
+ // AGENTS.md: every alias subtree needs a collision test. `by-uuid` keys
93
+ // only on the stable UUID, so the "collision" semantics here are the
94
+ // inverse of by-title/by-id: distinct UUIDs MUST produce distinct paths
95
+ // (the subtree's whole job is unambiguous lookup by uuid), and the same
96
+ // UUID MUST map to the same path regardless of any other field — that's
97
+ // what makes by-uuid the reconciliation anchor in the first place.
98
+ it('distinct UUIDs always produce distinct alias paths (no false collisions)', () => {
99
+ const uuidA = '8a3c9b50-22f0-4d2c-a07d-7e02d2cf6f9e';
100
+ const uuidB = 'f0e1d2c3-b4a5-9687-7869-5a4b3c2d1e0f';
101
+ const pathA = linearByUuidAliasPath('/linear/issues', uuidA);
102
+ const pathB = linearByUuidAliasPath('/linear/issues', uuidB);
103
+ assert.notEqual(pathA, pathB);
104
+ });
105
+ it('same UUID maps to the same path (idempotent — by-uuid is the rename-stable anchor)', () => {
106
+ // This is the property that lets `planIssueDelete` and the
107
+ // reconciliation read in `planIssueWrite` find prior state from a
108
+ // tombstone that carries only `{ id, _deleted: true }`. If the path
109
+ // shifted with identifier / title / state, the by-uuid anchor
110
+ // would be useless and bcb45996 wouldn't fix anything.
111
+ const uuid = '8a3c9b50-22f0-4d2c-a07d-7e02d2cf6f9e';
112
+ assert.equal(linearByUuidAliasPath('/linear/issues', uuid), linearByUuidAliasPath('/linear/issues', uuid));
113
+ });
114
+ it('keeps distinct paths across scopes for the same UUID (cross-scope safety)', () => {
115
+ // A UUID that happens to be reused across resource types (rare but
116
+ // not impossible if an operator reuses an id from one scope as a
117
+ // tombstone for another) must NOT alias to the same path. The
118
+ // `scope` prefix is what guarantees this — the test pins it.
119
+ const uuid = '8a3c9b50-22f0-4d2c-a07d-7e02d2cf6f9e';
120
+ const issueScope = linearByUuidAliasPath('/linear/issues', uuid);
121
+ const projectScope = linearByUuidAliasPath('/linear/projects', uuid);
122
+ assert.notEqual(issueScope, projectScope);
123
+ });
124
+ });
64
125
  });
65
126
  //# sourceMappingURL=path-mapper.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-mapper.test.js","sourceRoot":"","sources":["../../src/__tests__/path-mapper.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"path-mapper.test.js","sourceRoot":"","sources":["../../src/__tests__/path-mapper.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
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 { type AuxiliaryEmitterClient, type EmitAuxiliaryFilesResult } from '@relayfile/adapter-core';
54
+ import type { LinearComment, LinearCycle, LinearIssue, LinearMilestone, LinearProject, LinearRoadmap, LinearTeam, LinearUser } from './types.js';
55
+ /**
56
+ * Records accepted by `emitLinearAuxiliaryFiles`. Each entry is either a
57
+ * full domain object or a `{ id, _deleted: true }` tombstone. Mirrors the
58
+ * confluence shape so cloud's Phase 3 dispatcher routes uniformly.
59
+ */
60
+ export type LinearIssueEmitRecord = LinearIssue | {
61
+ id: string;
62
+ _deleted: true;
63
+ };
64
+ export type LinearCommentEmitRecord = LinearComment | {
65
+ id: string;
66
+ _deleted: true;
67
+ };
68
+ export type LinearUserEmitRecord = LinearUser | {
69
+ id: string;
70
+ _deleted: true;
71
+ };
72
+ export type LinearTeamEmitRecord = LinearTeam | {
73
+ id: string;
74
+ _deleted: true;
75
+ };
76
+ export type LinearProjectEmitRecord = LinearProject | {
77
+ id: string;
78
+ _deleted: true;
79
+ };
80
+ export type LinearCycleEmitRecord = LinearCycle | {
81
+ id: string;
82
+ _deleted: true;
83
+ };
84
+ export type LinearMilestoneEmitRecord = LinearMilestone | {
85
+ id: string;
86
+ _deleted: true;
87
+ };
88
+ export type LinearRoadmapEmitRecord = LinearRoadmap | {
89
+ id: string;
90
+ _deleted: true;
91
+ };
92
+ export interface LinearEmitAuxiliaryFilesInput {
93
+ workspaceId: string;
94
+ issues?: readonly LinearIssueEmitRecord[];
95
+ comments?: readonly LinearCommentEmitRecord[];
96
+ users?: readonly LinearUserEmitRecord[];
97
+ teams?: readonly LinearTeamEmitRecord[];
98
+ projects?: readonly LinearProjectEmitRecord[];
99
+ cycles?: readonly LinearCycleEmitRecord[];
100
+ milestones?: readonly LinearMilestoneEmitRecord[];
101
+ roadmaps?: readonly LinearRoadmapEmitRecord[];
102
+ /** Optional connection id wrapper field for downstream writeback routing. */
103
+ connectionId?: string;
104
+ }
105
+ /**
106
+ * Phase-2 entry point. Cloud's Phase-3 dispatcher iterates
107
+ * `(provider, records)` and calls this with a shimmed
108
+ * `AuxiliaryEmitterClient`.
109
+ */
110
+ export declare function emitLinearAuxiliaryFiles(client: AuxiliaryEmitterClient, input: LinearEmitAuxiliaryFilesInput): Promise<EmitAuxiliaryFilesResult>;
111
+ //# sourceMappingURL=emit-auxiliary-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-auxiliary-files.d.ts","sourceRoot":"","sources":["../src/emit-auxiliary-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,EAKL,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAI9B,MAAM,yBAAyB,CAAC;AAgCjC,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,WAAW,EACX,eAAe,EACf,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACX,MAAM,YAAY,CAAC;AAMpB;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AACjF,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AACrF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AAC/E,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AAC/E,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AACrF,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AACjF,MAAM,MAAM,yBAAyB,GAAG,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AACzF,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,CAAC;AAErF,MAAM,WAAW,6BAA6B;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC1C,QAAQ,CAAC,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC9C,KAAK,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACxC,KAAK,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACxC,QAAQ,CAAC,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC9C,MAAM,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC1C,UAAU,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAClD,QAAQ,CAAC,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC9C,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,wBAAwB,CAAC,CAoDnC"}