github-issue-tower-defence-management 1.45.0 → 1.47.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.
- package/CHANGELOG.md +20 -0
- package/README.md +64 -0
- package/bin/adapter/entry-points/cli/index.js +0 -52
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js +0 -2
- package/bin/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +20 -15
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/situationFileWriter.js +98 -0
- package/bin/adapter/entry-points/handlers/situationFileWriter.js.map +1 -0
- package/bin/adapter/repositories/BaseGitHubRepository.js +5 -22
- package/bin/adapter/repositories/BaseGitHubRepository.js.map +1 -1
- package/bin/adapter/repositories/GraphqlProjectRepository.js +40 -0
- package/bin/adapter/repositories/GraphqlProjectRepository.js.map +1 -1
- package/package.json +1 -2
- package/src/adapter/entry-points/cli/index.test.ts +0 -49
- package/src/adapter/entry-points/cli/index.ts +2 -21
- package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.test.ts +0 -6
- package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts +0 -2
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +23 -51
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +27 -18
- package/src/adapter/entry-points/handlers/situationFileWriter.test.ts +417 -0
- package/src/adapter/entry-points/handlers/situationFileWriter.ts +168 -0
- package/src/adapter/repositories/BaseGitHubRepository.test.ts +3 -48
- package/src/adapter/repositories/BaseGitHubRepository.ts +5 -33
- package/src/adapter/repositories/GraphqlProjectRepository.test.ts +72 -0
- package/src/adapter/repositories/GraphqlProjectRepository.ts +57 -1
- package/types/adapter/entry-points/cli/index.d.ts.map +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/entry-points/handlers/situationFileWriter.d.ts +30 -0
- package/types/adapter/entry-points/handlers/situationFileWriter.d.ts.map +1 -0
- package/types/adapter/repositories/BaseGitHubRepository.d.ts +0 -1
- package/types/adapter/repositories/BaseGitHubRepository.d.ts.map +1 -1
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts +5 -2
- package/types/adapter/repositories/GraphqlProjectRepository.d.ts.map +1 -1
- package/bin/adapter/repositories/CheerioProjectRepository.js +0 -45
- package/bin/adapter/repositories/CheerioProjectRepository.js.map +0 -1
- package/src/adapter/repositories/CheerioProjectRepository.test.ts +0 -122
- package/src/adapter/repositories/CheerioProjectRepository.ts +0 -65
- package/types/adapter/repositories/CheerioProjectRepository.d.ts +0 -17
- package/types/adapter/repositories/CheerioProjectRepository.d.ts.map +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { promises as fsPromises } from 'fs';
|
|
2
2
|
import { serialize } from 'cookie';
|
|
3
|
-
import { getCookieContent } from 'gh-cookie';
|
|
4
3
|
import fs from 'fs';
|
|
5
4
|
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
6
5
|
import ky from 'ky';
|
|
@@ -18,7 +17,6 @@ interface Cookie {
|
|
|
18
17
|
|
|
19
18
|
export class BaseGitHubRepository {
|
|
20
19
|
cookie: string | null;
|
|
21
|
-
protected cookieRefreshRetryDelayMs = 3000;
|
|
22
20
|
constructor(
|
|
23
21
|
readonly localStorageRepository: LocalStorageRepository,
|
|
24
22
|
readonly jsonFilePath: string = './tmp/github.com.cookies.json',
|
|
@@ -82,19 +80,7 @@ export class BaseGitHubRepository {
|
|
|
82
80
|
};
|
|
83
81
|
protected createCookieStringFromFile = async (): Promise<string> => {
|
|
84
82
|
if (!fs.existsSync(this.jsonFilePath)) {
|
|
85
|
-
|
|
86
|
-
!this.ghUserName ||
|
|
87
|
-
!this.ghUserPassword ||
|
|
88
|
-
!this.ghAuthenticatorKey
|
|
89
|
-
) {
|
|
90
|
-
throw new Error('No cookie file and no credentials provided');
|
|
91
|
-
}
|
|
92
|
-
const cookie = await getCookieContent(
|
|
93
|
-
this.ghUserName,
|
|
94
|
-
this.ghUserPassword,
|
|
95
|
-
this.ghAuthenticatorKey,
|
|
96
|
-
);
|
|
97
|
-
this.localStorageRepository.write(this.jsonFilePath, cookie);
|
|
83
|
+
throw new Error('No cookie file found');
|
|
98
84
|
}
|
|
99
85
|
const data = await fsPromises.readFile(this.jsonFilePath, {
|
|
100
86
|
encoding: 'utf-8',
|
|
@@ -169,24 +155,10 @@ export class BaseGitHubRepository {
|
|
|
169
155
|
);
|
|
170
156
|
}
|
|
171
157
|
const profileUrl = `https://github.com/${this.ghUserName}`;
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
await new Promise<void>((resolve) =>
|
|
177
|
-
setTimeout(resolve, this.cookieRefreshRetryDelayMs),
|
|
178
|
-
);
|
|
179
|
-
this.localStorageRepository.remove(this.jsonFilePath);
|
|
180
|
-
this.cookie = null;
|
|
181
|
-
}
|
|
182
|
-
const headers = await this.createHeader();
|
|
183
|
-
const html = await ky.get(profileUrl, { headers }).text();
|
|
184
|
-
if (
|
|
185
|
-
html.includes(`meta name="user-login" content="${this.ghUserName}"`)
|
|
186
|
-
) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
158
|
+
const headers = await this.createHeader();
|
|
159
|
+
const html = await ky.get(profileUrl, { headers }).text();
|
|
160
|
+
if (!html.includes(`meta name="user-login" content="${this.ghUserName}"`)) {
|
|
161
|
+
throw new Error('Failed to refresh cookie');
|
|
189
162
|
}
|
|
190
|
-
throw new Error('Failed to refresh cookie');
|
|
191
163
|
};
|
|
192
164
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { GraphqlProjectRepository } from './GraphqlProjectRepository';
|
|
2
2
|
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
3
|
+
import { FieldOption, Project } from '../../domain/entities/Project';
|
|
3
4
|
|
|
4
5
|
describe('GraphqlProjectRepository', () => {
|
|
5
6
|
const localStorageRepository = new LocalStorageRepository();
|
|
@@ -29,6 +30,77 @@ describe('GraphqlProjectRepository', () => {
|
|
|
29
30
|
});
|
|
30
31
|
});
|
|
31
32
|
|
|
33
|
+
describe('updateStoryList', () => {
|
|
34
|
+
const storyFieldId = 'PVTSSF_lAHOAGJHa84AFhgFzg1oBms';
|
|
35
|
+
const existingStories: FieldOption[] = [
|
|
36
|
+
{ id: 'af410dae', name: 'story1', color: 'GRAY', description: '' },
|
|
37
|
+
{
|
|
38
|
+
id: '696ccdef',
|
|
39
|
+
name: 'Workflow Management',
|
|
40
|
+
color: 'GRAY',
|
|
41
|
+
description: '',
|
|
42
|
+
},
|
|
43
|
+
{ id: '4fa21881', name: 'test', color: 'GRAY', description: '' },
|
|
44
|
+
];
|
|
45
|
+
const testProject: Project = {
|
|
46
|
+
id: projectId,
|
|
47
|
+
url: projectUrl,
|
|
48
|
+
databaseId: 1447941,
|
|
49
|
+
name: 'V2 project on owner for testing',
|
|
50
|
+
completionDate50PercentConfidence: null,
|
|
51
|
+
dependedIssueUrlSeparatedByComma: null,
|
|
52
|
+
nextActionDate: {
|
|
53
|
+
fieldId: 'PVTF_lAHOAGJHa84AFhgFzgVlnK4',
|
|
54
|
+
name: 'NextActionDate',
|
|
55
|
+
},
|
|
56
|
+
nextActionHour: null,
|
|
57
|
+
remainingEstimationMinutes: null,
|
|
58
|
+
status: {
|
|
59
|
+
fieldId: 'PVTSSF_lAHOAGJHa84AFhgFzgDLt0c',
|
|
60
|
+
name: 'Status',
|
|
61
|
+
statuses: [],
|
|
62
|
+
},
|
|
63
|
+
story: {
|
|
64
|
+
fieldId: storyFieldId,
|
|
65
|
+
databaseId: 224921195,
|
|
66
|
+
name: 'Story',
|
|
67
|
+
stories: existingStories,
|
|
68
|
+
workflowManagementStory: {
|
|
69
|
+
id: '696ccdef',
|
|
70
|
+
name: 'Workflow Management',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
it('should add a new option while preserving all existing options', async () => {
|
|
76
|
+
const newOption: Omit<FieldOption, 'id'> & { id: null } = {
|
|
77
|
+
id: null,
|
|
78
|
+
name: 'test-story-from-graphql-unit-test',
|
|
79
|
+
color: 'BLUE',
|
|
80
|
+
description: 'created by graphql unit test',
|
|
81
|
+
};
|
|
82
|
+
const inputList: Parameters<typeof repository.updateStoryList>['1'] = [
|
|
83
|
+
...existingStories,
|
|
84
|
+
newOption,
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const result = await repository.updateStoryList(testProject, inputList);
|
|
88
|
+
|
|
89
|
+
expect(result).toHaveLength(existingStories.length + 1);
|
|
90
|
+
existingStories.forEach((existing) => {
|
|
91
|
+
const found = result.find((r) => r.id === existing.id);
|
|
92
|
+
expect(found).toEqual(existing);
|
|
93
|
+
});
|
|
94
|
+
const added = result.find((r) => r.name === newOption.name);
|
|
95
|
+
expect(added).toBeDefined();
|
|
96
|
+
expect(added?.color).toEqual(newOption.color);
|
|
97
|
+
expect(added?.description).toEqual(newOption.description);
|
|
98
|
+
expect(added?.id).toBeDefined();
|
|
99
|
+
|
|
100
|
+
await repository.updateStoryList(testProject, existingStories);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
32
104
|
describe('getProject', () => {
|
|
33
105
|
it('should retrieve project details', async () => {
|
|
34
106
|
const project = await repository.getProject(projectId);
|
|
@@ -7,7 +7,10 @@ import { normalizeFieldName } from './utils';
|
|
|
7
7
|
export class GraphqlProjectRepository
|
|
8
8
|
extends BaseGitHubRepository
|
|
9
9
|
implements
|
|
10
|
-
Pick<
|
|
10
|
+
Pick<
|
|
11
|
+
ProjectRepository,
|
|
12
|
+
'getProject' | 'findProjectIdByUrl' | 'getByUrl' | 'updateStoryList'
|
|
13
|
+
>
|
|
11
14
|
{
|
|
12
15
|
extractProjectFromUrl = (
|
|
13
16
|
projectUrl: string,
|
|
@@ -306,4 +309,57 @@ export class GraphqlProjectRepository
|
|
|
306
309
|
}
|
|
307
310
|
return project;
|
|
308
311
|
};
|
|
312
|
+
updateStoryList = async (
|
|
313
|
+
project: Project,
|
|
314
|
+
newStoryList: (Omit<FieldOption, 'id'> & {
|
|
315
|
+
id: FieldOption['id'] | null;
|
|
316
|
+
})[],
|
|
317
|
+
): Promise<FieldOption[]> => {
|
|
318
|
+
if (!project.story) {
|
|
319
|
+
throw new Error('Project has no story field');
|
|
320
|
+
}
|
|
321
|
+
const mutation = `mutation UpdateStoryOptions($fieldId: ID!, $options: [ProjectV2SingleSelectFieldOptionInput!]!) {
|
|
322
|
+
updateProjectV2Field(input: {
|
|
323
|
+
fieldId: $fieldId
|
|
324
|
+
singleSelectOptions: $options
|
|
325
|
+
}) {
|
|
326
|
+
projectV2Field {
|
|
327
|
+
... on ProjectV2SingleSelectField {
|
|
328
|
+
options {
|
|
329
|
+
id
|
|
330
|
+
name
|
|
331
|
+
color
|
|
332
|
+
description
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}`;
|
|
338
|
+
const variables = {
|
|
339
|
+
fieldId: project.story.fieldId,
|
|
340
|
+
options: newStoryList.map(({ id, name, color, description }) => ({
|
|
341
|
+
...(id !== null ? { id } : {}),
|
|
342
|
+
name,
|
|
343
|
+
color,
|
|
344
|
+
description,
|
|
345
|
+
})),
|
|
346
|
+
};
|
|
347
|
+
const response = await ky
|
|
348
|
+
.post('https://api.github.com/graphql', {
|
|
349
|
+
json: { query: mutation, variables },
|
|
350
|
+
headers: {
|
|
351
|
+
Authorization: `Bearer ${this.ghToken}`,
|
|
352
|
+
},
|
|
353
|
+
})
|
|
354
|
+
.json<{
|
|
355
|
+
data: {
|
|
356
|
+
updateProjectV2Field: {
|
|
357
|
+
projectV2Field: {
|
|
358
|
+
options: FieldOption[];
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
};
|
|
362
|
+
}>();
|
|
363
|
+
return response.data.updateProjectV2Field.projectV2Field.options;
|
|
364
|
+
};
|
|
309
365
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAuEzB,eAAO,MAAM,OAAO,SAAgB,CAAC"}
|
|
@@ -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;
|
|
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,CAqEA;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAoB3D,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,CA8QP;CACH"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Issue } from '../../../domain/entities/Issue';
|
|
2
|
+
import type { LocalCommandRunner } from '../../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
3
|
+
export type SituationFileParams = {
|
|
4
|
+
cachePath: string;
|
|
5
|
+
projectId: string;
|
|
6
|
+
issues: Issue[];
|
|
7
|
+
statusNames: {
|
|
8
|
+
awaitingQualityCheckStatus: string | null;
|
|
9
|
+
preparationStatus: string | null;
|
|
10
|
+
awaitingWorkspaceStatus: string | null;
|
|
11
|
+
};
|
|
12
|
+
config: {
|
|
13
|
+
maximumPreparingIssuesCount: number | null;
|
|
14
|
+
utilizationPercentageThreshold: number;
|
|
15
|
+
allowIssueCacheMinutes: number;
|
|
16
|
+
thresholdForAutoReject: number;
|
|
17
|
+
};
|
|
18
|
+
preparationProcessCheckCommand?: string | null;
|
|
19
|
+
localCommandRunner?: LocalCommandRunner;
|
|
20
|
+
};
|
|
21
|
+
type MeminfoValues = {
|
|
22
|
+
memTotalKb: number;
|
|
23
|
+
memAvailableKb: number;
|
|
24
|
+
swapTotalKb: number;
|
|
25
|
+
swapFreeKb: number;
|
|
26
|
+
};
|
|
27
|
+
export declare const parseMeminfo: (meminfo: string) => MeminfoValues;
|
|
28
|
+
export declare const writeSituationFile: (params: SituationFileParams) => Promise<void>;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=situationFileWriter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"situationFileWriter.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/situationFileWriter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gEAAgE,CAAC;AAEzG,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,WAAW,EAAE;QACX,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1C,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;KACxC,CAAC;IACF,MAAM,EAAE;QACN,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3C,8BAA8B,EAAE,MAAM,CAAC;QACvC,sBAAsB,EAAE,MAAM,CAAC;QAC/B,sBAAsB,EAAE,MAAM,CAAC;KAChC,CAAC;IACF,8BAA8B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,aAW9C,CAAC;AAiCF,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,mBAAmB,KAC1B,OAAO,CAAC,IAAI,CA2Fd,CAAC"}
|
|
@@ -17,7 +17,6 @@ export declare class BaseGitHubRepository {
|
|
|
17
17
|
readonly ghUserPassword: string | undefined;
|
|
18
18
|
readonly ghAuthenticatorKey: string | undefined;
|
|
19
19
|
cookie: string | null;
|
|
20
|
-
protected cookieRefreshRetryDelayMs: number;
|
|
21
20
|
constructor(localStorageRepository: LocalStorageRepository, jsonFilePath?: string, ghToken?: string, ghUserName?: string | undefined, ghUserPassword?: string | undefined, ghAuthenticatorKey?: string | undefined);
|
|
22
21
|
protected extractIssueFromUrl: (issueUrl: string) => {
|
|
23
22
|
owner: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseGitHubRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/BaseGitHubRepository.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BaseGitHubRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/BaseGitHubRepository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,UAAU,MAAM;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACtC;AAED,qBAAa,oBAAoB;IAG7B,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB;IACvD,QAAQ,CAAC,YAAY,EAAE,MAAM;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;IACvC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS;IAC3C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS;IAPjD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;gBAEX,sBAAsB,EAAE,sBAAsB,EAC9C,YAAY,GAAE,MAAwC,EACtD,OAAO,GAAE,MAAwC,EACjD,UAAU,GAAE,MAAM,GAAG,SAAoC,EACzD,cAAc,GAAE,MAAM,GAAG,SAAwC,EACjE,kBAAkB,GAAE,MAAM,GAAG,SACf;IAIzB,SAAS,CAAC,mBAAmB,GAC3B,UAAU,MAAM,KACf;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAevE;IAEF,SAAS,QAAa,OAAO,CAAC,MAAM,CAAC,CAKnC;IACF,YAAY,QAAa,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAwBtD;IACF,SAAS,CAAC,0BAA0B,QAAa,OAAO,CAAC,MAAM,CAAC,CAS9D;IACF,SAAS,CAAC,QAAQ,GAAI,QAAQ,MAAM,KAAG,MAAM,IAAI,MAAM,CAoBrD;IAEF,SAAS,CAAC,4BAA4B,GACpC,YAAY,OAAO,KAClB,OAAO,CAAC,MAAM,CAAC,CAmChB;IACF,aAAa,QAAa,OAAO,CAAC,IAAI,CAAC,CAYrC;CACH"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseGitHubRepository } from './BaseGitHubRepository';
|
|
2
2
|
import { ProjectRepository } from '../../domain/usecases/adapter-interfaces/ProjectRepository';
|
|
3
|
-
import { Project } from '../../domain/entities/Project';
|
|
4
|
-
export declare class GraphqlProjectRepository extends BaseGitHubRepository implements Pick<ProjectRepository, 'getProject' | 'findProjectIdByUrl' | 'getByUrl'> {
|
|
3
|
+
import { FieldOption, Project } from '../../domain/entities/Project';
|
|
4
|
+
export declare class GraphqlProjectRepository extends BaseGitHubRepository implements Pick<ProjectRepository, 'getProject' | 'findProjectIdByUrl' | 'getByUrl' | 'updateStoryList'> {
|
|
5
5
|
extractProjectFromUrl: (projectUrl: string) => {
|
|
6
6
|
owner: string;
|
|
7
7
|
projectNumber: number;
|
|
@@ -10,5 +10,8 @@ export declare class GraphqlProjectRepository extends BaseGitHubRepository imple
|
|
|
10
10
|
findProjectIdByUrl: (projectUrl: string) => Promise<Project["id"] | null>;
|
|
11
11
|
getProject: (projectId: Project["id"]) => Promise<Project | null>;
|
|
12
12
|
getByUrl: (url: string) => Promise<Project>;
|
|
13
|
+
updateStoryList: (project: Project, newStoryList: (Omit<FieldOption, "id"> & {
|
|
14
|
+
id: FieldOption["id"] | null;
|
|
15
|
+
})[]) => Promise<FieldOption[]>;
|
|
13
16
|
}
|
|
14
17
|
//# sourceMappingURL=GraphqlProjectRepository.d.ts.map
|
|
@@ -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,
|
|
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;AAGrE,qBAAa,wBACX,SAAQ,oBACR,YACE,IAAI,CACF,iBAAiB,EACjB,YAAY,GAAG,oBAAoB,GAAG,UAAU,GAAG,iBAAiB,CACrE;IAEH,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,CAqDhB;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,CAkNpE;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;CACH"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.CheerioProjectRepository = void 0;
|
|
7
|
-
const ky_1 = __importDefault(require("ky"));
|
|
8
|
-
const BaseGitHubRepository_1 = require("./BaseGitHubRepository");
|
|
9
|
-
class CheerioProjectRepository extends BaseGitHubRepository_1.BaseGitHubRepository {
|
|
10
|
-
constructor(localStorageRepository, jsonFilePath = './tmp/github.com.cookies.json', ghToken = process.env.GH_TOKEN || 'dummy', ghUserName = process.env.GH_USER_NAME, ghUserPassword = process.env.GH_USER_PASSWORD, ghAuthenticatorKey = process.env
|
|
11
|
-
.GH_AUTHENTICATOR_KEY) {
|
|
12
|
-
super(localStorageRepository, jsonFilePath, ghToken, ghUserName, ghUserPassword, ghAuthenticatorKey);
|
|
13
|
-
this.localStorageRepository = localStorageRepository;
|
|
14
|
-
this.jsonFilePath = jsonFilePath;
|
|
15
|
-
this.ghToken = ghToken;
|
|
16
|
-
this.ghUserName = ghUserName;
|
|
17
|
-
this.ghUserPassword = ghUserPassword;
|
|
18
|
-
this.ghAuthenticatorKey = ghAuthenticatorKey;
|
|
19
|
-
this.updateStoryList = async (project, newStoryList) => {
|
|
20
|
-
const browserHeaders = await this.createHeader();
|
|
21
|
-
const raw = await ky_1.default
|
|
22
|
-
.put(`https://github.com/memexes/${project.databaseId}/columns`, {
|
|
23
|
-
json: {
|
|
24
|
-
memexProjectColumnId: project.story?.databaseId,
|
|
25
|
-
settings: { width: 200, options: newStoryList },
|
|
26
|
-
},
|
|
27
|
-
headers: {
|
|
28
|
-
'github-verified-fetch': 'true',
|
|
29
|
-
origin: 'https://github.com',
|
|
30
|
-
'x-requested-with': 'XMLHttpRequest',
|
|
31
|
-
...browserHeaders,
|
|
32
|
-
},
|
|
33
|
-
})
|
|
34
|
-
.json();
|
|
35
|
-
return raw.memexProjectColumn.settings.options.map((v) => ({
|
|
36
|
-
id: v.id,
|
|
37
|
-
name: v.name,
|
|
38
|
-
color: v.color,
|
|
39
|
-
description: v.description,
|
|
40
|
-
}));
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
exports.CheerioProjectRepository = CheerioProjectRepository;
|
|
45
|
-
//# sourceMappingURL=CheerioProjectRepository.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CheerioProjectRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/CheerioProjectRepository.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,iEAA8D;AAK9D,MAAa,wBACX,SAAQ,2CAAoB;IAG5B,YACW,sBAA8C,EAC9C,eAAuB,+BAA+B,EACtD,UAAkB,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,EACjD,aAAiC,OAAO,CAAC,GAAG,CAAC,YAAY,EACzD,iBAAqC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EACjE,qBAAyC,OAAO,CAAC,GAAG;SAC1D,oBAAoB;QAEvB,KAAK,CACH,sBAAsB,EACtB,YAAY,EACZ,OAAO,EACP,UAAU,EACV,cAAc,EACd,kBAAkB,CACnB,CAAC;QAfO,2BAAsB,GAAtB,sBAAsB,CAAwB;QAC9C,iBAAY,GAAZ,YAAY,CAA0C;QACtD,YAAO,GAAP,OAAO,CAA0C;QACjD,eAAU,GAAV,UAAU,CAA+C;QACzD,mBAAc,GAAd,cAAc,CAAmD;QACjE,uBAAkB,GAAlB,kBAAkB,CACJ;QAWzB,oBAAe,GAAG,KAAK,EACrB,OAAgB,EAChB,YAEI,EACoB,EAAE;YAC1B,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YACjD,MAAM,GAAG,GAAG,MAAM,YAAE;iBACjB,GAAG,CAAC,8BAA8B,OAAO,CAAC,UAAU,UAAU,EAAE;gBAC/D,IAAI,EAAE;oBACJ,oBAAoB,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU;oBAC/C,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE;iBAChD;gBACD,OAAO,EAAE;oBACP,uBAAuB,EAAE,MAAM;oBAC/B,MAAM,EAAE,oBAAoB;oBAC5B,kBAAkB,EAAE,gBAAgB;oBACpC,GAAG,cAAc;iBAClB;aACF,CAAC;iBACD,IAAI,EAQD,CAAC;YACP,OAAO,GAAG,CAAC,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACzD,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,WAAW,EAAE,CAAC,CAAC,WAAW;aAC3B,CAAC,CAAC,CAAC;QACN,CAAC,CAAC;IApCF,CAAC;CAqCF;AA1DD,4DA0DC"}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { CheerioProjectRepository } from './CheerioProjectRepository';
|
|
2
|
-
import dotenv from 'dotenv';
|
|
3
|
-
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
4
|
-
import { FieldOption, Project } from '../../domain/entities/Project';
|
|
5
|
-
|
|
6
|
-
dotenv.config();
|
|
7
|
-
|
|
8
|
-
describe('CheerioProjectRepository', () => {
|
|
9
|
-
jest.setTimeout(60 * 1000);
|
|
10
|
-
const localStorageRepository = new LocalStorageRepository();
|
|
11
|
-
|
|
12
|
-
const repository = new CheerioProjectRepository(
|
|
13
|
-
localStorageRepository,
|
|
14
|
-
'./tmp/github.com.cookies.json',
|
|
15
|
-
process.env.GH_TOKEN,
|
|
16
|
-
);
|
|
17
|
-
beforeAll(async () => {
|
|
18
|
-
await repository.refreshCookie();
|
|
19
|
-
});
|
|
20
|
-
beforeEach(async () => {
|
|
21
|
-
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe('updateStoryList', () => {
|
|
25
|
-
it('success', async () => {
|
|
26
|
-
const project: Project = {
|
|
27
|
-
completionDate50PercentConfidence: null,
|
|
28
|
-
dependedIssueUrlSeparatedByComma: null,
|
|
29
|
-
id: 'PVT_kwHOAGJHa84AFhgF',
|
|
30
|
-
url: 'https://github.com/users/HiromiShikata/projects/49',
|
|
31
|
-
databaseId: 1447941,
|
|
32
|
-
name: 'V2 project on owner for testing',
|
|
33
|
-
nextActionDate: {
|
|
34
|
-
fieldId: 'PVTF_lAHOAGJHa84AFhgFzgVlnK4',
|
|
35
|
-
name: 'NextActionDate',
|
|
36
|
-
},
|
|
37
|
-
nextActionHour: null,
|
|
38
|
-
remainingEstimationMinutes: null,
|
|
39
|
-
status: {
|
|
40
|
-
fieldId: 'PVTSSF_lAHOAGJHa84AFhgFzgDLt0c',
|
|
41
|
-
name: 'Status',
|
|
42
|
-
statuses: [
|
|
43
|
-
{
|
|
44
|
-
color: 'GRAY',
|
|
45
|
-
description: '',
|
|
46
|
-
id: 'f75ad846',
|
|
47
|
-
name: 'Todo',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
color: 'GRAY',
|
|
51
|
-
description: '',
|
|
52
|
-
id: '47fc9ee4',
|
|
53
|
-
name: 'In Progress',
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
color: 'GRAY',
|
|
57
|
-
description: '',
|
|
58
|
-
id: '98236657',
|
|
59
|
-
name: 'Done',
|
|
60
|
-
},
|
|
61
|
-
],
|
|
62
|
-
},
|
|
63
|
-
story: {
|
|
64
|
-
fieldId: 'PVTSSF_lAHOAGJHa84AFhgFzg1oBms',
|
|
65
|
-
databaseId: 224921195,
|
|
66
|
-
name: 'Story',
|
|
67
|
-
stories: [
|
|
68
|
-
{
|
|
69
|
-
color: 'GRAY',
|
|
70
|
-
description: '',
|
|
71
|
-
id: 'af410dae',
|
|
72
|
-
name: 'story1',
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
color: 'GRAY',
|
|
76
|
-
description: '',
|
|
77
|
-
id: '696ccdef',
|
|
78
|
-
name: 'Workflow Management',
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
color: 'GRAY',
|
|
82
|
-
description: '',
|
|
83
|
-
id: '4fa21881',
|
|
84
|
-
name: 'test',
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
workflowManagementStory: {
|
|
88
|
-
id: '696ccdef',
|
|
89
|
-
name: 'Workflow Management',
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const storyOption: Omit<FieldOption, 'id'> & { id: null } = {
|
|
95
|
-
id: null,
|
|
96
|
-
name: 'test-story-from-unit-test',
|
|
97
|
-
color: 'BLUE',
|
|
98
|
-
description: 'created by unit test',
|
|
99
|
-
};
|
|
100
|
-
const story = project.story;
|
|
101
|
-
if (!story) {
|
|
102
|
-
throw new Error('story is null');
|
|
103
|
-
}
|
|
104
|
-
const newStoryList: Parameters<typeof repository.updateStoryList>['1'] =
|
|
105
|
-
[];
|
|
106
|
-
newStoryList.push(...story.stories.slice(0, 2), storyOption);
|
|
107
|
-
|
|
108
|
-
const res = await repository.updateStoryList(project, newStoryList);
|
|
109
|
-
expect(res[0]).toEqual(newStoryList[0]);
|
|
110
|
-
expect(res[1]).toEqual(newStoryList[1]);
|
|
111
|
-
expect(res[1].id).toBeDefined();
|
|
112
|
-
expect(res[2].name).toEqual(newStoryList[2].name);
|
|
113
|
-
expect(res[2].color).toEqual(newStoryList[2].color);
|
|
114
|
-
expect(res[2].description).toEqual(newStoryList[2].description);
|
|
115
|
-
const resRemoved = await repository.updateStoryList(
|
|
116
|
-
project,
|
|
117
|
-
story.stories,
|
|
118
|
-
);
|
|
119
|
-
expect(resRemoved).toEqual(story.stories);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import ky from 'ky';
|
|
2
|
-
import { BaseGitHubRepository } from './BaseGitHubRepository';
|
|
3
|
-
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
4
|
-
import { FieldOption, Project } from '../../domain/entities/Project';
|
|
5
|
-
import { ProjectRepository } from '../../domain/usecases/adapter-interfaces/ProjectRepository';
|
|
6
|
-
|
|
7
|
-
export class CheerioProjectRepository
|
|
8
|
-
extends BaseGitHubRepository
|
|
9
|
-
implements Pick<ProjectRepository, 'updateStoryList'>
|
|
10
|
-
{
|
|
11
|
-
constructor(
|
|
12
|
-
readonly localStorageRepository: LocalStorageRepository,
|
|
13
|
-
readonly jsonFilePath: string = './tmp/github.com.cookies.json',
|
|
14
|
-
readonly ghToken: string = process.env.GH_TOKEN || 'dummy',
|
|
15
|
-
readonly ghUserName: string | undefined = process.env.GH_USER_NAME,
|
|
16
|
-
readonly ghUserPassword: string | undefined = process.env.GH_USER_PASSWORD,
|
|
17
|
-
readonly ghAuthenticatorKey: string | undefined = process.env
|
|
18
|
-
.GH_AUTHENTICATOR_KEY,
|
|
19
|
-
) {
|
|
20
|
-
super(
|
|
21
|
-
localStorageRepository,
|
|
22
|
-
jsonFilePath,
|
|
23
|
-
ghToken,
|
|
24
|
-
ghUserName,
|
|
25
|
-
ghUserPassword,
|
|
26
|
-
ghAuthenticatorKey,
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
updateStoryList = async (
|
|
30
|
-
project: Project,
|
|
31
|
-
newStoryList: (Omit<FieldOption, 'id'> & {
|
|
32
|
-
id: FieldOption['id'] | null;
|
|
33
|
-
})[],
|
|
34
|
-
): Promise<FieldOption[]> => {
|
|
35
|
-
const browserHeaders = await this.createHeader();
|
|
36
|
-
const raw = await ky
|
|
37
|
-
.put(`https://github.com/memexes/${project.databaseId}/columns`, {
|
|
38
|
-
json: {
|
|
39
|
-
memexProjectColumnId: project.story?.databaseId,
|
|
40
|
-
settings: { width: 200, options: newStoryList },
|
|
41
|
-
},
|
|
42
|
-
headers: {
|
|
43
|
-
'github-verified-fetch': 'true',
|
|
44
|
-
origin: 'https://github.com',
|
|
45
|
-
'x-requested-with': 'XMLHttpRequest',
|
|
46
|
-
...browserHeaders,
|
|
47
|
-
},
|
|
48
|
-
})
|
|
49
|
-
.json<{
|
|
50
|
-
memexProjectColumn: {
|
|
51
|
-
id: string;
|
|
52
|
-
settings: {
|
|
53
|
-
width: number;
|
|
54
|
-
options: FieldOption[];
|
|
55
|
-
};
|
|
56
|
-
};
|
|
57
|
-
}>();
|
|
58
|
-
return raw.memexProjectColumn.settings.options.map((v) => ({
|
|
59
|
-
id: v.id,
|
|
60
|
-
name: v.name,
|
|
61
|
-
color: v.color,
|
|
62
|
-
description: v.description,
|
|
63
|
-
}));
|
|
64
|
-
};
|
|
65
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { BaseGitHubRepository } from './BaseGitHubRepository';
|
|
2
|
-
import { LocalStorageRepository } from './LocalStorageRepository';
|
|
3
|
-
import { FieldOption, Project } from '../../domain/entities/Project';
|
|
4
|
-
import { ProjectRepository } from '../../domain/usecases/adapter-interfaces/ProjectRepository';
|
|
5
|
-
export declare class CheerioProjectRepository extends BaseGitHubRepository implements Pick<ProjectRepository, 'updateStoryList'> {
|
|
6
|
-
readonly localStorageRepository: LocalStorageRepository;
|
|
7
|
-
readonly jsonFilePath: string;
|
|
8
|
-
readonly ghToken: string;
|
|
9
|
-
readonly ghUserName: string | undefined;
|
|
10
|
-
readonly ghUserPassword: string | undefined;
|
|
11
|
-
readonly ghAuthenticatorKey: string | undefined;
|
|
12
|
-
constructor(localStorageRepository: LocalStorageRepository, jsonFilePath?: string, ghToken?: string, ghUserName?: string | undefined, ghUserPassword?: string | undefined, ghAuthenticatorKey?: string | undefined);
|
|
13
|
-
updateStoryList: (project: Project, newStoryList: (Omit<FieldOption, "id"> & {
|
|
14
|
-
id: FieldOption["id"] | null;
|
|
15
|
-
})[]) => Promise<FieldOption[]>;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=CheerioProjectRepository.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CheerioProjectRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/CheerioProjectRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4DAA4D,CAAC;AAE/F,qBAAa,wBACX,SAAQ,oBACR,YAAW,IAAI,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAGnD,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB;IACvD,QAAQ,CAAC,YAAY,EAAE,MAAM;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;IACvC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS;IAC3C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS;gBALtC,sBAAsB,EAAE,sBAAsB,EAC9C,YAAY,GAAE,MAAwC,EACtD,OAAO,GAAE,MAAwC,EACjD,UAAU,GAAE,MAAM,GAAG,SAAoC,EACzD,cAAc,GAAE,MAAM,GAAG,SAAwC,EACjE,kBAAkB,GAAE,MAAM,GAAG,SACf;IAWzB,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,CA8BvB;CACH"}
|