npm-cli-gh-issue-preparator 1.0.0

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.
Files changed (91) hide show
  1. package/.env.example +0 -0
  2. package/.eslintrc.cjs +65 -0
  3. package/.github/CODEOWNERS +2 -0
  4. package/.github/workflows/commit-lint.yml +52 -0
  5. package/.github/workflows/configs/commitlint.config.js +27 -0
  6. package/.github/workflows/create-pr.yml +66 -0
  7. package/.github/workflows/empty-format-test-job.yml +28 -0
  8. package/.github/workflows/format.yml +25 -0
  9. package/.github/workflows/publish.yml +47 -0
  10. package/.github/workflows/test.yml +38 -0
  11. package/.github/workflows/umino-project.yml +191 -0
  12. package/.prettierignore +22 -0
  13. package/.prettierrc +5 -0
  14. package/CHANGELOG.md +27 -0
  15. package/CONTRIBUTING.md +107 -0
  16. package/README.md +49 -0
  17. package/bin/adapter/entry-points/cli/index.js +72 -0
  18. package/bin/adapter/entry-points/cli/index.js.map +1 -0
  19. package/bin/adapter/repositories/GitHubIssueRepository.js +340 -0
  20. package/bin/adapter/repositories/GitHubIssueRepository.js.map +1 -0
  21. package/bin/adapter/repositories/GitHubProjectRepository.js +123 -0
  22. package/bin/adapter/repositories/GitHubProjectRepository.js.map +1 -0
  23. package/bin/adapter/repositories/NodeLocalCommandRunner.js +34 -0
  24. package/bin/adapter/repositories/NodeLocalCommandRunner.js.map +1 -0
  25. package/bin/domain/entities/Issue.js +3 -0
  26. package/bin/domain/entities/Issue.js.map +1 -0
  27. package/bin/domain/entities/Project.js +3 -0
  28. package/bin/domain/entities/Project.js.map +1 -0
  29. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +37 -0
  30. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -0
  31. package/bin/domain/usecases/StartPreparationUseCase.js +31 -0
  32. package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -0
  33. package/bin/domain/usecases/adapter-interfaces/IssueRepository.js +3 -0
  34. package/bin/domain/usecases/adapter-interfaces/IssueRepository.js.map +1 -0
  35. package/bin/domain/usecases/adapter-interfaces/LocalCommandRunner.js +3 -0
  36. package/bin/domain/usecases/adapter-interfaces/LocalCommandRunner.js.map +1 -0
  37. package/bin/domain/usecases/adapter-interfaces/ProjectRepository.js +3 -0
  38. package/bin/domain/usecases/adapter-interfaces/ProjectRepository.js.map +1 -0
  39. package/bin/index.js +6 -0
  40. package/bin/index.js.map +1 -0
  41. package/commitlint.config.js +6 -0
  42. package/jest.config.js +33 -0
  43. package/package.json +75 -0
  44. package/renovate.json +37 -0
  45. package/src/adapter/entry-points/cli/index.integration.test.ts +143 -0
  46. package/src/adapter/entry-points/cli/index.test.ts +165 -0
  47. package/src/adapter/entry-points/cli/index.ts +110 -0
  48. package/src/adapter/repositories/GitHubIssueRepository.integration.test.ts +50 -0
  49. package/src/adapter/repositories/GitHubIssueRepository.test.ts +996 -0
  50. package/src/adapter/repositories/GitHubIssueRepository.ts +470 -0
  51. package/src/adapter/repositories/GitHubProjectRepository.test.ts +252 -0
  52. package/src/adapter/repositories/GitHubProjectRepository.ts +162 -0
  53. package/src/adapter/repositories/NodeLocalCommandRunner.test.ts +80 -0
  54. package/src/adapter/repositories/NodeLocalCommandRunner.ts +37 -0
  55. package/src/domain/entities/Issue.ts +7 -0
  56. package/src/domain/entities/Project.ts +7 -0
  57. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +109 -0
  58. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +48 -0
  59. package/src/domain/usecases/StartPreparationUseCase.test.ts +150 -0
  60. package/src/domain/usecases/StartPreparationUseCase.ts +48 -0
  61. package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +8 -0
  62. package/src/domain/usecases/adapter-interfaces/LocalCommandRunner.ts +7 -0
  63. package/src/domain/usecases/adapter-interfaces/ProjectRepository.ts +5 -0
  64. package/src/index.test.ts +7 -0
  65. package/src/index.ts +3 -0
  66. package/tsconfig.build.json +11 -0
  67. package/tsconfig.json +16 -0
  68. package/types/adapter/entry-points/cli/index.d.ts +5 -0
  69. package/types/adapter/entry-points/cli/index.d.ts.map +1 -0
  70. package/types/adapter/repositories/GitHubIssueRepository.d.ts +14 -0
  71. package/types/adapter/repositories/GitHubIssueRepository.d.ts.map +1 -0
  72. package/types/adapter/repositories/GitHubProjectRepository.d.ts +9 -0
  73. package/types/adapter/repositories/GitHubProjectRepository.d.ts.map +1 -0
  74. package/types/adapter/repositories/NodeLocalCommandRunner.d.ts +9 -0
  75. package/types/adapter/repositories/NodeLocalCommandRunner.d.ts.map +1 -0
  76. package/types/domain/entities/Issue.d.ts +8 -0
  77. package/types/domain/entities/Issue.d.ts.map +1 -0
  78. package/types/domain/entities/Project.d.ts +8 -0
  79. package/types/domain/entities/Project.d.ts.map +1 -0
  80. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +20 -0
  81. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -0
  82. package/types/domain/usecases/StartPreparationUseCase.d.ts +17 -0
  83. package/types/domain/usecases/StartPreparationUseCase.d.ts.map +1 -0
  84. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +8 -0
  85. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -0
  86. package/types/domain/usecases/adapter-interfaces/LocalCommandRunner.d.ts +8 -0
  87. package/types/domain/usecases/adapter-interfaces/LocalCommandRunner.d.ts.map +1 -0
  88. package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts +5 -0
  89. package/types/domain/usecases/adapter-interfaces/ProjectRepository.d.ts.map +1 -0
  90. package/types/index.d.ts +3 -0
  91. package/types/index.d.ts.map +1 -0
@@ -0,0 +1,107 @@
1
+ # CONTRIBUTING
2
+
3
+ First off, thank you for considering contributing to our project. We value all our contributors and the insights they bring to the table.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Code of Conduct](#code-of-conduct)
8
+ - [Coding Guidelines](#coding-guidelines)
9
+ - [Clean Architecture Rules](#clean-architecture-rules)
10
+ - [Type-Safe Programming](#type-safe-programming)
11
+ - [Writing Tests](#writing-tests)
12
+ - [How to Submit Changes](#how-to-submit-changes)
13
+ - [Recognition](#recognition)
14
+ - [Getting Help](#getting-help)
15
+
16
+ ## Code of Conduct
17
+
18
+ We expect everyone participating in this project to adhere to our Code of Conduct. Below are the main points, but we encourage you to read the full Code of Conduct.
19
+
20
+ - Treat everyone with respect.
21
+ - Avoid making assumptions about other people's identities and experiences.
22
+ - Keep criticism constructive and respectful.
23
+ - Report any incidents of harassment or inappropriate behavior to the project maintainers.
24
+
25
+ ## Coding Guidelines
26
+
27
+ ### Clean Architecture Rules
28
+
29
+ Our project follows the principles of Clean Architecture. This means that we separate concerns, make the project independent of any frameworks, and make it testable and independent of the UI.
30
+
31
+ In addition, our domain layer should not depend on the adapter layer. Please ensure that any contributions you make maintain this separation and adhere to these principles.
32
+
33
+ ### Type-Safe Programming
34
+
35
+ We aim for a type-safe programming style, so please avoid using `any` or `as`. Instead, use type guards or other means to determine types.
36
+
37
+ ### Code Style
38
+
39
+ - As a general rule, please refrain from writing comments whenever possible.
40
+ - Your first approach should be to make your variable and function names as descriptive and self-explanatory as possible.
41
+ - Only when this is not sufficient, and the functionality or purpose of the code is not immediately clear, should comments be used.
42
+ - We encourage the use of the arrow function style as much as possible. It offers a more concise syntax and aligns with contemporary JavaScript practices. Please favor this style when contributing to our codebase.
43
+
44
+ ## Writing Tests
45
+
46
+ Testing is a crucial part of our development process. We expect all code contributions to be accompanied by corresponding tests. This helps us maintain the quality of the project and catch any potential issues early.
47
+
48
+ ### Unit Test Template
49
+
50
+ ```
51
+ import { ReplaceAllWords } from './ReplaceAllWords';
52
+ import { FileRepository } from './adapter-interfaces/FileRepository';
53
+ import { StringConvertor } from './adapter-interfaces/StringConvertor';
54
+ type Mocked<T> = jest.Mocked<T> & jest.MockedObject<T>
55
+
56
+ describe('ReplaceAllWords', () => {
57
+
58
+ beforeEach(() => {
59
+ jest.resetAllMocks();
60
+ });
61
+
62
+ const createUseCaseAndMockRepositories = ()=>{
63
+ const fileRepository: Mocked<FileRepository> = {
64
+ readdirSync: jest.fn(),
65
+ renameSync: jest.fn(),
66
+ lstatSync: jest.fn(),
67
+ statSync: jest.fn(),
68
+ readFileSync: jest.fn(),
69
+ writeFileSync: jest.fn(),
70
+ };
71
+
72
+ const stringConvertor: Mocked<StringConvertor> = {
73
+ camelCase: jest.fn(),
74
+ snakeCase: jest.fn(),
75
+ pascalCase: jest.fn(),
76
+ kebabCase: jest.fn(),
77
+ screamSnakeCase: jest.fn(),
78
+ };
79
+
80
+ const useCase: ReplaceAllWords = new ReplaceAllWords(fileRepository, stringConvertor);
81
+ return {
82
+ fileRepository,
83
+ stringConvertor,
84
+ useCase
85
+ }
86
+ }
87
+ });
88
+
89
+ ```
90
+
91
+ ## How to Submit Changes
92
+
93
+ Once you've identified a bug or an enhancement you'd like to work on, follow these steps to make and submit your changes:
94
+
95
+ 1. Fork the repository.
96
+ 2. Create a new branch.
97
+ 3. Make your changes, ensuring you follow our coding conventions and style guide.
98
+ 4. Write tests for your changes.
99
+ 5. Submit a pull request.
100
+
101
+ Please note that we may take a while to respond, but we appreciate your patience. We aim to make the contribution process as transparent as possible and will keep you updated every step of the way.
102
+
103
+ ## Getting Help
104
+
105
+ If you need help or have any questions, please create an issue in the project's GitHub repository. We aim to respond to issues promptly and appreciate your patience.
106
+
107
+ Again, thank you for considering contributing to our project. Your input is valuable, and we look forward to working with you.
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # npm-cli-gh-issue-preparator
2
+
3
+ [![Test](https://github.com/HiromiShikata/npm-cli-gh-issue-preparator/actions/workflows/test.yml/badge.svg)](https://github.com/HiromiShikata/npm-cli-gh-issue-preparator/actions/workflows/test.yml)
4
+ [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
5
+ [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
6
+
7
+ Welcome to npm-cli-gh-issue-preparator, this tool helps you to prepare you task by AI.
8
+
9
+ ## Usage 🛠️
10
+
11
+ Here's how you can use npm-cli-gh-issue-preparator:
12
+
13
+ ```
14
+ Usage: npm-cli-gh-issue-preparator [options] [command]
15
+
16
+ CLI tool to prepare GitHub issues
17
+
18
+ Options:
19
+ -h, --help display help for command
20
+
21
+ Commands:
22
+ startDaemon [options] Start daemon to prepare GitHub issues
23
+ notifyFinishedIssuePreparation [options] Notify that issue preparation is finished
24
+ help [command] display help for command
25
+ ```
26
+
27
+ ## Example 📖
28
+
29
+ Here's a quick example to illustrate its usage:
30
+
31
+ ### Start daemon
32
+
33
+ ```
34
+ npx npm-cli-gh-issue-preparator startDaemon --projectUrl <projectUrl> --awaitingWorkspaceStatus "Awaiting workspace" --preparationStatus "Preparation" --defaultAgentName "impl"
35
+ ```
36
+
37
+ ### Notify finished issue preparation
38
+
39
+ ```
40
+ npx npm-cli-gh-issue-preparator notifyFinishedIssuePreparation --projectUrl <projectUrl> --issueUrl <issueUrl> --preparationStatus "Preparation" --awaitingQualityCheckStatus "Awaiting quality check"
41
+ ```
42
+
43
+ ## Contributing
44
+
45
+ See [CONTRIBUTING.md](./CONTRIBUTING.md)
46
+
47
+ ## License
48
+
49
+ MIT
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.program = void 0;
8
+ const dotenv_1 = __importDefault(require("dotenv"));
9
+ dotenv_1.default.config();
10
+ const commander_1 = require("commander");
11
+ const StartPreparationUseCase_1 = require("../../../domain/usecases/StartPreparationUseCase");
12
+ const NotifyFinishedIssuePreparationUseCase_1 = require("../../../domain/usecases/NotifyFinishedIssuePreparationUseCase");
13
+ const GitHubProjectRepository_1 = require("../../repositories/GitHubProjectRepository");
14
+ const GitHubIssueRepository_1 = require("../../repositories/GitHubIssueRepository");
15
+ const NodeLocalCommandRunner_1 = require("../../repositories/NodeLocalCommandRunner");
16
+ const program = new commander_1.Command();
17
+ exports.program = program;
18
+ program
19
+ .name('npm-cli-gh-issue-preparator')
20
+ .description('CLI tool to prepare GitHub issues');
21
+ program
22
+ .command('startDaemon')
23
+ .description('Start daemon to prepare GitHub issues')
24
+ .requiredOption('--projectUrl <url>', 'GitHub project URL')
25
+ .requiredOption('--awaitingWorkspaceStatus <status>', 'Status for issues awaiting workspace')
26
+ .requiredOption('--preparationStatus <status>', 'Status for issues in preparation')
27
+ .requiredOption('--defaultAgentName <name>', 'Default agent name')
28
+ .action(async (options) => {
29
+ const token = process.env.GH_TOKEN;
30
+ if (!token) {
31
+ console.error('GH_TOKEN environment variable is required');
32
+ process.exit(1);
33
+ }
34
+ const projectRepository = new GitHubProjectRepository_1.GitHubProjectRepository(token);
35
+ const issueRepository = new GitHubIssueRepository_1.GitHubIssueRepository(token);
36
+ const localCommandRunner = new NodeLocalCommandRunner_1.NodeLocalCommandRunner();
37
+ const useCase = new StartPreparationUseCase_1.StartPreparationUseCase(projectRepository, issueRepository, localCommandRunner);
38
+ await useCase.run({
39
+ projectUrl: options.projectUrl,
40
+ awaitingWorkspaceStatus: options.awaitingWorkspaceStatus,
41
+ preparationStatus: options.preparationStatus,
42
+ defaultAgentName: options.defaultAgentName,
43
+ });
44
+ });
45
+ program
46
+ .command('notifyFinishedIssuePreparation')
47
+ .description('Notify that issue preparation is finished')
48
+ .requiredOption('--projectUrl <url>', 'GitHub project URL')
49
+ .requiredOption('--issueUrl <url>', 'GitHub issue URL')
50
+ .requiredOption('--preparationStatus <status>', 'Status for issues in preparation')
51
+ .requiredOption('--awaitingQualityCheckStatus <status>', 'Status for issues awaiting quality check')
52
+ .action(async (options) => {
53
+ const token = process.env.GH_TOKEN;
54
+ if (!token) {
55
+ console.error('GH_TOKEN environment variable is required');
56
+ process.exit(1);
57
+ }
58
+ const projectRepository = new GitHubProjectRepository_1.GitHubProjectRepository(token);
59
+ const issueRepository = new GitHubIssueRepository_1.GitHubIssueRepository(token);
60
+ const useCase = new NotifyFinishedIssuePreparationUseCase_1.NotifyFinishedIssuePreparationUseCase(projectRepository, issueRepository);
61
+ await useCase.run({
62
+ projectUrl: options.projectUrl,
63
+ issueUrl: options.issueUrl,
64
+ preparationStatus: options.preparationStatus,
65
+ awaitingQualityCheckStatus: options.awaitingQualityCheckStatus,
66
+ });
67
+ });
68
+ /* istanbul ignore next */
69
+ if (process.argv && require.main === module) {
70
+ program.parse(process.argv);
71
+ }
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";;;;;;;AACA,oDAA4B;AAC5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,yCAAoC;AACpC,8FAA2F;AAC3F,0HAAuH;AACvH,wFAAqF;AACrF,oFAAiF;AACjF,sFAAmF;AAgBnF,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAoFrB,0BAAO;AAnFhB,OAAO;KACJ,IAAI,CAAC,6BAA6B,CAAC;KACnC,WAAW,CAAC,mCAAmC,CAAC,CAAC;AAEpD,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,uCAAuC,CAAC;KACpD,cAAc,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;KAC1D,cAAc,CACb,oCAAoC,EACpC,sCAAsC,CACvC;KACA,cAAc,CACb,8BAA8B,EAC9B,kCAAkC,CACnC;KACA,cAAc,CAAC,2BAA2B,EAAE,oBAAoB,CAAC;KACjE,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAI,iDAAuB,CAAC,KAAK,CAAC,CAAC;IAC7D,MAAM,eAAe,GAAG,IAAI,6CAAqB,CAAC,KAAK,CAAC,CAAC;IACzD,MAAM,kBAAkB,GAAG,IAAI,+CAAsB,EAAE,CAAC;IAExD,MAAM,OAAO,GAAG,IAAI,iDAAuB,CACzC,iBAAiB,EACjB,eAAe,EACf,kBAAkB,CACnB,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,uBAAuB,EAAE,OAAO,CAAC,uBAAuB;QACxD,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;KAC3C,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,gCAAgC,CAAC;KACzC,WAAW,CAAC,2CAA2C,CAAC;KACxD,cAAc,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;KAC1D,cAAc,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;KACtD,cAAc,CACb,8BAA8B,EAC9B,kCAAkC,CACnC;KACA,cAAc,CACb,uCAAuC,EACvC,0CAA0C,CAC3C;KACA,MAAM,CAAC,KAAK,EAAE,OAA8B,EAAE,EAAE;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAI,iDAAuB,CAAC,KAAK,CAAC,CAAC;IAC7D,MAAM,eAAe,GAAG,IAAI,6CAAqB,CAAC,KAAK,CAAC,CAAC;IAEzD,MAAM,OAAO,GAAG,IAAI,6EAAqC,CACvD,iBAAiB,EACjB,eAAe,CAChB,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,0BAA0B,EAAE,OAAO,CAAC,0BAA0B;KAC/D,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,0BAA0B;AAC1B,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,340 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitHubIssueRepository = void 0;
4
+ function isProjectItemsResponse(value) {
5
+ if (typeof value !== 'object' || value === null)
6
+ return false;
7
+ return true;
8
+ }
9
+ function isUpdateItemResponse(value) {
10
+ if (typeof value !== 'object' || value === null)
11
+ return false;
12
+ return true;
13
+ }
14
+ function isStatusFieldsResponse(value) {
15
+ if (typeof value !== 'object' || value === null)
16
+ return false;
17
+ return true;
18
+ }
19
+ class GitHubIssueRepository {
20
+ constructor(token) {
21
+ this.token = token;
22
+ }
23
+ parseProjectInfo(project) {
24
+ const urlMatch = project.url.match(/github\.com\/(?:orgs|users)\/([^/]+)\/projects\/(\d+)/);
25
+ if (!urlMatch) {
26
+ throw new Error(`Invalid GitHub project URL: ${project.url}`);
27
+ }
28
+ const owner = urlMatch[1];
29
+ const projectNumber = parseInt(urlMatch[2], 10);
30
+ return { owner, projectNumber };
31
+ }
32
+ buildProjectItemsQuery() {
33
+ return `
34
+ query($owner: String!, $number: Int!) {
35
+ organization(login: $owner) {
36
+ projectV2(number: $number) {
37
+ items(first: 100) {
38
+ nodes {
39
+ id
40
+ content {
41
+ ... on Issue {
42
+ url
43
+ title
44
+ number
45
+ labels(first: 10) {
46
+ nodes {
47
+ name
48
+ }
49
+ }
50
+ }
51
+ }
52
+ fieldValues(first: 20) {
53
+ nodes {
54
+ __typename
55
+ ... on ProjectV2ItemFieldSingleSelectValue {
56
+ name
57
+ field {
58
+ ... on ProjectV2SingleSelectField {
59
+ name
60
+ }
61
+ }
62
+ }
63
+ ... on ProjectV2ItemFieldTextValue {
64
+ text
65
+ field {
66
+ ... on ProjectV2Field {
67
+ name
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ user(login: $owner) {
78
+ projectV2(number: $number) {
79
+ items(first: 100) {
80
+ nodes {
81
+ id
82
+ content {
83
+ ... on Issue {
84
+ url
85
+ title
86
+ number
87
+ labels(first: 10) {
88
+ nodes {
89
+ name
90
+ }
91
+ }
92
+ }
93
+ }
94
+ fieldValues(first: 20) {
95
+ nodes {
96
+ __typename
97
+ ... on ProjectV2ItemFieldSingleSelectValue {
98
+ name
99
+ field {
100
+ ... on ProjectV2SingleSelectField {
101
+ name
102
+ }
103
+ }
104
+ }
105
+ ... on ProjectV2ItemFieldTextValue {
106
+ text
107
+ field {
108
+ ... on ProjectV2Field {
109
+ name
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ `;
121
+ }
122
+ async getStatusOptionId(project, statusName) {
123
+ const { owner, projectNumber } = this.parseProjectInfo(project);
124
+ const query = `
125
+ query($owner: String!, $number: Int!) {
126
+ organization(login: $owner) {
127
+ projectV2(number: $number) {
128
+ fields(first: 10) {
129
+ nodes {
130
+ ... on ProjectV2SingleSelectField {
131
+ id
132
+ name
133
+ options {
134
+ id
135
+ name
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+ user(login: $owner) {
143
+ projectV2(number: $number) {
144
+ fields(first: 10) {
145
+ nodes {
146
+ ... on ProjectV2SingleSelectField {
147
+ id
148
+ name
149
+ options {
150
+ id
151
+ name
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
158
+ }
159
+ `;
160
+ const response = await fetch('https://api.github.com/graphql', {
161
+ method: 'POST',
162
+ headers: {
163
+ Authorization: `Bearer ${this.token}`,
164
+ 'Content-Type': 'application/json',
165
+ },
166
+ body: JSON.stringify({
167
+ query,
168
+ variables: {
169
+ owner,
170
+ number: projectNumber,
171
+ },
172
+ }),
173
+ });
174
+ if (!response.ok) {
175
+ return null;
176
+ }
177
+ const responseData = await response.json();
178
+ if (!isStatusFieldsResponse(responseData)) {
179
+ return null;
180
+ }
181
+ const result = responseData;
182
+ const fields = result.data?.organization?.projectV2?.fields.nodes ||
183
+ result.data?.user?.projectV2?.fields.nodes ||
184
+ [];
185
+ const statusField = fields.find((f) => f.name === 'Status');
186
+ if (!statusField) {
187
+ return null;
188
+ }
189
+ const option = statusField.options.find((o) => o.name === statusName);
190
+ if (!option) {
191
+ return null;
192
+ }
193
+ return {
194
+ fieldId: statusField.id,
195
+ optionId: option.id,
196
+ };
197
+ }
198
+ async getAllOpened(project) {
199
+ const { owner, projectNumber } = this.parseProjectInfo(project);
200
+ const query = this.buildProjectItemsQuery();
201
+ const response = await fetch('https://api.github.com/graphql', {
202
+ method: 'POST',
203
+ headers: {
204
+ Authorization: `Bearer ${this.token}`,
205
+ 'Content-Type': 'application/json',
206
+ },
207
+ body: JSON.stringify({
208
+ query,
209
+ variables: {
210
+ owner,
211
+ number: projectNumber,
212
+ },
213
+ }),
214
+ });
215
+ if (!response.ok) {
216
+ const errorText = await response.text();
217
+ throw new Error(`GitHub API error: ${errorText}`);
218
+ }
219
+ const responseData = await response.json();
220
+ if (!isProjectItemsResponse(responseData)) {
221
+ throw new Error('Invalid API response format');
222
+ }
223
+ const result = responseData;
224
+ const items = result.data?.organization?.projectV2?.items.nodes ||
225
+ result.data?.user?.projectV2?.items.nodes ||
226
+ [];
227
+ const issues = [];
228
+ for (const item of items) {
229
+ if (!item.content)
230
+ continue;
231
+ const statusField = item.fieldValues?.nodes.find((fv) => fv.field?.name === 'Status');
232
+ const status = statusField?.name || '';
233
+ issues.push({
234
+ id: item.id,
235
+ url: item.content.url,
236
+ title: item.content.title,
237
+ labels: item.content.labels.nodes.map((l) => l.name),
238
+ status,
239
+ });
240
+ }
241
+ return issues;
242
+ }
243
+ async update(issue, project) {
244
+ const statusInfo = await this.getStatusOptionId(project, issue.status);
245
+ if (!statusInfo) {
246
+ throw new Error(`Status option not found for status: ${issue.status}`);
247
+ }
248
+ const mutation = `
249
+ mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $value: ProjectV2FieldValue!) {
250
+ updateProjectV2ItemFieldValue(
251
+ input: {
252
+ projectId: $projectId
253
+ itemId: $itemId
254
+ fieldId: $fieldId
255
+ value: $value
256
+ }
257
+ ) {
258
+ projectV2Item {
259
+ id
260
+ }
261
+ }
262
+ }
263
+ `;
264
+ const response = await fetch('https://api.github.com/graphql', {
265
+ method: 'POST',
266
+ headers: {
267
+ Authorization: `Bearer ${this.token}`,
268
+ 'Content-Type': 'application/json',
269
+ },
270
+ body: JSON.stringify({
271
+ query: mutation,
272
+ variables: {
273
+ projectId: project.id,
274
+ itemId: issue.id,
275
+ fieldId: statusInfo.fieldId,
276
+ value: { singleSelectOptionId: statusInfo.optionId },
277
+ },
278
+ }),
279
+ });
280
+ const responseData = await response.json();
281
+ if (!response.ok) {
282
+ throw new Error(`GitHub API error: ${JSON.stringify(responseData)}`);
283
+ }
284
+ if (typeof responseData === 'object' &&
285
+ responseData !== null &&
286
+ 'errors' in responseData) {
287
+ throw new Error(`GraphQL errors: ${JSON.stringify(responseData.errors)}`);
288
+ }
289
+ if (!isUpdateItemResponse(responseData)) {
290
+ throw new Error('Invalid API response format');
291
+ }
292
+ }
293
+ async get(issueUrl, project) {
294
+ const { owner, projectNumber } = this.parseProjectInfo(project);
295
+ const query = this.buildProjectItemsQuery();
296
+ const response = await fetch('https://api.github.com/graphql', {
297
+ method: 'POST',
298
+ headers: {
299
+ Authorization: `Bearer ${this.token}`,
300
+ 'Content-Type': 'application/json',
301
+ },
302
+ body: JSON.stringify({
303
+ query,
304
+ variables: {
305
+ owner,
306
+ number: projectNumber,
307
+ },
308
+ }),
309
+ });
310
+ if (!response.ok) {
311
+ return null;
312
+ }
313
+ const responseData = await response.json();
314
+ if (!isProjectItemsResponse(responseData)) {
315
+ return null;
316
+ }
317
+ const result = responseData;
318
+ const items = result.data?.organization?.projectV2?.items.nodes ||
319
+ result.data?.user?.projectV2?.items.nodes ||
320
+ [];
321
+ for (const item of items) {
322
+ if (!item.content)
323
+ continue;
324
+ if (item.content.url === issueUrl) {
325
+ const statusField = item.fieldValues?.nodes.find((fv) => fv.field?.name === 'Status');
326
+ const status = statusField?.name || '';
327
+ return {
328
+ id: item.id,
329
+ url: item.content.url,
330
+ title: item.content.title,
331
+ labels: item.content.labels.nodes.map((l) => l.name),
332
+ status,
333
+ };
334
+ }
335
+ }
336
+ return null;
337
+ }
338
+ }
339
+ exports.GitHubIssueRepository = GitHubIssueRepository;
340
+ //# sourceMappingURL=GitHubIssueRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubIssueRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubIssueRepository.ts"],"names":[],"mappings":"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"}