@jonit-dev/night-watch-cli 1.7.1 → 1.7.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/board/factory.d.ts +3 -0
- package/dist/board/factory.d.ts.map +1 -0
- package/dist/board/factory.js +10 -0
- package/dist/board/factory.js.map +1 -0
- package/dist/board/providers/github-graphql.d.ts +16 -0
- package/dist/board/providers/github-graphql.d.ts.map +1 -0
- package/dist/board/providers/github-graphql.js +43 -0
- package/dist/board/providers/github-graphql.js.map +1 -0
- package/dist/board/providers/github-projects.d.ts +33 -0
- package/dist/board/providers/github-projects.d.ts.map +1 -0
- package/dist/board/providers/github-projects.js +443 -0
- package/dist/board/providers/github-projects.js.map +1 -0
- package/dist/board/types.d.ts +59 -0
- package/dist/board/types.d.ts.map +1 -0
- package/dist/board/types.js +4 -0
- package/dist/board/types.js.map +1 -0
- package/dist/commands/board.d.ts +9 -0
- package/dist/commands/board.d.ts.map +1 -0
- package/dist/commands/board.js +254 -0
- package/dist/commands/board.js.map +1 -0
- package/dist/commands/cancel.d.ts +1 -1
- package/dist/commands/cancel.d.ts.map +1 -1
- package/dist/commands/cancel.js +6 -7
- package/dist/commands/cancel.js.map +1 -1
- package/dist/commands/review.d.ts +4 -0
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +51 -19
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/run.d.ts +6 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +65 -21
- package/dist/commands/run.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +22 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +185 -4
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/github.d.ts +10 -0
- package/dist/utils/github.d.ts.map +1 -1
- package/dist/utils/github.js +48 -26
- package/dist/utils/github.js.map +1 -1
- package/dist/utils/script-result.d.ts +12 -0
- package/dist/utils/script-result.d.ts.map +1 -0
- package/dist/utils/script-result.js +46 -0
- package/dist/utils/script-result.js.map +1 -0
- package/dist/utils/shell.d.ts +14 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +21 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/status-data.d.ts +2 -0
- package/dist/utils/status-data.d.ts.map +1 -1
- package/dist/utils/status-data.js +30 -1
- package/dist/utils/status-data.js.map +1 -1
- package/package.json +1 -1
- package/scripts/night-watch-cron.sh +143 -18
- package/scripts/night-watch-helpers.sh +39 -0
- package/scripts/night-watch-pr-reviewer-cron.sh +23 -2
- package/web/dist/assets/index-BCMat9cx.js +350 -0
- package/web/dist/assets/{index-Dx_ZY5CY.css → index-BW6hS5jr.css} +1 -1
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-Cogy7oRw.js +0 -350
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/board/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGlE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAO7F"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { GitHubProjectsProvider } from "./providers/github-projects.js";
|
|
2
|
+
export function createBoardProvider(config, cwd) {
|
|
3
|
+
switch (config.provider) {
|
|
4
|
+
case "github":
|
|
5
|
+
return new GitHubProjectsProvider(config, cwd);
|
|
6
|
+
default:
|
|
7
|
+
throw new Error(`Unsupported board provider: ${config.provider}. Supported: github`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/board/factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAExE,MAAM,UAAU,mBAAmB,CAAC,MAA4B,EAAE,GAAW;IAC3E,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,QAAQ;YACX,OAAO,IAAI,sBAAsB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACjD;YACE,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,QAAQ,qBAAqB,CAAC,CAAC;IACzF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execute a GraphQL query/mutation against the GitHub API using the `gh` CLI.
|
|
3
|
+
*
|
|
4
|
+
* Variables with numeric values are passed using `-F` (capital F) so the GitHub
|
|
5
|
+
* API receives them as numbers rather than strings. All other values use `-f`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function graphql<T>(query: string, variables: Record<string, unknown>, cwd: string): T;
|
|
8
|
+
/**
|
|
9
|
+
* Return the "owner/repo" name for the current working directory using `gh repo view`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getRepoNwo(cwd: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Return the authenticated GitHub user's login.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getViewerLogin(cwd: string): string;
|
|
16
|
+
//# sourceMappingURL=github-graphql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-graphql.d.ts","sourceRoot":"","sources":["../../../src/board/providers/github-graphql.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,GAAG,EAAE,MAAM,GACV,CAAC,CA2BH;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO9C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Execute a GraphQL query/mutation against the GitHub API using the `gh` CLI.
|
|
4
|
+
*
|
|
5
|
+
* Variables with numeric values are passed using `-F` (capital F) so the GitHub
|
|
6
|
+
* API receives them as numbers rather than strings. All other values use `-f`.
|
|
7
|
+
*/
|
|
8
|
+
export function graphql(query, variables, cwd) {
|
|
9
|
+
const args = ["api", "graphql", "-f", `query=${query}`];
|
|
10
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
11
|
+
if (typeof value === "number") {
|
|
12
|
+
args.push("-F", `${key}=${String(value)}`);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
args.push("-f", `${key}=${String(value)}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const output = execFileSync("gh", args, {
|
|
19
|
+
cwd,
|
|
20
|
+
encoding: "utf-8",
|
|
21
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
22
|
+
});
|
|
23
|
+
const parsed = JSON.parse(output);
|
|
24
|
+
if (parsed.errors?.length) {
|
|
25
|
+
throw new Error(`GraphQL error: ${parsed.errors[0].message}`);
|
|
26
|
+
}
|
|
27
|
+
return parsed.data;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Return the "owner/repo" name for the current working directory using `gh repo view`.
|
|
31
|
+
*/
|
|
32
|
+
export function getRepoNwo(cwd) {
|
|
33
|
+
const output = execFileSync("gh", ["repo", "view", "--json", "nameWithOwner", "-q", ".nameWithOwner"], { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
34
|
+
return output.trim();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Return the authenticated GitHub user's login.
|
|
38
|
+
*/
|
|
39
|
+
export function getViewerLogin(cwd) {
|
|
40
|
+
const result = graphql(`query { viewer { login } }`, {}, cwd);
|
|
41
|
+
return result.viewer.login;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=github-graphql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-graphql.js","sourceRoot":"","sources":["../../../src/board/providers/github-graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CACrB,KAAa,EACb,SAAkC,EAClC,GAAW;IAEX,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC;IAExD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE;QACtC,GAAG;QACH,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;KAChC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAG/B,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,kBAAkB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,MAAM,CAAC,IAAS,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,YAAY,CACzB,IAAI,EACJ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,CAAC,EACnE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAC5D,CAAC;IACF,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,MAAM,GAAG,OAAO,CACpB,4BAA4B,EAC5B,EAAE,EACF,GAAG,CACJ,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BoardColumnName, IBoardColumn, IBoardInfo, IBoardIssue, IBoardProvider, IBoardProviderConfig, ICreateIssueInput } from "../../board/types.js";
|
|
2
|
+
export declare class GitHubProjectsProvider implements IBoardProvider {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private readonly cwd;
|
|
5
|
+
private cachedProjectId;
|
|
6
|
+
private cachedFieldId;
|
|
7
|
+
private cachedOptionIds;
|
|
8
|
+
constructor(config: IBoardProviderConfig, cwd: string);
|
|
9
|
+
private getRepo;
|
|
10
|
+
/**
|
|
11
|
+
* Fetch and cache the project node ID, Status field ID, and option IDs.
|
|
12
|
+
* Throws if the project cannot be found or has no Status field.
|
|
13
|
+
*/
|
|
14
|
+
private ensureProjectCache;
|
|
15
|
+
/** Try user query first, fall back to org query. */
|
|
16
|
+
private fetchProjectNode;
|
|
17
|
+
/**
|
|
18
|
+
* Parse a raw project item node into IBoardIssue, returning null for items
|
|
19
|
+
* that are not issues.
|
|
20
|
+
*/
|
|
21
|
+
private parseItem;
|
|
22
|
+
setupBoard(title: string): Promise<IBoardInfo>;
|
|
23
|
+
getBoard(): Promise<IBoardInfo | null>;
|
|
24
|
+
getColumns(): Promise<IBoardColumn[]>;
|
|
25
|
+
createIssue(input: ICreateIssueInput): Promise<IBoardIssue>;
|
|
26
|
+
getIssue(issueNumber: number): Promise<IBoardIssue | null>;
|
|
27
|
+
getIssuesByColumn(column: BoardColumnName): Promise<IBoardIssue[]>;
|
|
28
|
+
getAllIssues(): Promise<IBoardIssue[]>;
|
|
29
|
+
moveIssue(issueNumber: number, targetColumn: BoardColumnName): Promise<void>;
|
|
30
|
+
closeIssue(issueNumber: number): Promise<void>;
|
|
31
|
+
commentOnIssue(issueNumber: number, body: string): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=github-projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-projects.d.ts","sourceRoot":"","sources":["../../../src/board/providers/github-projects.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,eAAe,EACf,YAAY,EACZ,UAAU,EACV,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,kBAAkB,CAAC;AA8G1B,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,eAAe,CAAkC;gBAE7C,MAAM,EAAE,oBAAoB,EAAE,GAAG,EAAE,MAAM;IASrD,OAAO,CAAC,OAAO;IAIf;;;OAGG;YACW,kBAAkB;IA0EhC,oDAAoD;IACpD,OAAO,CAAC,gBAAgB;IAmDxB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAmCX,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA8D9C,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAkBtC,UAAU,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAQrC,WAAW,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;IA6F3D,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA+C1D,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKlE,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAoDtC,SAAS,CACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,eAAe,GAC5B,OAAO,CAAC,IAAI,CAAC;IAyEV,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9C,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQvE"}
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { BOARD_COLUMNS, } from "../../board/types.js";
|
|
3
|
+
import { getRepoNwo, getViewerLogin, graphql } from "./github-graphql.js";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// GitHubProjectsProvider
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
export class GitHubProjectsProvider {
|
|
8
|
+
config;
|
|
9
|
+
cwd;
|
|
10
|
+
cachedProjectId = null;
|
|
11
|
+
cachedFieldId = null;
|
|
12
|
+
cachedOptionIds = new Map();
|
|
13
|
+
constructor(config, cwd) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.cwd = cwd;
|
|
16
|
+
}
|
|
17
|
+
// -------------------------------------------------------------------------
|
|
18
|
+
// Helpers
|
|
19
|
+
// -------------------------------------------------------------------------
|
|
20
|
+
getRepo() {
|
|
21
|
+
return this.config.repo ?? getRepoNwo(this.cwd);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Fetch and cache the project node ID, Status field ID, and option IDs.
|
|
25
|
+
* Throws if the project cannot be found or has no Status field.
|
|
26
|
+
*/
|
|
27
|
+
async ensureProjectCache() {
|
|
28
|
+
if (this.cachedProjectId !== null &&
|
|
29
|
+
this.cachedFieldId !== null &&
|
|
30
|
+
this.cachedOptionIds.size > 0) {
|
|
31
|
+
return {
|
|
32
|
+
projectId: this.cachedProjectId,
|
|
33
|
+
fieldId: this.cachedFieldId,
|
|
34
|
+
optionIds: this.cachedOptionIds,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const projectNumber = this.config.projectNumber;
|
|
38
|
+
if (!projectNumber) {
|
|
39
|
+
throw new Error("No projectNumber configured. Run `night-watch board setup` first.");
|
|
40
|
+
}
|
|
41
|
+
const login = getViewerLogin(this.cwd);
|
|
42
|
+
const projectNode = await this.fetchProjectNode(login, projectNumber);
|
|
43
|
+
if (!projectNode) {
|
|
44
|
+
throw new Error(`GitHub Project #${projectNumber} not found for login "${login}".`);
|
|
45
|
+
}
|
|
46
|
+
this.cachedProjectId = projectNode.id;
|
|
47
|
+
// Fetch Status field
|
|
48
|
+
const fieldData = graphql(`query GetStatusField($projectId: ID!) {
|
|
49
|
+
node(id: $projectId) {
|
|
50
|
+
... on ProjectV2 {
|
|
51
|
+
field(name: "Status") {
|
|
52
|
+
... on ProjectV2SingleSelectField {
|
|
53
|
+
id
|
|
54
|
+
options {
|
|
55
|
+
id
|
|
56
|
+
name
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}`, { projectId: projectNode.id }, this.cwd);
|
|
63
|
+
const field = fieldData.node?.field;
|
|
64
|
+
if (!field) {
|
|
65
|
+
throw new Error(`Status field not found on project #${projectNumber}. ` +
|
|
66
|
+
`Run \`night-watch board setup\` to create it.`);
|
|
67
|
+
}
|
|
68
|
+
this.cachedFieldId = field.id;
|
|
69
|
+
this.cachedOptionIds = new Map(field.options.map((o) => [o.name, o.id]));
|
|
70
|
+
return {
|
|
71
|
+
projectId: this.cachedProjectId,
|
|
72
|
+
fieldId: this.cachedFieldId,
|
|
73
|
+
optionIds: this.cachedOptionIds,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** Try user query first, fall back to org query. */
|
|
77
|
+
fetchProjectNode(login, projectNumber) {
|
|
78
|
+
try {
|
|
79
|
+
const userData = graphql(`query GetProject($login: String!, $number: Int!) {
|
|
80
|
+
user(login: $login) {
|
|
81
|
+
projectV2(number: $number) {
|
|
82
|
+
id
|
|
83
|
+
title
|
|
84
|
+
url
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}`, { login, number: projectNumber }, this.cwd);
|
|
88
|
+
if (userData.user?.projectV2) {
|
|
89
|
+
return userData.user.projectV2;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// Swallow — try org query next
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const orgData = graphql(`query GetOrgProject($login: String!, $number: Int!) {
|
|
97
|
+
organization(login: $login) {
|
|
98
|
+
projectV2(number: $number) {
|
|
99
|
+
id
|
|
100
|
+
title
|
|
101
|
+
url
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}`, { login, number: projectNumber }, this.cwd);
|
|
105
|
+
if (orgData.organization?.projectV2) {
|
|
106
|
+
return orgData.organization.projectV2;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Swallow
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse a raw project item node into IBoardIssue, returning null for items
|
|
116
|
+
* that are not issues.
|
|
117
|
+
*/
|
|
118
|
+
parseItem(item) {
|
|
119
|
+
const content = item.content;
|
|
120
|
+
if (!content || content.number === undefined) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
// Find the Status column value from the field values
|
|
124
|
+
let column = null;
|
|
125
|
+
for (const fv of item.fieldValues.nodes) {
|
|
126
|
+
if (fv.field?.name === "Status" && fv.name) {
|
|
127
|
+
const candidate = fv.name;
|
|
128
|
+
if (BOARD_COLUMNS.includes(candidate)) {
|
|
129
|
+
column = candidate;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
id: content.id ?? item.id,
|
|
135
|
+
number: content.number,
|
|
136
|
+
title: content.title ?? "",
|
|
137
|
+
body: content.body ?? "",
|
|
138
|
+
url: content.url ?? "",
|
|
139
|
+
column,
|
|
140
|
+
labels: content.labels?.nodes.map((l) => l.name) ?? [],
|
|
141
|
+
assignees: content.assignees?.nodes.map((a) => a.login) ?? [],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// -------------------------------------------------------------------------
|
|
145
|
+
// IBoardProvider implementation
|
|
146
|
+
// -------------------------------------------------------------------------
|
|
147
|
+
async setupBoard(title) {
|
|
148
|
+
// Resolve the authenticated user/org node ID
|
|
149
|
+
const viewerData = graphql(`query { viewer { id login } }`, {}, this.cwd);
|
|
150
|
+
const ownerId = viewerData.viewer.id;
|
|
151
|
+
// Create the project
|
|
152
|
+
const createData = graphql(`mutation CreateProject($ownerId: ID!, $title: String!) {
|
|
153
|
+
createProjectV2(input: { ownerId: $ownerId, title: $title }) {
|
|
154
|
+
projectV2 {
|
|
155
|
+
id
|
|
156
|
+
number
|
|
157
|
+
url
|
|
158
|
+
title
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}`, { ownerId, title }, this.cwd);
|
|
162
|
+
const project = createData.createProjectV2.projectV2;
|
|
163
|
+
this.cachedProjectId = project.id;
|
|
164
|
+
// Create the Status field with the five lifecycle columns
|
|
165
|
+
const createFieldData = graphql(`mutation CreateStatusField($projectId: ID!) {
|
|
166
|
+
createProjectV2Field(input: {
|
|
167
|
+
projectId: $projectId,
|
|
168
|
+
dataType: SINGLE_SELECT,
|
|
169
|
+
name: "Status",
|
|
170
|
+
singleSelectOptions: [
|
|
171
|
+
{ name: "Draft", color: GRAY, description: "" },
|
|
172
|
+
{ name: "Ready", color: BLUE, description: "" },
|
|
173
|
+
{ name: "In Progress", color: YELLOW, description: "" },
|
|
174
|
+
{ name: "Review", color: ORANGE, description: "" },
|
|
175
|
+
{ name: "Done", color: GREEN, description: "" }
|
|
176
|
+
]
|
|
177
|
+
}) {
|
|
178
|
+
projectV2Field {
|
|
179
|
+
... on ProjectV2SingleSelectField {
|
|
180
|
+
id
|
|
181
|
+
options { id name }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}`, { projectId: project.id }, this.cwd);
|
|
186
|
+
const field = createFieldData.createProjectV2Field.projectV2Field;
|
|
187
|
+
this.cachedFieldId = field.id;
|
|
188
|
+
this.cachedOptionIds = new Map(field.options.map((o) => [o.name, o.id]));
|
|
189
|
+
return { id: project.id, title: project.title, url: project.url };
|
|
190
|
+
}
|
|
191
|
+
async getBoard() {
|
|
192
|
+
const projectNumber = this.config.projectNumber;
|
|
193
|
+
if (!projectNumber) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const login = getViewerLogin(this.cwd);
|
|
198
|
+
const node = this.fetchProjectNode(login, projectNumber);
|
|
199
|
+
if (!node) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return { id: node.id, title: node.title, url: node.url };
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async getColumns() {
|
|
209
|
+
const { fieldId, optionIds } = await this.ensureProjectCache();
|
|
210
|
+
return BOARD_COLUMNS.map((name) => ({
|
|
211
|
+
id: optionIds.get(name) ?? fieldId,
|
|
212
|
+
name,
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
async createIssue(input) {
|
|
216
|
+
const repo = this.getRepo();
|
|
217
|
+
const { projectId, fieldId, optionIds } = await this.ensureProjectCache();
|
|
218
|
+
// Create the issue via gh CLI (REST is simpler here)
|
|
219
|
+
const issueArgs = [
|
|
220
|
+
"issue",
|
|
221
|
+
"create",
|
|
222
|
+
"--title",
|
|
223
|
+
input.title,
|
|
224
|
+
"--body",
|
|
225
|
+
input.body,
|
|
226
|
+
"--repo",
|
|
227
|
+
repo,
|
|
228
|
+
"--json",
|
|
229
|
+
"number,id,url",
|
|
230
|
+
];
|
|
231
|
+
if (input.labels && input.labels.length > 0) {
|
|
232
|
+
issueArgs.push("--label", input.labels.join(","));
|
|
233
|
+
}
|
|
234
|
+
const issueOutput = execFileSync("gh", issueArgs, {
|
|
235
|
+
cwd: this.cwd,
|
|
236
|
+
encoding: "utf-8",
|
|
237
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
238
|
+
});
|
|
239
|
+
const issueJson = JSON.parse(issueOutput);
|
|
240
|
+
// Add the issue to the project board
|
|
241
|
+
const addData = graphql(`mutation AddProjectItem($projectId: ID!, $contentId: ID!) {
|
|
242
|
+
addProjectV2ItemById(input: { projectId: $projectId, contentId: $contentId }) {
|
|
243
|
+
item {
|
|
244
|
+
id
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}`, { projectId, contentId: issueJson.id }, this.cwd);
|
|
248
|
+
const itemId = addData.addProjectV2ItemById.item.id;
|
|
249
|
+
const targetColumn = input.column ?? "Draft";
|
|
250
|
+
const optionId = optionIds.get(targetColumn);
|
|
251
|
+
if (optionId) {
|
|
252
|
+
graphql(`mutation UpdateItemField(
|
|
253
|
+
$projectId: ID!,
|
|
254
|
+
$itemId: ID!,
|
|
255
|
+
$fieldId: ID!,
|
|
256
|
+
$optionId: String!
|
|
257
|
+
) {
|
|
258
|
+
updateProjectV2ItemFieldValue(input: {
|
|
259
|
+
projectId: $projectId,
|
|
260
|
+
itemId: $itemId,
|
|
261
|
+
fieldId: $fieldId,
|
|
262
|
+
value: { singleSelectOptionId: $optionId }
|
|
263
|
+
}) {
|
|
264
|
+
projectV2Item {
|
|
265
|
+
id
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}`, { projectId, itemId, fieldId, optionId }, this.cwd);
|
|
269
|
+
}
|
|
270
|
+
// Fetch the full issue details so we can return a complete IBoardIssue
|
|
271
|
+
const fullIssue = await this.getIssue(issueJson.number);
|
|
272
|
+
if (fullIssue) {
|
|
273
|
+
return { ...fullIssue, column: targetColumn };
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
id: issueJson.id,
|
|
277
|
+
number: issueJson.number,
|
|
278
|
+
title: input.title,
|
|
279
|
+
body: input.body,
|
|
280
|
+
url: issueJson.url,
|
|
281
|
+
column: targetColumn,
|
|
282
|
+
labels: input.labels ?? [],
|
|
283
|
+
assignees: [],
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
async getIssue(issueNumber) {
|
|
287
|
+
const repo = this.getRepo();
|
|
288
|
+
let rawIssue;
|
|
289
|
+
try {
|
|
290
|
+
const output = execFileSync("gh", [
|
|
291
|
+
"issue",
|
|
292
|
+
"view",
|
|
293
|
+
String(issueNumber),
|
|
294
|
+
"--repo",
|
|
295
|
+
repo,
|
|
296
|
+
"--json",
|
|
297
|
+
"number,title,body,url,id,labels,assignees",
|
|
298
|
+
], { cwd: this.cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
299
|
+
rawIssue = JSON.parse(output);
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
// Find which column this issue sits in by scanning all board items
|
|
305
|
+
let column = null;
|
|
306
|
+
try {
|
|
307
|
+
const allIssues = await this.getAllIssues();
|
|
308
|
+
const match = allIssues.find((i) => i.number === issueNumber);
|
|
309
|
+
if (match) {
|
|
310
|
+
column = match.column;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
// Column stays null
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
id: rawIssue.id,
|
|
318
|
+
number: rawIssue.number,
|
|
319
|
+
title: rawIssue.title,
|
|
320
|
+
body: rawIssue.body,
|
|
321
|
+
url: rawIssue.url,
|
|
322
|
+
column,
|
|
323
|
+
labels: rawIssue.labels.map((l) => l.name),
|
|
324
|
+
assignees: rawIssue.assignees.map((a) => a.login),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
async getIssuesByColumn(column) {
|
|
328
|
+
const all = await this.getAllIssues();
|
|
329
|
+
return all.filter((issue) => issue.column === column);
|
|
330
|
+
}
|
|
331
|
+
async getAllIssues() {
|
|
332
|
+
const { projectId } = await this.ensureProjectCache();
|
|
333
|
+
const data = graphql(`query GetProjectItems($projectId: ID!) {
|
|
334
|
+
node(id: $projectId) {
|
|
335
|
+
... on ProjectV2 {
|
|
336
|
+
items(first: 100) {
|
|
337
|
+
nodes {
|
|
338
|
+
id
|
|
339
|
+
content {
|
|
340
|
+
... on Issue {
|
|
341
|
+
number
|
|
342
|
+
title
|
|
343
|
+
body
|
|
344
|
+
url
|
|
345
|
+
id
|
|
346
|
+
labels(first: 10) { nodes { name } }
|
|
347
|
+
assignees(first: 10) { nodes { login } }
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
fieldValues(first: 10) {
|
|
351
|
+
nodes {
|
|
352
|
+
... on ProjectV2ItemFieldSingleSelectValue {
|
|
353
|
+
name
|
|
354
|
+
field {
|
|
355
|
+
... on ProjectV2SingleSelectField {
|
|
356
|
+
name
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}`, { projectId }, this.cwd);
|
|
367
|
+
const results = [];
|
|
368
|
+
for (const item of data.node.items.nodes) {
|
|
369
|
+
const parsed = this.parseItem(item);
|
|
370
|
+
if (parsed) {
|
|
371
|
+
results.push(parsed);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return results;
|
|
375
|
+
}
|
|
376
|
+
async moveIssue(issueNumber, targetColumn) {
|
|
377
|
+
const { projectId, fieldId, optionIds } = await this.ensureProjectCache();
|
|
378
|
+
// Fetch project items to find the item node ID for the target issue
|
|
379
|
+
const data = graphql(`query GetProjectItems($projectId: ID!) {
|
|
380
|
+
node(id: $projectId) {
|
|
381
|
+
... on ProjectV2 {
|
|
382
|
+
items(first: 100) {
|
|
383
|
+
nodes {
|
|
384
|
+
id
|
|
385
|
+
content {
|
|
386
|
+
... on Issue {
|
|
387
|
+
number
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
fieldValues(first: 10) {
|
|
391
|
+
nodes {
|
|
392
|
+
... on ProjectV2ItemFieldSingleSelectValue {
|
|
393
|
+
name
|
|
394
|
+
field {
|
|
395
|
+
... on ProjectV2SingleSelectField {
|
|
396
|
+
name
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}`, { projectId }, this.cwd);
|
|
407
|
+
// Find the project item for this issue number
|
|
408
|
+
const itemNode = data.node.items.nodes.find((n) => n.content?.number === issueNumber);
|
|
409
|
+
if (!itemNode) {
|
|
410
|
+
throw new Error(`Issue #${issueNumber} not found on the project board.`);
|
|
411
|
+
}
|
|
412
|
+
const optionId = optionIds.get(targetColumn);
|
|
413
|
+
if (!optionId) {
|
|
414
|
+
throw new Error(`Column "${targetColumn}" not found on the project board.`);
|
|
415
|
+
}
|
|
416
|
+
graphql(`mutation UpdateItemField(
|
|
417
|
+
$projectId: ID!,
|
|
418
|
+
$itemId: ID!,
|
|
419
|
+
$fieldId: ID!,
|
|
420
|
+
$optionId: String!
|
|
421
|
+
) {
|
|
422
|
+
updateProjectV2ItemFieldValue(input: {
|
|
423
|
+
projectId: $projectId,
|
|
424
|
+
itemId: $itemId,
|
|
425
|
+
fieldId: $fieldId,
|
|
426
|
+
value: { singleSelectOptionId: $optionId }
|
|
427
|
+
}) {
|
|
428
|
+
projectV2Item {
|
|
429
|
+
id
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}`, { projectId, itemId: itemNode.id, fieldId, optionId }, this.cwd);
|
|
433
|
+
}
|
|
434
|
+
async closeIssue(issueNumber) {
|
|
435
|
+
const repo = this.getRepo();
|
|
436
|
+
execFileSync("gh", ["issue", "close", String(issueNumber), "--repo", repo], { cwd: this.cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
437
|
+
}
|
|
438
|
+
async commentOnIssue(issueNumber, body) {
|
|
439
|
+
const repo = this.getRepo();
|
|
440
|
+
execFileSync("gh", ["issue", "comment", String(issueNumber), "--repo", repo, "--body", body], { cwd: this.cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
//# sourceMappingURL=github-projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-projects.js","sourceRoot":"","sources":["../../../src/board/providers/github-projects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export type BoardColumnName = "Draft" | "Ready" | "In Progress" | "Review" | "Done";
|
|
2
|
+
export declare const BOARD_COLUMNS: BoardColumnName[];
|
|
3
|
+
export interface IBoardInfo {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
export interface IBoardColumn {
|
|
9
|
+
id: string;
|
|
10
|
+
name: BoardColumnName;
|
|
11
|
+
}
|
|
12
|
+
export interface IBoardIssue {
|
|
13
|
+
id: string;
|
|
14
|
+
number: number;
|
|
15
|
+
title: string;
|
|
16
|
+
body: string;
|
|
17
|
+
url: string;
|
|
18
|
+
column: BoardColumnName | null;
|
|
19
|
+
labels: string[];
|
|
20
|
+
assignees: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface ICreateIssueInput {
|
|
23
|
+
title: string;
|
|
24
|
+
body: string;
|
|
25
|
+
column?: BoardColumnName;
|
|
26
|
+
labels?: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface IBoardProvider {
|
|
29
|
+
/** Create a new project board with lifecycle columns. Returns board info. */
|
|
30
|
+
setupBoard(title: string): Promise<IBoardInfo>;
|
|
31
|
+
/** Get the configured board. Returns null if not set up. */
|
|
32
|
+
getBoard(): Promise<IBoardInfo | null>;
|
|
33
|
+
/** List all columns on the board. */
|
|
34
|
+
getColumns(): Promise<IBoardColumn[]>;
|
|
35
|
+
/** Create a GitHub issue and add it to the board in the specified column. */
|
|
36
|
+
createIssue(input: ICreateIssueInput): Promise<IBoardIssue>;
|
|
37
|
+
/** Get a single issue by number. */
|
|
38
|
+
getIssue(issueNumber: number): Promise<IBoardIssue | null>;
|
|
39
|
+
/** List issues in a specific column, ordered by priority. */
|
|
40
|
+
getIssuesByColumn(column: BoardColumnName): Promise<IBoardIssue[]>;
|
|
41
|
+
/** List all issues on the board. */
|
|
42
|
+
getAllIssues(): Promise<IBoardIssue[]>;
|
|
43
|
+
/** Move an issue to a different column. */
|
|
44
|
+
moveIssue(issueNumber: number, targetColumn: BoardColumnName): Promise<void>;
|
|
45
|
+
/** Close an issue (e.g., when done). */
|
|
46
|
+
closeIssue(issueNumber: number): Promise<void>;
|
|
47
|
+
/** Add a comment to an issue. */
|
|
48
|
+
commentOnIssue(issueNumber: number, body: string): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export type BoardProviderType = "github" | "jira" | "linear";
|
|
51
|
+
export interface IBoardProviderConfig {
|
|
52
|
+
enabled: boolean;
|
|
53
|
+
provider: BoardProviderType;
|
|
54
|
+
/** GitHub Projects V2 project number (set after `board setup`) */
|
|
55
|
+
projectNumber?: number;
|
|
56
|
+
/** Repository owner/name (auto-detected from git remote) */
|
|
57
|
+
repo?: string;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/board/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpF,eAAO,MAAM,aAAa,EAAE,eAAe,EAE1C,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,6EAA6E;IAC7E,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE/C,4DAA4D;IAC5D,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAEvC,qCAAqC;IACrC,UAAU,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEtC,6EAA6E;IAC7E,WAAW,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAE5D,oCAAoC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE3D,6DAA6D;IAC7D,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEnE,oCAAoC;IACpC,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEvC,2CAA2C;IAC3C,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7E,wCAAwC;IACxC,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C,iCAAiC;IACjC,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/board/types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM;CAClD,CAAC"}
|