@on-par/factory-core 0.9.28-next.3 → 0.9.28-next.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.
- package/dist/work/index.d.ts +2 -2
- package/dist/work/index.d.ts.map +1 -1
- package/dist/work/index.js +4 -2
- package/dist/work/index.js.map +1 -1
- package/dist/work/linear-client.d.ts +21 -0
- package/dist/work/linear-client.d.ts.map +1 -0
- package/dist/work/linear-client.js +69 -0
- package/dist/work/linear-client.js.map +1 -0
- package/dist/work/linear-issue.d.ts +11 -0
- package/dist/work/linear-issue.d.ts.map +1 -0
- package/dist/work/linear-issue.js +69 -0
- package/dist/work/linear-issue.js.map +1 -0
- package/package.json +5 -5
package/dist/work/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { WorkKey } from './work-key.js';
|
|
|
3
3
|
import { type BriefFileReader } from './local-brief.js';
|
|
4
4
|
export * from './work-key.js';
|
|
5
5
|
/** Registered input sources. Open-ended by design — adapters register by string key. */
|
|
6
|
-
export type WorkRequestSourceKind = 'github-issue' | 'local-brief' | (string & {});
|
|
6
|
+
export type WorkRequestSourceKind = 'github-issue' | 'local-brief' | 'linear-issue' | (string & {});
|
|
7
7
|
/** Source-native lifecycle state, for sources that have one. */
|
|
8
8
|
export type WorkRequestState = 'open' | 'closed';
|
|
9
9
|
/** Where the request came from, for traceability back to the native artifact. */
|
|
@@ -61,7 +61,7 @@ export declare class WorkSourceRegistry {
|
|
|
61
61
|
kinds(): WorkRequestSourceKind[];
|
|
62
62
|
resolve(kind: WorkRequestSourceKind, params: unknown): Promise<WorkRequest>;
|
|
63
63
|
}
|
|
64
|
-
/** Registry with the built-in input sources — GitHub issue + local Markdown brief
|
|
64
|
+
/** Registry with the built-in input sources — GitHub issue + local Markdown brief + Linear issue (lazy: no env/network until resolve). */
|
|
65
65
|
export declare function createDefaultWorkSourceRegistry(deps: {
|
|
66
66
|
octokit: Octokit;
|
|
67
67
|
briefReader?: BriefFileReader;
|
package/dist/work/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/work/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/work/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,KAAK,eAAe,EAAgD,MAAM,kBAAkB,CAAC;AAEtG,cAAc,eAAe,CAAC;AAE9B,wFAAwF;AACxF,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,aAAa,GAAG,cAAc,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAEpG,gEAAgE;AAChE,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEjD,iFAAiF;AACjF,MAAM,WAAW,oBAAoB;IACnC,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,mFAAmF;AACnF,MAAM,WAAW,WAAW;IAC1B,0FAA0F;IAC1F,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,qBAAqB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B;qFACiF;IACjF,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,mGAAmG;IACnG,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAChD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,qBAAqB,EAAE,CAAC;IAC5C,YAAY,IAAI,EAAE,qBAAqB,EAAE,SAAS,EAAE,SAAS,qBAAqB,EAAE,EAMnF;CACF;AAED,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,YAAY,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAItD;CACF;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IAEjE,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAGzC;IAED,GAAG,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAExC;IAED,+CAA+C;IAC/C,KAAK,IAAI,qBAAqB,EAAE,CAE/B;IAEK,OAAO,CAAC,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAMhF;CACF;AAED,0IAA0I;AAC1I,wBAAgB,+BAA+B,CAAC,IAAI,EAAE;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,GAAG,kBAAkB,CAKrB;AAED;;+CAE+C;AAC/C,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAGrE"}
|
package/dist/work/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// packages/core/src/work/index.ts — Canonical work request + input-source seam (#505).
|
|
2
2
|
import { createGithubIssueAdapter, createOctokitIssueClient } from './github-issue.js';
|
|
3
|
+
import { createLinearIssueAdapter } from './linear-issue.js';
|
|
3
4
|
import { createFsBriefReader, createLocalBriefAdapter } from './local-brief.js';
|
|
4
5
|
export * from './work-key.js';
|
|
5
6
|
export class UnsupportedWorkSourceError extends Error {
|
|
@@ -43,11 +44,12 @@ export class WorkSourceRegistry {
|
|
|
43
44
|
return adapter.resolve(params);
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
|
-
/** Registry with the built-in input sources — GitHub issue + local Markdown brief
|
|
47
|
+
/** Registry with the built-in input sources — GitHub issue + local Markdown brief + Linear issue (lazy: no env/network until resolve). */
|
|
47
48
|
export function createDefaultWorkSourceRegistry(deps) {
|
|
48
49
|
return new WorkSourceRegistry()
|
|
49
50
|
.register(createGithubIssueAdapter(createOctokitIssueClient(deps.octokit)))
|
|
50
|
-
.register(createLocalBriefAdapter(deps.briefReader ?? createFsBriefReader()))
|
|
51
|
+
.register(createLocalBriefAdapter(deps.briefReader ?? createFsBriefReader()))
|
|
52
|
+
.register(createLinearIssueAdapter());
|
|
51
53
|
}
|
|
52
54
|
/** The reason to refuse this work before committing any resource, or null to proceed.
|
|
53
55
|
* Deliberately fails open: only the literal 'closed' skips, so an absent or unknown
|
package/dist/work/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/work/index.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAIvF,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/work/index.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAIvF,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,EAAwB,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEtG,cAAc,eAAe,CAAC;AAgD9B,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,CAAwB;IAC5B,SAAS,CAA0B;IAC5C,YAAY,IAA2B,EAAE,SAA2C;QAClF,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAClE,KAAK,CAAC,oCAAoC,IAAI,2BAA2B,IAAI,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IAC5C,IAAI,CAAwB;IACrC,YAAY,IAA2B,EAAE,MAAc;QACrD,KAAK,CAAC,0CAA0C,IAAI,MAAM,MAAM,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,kBAAkB;IACZ,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAC;IAEjE,+DAA+D;IAC/D,QAAQ,CAAC,OAA0B;QACjC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,IAA2B;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,+CAA+C;IAC/C,KAAK;QACH,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAA2B,EAAE,MAAe;QACxD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;CACF;AAED,0IAA0I;AAC1I,MAAM,UAAU,+BAA+B,CAAC,IAG/C;IACC,OAAO,IAAI,kBAAkB,EAAE;SAC5B,QAAQ,CAAC,wBAAwB,CAAC,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;SAC1E,QAAQ,CAAC,uBAAuB,CAAC,IAAI,CAAC,WAAW,IAAI,mBAAmB,EAAE,CAAC,CAAC;SAC5E,QAAQ,CAAC,wBAAwB,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED;;+CAE+C;AAC/C,MAAM,UAAU,oBAAoB,CAAC,IAAiB;IACpD,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,GAAG,IAAI,CAAC,EAAE,uFAAuF,CAAC;AAC3G,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type LinearIssueRecord = {
|
|
2
|
+
id: string;
|
|
3
|
+
identifier: string;
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
url: string;
|
|
7
|
+
stateType: string;
|
|
8
|
+
labels: string[];
|
|
9
|
+
};
|
|
10
|
+
export declare class LinearApiError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare function createLinearClient(opts: {
|
|
14
|
+
apiKey: string;
|
|
15
|
+
fetch?: typeof globalThis.fetch;
|
|
16
|
+
endpoint?: string;
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
}): {
|
|
19
|
+
fetchIssue(ref: string): Promise<LinearIssueRecord>;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=linear-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-client.d.ts","sourceRoot":"","sources":["../../src/work/linear-client.ts"],"names":[],"mappings":"AA6BA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,qBAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG;IAAE,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;CAAE,CAsC1D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// packages/core/src/work/linear-client.ts — read-only Linear GraphQL client (#3889).
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
const LINEAR_GRAPHQL_ENDPOINT = 'https://api.linear.app/graphql';
|
|
4
|
+
const ISSUE_QUERY = `query FactoryIssue($id: String!) {
|
|
5
|
+
issue(id: $id) {
|
|
6
|
+
id identifier title description url
|
|
7
|
+
state { type }
|
|
8
|
+
labels { nodes { name } }
|
|
9
|
+
}
|
|
10
|
+
}`;
|
|
11
|
+
const IssueSchema = z.object({
|
|
12
|
+
id: z.string().min(1),
|
|
13
|
+
identifier: z.string().min(1),
|
|
14
|
+
title: z.string(),
|
|
15
|
+
description: z.string().nullable().optional(),
|
|
16
|
+
url: z.url(),
|
|
17
|
+
state: z.object({ type: z.string() }),
|
|
18
|
+
labels: z.object({ nodes: z.array(z.object({ name: z.string() })) }),
|
|
19
|
+
});
|
|
20
|
+
const ResponseSchema = z.object({
|
|
21
|
+
data: z.object({ issue: IssueSchema.nullable() }).nullable().optional(),
|
|
22
|
+
errors: z.array(z.object({ message: z.string() })).optional(),
|
|
23
|
+
});
|
|
24
|
+
export class LinearApiError extends Error {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'LinearApiError';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function createLinearClient(opts) {
|
|
31
|
+
const fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
32
|
+
return {
|
|
33
|
+
async fetchIssue(ref) {
|
|
34
|
+
const res = await fetchImpl(opts.endpoint ?? LINEAR_GRAPHQL_ENDPOINT, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers: { 'Content-Type': 'application/json', Authorization: opts.apiKey },
|
|
37
|
+
body: JSON.stringify({ query: ISSUE_QUERY, variables: { id: ref } }),
|
|
38
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? 30_000),
|
|
39
|
+
});
|
|
40
|
+
if (!res.ok) {
|
|
41
|
+
throw new LinearApiError(`Linear API returned HTTP ${res.status} for ${ref}`);
|
|
42
|
+
}
|
|
43
|
+
const parsed = ResponseSchema.safeParse(await res.json());
|
|
44
|
+
if (!parsed.success) {
|
|
45
|
+
const first = parsed.error.issues[0];
|
|
46
|
+
const where = first ? `${first.path.join('.')}: ${first.message}` : 'unknown';
|
|
47
|
+
throw new LinearApiError(`malformed Linear response for ${ref}: ${where}`);
|
|
48
|
+
}
|
|
49
|
+
const { data, errors } = parsed.data;
|
|
50
|
+
if (errors && errors.length > 0) {
|
|
51
|
+
throw new LinearApiError(`Linear API error for ${ref}: ${errors.map((e) => e.message).join('; ')}`);
|
|
52
|
+
}
|
|
53
|
+
const issue = data?.issue;
|
|
54
|
+
if (issue == null) {
|
|
55
|
+
throw new LinearApiError(`Linear issue ${ref} not found`);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
id: issue.id,
|
|
59
|
+
identifier: issue.identifier,
|
|
60
|
+
title: issue.title,
|
|
61
|
+
description: issue.description ?? '',
|
|
62
|
+
url: issue.url,
|
|
63
|
+
stateType: issue.state.type,
|
|
64
|
+
labels: issue.labels.nodes.map((l) => l.name),
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=linear-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-client.js","sourceRoot":"","sources":["../../src/work/linear-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type WorkSourceAdapter } from './index.js';
|
|
2
|
+
export declare const LINEAR_ISSUE_SOURCE = "linear-issue";
|
|
3
|
+
export interface LinearIssueSourceDeps {
|
|
4
|
+
fetch?: typeof globalThis.fetch;
|
|
5
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
6
|
+
endpoint?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Turns "ON-12" or a linear.app issue URL into the upper-cased issue key. */
|
|
9
|
+
export declare function parseLinearIssueRef(input: string): string;
|
|
10
|
+
export declare function createLinearIssueAdapter(deps?: LinearIssueSourceDeps): WorkSourceAdapter;
|
|
11
|
+
//# sourceMappingURL=linear-issue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-issue.d.ts","sourceRoot":"","sources":["../../src/work/linear-issue.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkD,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAIpG,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAOlD,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAOD,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAazD;AAUD,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,qBAA0B,GAAG,iBAAiB,CA2B5F"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// packages/core/src/work/linear-issue.ts — read-only Linear issue input-source adapter (#3889).
|
|
2
|
+
import { extractAcceptanceCriteria } from './acceptance.js';
|
|
3
|
+
import { InvalidWorkRequestInputError } from './index.js';
|
|
4
|
+
import { createLinearClient } from './linear-client.js';
|
|
5
|
+
import { toWorkKey } from './work-key.js';
|
|
6
|
+
export const LINEAR_ISSUE_SOURCE = 'linear-issue';
|
|
7
|
+
const EXPECTED_FORM = 'expected a Linear issue key like "ON-12" or a URL like https://linear.app/<workspace>/issue/ON-12';
|
|
8
|
+
const KEY_RE = /^[A-Za-z][A-Za-z0-9]*-[1-9]\d*$/;
|
|
9
|
+
const CLOSED_STATE_TYPES = new Set(['completed', 'canceled']);
|
|
10
|
+
function usageError(input) {
|
|
11
|
+
const shown = input.length > 200 ? `${input.slice(0, 200)}…` : input;
|
|
12
|
+
return new InvalidWorkRequestInputError(LINEAR_ISSUE_SOURCE, `${EXPECTED_FORM}, got "${shown}"`);
|
|
13
|
+
}
|
|
14
|
+
/** Turns "ON-12" or a linear.app issue URL into the upper-cased issue key. */
|
|
15
|
+
export function parseLinearIssueRef(input) {
|
|
16
|
+
const trimmed = input.trim();
|
|
17
|
+
if (KEY_RE.test(trimmed))
|
|
18
|
+
return trimmed.toUpperCase();
|
|
19
|
+
let url;
|
|
20
|
+
try {
|
|
21
|
+
url = new URL(trimmed);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw usageError(trimmed);
|
|
25
|
+
}
|
|
26
|
+
if (url.protocol !== 'https:' || url.hostname !== 'linear.app')
|
|
27
|
+
throw usageError(trimmed);
|
|
28
|
+
const [workspace, segment, key] = url.pathname.split('/').filter((s) => s !== '');
|
|
29
|
+
if (!workspace || segment !== 'issue' || key === undefined || !KEY_RE.test(key))
|
|
30
|
+
throw usageError(trimmed);
|
|
31
|
+
return key.toUpperCase();
|
|
32
|
+
}
|
|
33
|
+
function rawRef(params) {
|
|
34
|
+
if (typeof params === 'string')
|
|
35
|
+
return params;
|
|
36
|
+
if (typeof params === 'object' && params !== null && 'ref' in params && typeof params.ref === 'string') {
|
|
37
|
+
return params.ref;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
export function createLinearIssueAdapter(deps = {}) {
|
|
42
|
+
return {
|
|
43
|
+
kind: LINEAR_ISSUE_SOURCE,
|
|
44
|
+
async resolve(params) {
|
|
45
|
+
const raw = rawRef(params);
|
|
46
|
+
if (raw === undefined) {
|
|
47
|
+
throw new InvalidWorkRequestInputError(LINEAR_ISSUE_SOURCE, EXPECTED_FORM);
|
|
48
|
+
}
|
|
49
|
+
const ref = parseLinearIssueRef(raw);
|
|
50
|
+
const apiKey = (deps.env ?? process.env).LINEAR_API_KEY?.trim();
|
|
51
|
+
if (!apiKey) {
|
|
52
|
+
throw new Error('LINEAR_API_KEY is not set — export a Linear personal API key to resolve Linear issues');
|
|
53
|
+
}
|
|
54
|
+
const issue = await createLinearClient({ apiKey, fetch: deps.fetch, endpoint: deps.endpoint }).fetchIssue(ref);
|
|
55
|
+
return {
|
|
56
|
+
id: `${LINEAR_ISSUE_SOURCE}:${issue.identifier}`,
|
|
57
|
+
kind: LINEAR_ISSUE_SOURCE,
|
|
58
|
+
key: toWorkKey(issue.identifier),
|
|
59
|
+
title: issue.title,
|
|
60
|
+
brief: issue.description,
|
|
61
|
+
acceptanceCriteria: extractAcceptanceCriteria(issue.description),
|
|
62
|
+
state: CLOSED_STATE_TYPES.has(issue.stateType) ? 'closed' : 'open',
|
|
63
|
+
labels: issue.labels,
|
|
64
|
+
reference: { externalId: issue.id, url: issue.url },
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=linear-issue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear-issue.js","sourceRoot":"","sources":["../../src/work/linear-issue.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@on-par/factory-core",
|
|
3
|
-
"version": "0.9.28-next.
|
|
3
|
+
"version": "0.9.28-next.4",
|
|
4
4
|
"description": "Core engine: model router, constitutions, checkers, and pipeline phases for the Software Factory.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"prepack": "node ../../scripts/pack-hygiene-cli.ts prepack"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@on-par/adr-kit": "0.9.28-next.
|
|
58
|
-
"@on-par/contracts": "0.9.28-next.
|
|
59
|
-
"@on-par/factory-config": "0.9.28-next.
|
|
60
|
-
"@on-par/repo-context": "0.9.28-next.
|
|
57
|
+
"@on-par/adr-kit": "0.9.28-next.4",
|
|
58
|
+
"@on-par/contracts": "0.9.28-next.4",
|
|
59
|
+
"@on-par/factory-config": "0.9.28-next.4",
|
|
60
|
+
"@on-par/repo-context": "0.9.28-next.4",
|
|
61
61
|
"@octokit/rest": "^22.0.0",
|
|
62
62
|
"execa": "^10.2.1",
|
|
63
63
|
"gray-matter": "^4.0.3",
|