github-issue-tower-defence-management 1.173.3 → 1.174.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 (62) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +15 -0
  3. package/bin/adapter/entry-points/cli/index.js +5 -3
  4. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  5. package/bin/adapter/entry-points/console/consoleGithubTokenResolver.js +16 -5
  6. package/bin/adapter/entry-points/console/consoleGithubTokenResolver.js.map +1 -1
  7. package/bin/adapter/entry-points/console/ui-dist/assets/{index-BcnLfodS.js → index-g4SqIzCh.js} +2 -2
  8. package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
  9. package/bin/adapter/entry-points/console/webServer.js +16 -2
  10. package/bin/adapter/entry-points/console/webServer.js.map +1 -1
  11. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +3 -1
  12. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  13. package/bin/adapter/repositories/LocalCommandIssueAttachmentRepository.js +7 -12
  14. package/bin/adapter/repositories/LocalCommandIssueAttachmentRepository.js.map +1 -1
  15. package/bin/domain/usecases/HandleScheduledEventUseCase.js +10 -5
  16. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  17. package/bin/domain/usecases/TriagerApprovalDispatchUseCase.js +142 -0
  18. package/bin/domain/usecases/TriagerApprovalDispatchUseCase.js.map +1 -0
  19. package/bin/domain/usecases/agentReportPrefix.js +5 -0
  20. package/bin/domain/usecases/agentReportPrefix.js.map +1 -0
  21. package/bin/domain/usecases/isPullRequestDeclaredUnnecessary.js +2 -2
  22. package/bin/domain/usecases/isPullRequestDeclaredUnnecessary.js.map +1 -1
  23. package/bin/domain/usecases/isRecord.js +6 -0
  24. package/bin/domain/usecases/isRecord.js.map +1 -0
  25. package/package.json +1 -1
  26. package/src/adapter/entry-points/cli/index.ts +8 -4
  27. package/src/adapter/entry-points/console/consoleGithubTokenResolver.test.ts +29 -2
  28. package/src/adapter/entry-points/console/consoleGithubTokenResolver.ts +21 -4
  29. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.stories.tsx +5 -1
  30. package/src/adapter/entry-points/console/ui/src/features/console/lib/imageProxy.test.ts +8 -5
  31. package/src/adapter/entry-points/console/ui/src/features/console/lib/imageProxy.ts +2 -2
  32. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +2 -2
  33. package/src/adapter/entry-points/console/ui-dist/assets/{index-BcnLfodS.js → index-g4SqIzCh.js} +2 -2
  34. package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
  35. package/src/adapter/entry-points/console/webServer.test.ts +56 -5
  36. package/src/adapter/entry-points/console/webServer.ts +20 -3
  37. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +7 -0
  38. package/src/adapter/repositories/LocalCommandIssueAttachmentRepository.test.ts +53 -70
  39. package/src/adapter/repositories/LocalCommandIssueAttachmentRepository.ts +10 -13
  40. package/src/domain/usecases/HandleScheduledEventUseCase.test.ts +27 -0
  41. package/src/domain/usecases/HandleScheduledEventUseCase.ts +7 -3
  42. package/src/domain/usecases/TriagerApprovalDispatchUseCase.test.ts +879 -0
  43. package/src/domain/usecases/TriagerApprovalDispatchUseCase.ts +247 -0
  44. package/src/domain/usecases/agentReportPrefix.ts +1 -0
  45. package/src/domain/usecases/isPullRequestDeclaredUnnecessary.ts +1 -1
  46. package/src/domain/usecases/isRecord.ts +2 -0
  47. package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
  48. package/types/adapter/entry-points/console/consoleGithubTokenResolver.d.ts +1 -0
  49. package/types/adapter/entry-points/console/consoleGithubTokenResolver.d.ts.map +1 -1
  50. package/types/adapter/entry-points/console/webServer.d.ts +2 -1
  51. package/types/adapter/entry-points/console/webServer.d.ts.map +1 -1
  52. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  53. package/types/adapter/repositories/LocalCommandIssueAttachmentRepository.d.ts +3 -2
  54. package/types/adapter/repositories/LocalCommandIssueAttachmentRepository.d.ts.map +1 -1
  55. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +3 -1
  56. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  57. package/types/domain/usecases/TriagerApprovalDispatchUseCase.d.ts +15 -0
  58. package/types/domain/usecases/TriagerApprovalDispatchUseCase.d.ts.map +1 -0
  59. package/types/domain/usecases/agentReportPrefix.d.ts +2 -0
  60. package/types/domain/usecases/agentReportPrefix.d.ts.map +1 -0
  61. package/types/domain/usecases/isRecord.d.ts +2 -0
  62. package/types/domain/usecases/isRecord.d.ts.map +1 -0
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  createConsoleGithubTokenResolver,
3
+ createConsoleGithubTokenResolverByItemUrl,
3
4
  createConsoleIssueRepositoryResolver,
4
5
  createConsoleProjectRepositoryResolver,
5
6
  extractProjectOwner,
@@ -50,6 +51,30 @@ describe('createConsoleProjectRepositoryResolver', () => {
50
51
  });
51
52
  });
52
53
 
54
+ describe('createConsoleGithubTokenResolverByItemUrl', () => {
55
+ it('returns the token for the owner of the given item url', () => {
56
+ const resolve = createConsoleGithubTokenResolverByItemUrl(
57
+ (repositoryOwner) => `token-of-${repositoryOwner}`,
58
+ );
59
+
60
+ expect(
61
+ resolve('https://github.com/acme-labs/acme-portal-mock/issues/178'),
62
+ ).toBe('token-of-acme-labs');
63
+ });
64
+
65
+ it('throws when the repository owner cannot be read from the url', () => {
66
+ const resolve = createConsoleGithubTokenResolverByItemUrl(
67
+ (repositoryOwner) => `token-of-${repositoryOwner}`,
68
+ );
69
+
70
+ expect(() =>
71
+ resolve('https://github.com/acme-labs/acme-portal-mock'),
72
+ ).toThrow(
73
+ 'The repository owner cannot be read from the url: https://github.com/acme-labs/acme-portal-mock',
74
+ );
75
+ });
76
+ });
77
+
53
78
  describe('createConsoleIssueRepositoryResolver', () => {
54
79
  it('builds the issue repository from the token of the owner in the url', () => {
55
80
  const resolve = createConsoleIssueRepositoryResolver<string>(
@@ -128,14 +153,16 @@ describe('createConsoleGithubTokenResolver', () => {
128
153
  expect(resolve('acme-labs')).toBe('fine-grained-token');
129
154
  });
130
155
 
131
- it('should keep using the default token for the other owners when one owner has a token file', () => {
156
+ it('should throw when the per-owner token map is provided but the owner has no entry in it', () => {
132
157
  const resolve = createConsoleGithubTokenResolver(
133
158
  'default-token',
134
159
  { 'acme-labs': '/creds/acme-labs-token.txt' },
135
160
  () => 'fine-grained-token',
136
161
  );
137
162
 
138
- expect(resolve('globex-inc')).toBe('default-token');
163
+ expect(() => resolve('globex-inc')).toThrow(
164
+ 'No GitHub token file is configured for repository owner "globex-inc". Add an entry for this owner in consoleGithubTokenFilesByRepositoryOwner.',
165
+ );
139
166
  });
140
167
 
141
168
  it('should read the token file only once per owner', () => {
@@ -50,6 +50,20 @@ export const createConsoleProjectRepositoryResolver = <ProjectRepositoryType>(
50
50
  };
51
51
  };
52
52
 
53
+ export const createConsoleGithubTokenResolverByItemUrl = (
54
+ resolveGithubToken: ConsoleGithubTokenResolver,
55
+ ): ((itemUrl: string) => string) => {
56
+ return (itemUrl: string): string => {
57
+ const owner = extractRepositoryOwner(itemUrl);
58
+ if (owner === null) {
59
+ throw new Error(
60
+ `The repository owner cannot be read from the url: ${itemUrl}`,
61
+ );
62
+ }
63
+ return resolveGithubToken(owner);
64
+ };
65
+ };
66
+
53
67
  export const createConsoleGithubTokenResolver = (
54
68
  defaultToken: string,
55
69
  githubTokenFilePathByRepositoryOwner: Record<string, string> | null,
@@ -61,12 +75,15 @@ export const createConsoleGithubTokenResolver = (
61
75
  if (alreadyResolved !== undefined) {
62
76
  return alreadyResolved;
63
77
  }
64
- const filePath = githubTokenFilePathByRepositoryOwner
65
- ? githubTokenFilePathByRepositoryOwner[repositoryOwner]
66
- : undefined;
67
- if (filePath === undefined) {
78
+ if (githubTokenFilePathByRepositoryOwner === null) {
68
79
  return defaultToken;
69
80
  }
81
+ const filePath = githubTokenFilePathByRepositoryOwner[repositoryOwner];
82
+ if (filePath === undefined) {
83
+ throw new Error(
84
+ `No GitHub token file is configured for repository owner "${repositoryOwner}". Add an entry for this owner in consoleGithubTokenFilesByRepositoryOwner.`,
85
+ );
86
+ }
70
87
  const token = readTokenFile(filePath).trim();
71
88
  if (token.length === 0) {
72
89
  throw new Error(
@@ -35,7 +35,11 @@ export const WithCodeFence: Story = {
35
35
  export const WithProxiedGitHubImages: Story = {
36
36
  args: {
37
37
  body: consoleMarkdownImageBodyFixture,
38
- buildImageProxyUrl: (src) => buildImageProxyUrl(src),
38
+ buildImageProxyUrl: (src) =>
39
+ buildImageProxyUrl(
40
+ src,
41
+ 'https://github.com/example-owner/example-repo/issues/1',
42
+ ),
39
43
  },
40
44
  };
41
45
 
@@ -4,6 +4,8 @@ import {
4
4
  rewriteGitHubImageSources,
5
5
  } from './imageProxy';
6
6
 
7
+ const itemUrl = 'https://github.com/example-owner/example-repo/issues/1';
8
+
7
9
  describe('isProxyableImageUrl', () => {
8
10
  it('matches github user-attachments urls', () => {
9
11
  expect(
@@ -27,21 +29,22 @@ describe('isProxyableImageUrl', () => {
27
29
  });
28
30
 
29
31
  describe('buildImageProxyUrl', () => {
30
- it('encodes the source url without appending a token', () => {
32
+ it('encodes the source url and the item url without appending a token', () => {
31
33
  const src = 'https://github.com/user-attachments/assets/abc?x=1';
32
- expect(buildImageProxyUrl(src)).toBe(
33
- `/api/img?url=${encodeURIComponent(src)}`,
34
+ expect(buildImageProxyUrl(src, itemUrl)).toBe(
35
+ `/api/img?url=${encodeURIComponent(src)}&itemUrl=${encodeURIComponent(itemUrl)}`,
34
36
  );
35
37
  });
36
38
 
37
39
  it('does not include a token query parameter', () => {
38
40
  const src = 'https://github.com/user-attachments/assets/abc';
39
- expect(buildImageProxyUrl(src)).not.toContain('k=');
41
+ expect(buildImageProxyUrl(src, itemUrl)).not.toContain('k=');
40
42
  });
41
43
  });
42
44
 
43
45
  describe('rewriteGitHubImageSources', () => {
44
- const buildProxyUrl = (src: string): string => buildImageProxyUrl(src);
46
+ const buildProxyUrl = (src: string): string =>
47
+ buildImageProxyUrl(src, itemUrl);
45
48
 
46
49
  it('rewrites an allow-listed github image src to the proxy url', () => {
47
50
  const githubSrc = 'https://github.com/user-attachments/assets/abc';
@@ -6,8 +6,8 @@ export const isProxyableImageUrl = (src: string): boolean =>
6
6
 
7
7
  export type ImageProxyUrlBuilder = (src: string) => string;
8
8
 
9
- export const buildImageProxyUrl = (src: string): string =>
10
- `/api/img?url=${encodeURIComponent(src)}`;
9
+ export const buildImageProxyUrl = (src: string, itemUrl: string): string =>
10
+ `/api/img?url=${encodeURIComponent(src)}&itemUrl=${encodeURIComponent(itemUrl)}`;
11
11
 
12
12
  export const rewriteGitHubImageSources = (
13
13
  html: string,
@@ -60,8 +60,8 @@ export const ConsoleItemDetailContainer = ({
60
60
  }: ConsoleItemDetailContainerProps) => {
61
61
  const detail = useConsoleItemDetailData(caches, item);
62
62
  const resolveImageProxyUrl = useCallback(
63
- (src: string): string => buildImageProxyUrl(src),
64
- [],
63
+ (src: string): string => buildImageProxyUrl(src, item.url),
64
+ [item.url],
65
65
  );
66
66
  const renderReferenceLink = useCallback(
67
67
  (href: string, fallbackText: string) => (