github-issue-tower-defence-management 1.108.0 → 1.109.1
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/CHANGELOG.md +19 -0
- package/README.md +12 -0
- package/bin/adapter/entry-points/cli/index.js +4 -4
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js +1 -1
- package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/repositories/GraphqlProjectRepository.js +41 -2
- package/bin/adapter/repositories/GraphqlProjectRepository.js.map +1 -1
- package/bin/adapter/repositories/LocalStorageCacheRepository.js +5 -1
- package/bin/adapter/repositories/LocalStorageCacheRepository.js.map +1 -1
- package/bin/adapter/repositories/LocalStorageRepository.js +3 -0
- package/bin/adapter/repositories/LocalStorageRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +1 -1
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/cli/index.ts +4 -0
- package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.test.ts +6 -1
- package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts +4 -1
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +6 -1
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +1 -0
- package/src/adapter/repositories/GraphqlProjectRepository.diskCache.test.ts +254 -0
- package/src/adapter/repositories/GraphqlProjectRepository.ts +66 -0
- package/src/adapter/repositories/LocalStorageCacheRepository.test.ts +35 -2
- package/src/adapter/repositories/LocalStorageCacheRepository.ts +5 -4
- package/src/adapter/repositories/LocalStorageRepository.test.ts +12 -0
- package/src/adapter/repositories/LocalStorageRepository.ts +3 -0
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.test.ts +3 -6
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +1 -1
- package/types/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts +6 -0
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts.map +1 -1
- package/types/adapter/repositories/LocalStorageCacheRepository.d.ts.map +1 -1
- package/types/adapter/repositories/LocalStorageRepository.d.ts +1 -0
- package/types/adapter/repositories/LocalStorageRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts +1 -1
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
|
@@ -53,7 +53,10 @@ export class GetStoryObjectMapUseCaseHandler {
|
|
|
53
53
|
typeof BaseGitHubRepository
|
|
54
54
|
> = [localStorageRepository, input.credentials.bot.github.token];
|
|
55
55
|
const projectRepository = {
|
|
56
|
-
...new GraphqlProjectRepository(
|
|
56
|
+
...new GraphqlProjectRepository(
|
|
57
|
+
...githubRepositoryParams,
|
|
58
|
+
localStorageCacheRepository,
|
|
59
|
+
),
|
|
57
60
|
};
|
|
58
61
|
const apiV3IssueRepository = new ApiV3IssueRepository(
|
|
59
62
|
...githubRepositoryParams,
|
|
@@ -202,7 +202,6 @@ describe('HandleScheduledEventUseCaseHandler', () => {
|
|
|
202
202
|
await handler.handle('config.yml', false);
|
|
203
203
|
|
|
204
204
|
for (const MockedClass of [
|
|
205
|
-
MockedGraphqlProjectRepository,
|
|
206
205
|
MockedApiV3IssueRepository,
|
|
207
206
|
MockedRestIssueRepository,
|
|
208
207
|
MockedGraphqlProjectItemRepository,
|
|
@@ -210,6 +209,12 @@ describe('HandleScheduledEventUseCaseHandler', () => {
|
|
|
210
209
|
expect(MockedClass).toHaveBeenCalledWith(expect.anything(), 'test-token');
|
|
211
210
|
}
|
|
212
211
|
|
|
212
|
+
expect(MockedGraphqlProjectRepository).toHaveBeenCalledWith(
|
|
213
|
+
expect.anything(),
|
|
214
|
+
'test-token',
|
|
215
|
+
expect.anything(),
|
|
216
|
+
);
|
|
217
|
+
|
|
213
218
|
expect(MockedApiV3CheerioRestIssueRepository).toHaveBeenCalledWith(
|
|
214
219
|
expect.anything(),
|
|
215
220
|
expect.anything(),
|
|
@@ -246,6 +246,7 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
246
246
|
> = [localStorageRepository, input.credentials.bot.github.token];
|
|
247
247
|
const projectRepository = new GraphqlProjectRepository(
|
|
248
248
|
...githubRepositoryParams,
|
|
249
|
+
localStorageCacheRepository,
|
|
249
250
|
);
|
|
250
251
|
const apiV3IssueRepository = new ApiV3IssueRepository(
|
|
251
252
|
...githubRepositoryParams,
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
const mockPost = jest.fn();
|
|
2
|
+
|
|
3
|
+
jest.mock('ky', () => ({
|
|
4
|
+
default: {
|
|
5
|
+
post: mockPost,
|
|
6
|
+
get: jest.fn(),
|
|
7
|
+
put: jest.fn(),
|
|
8
|
+
patch: jest.fn(),
|
|
9
|
+
delete: jest.fn(),
|
|
10
|
+
extend: jest.fn(),
|
|
11
|
+
create: jest.fn(),
|
|
12
|
+
stop: jest.fn(),
|
|
13
|
+
},
|
|
14
|
+
__esModule: true,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
import { GraphqlProjectRepository } from './GraphqlProjectRepository';
|
|
18
|
+
import { LocalStorageCacheRepository } from './LocalStorageCacheRepository';
|
|
19
|
+
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
20
|
+
import { Project } from '../../domain/entities/Project';
|
|
21
|
+
|
|
22
|
+
const mockJsonResponse = <T>(data: T) => ({
|
|
23
|
+
json: jest.fn().mockResolvedValue(data),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const projectId = 'PVT_project123';
|
|
27
|
+
|
|
28
|
+
const getProjectResponse = {
|
|
29
|
+
data: {
|
|
30
|
+
node: {
|
|
31
|
+
id: projectId,
|
|
32
|
+
databaseId: 1,
|
|
33
|
+
title: 'A project',
|
|
34
|
+
shortDescription: '',
|
|
35
|
+
public: true,
|
|
36
|
+
closed: false,
|
|
37
|
+
createdAt: '2024-01-01T00:00:00.000Z',
|
|
38
|
+
updatedAt: '2024-01-01T00:00:00.000Z',
|
|
39
|
+
number: 49,
|
|
40
|
+
url: 'https://github.com/users/owner/projects/49',
|
|
41
|
+
fields: {
|
|
42
|
+
nodes: [
|
|
43
|
+
{
|
|
44
|
+
id: 'PVTSSF_status',
|
|
45
|
+
databaseId: 10,
|
|
46
|
+
name: 'Status',
|
|
47
|
+
dataType: 'SINGLE_SELECT',
|
|
48
|
+
options: [
|
|
49
|
+
{ id: 'st1', name: 'Todo', description: '', color: 'GRAY' },
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const expectedProject: Project = {
|
|
59
|
+
id: projectId,
|
|
60
|
+
url: 'https://github.com/users/owner/projects/49',
|
|
61
|
+
databaseId: 1,
|
|
62
|
+
name: 'A project',
|
|
63
|
+
status: {
|
|
64
|
+
name: 'Status',
|
|
65
|
+
fieldId: 'PVTSSF_status',
|
|
66
|
+
statuses: [{ id: 'st1', name: 'Todo', color: 'GRAY', description: '' }],
|
|
67
|
+
},
|
|
68
|
+
nextActionDate: null,
|
|
69
|
+
nextActionHour: null,
|
|
70
|
+
story: null,
|
|
71
|
+
remainingEstimationMinutes: null,
|
|
72
|
+
dependedIssueUrlSeparatedByComma: null,
|
|
73
|
+
completionDate50PercentConfidence: null,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const fetchProjectIdResponse = {
|
|
77
|
+
data: {
|
|
78
|
+
organization: null,
|
|
79
|
+
user: { projectV2: { id: projectId, databaseId: 1 } },
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type CacheEntry = { value: object; timestamp: Date } | null;
|
|
84
|
+
|
|
85
|
+
const buildCacheStub = (overrides?: {
|
|
86
|
+
getLatest?: jest.Mock;
|
|
87
|
+
set?: jest.Mock;
|
|
88
|
+
}): Pick<LocalStorageCacheRepository, 'getLatest' | 'set'> & {
|
|
89
|
+
getLatest: jest.Mock;
|
|
90
|
+
set: jest.Mock;
|
|
91
|
+
} => ({
|
|
92
|
+
getLatest: overrides?.getLatest ?? jest.fn().mockResolvedValue(null),
|
|
93
|
+
set: overrides?.set ?? jest.fn().mockResolvedValue(undefined),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('GraphqlProjectRepository disk cache', () => {
|
|
97
|
+
const localStorageRepository = new LocalStorageRepository();
|
|
98
|
+
|
|
99
|
+
beforeEach(() => {
|
|
100
|
+
jest.useFakeTimers();
|
|
101
|
+
mockPost.mockReset();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
afterEach(() => {
|
|
105
|
+
jest.useRealTimers();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('getProject', () => {
|
|
109
|
+
it('always fetches the project fresh via GraphQL without reading or writing the disk cache', async () => {
|
|
110
|
+
const cache = buildCacheStub();
|
|
111
|
+
mockPost.mockReturnValueOnce(mockJsonResponse(getProjectResponse));
|
|
112
|
+
const repository = new GraphqlProjectRepository(
|
|
113
|
+
localStorageRepository,
|
|
114
|
+
'dummy',
|
|
115
|
+
cache,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const project = await repository.getProject(projectId);
|
|
119
|
+
|
|
120
|
+
expect(project).toEqual(expectedProject);
|
|
121
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
122
|
+
expect(cache.getLatest).not.toHaveBeenCalled();
|
|
123
|
+
expect(cache.set).not.toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('does not serve a project from the disk cache even when one is present', async () => {
|
|
127
|
+
const cache = buildCacheStub({
|
|
128
|
+
getLatest: jest.fn().mockResolvedValue({
|
|
129
|
+
value: expectedProject,
|
|
130
|
+
timestamp: new Date(),
|
|
131
|
+
} satisfies CacheEntry),
|
|
132
|
+
});
|
|
133
|
+
mockPost.mockReturnValueOnce(mockJsonResponse(getProjectResponse));
|
|
134
|
+
const repository = new GraphqlProjectRepository(
|
|
135
|
+
localStorageRepository,
|
|
136
|
+
'dummy',
|
|
137
|
+
cache,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const project = await repository.getProject(projectId);
|
|
141
|
+
|
|
142
|
+
expect(project).toEqual(expectedProject);
|
|
143
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
144
|
+
expect(cache.set).not.toHaveBeenCalled();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('fetchProjectId', () => {
|
|
149
|
+
it('fetches via GraphQL and writes the cache on a cache miss', async () => {
|
|
150
|
+
const cache = buildCacheStub();
|
|
151
|
+
mockPost.mockReturnValueOnce(mockJsonResponse(fetchProjectIdResponse));
|
|
152
|
+
const repository = new GraphqlProjectRepository(
|
|
153
|
+
localStorageRepository,
|
|
154
|
+
'dummy',
|
|
155
|
+
cache,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const result = await repository.fetchProjectId('owner', 49);
|
|
159
|
+
|
|
160
|
+
expect(result).toBe(projectId);
|
|
161
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
162
|
+
expect(cache.set).toHaveBeenCalledWith('projectId-owner:49', {
|
|
163
|
+
projectId,
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('returns the disk-cached project ID without any GraphQL call', async () => {
|
|
168
|
+
const cache = buildCacheStub({
|
|
169
|
+
getLatest: jest.fn().mockResolvedValue({
|
|
170
|
+
value: { projectId },
|
|
171
|
+
timestamp: new Date(),
|
|
172
|
+
} satisfies CacheEntry),
|
|
173
|
+
});
|
|
174
|
+
const repository = new GraphqlProjectRepository(
|
|
175
|
+
localStorageRepository,
|
|
176
|
+
'dummy',
|
|
177
|
+
cache,
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
const result = await repository.fetchProjectId('owner', 49);
|
|
181
|
+
|
|
182
|
+
expect(result).toBe(projectId);
|
|
183
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
184
|
+
expect(cache.set).not.toHaveBeenCalled();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('does not apply a TTL to the project ID cache because the mapping is static', async () => {
|
|
188
|
+
const cache = buildCacheStub({
|
|
189
|
+
getLatest: jest.fn().mockResolvedValue({
|
|
190
|
+
value: { projectId },
|
|
191
|
+
timestamp: new Date(Date.now() - 365 * 24 * 60 * 60 * 1000),
|
|
192
|
+
} satisfies CacheEntry),
|
|
193
|
+
});
|
|
194
|
+
const repository = new GraphqlProjectRepository(
|
|
195
|
+
localStorageRepository,
|
|
196
|
+
'dummy',
|
|
197
|
+
cache,
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const result = await repository.fetchProjectId('owner', 49);
|
|
201
|
+
|
|
202
|
+
expect(result).toBe(projectId);
|
|
203
|
+
expect(mockPost).not.toHaveBeenCalled();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('falls back to a live GraphQL fetch when the project ID cache read throws', async () => {
|
|
207
|
+
const cache = buildCacheStub({
|
|
208
|
+
getLatest: jest.fn().mockRejectedValue(new Error('corrupted file')),
|
|
209
|
+
});
|
|
210
|
+
mockPost.mockReturnValueOnce(mockJsonResponse(fetchProjectIdResponse));
|
|
211
|
+
const repository = new GraphqlProjectRepository(
|
|
212
|
+
localStorageRepository,
|
|
213
|
+
'dummy',
|
|
214
|
+
cache,
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
const result = await repository.fetchProjectId('owner', 49);
|
|
218
|
+
|
|
219
|
+
expect(result).toBe(projectId);
|
|
220
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('serves the second call from the in-memory L1 cache without a disk read', async () => {
|
|
224
|
+
const cache = buildCacheStub();
|
|
225
|
+
mockPost.mockReturnValueOnce(mockJsonResponse(fetchProjectIdResponse));
|
|
226
|
+
const repository = new GraphqlProjectRepository(
|
|
227
|
+
localStorageRepository,
|
|
228
|
+
'dummy',
|
|
229
|
+
cache,
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
await repository.fetchProjectId('owner', 49);
|
|
233
|
+
await repository.fetchProjectId('owner', 49);
|
|
234
|
+
|
|
235
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
236
|
+
expect(cache.getLatest).toHaveBeenCalledTimes(1);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('without a cache repository', () => {
|
|
241
|
+
it('still works using the in-memory cache only', async () => {
|
|
242
|
+
mockPost.mockReturnValueOnce(mockJsonResponse(fetchProjectIdResponse));
|
|
243
|
+
const repository = new GraphqlProjectRepository(
|
|
244
|
+
localStorageRepository,
|
|
245
|
+
'dummy',
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const result = await repository.fetchProjectId('owner', 49);
|
|
249
|
+
|
|
250
|
+
expect(result).toBe(projectId);
|
|
251
|
+
expect(mockPost).toHaveBeenCalledTimes(1);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
});
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import ky from 'ky';
|
|
2
2
|
import { BaseGitHubRepository } from './BaseGitHubRepository';
|
|
3
|
+
import { LocalStorageCacheRepository } from './LocalStorageCacheRepository';
|
|
4
|
+
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
3
5
|
import { ProjectRepository } from '../../domain/usecases/adapter-interfaces/ProjectRepository';
|
|
4
6
|
import { FieldOption, Project } from '../../domain/entities/Project';
|
|
5
7
|
import { normalizeFieldName } from './utils';
|
|
6
8
|
|
|
7
9
|
const ONE_HOUR_MS = 60 * 60 * 1000;
|
|
8
10
|
|
|
11
|
+
const PROJECT_ID_DISK_CACHE_KEY_PREFIX = 'projectId';
|
|
12
|
+
|
|
9
13
|
export const convertToFieldOptionColor = (
|
|
10
14
|
color: string,
|
|
11
15
|
): FieldOption['color'] => {
|
|
@@ -38,6 +42,62 @@ export class GraphqlProjectRepository
|
|
|
38
42
|
{
|
|
39
43
|
private readonly projectIdCache = new Map<string, string>();
|
|
40
44
|
private readonly fetchProjectIdFailedAt = new Map<string, number>();
|
|
45
|
+
private readonly projectCache?: Pick<
|
|
46
|
+
LocalStorageCacheRepository,
|
|
47
|
+
'getLatest' | 'set'
|
|
48
|
+
>;
|
|
49
|
+
|
|
50
|
+
constructor(
|
|
51
|
+
localStorageRepository: LocalStorageRepository,
|
|
52
|
+
ghToken: string = process.env.GH_TOKEN || 'dummy',
|
|
53
|
+
projectCache?: Pick<LocalStorageCacheRepository, 'getLatest' | 'set'>,
|
|
54
|
+
) {
|
|
55
|
+
super(localStorageRepository, ghToken);
|
|
56
|
+
this.projectCache = projectCache;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private readProjectIdFromDiskCache = async (
|
|
60
|
+
cacheKey: string,
|
|
61
|
+
): Promise<string | null> => {
|
|
62
|
+
if (!this.projectCache) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
let cache: { value: object; timestamp: Date } | null;
|
|
66
|
+
try {
|
|
67
|
+
cache = await this.projectCache.getLatest(
|
|
68
|
+
`${PROJECT_ID_DISK_CACHE_KEY_PREFIX}-${cacheKey}`,
|
|
69
|
+
);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
if (!cache) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (
|
|
77
|
+
'projectId' in cache.value &&
|
|
78
|
+
typeof cache.value.projectId === 'string'
|
|
79
|
+
) {
|
|
80
|
+
return cache.value.projectId;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
private writeProjectIdToDiskCache = async (
|
|
86
|
+
cacheKey: string,
|
|
87
|
+
projectId: string,
|
|
88
|
+
): Promise<void> => {
|
|
89
|
+
if (!this.projectCache) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
await this.projectCache.set(
|
|
94
|
+
`${PROJECT_ID_DISK_CACHE_KEY_PREFIX}-${cacheKey}`,
|
|
95
|
+
{ projectId },
|
|
96
|
+
);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
41
101
|
|
|
42
102
|
extractProjectFromUrl = (
|
|
43
103
|
projectUrl: string,
|
|
@@ -60,6 +120,11 @@ export class GraphqlProjectRepository
|
|
|
60
120
|
if (cached) {
|
|
61
121
|
return cached;
|
|
62
122
|
}
|
|
123
|
+
const diskCached = await this.readProjectIdFromDiskCache(cacheKey);
|
|
124
|
+
if (diskCached) {
|
|
125
|
+
this.projectIdCache.set(cacheKey, diskCached);
|
|
126
|
+
return diskCached;
|
|
127
|
+
}
|
|
63
128
|
const failedAt = this.fetchProjectIdFailedAt.get(cacheKey);
|
|
64
129
|
if (failedAt !== undefined && Date.now() - failedAt < ONE_HOUR_MS) {
|
|
65
130
|
throw new Error(
|
|
@@ -139,6 +204,7 @@ export class GraphqlProjectRepository
|
|
|
139
204
|
);
|
|
140
205
|
}
|
|
141
206
|
this.projectIdCache.set(cacheKey, projectId);
|
|
207
|
+
await this.writeProjectIdToDiskCache(cacheKey, projectId);
|
|
142
208
|
return projectId;
|
|
143
209
|
};
|
|
144
210
|
findProjectIdByUrl = async (
|
|
@@ -15,6 +15,7 @@ describe('LocalStorageCacheRepository', () => {
|
|
|
15
15
|
listFiles: jest.fn(),
|
|
16
16
|
read: jest.fn(),
|
|
17
17
|
write: jest.fn(),
|
|
18
|
+
rename: jest.fn(),
|
|
18
19
|
mkdir: jest.fn(),
|
|
19
20
|
remove: jest.fn(),
|
|
20
21
|
};
|
|
@@ -69,6 +70,19 @@ describe('LocalStorageCacheRepository', () => {
|
|
|
69
70
|
timestamp: new Date('2024-01-01T00:00:00.000Z'),
|
|
70
71
|
},
|
|
71
72
|
},
|
|
73
|
+
{
|
|
74
|
+
name: 'ignores in-progress temp files and reads the latest committed file',
|
|
75
|
+
key: 'test-key',
|
|
76
|
+
files: [
|
|
77
|
+
'2024-01-01T00:00:00.000Z.json',
|
|
78
|
+
'2024-01-01T00:00:01.000Z.json.1234.abc.tmp',
|
|
79
|
+
],
|
|
80
|
+
fileContent: '{"test": "value"}',
|
|
81
|
+
expected: {
|
|
82
|
+
value: { test: 'value' },
|
|
83
|
+
timestamp: new Date('2024-01-01T00:00:00.000Z'),
|
|
84
|
+
},
|
|
85
|
+
},
|
|
72
86
|
];
|
|
73
87
|
|
|
74
88
|
test.each(testCases)(
|
|
@@ -137,11 +151,30 @@ describe('LocalStorageCacheRepository', () => {
|
|
|
137
151
|
expect(localStorageRepository.mkdir).toHaveBeenCalledWith(
|
|
138
152
|
expectedDirPath,
|
|
139
153
|
);
|
|
140
|
-
|
|
154
|
+
const writeArgs = localStorageRepository.write.mock.calls[0];
|
|
155
|
+
const writtenPath = writeArgs[0];
|
|
156
|
+
expect(writtenPath.startsWith(`${expectedFilePath}.`)).toBe(true);
|
|
157
|
+
expect(writtenPath.endsWith('.tmp')).toBe(true);
|
|
158
|
+
expect(writeArgs[1]).toBe(expectedContent);
|
|
159
|
+
expect(localStorageRepository.rename).toHaveBeenCalledWith(
|
|
160
|
+
writtenPath,
|
|
141
161
|
expectedFilePath,
|
|
142
|
-
expectedContent,
|
|
143
162
|
);
|
|
144
163
|
},
|
|
145
164
|
);
|
|
165
|
+
|
|
166
|
+
test('writes to the temp file before renaming it into place', async () => {
|
|
167
|
+
const callOrder: string[] = [];
|
|
168
|
+
localStorageRepository.write.mockImplementation(() => {
|
|
169
|
+
callOrder.push('write');
|
|
170
|
+
});
|
|
171
|
+
localStorageRepository.rename.mockImplementation(() => {
|
|
172
|
+
callOrder.push('rename');
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
await repository.set('ordering-key', { ordered: true });
|
|
176
|
+
|
|
177
|
+
expect(callOrder).toEqual(['write', 'rename']);
|
|
178
|
+
});
|
|
146
179
|
});
|
|
147
180
|
});
|
|
@@ -15,6 +15,7 @@ export class LocalStorageCacheRepository {
|
|
|
15
15
|
const dirPath = `${this.cachePath}/${key}`;
|
|
16
16
|
const latestFile = this.localStorageRepository
|
|
17
17
|
.listFiles(dirPath)
|
|
18
|
+
.filter((fileName) => !fileName.endsWith('.tmp'))
|
|
18
19
|
.sort((a, b) => a.localeCompare(b))
|
|
19
20
|
.reverse()[0];
|
|
20
21
|
if (!latestFile) {
|
|
@@ -45,9 +46,9 @@ export class LocalStorageCacheRepository {
|
|
|
45
46
|
const dirPath = `${this.cachePath}/${key}`;
|
|
46
47
|
this.localStorageRepository.mkdir(dirPath);
|
|
47
48
|
const timestamp = new Date().toISOString();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
);
|
|
49
|
+
const finalPath = `${dirPath}/${timestamp}.json`;
|
|
50
|
+
const tmpPath = `${finalPath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
51
|
+
this.localStorageRepository.write(tmpPath, JSON.stringify(value));
|
|
52
|
+
this.localStorageRepository.rename(tmpPath, finalPath);
|
|
52
53
|
};
|
|
53
54
|
}
|
|
@@ -15,6 +15,7 @@ describe('LocalStorageRepository', () => {
|
|
|
15
15
|
let mockReaddirSync: jest.SpyInstance;
|
|
16
16
|
let mockMkdirSync: jest.SpyInstance;
|
|
17
17
|
let mockExistsSync: jest.SpyInstance;
|
|
18
|
+
let mockRenameSync: jest.SpyInstance;
|
|
18
19
|
|
|
19
20
|
beforeEach(() => {
|
|
20
21
|
repository = new LocalStorageRepository();
|
|
@@ -23,6 +24,7 @@ describe('LocalStorageRepository', () => {
|
|
|
23
24
|
mockReaddirSync = jest.spyOn(fs, 'readdirSync').mockImplementation();
|
|
24
25
|
mockMkdirSync = jest.spyOn(fs, 'mkdirSync').mockImplementation();
|
|
25
26
|
mockExistsSync = jest.spyOn(fs, 'existsSync').mockImplementation();
|
|
27
|
+
mockRenameSync = jest.spyOn(fs, 'renameSync').mockImplementation();
|
|
26
28
|
});
|
|
27
29
|
|
|
28
30
|
afterEach(() => {
|
|
@@ -59,6 +61,16 @@ describe('LocalStorageRepository', () => {
|
|
|
59
61
|
});
|
|
60
62
|
});
|
|
61
63
|
|
|
64
|
+
describe('rename', () => {
|
|
65
|
+
test('renames a file from the old path to the new path', () => {
|
|
66
|
+
repository.rename('/path/to/file.txt.tmp', '/path/to/file.txt');
|
|
67
|
+
expect(mockRenameSync).toHaveBeenCalledWith(
|
|
68
|
+
'/path/to/file.txt.tmp',
|
|
69
|
+
'/path/to/file.txt',
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
62
74
|
describe('read', () => {
|
|
63
75
|
const testCases: Array<{
|
|
64
76
|
name: string;
|
|
@@ -9,6 +9,9 @@ export class LocalStorageRepository {
|
|
|
9
9
|
read = (path: string): string | null => {
|
|
10
10
|
return fs.readFileSync(path, 'utf8');
|
|
11
11
|
};
|
|
12
|
+
rename = (oldPath: string, newPath: string) => {
|
|
13
|
+
fs.renameSync(oldPath, newPath);
|
|
14
|
+
};
|
|
12
15
|
listFiles = (dirPath: string): string[] => {
|
|
13
16
|
if (!fs.existsSync(dirPath)) {
|
|
14
17
|
return [];
|
|
@@ -466,7 +466,7 @@ describe('GraphqlProjectItemRepository', () => {
|
|
|
466
466
|
expect(requestedFirstSeries).toEqual([100, 50, 25, 12, 6, 3, 1]);
|
|
467
467
|
});
|
|
468
468
|
|
|
469
|
-
it('should
|
|
469
|
+
it('should sleep the 5000ms blanket delay between pages', async () => {
|
|
470
470
|
const localStorageRepository = new LocalStorageRepository();
|
|
471
471
|
const repository = new GraphqlProjectItemRepository(
|
|
472
472
|
localStorageRepository,
|
|
@@ -483,11 +483,8 @@ describe('GraphqlProjectItemRepository', () => {
|
|
|
483
483
|
const result = await resultPromise;
|
|
484
484
|
|
|
485
485
|
expect(result).toHaveLength(2);
|
|
486
|
-
expect(PAGINATION_DELAY_MS).
|
|
487
|
-
expect(setTimeoutSpy).
|
|
488
|
-
expect.any(Function),
|
|
489
|
-
5000,
|
|
490
|
-
);
|
|
486
|
+
expect(PAGINATION_DELAY_MS).toBe(5000);
|
|
487
|
+
expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 5000);
|
|
491
488
|
setTimeoutSpy.mockRestore();
|
|
492
489
|
});
|
|
493
490
|
|
|
@@ -20,7 +20,7 @@ export type ProjectItem = {
|
|
|
20
20
|
value: string | null;
|
|
21
21
|
}[];
|
|
22
22
|
};
|
|
23
|
-
export const PAGINATION_DELAY_MS =
|
|
23
|
+
export const PAGINATION_DELAY_MS = 5000;
|
|
24
24
|
export const FETCH_PROJECT_ITEMS_INITIAL_PAGE_SIZE = 100;
|
|
25
25
|
export const FETCH_PROJECT_ITEMS_GRAPHQL_ERROR_PAYLOAD_MAX_LENGTH = 4000;
|
|
26
26
|
export const RATE_LIMIT_MAX_RETRIES = 6;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GetStoryObjectMapUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAEzE,qBAAa,+BAA+B;IAC1C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,EACjB,oBAAoB,MAAM,KACzB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,cAAc,EAAE,cAAc,CAAC;KAChC,CAAC,
|
|
1
|
+
{"version":3,"file":"GetStoryObjectMapUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAG3D,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAEzE,qBAAa,+BAA+B;IAC1C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,EACjB,oBAAoB,MAAM,KACzB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,cAAc,EAAE,cAAc,CAAC;KAChC,CAAC,CA8DA;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAgC3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,KAChB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;KACzB,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAgC3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,KAChB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;KACzB,GAAG,IAAI,CAAC,CAycP;CACH"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { BaseGitHubRepository } from './BaseGitHubRepository';
|
|
2
|
+
import { LocalStorageCacheRepository } from './LocalStorageCacheRepository';
|
|
3
|
+
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
2
4
|
import { ProjectRepository } from '../../domain/usecases/adapter-interfaces/ProjectRepository';
|
|
3
5
|
import { FieldOption, Project } from '../../domain/entities/Project';
|
|
4
6
|
export declare const convertToFieldOptionColor: (color: string) => FieldOption["color"];
|
|
5
7
|
export declare class GraphqlProjectRepository extends BaseGitHubRepository implements Pick<ProjectRepository, 'getProject' | 'findProjectIdByUrl' | 'getByUrl' | 'updateStoryList' | 'updateStatusList'> {
|
|
6
8
|
private readonly projectIdCache;
|
|
7
9
|
private readonly fetchProjectIdFailedAt;
|
|
10
|
+
private readonly projectCache?;
|
|
11
|
+
constructor(localStorageRepository: LocalStorageRepository, ghToken?: string, projectCache?: Pick<LocalStorageCacheRepository, 'getLatest' | 'set'>);
|
|
12
|
+
private readProjectIdFromDiskCache;
|
|
13
|
+
private writeProjectIdToDiskCache;
|
|
8
14
|
extractProjectFromUrl: (projectUrl: string) => {
|
|
9
15
|
owner: string;
|
|
10
16
|
projectNumber: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlProjectRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/GraphqlProjectRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"GraphqlProjectRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/GraphqlProjectRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAC/F,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAOrE,eAAO,MAAM,yBAAyB,GACpC,OAAO,MAAM,KACZ,WAAW,CAAC,OAAO,CAcrB,CAAC;AAEF,qBAAa,wBACX,SAAQ,oBACR,YACE,IAAI,CACF,iBAAiB,EACf,YAAY,GACZ,oBAAoB,GACpB,UAAU,GACV,iBAAiB,GACjB,kBAAkB,CACrB;IAEH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA6B;IACpE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAG5B;gBAGA,sBAAsB,EAAE,sBAAsB,EAC9C,OAAO,GAAE,MAAwC,EACjD,YAAY,CAAC,EAAE,IAAI,CAAC,2BAA2B,EAAE,WAAW,GAAG,KAAK,CAAC;IAMvE,OAAO,CAAC,0BAA0B,CAwBhC;IAEF,OAAO,CAAC,yBAAyB,CAe/B;IAEF,qBAAqB,GACnB,YAAY,MAAM,KACjB;QACD,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;KACvB,CAMC;IACF,cAAc,GACZ,OAAO,MAAM,EACb,eAAe,MAAM,KACpB,OAAO,CAAC,MAAM,CAAC,CA4FhB;IACF,kBAAkB,GAChB,YAAY,MAAM,KACjB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAG9B;IACF,UAAU,GAAU,WAAW,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA8MpE;IACF,QAAQ,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC,CAU9C;IACF,eAAe,GACb,SAAS,OAAO,EAChB,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG;QACvC,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC9B,CAAC,EAAE,KACH,OAAO,CAAC,WAAW,EAAE,CAAC,CA+CvB;IACF,gBAAgB,GACd,SAAS,OAAO,EAChB,eAAe,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG;QACxC,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC9B,CAAC,EAAE,KACH,OAAO,CAAC,WAAW,EAAE,CAAC,CA4CvB;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalStorageCacheRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/LocalStorageCacheRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,qBAAa,2BAA2B;IAEpC,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB;IACvD,QAAQ,CAAC,SAAS;gBADT,sBAAsB,EAAE,sBAAsB,EAC9C,SAAS,SAAgB;IAGpC,SAAS,GACP,KAAK,MAAM,KACV,OAAO,CAAC;QACT,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,IAAI,CAAC;KACjB,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"LocalStorageCacheRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/LocalStorageCacheRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,qBAAa,2BAA2B;IAEpC,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB;IACvD,QAAQ,CAAC,SAAS;gBADT,sBAAsB,EAAE,sBAAsB,EAC9C,SAAS,SAAgB;IAGpC,SAAS,GACP,KAAK,MAAM,KACV,OAAO,CAAC;QACT,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,IAAI,CAAC;KACjB,GAAG,IAAI,CAAC,CA8BP;IACF,GAAG,GAAU,CAAC,EAAE,KAAK,MAAM,EAAE,OAAO,CAAC,KAAG,OAAO,CAAC,IAAI,CAAC,CAQnD;CACH"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare class LocalStorageRepository {
|
|
2
2
|
write: (path: string, value: string) => void;
|
|
3
3
|
read: (path: string) => string | null;
|
|
4
|
+
rename: (oldPath: string, newPath: string) => void;
|
|
4
5
|
listFiles: (dirPath: string) => string[];
|
|
5
6
|
mkdir: (dirPath: string) => void;
|
|
6
7
|
remove: (path: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalStorageRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/LocalStorageRepository.ts"],"names":[],"mappings":"AAEA,qBAAa,sBAAsB;IACjC,KAAK,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,UAIlC;IACF,IAAI,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,IAAI,CAElC;IACF,SAAS,GAAI,SAAS,MAAM,KAAG,MAAM,EAAE,CAKrC;IACF,KAAK,GAAI,SAAS,MAAM,UAEtB;IACF,MAAM,GAAI,MAAM,MAAM,UAKpB;CACH"}
|
|
1
|
+
{"version":3,"file":"LocalStorageRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/LocalStorageRepository.ts"],"names":[],"mappings":"AAEA,qBAAa,sBAAsB;IACjC,KAAK,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,UAIlC;IACF,IAAI,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,IAAI,CAElC;IACF,MAAM,GAAI,SAAS,MAAM,EAAE,SAAS,MAAM,UAExC;IACF,SAAS,GAAI,SAAS,MAAM,KAAG,MAAM,EAAE,CAKrC;IACF,KAAK,GAAI,SAAS,MAAM,UAEtB;IACF,MAAM,GAAI,MAAM,MAAM,UAKpB;CACH"}
|
|
@@ -19,7 +19,7 @@ export type ProjectItem = {
|
|
|
19
19
|
value: string | null;
|
|
20
20
|
}[];
|
|
21
21
|
};
|
|
22
|
-
export declare const PAGINATION_DELAY_MS =
|
|
22
|
+
export declare const PAGINATION_DELAY_MS = 5000;
|
|
23
23
|
export declare const FETCH_PROJECT_ITEMS_INITIAL_PAGE_SIZE = 100;
|
|
24
24
|
export declare const FETCH_PROJECT_ITEMS_GRAPHQL_ERROR_PAYLOAD_MAX_LENGTH = 4000;
|
|
25
25
|
export declare const RATE_LIMIT_MAX_RETRIES = 6;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlProjectItemRepository.d.ts","sourceRoot":"","sources":["../../../../src/adapter/repositories/issue/GraphqlProjectItemRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,YAAY,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,EAAE,CAAC;CACL,CAAC;AACF,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"GraphqlProjectItemRepository.d.ts","sourceRoot":"","sources":["../../../../src/adapter/repositories/issue/GraphqlProjectItemRepository.ts"],"names":[],"mappings":"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"}
|