github-issue-tower-defence-management 1.147.2 → 1.147.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js +33 -4
- package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.test.ts +141 -0
- package/src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts +50 -4
- package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts +2 -0
- package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [1.147.4](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.147.3...v1.147.4) (2026-08-09)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **story:** consolidate a story view link written for an earlier view id ([#1464](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1464)) ([31c2035](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/31c2035320933b65544a3c0e3bc88b90d1a20c07))
|
|
7
|
+
|
|
8
|
+
## [1.147.3](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.147.2...v1.147.3) (2026-08-09)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **story:** keep the story view link on the first line of the story issue body ([#1460](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1460)) ([20b911a](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/20b911a5062e65d726e9a1a8b8be03f2307b2e17))
|
|
14
|
+
|
|
1
15
|
## [1.147.2](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.147.1...v1.147.2) (2026-08-09)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -29,10 +29,8 @@ class ConvertCheckboxToIssueInStoryIssueUseCase {
|
|
|
29
29
|
console.warn(`ConvertCheckboxToIssueInStoryIssueUseCase: story issue not found by URL (possibly deleted), skipping story. storyIssueUrl: ${storyIssue.url}`);
|
|
30
30
|
continue;
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!freshStoryIssue.body.includes(storyViewLink)) {
|
|
35
|
-
newBody = `${storyViewLink}\n\n${newBody}`;
|
|
32
|
+
let newBody = this.bodyWithStoryViewLinkOnFirstLine(freshStoryIssue.body, input.urlOfStoryView, storyOption.name);
|
|
33
|
+
if (newBody !== freshStoryIssue.body) {
|
|
36
34
|
await this.issueRepository.updateIssue({
|
|
37
35
|
...freshStoryIssue,
|
|
38
36
|
body: newBody,
|
|
@@ -64,9 +62,40 @@ class ConvertCheckboxToIssueInStoryIssueUseCase {
|
|
|
64
62
|
}
|
|
65
63
|
}
|
|
66
64
|
};
|
|
65
|
+
this.bodyWithStoryViewLinkOnFirstLine = (body, urlOfStoryView, storyName) => {
|
|
66
|
+
const storyViewLink = this.buildStoryViewLink(urlOfStoryView, storyName);
|
|
67
|
+
const storyViewLinkPattern = this.buildStoryViewLinkPattern(urlOfStoryView, storyName);
|
|
68
|
+
const isStoryViewLinkLine = (line) => storyViewLinkPattern.test(line);
|
|
69
|
+
const lines = body.split('\n');
|
|
70
|
+
const remainingLines = [];
|
|
71
|
+
for (let i = 0; i < lines.length; i++) {
|
|
72
|
+
if (!isStoryViewLinkLine(lines[i])) {
|
|
73
|
+
remainingLines.push(lines[i]);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (i + 1 < lines.length && lines[i + 1].trim() === '') {
|
|
77
|
+
i++;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (remainingLines.length > 0 &&
|
|
81
|
+
remainingLines[remainingLines.length - 1].trim() === '') {
|
|
82
|
+
remainingLines.pop();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
while (remainingLines.length > 0 && remainingLines[0].trim() === '') {
|
|
86
|
+
remainingLines.shift();
|
|
87
|
+
}
|
|
88
|
+
return `${storyViewLink}\n\n${remainingLines.join('\n')}`;
|
|
89
|
+
};
|
|
67
90
|
this.buildStoryViewLink = (urlOfStoryView, storyName) => {
|
|
68
91
|
return `${urlOfStoryView}?sliceBy%5Bvalue%5D=${(0, utils_1.encodeForURI)(storyName)}`;
|
|
69
92
|
};
|
|
93
|
+
this.buildStoryViewLinkPattern = (urlOfStoryView, storyName) => {
|
|
94
|
+
const escapeForRegularExpression = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
95
|
+
const storyViewProjectUrl = urlOfStoryView.split('/views/')[0];
|
|
96
|
+
const storySliceQuery = `?sliceBy%5Bvalue%5D=${(0, utils_1.encodeForURI)(storyName)}`;
|
|
97
|
+
return new RegExp(`${escapeForRegularExpression(storyViewProjectUrl)}(/views/\\d+)?${escapeForRegularExpression(storySliceQuery)}(?![\\w%])`);
|
|
98
|
+
};
|
|
70
99
|
this.findCheckboxTextsNotCreatedIssue = (storyIssueBody) => {
|
|
71
100
|
const regexToFindCheckboxes = /^- \[ ] (.*)$/gm;
|
|
72
101
|
const match = storyIssueBody.match(regexToFindCheckboxes);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvertCheckboxToIssueInStoryIssueUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts"],"names":[],"mappings":";;;AAIA,mCAAuC;AACvC,+DAAgE;AAGhE,MAAa,yCAAyC;IACpD,YACW,eAOR;QAPQ,oBAAe,GAAf,eAAe,CAOvB;QAGH,QAAG,GAAG,KAAK,EAAE,KAQZ,EAAiB,EAAE;YAClB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAClC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YAED,KAAK,MAAM,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;gBAC7D,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAC7C,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CACzC,CAAC;gBACF,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBAC/D,IAAI,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC9C,SAAS;gBACX,CAAC;qBAAM,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,EAAE,CAAC;oBACvC,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;gBAChE,CAAC;qBAAM,IACL,UAAU,CAAC,QAAQ;oBACnB,UAAU,CAAC,MAAM,KAAK,mCAAkB,EACxC,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAC9D,UAAU,CAAC,GAAG,CACf,CAAC;gBACF,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,OAAO,CAAC,IAAI,CACV,8HAA8H,UAAU,CAAC,GAAG,EAAE,CAC/I,CAAC;oBACF,SAAS;gBACX,CAAC;gBACD,
|
|
1
|
+
{"version":3,"file":"ConvertCheckboxToIssueInStoryIssueUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1208,6 +1208,147 @@ Some description without checkboxes`,
|
|
|
1208
1208
|
}),
|
|
1209
1209
|
).rejects.toThrow('GraphQL request failed');
|
|
1210
1210
|
});
|
|
1211
|
+
|
|
1212
|
+
describe('story view link position', () => {
|
|
1213
|
+
const storyViewLink = 'https://example.com?sliceBy%5Bvalue%5D=Story%201';
|
|
1214
|
+
|
|
1215
|
+
const runWithBody = async (body: string): Promise<void> => {
|
|
1216
|
+
jest.clearAllMocks();
|
|
1217
|
+
mockIssueRepository.getIssueByUrl.mockResolvedValue({
|
|
1218
|
+
...basicStoryIssue1,
|
|
1219
|
+
body,
|
|
1220
|
+
});
|
|
1221
|
+
const useCase = new ConvertCheckboxToIssueInStoryIssueUseCase(
|
|
1222
|
+
mockIssueRepository,
|
|
1223
|
+
);
|
|
1224
|
+
await useCase.run({
|
|
1225
|
+
project: singleStoryProject,
|
|
1226
|
+
issues: [basicStoryIssue1],
|
|
1227
|
+
cacheUsed: false,
|
|
1228
|
+
urlOfStoryView: 'https://example.com',
|
|
1229
|
+
storyObjectMap: singleStoryObjectMap,
|
|
1230
|
+
manager: 'ManagerName',
|
|
1231
|
+
createTaskFromStoryBodyCheckboxEnabled: false,
|
|
1232
|
+
});
|
|
1233
|
+
};
|
|
1234
|
+
|
|
1235
|
+
it('moves the story view link back to the first line when it sits in the middle of the body', async () => {
|
|
1236
|
+
await runWithBody(`Background text
|
|
1237
|
+
|
|
1238
|
+
${storyViewLink}
|
|
1239
|
+
|
|
1240
|
+
- [ ] Task 1`);
|
|
1241
|
+
|
|
1242
|
+
expect(mockIssueRepository.updateIssue.mock.calls).toHaveLength(1);
|
|
1243
|
+
expect(mockIssueRepository.updateIssue.mock.calls[0][0].body)
|
|
1244
|
+
.toBe(`${storyViewLink}
|
|
1245
|
+
|
|
1246
|
+
Background text
|
|
1247
|
+
|
|
1248
|
+
- [ ] Task 1`);
|
|
1249
|
+
});
|
|
1250
|
+
|
|
1251
|
+
it('moves the story view link back to the first line when it sits at the bottom of the body', async () => {
|
|
1252
|
+
await runWithBody(`Background text
|
|
1253
|
+
|
|
1254
|
+
- [ ] Task 1
|
|
1255
|
+
|
|
1256
|
+
${storyViewLink}`);
|
|
1257
|
+
|
|
1258
|
+
expect(mockIssueRepository.updateIssue.mock.calls).toHaveLength(1);
|
|
1259
|
+
expect(mockIssueRepository.updateIssue.mock.calls[0][0].body)
|
|
1260
|
+
.toBe(`${storyViewLink}
|
|
1261
|
+
|
|
1262
|
+
Background text
|
|
1263
|
+
|
|
1264
|
+
- [ ] Task 1`);
|
|
1265
|
+
});
|
|
1266
|
+
|
|
1267
|
+
it('leaves a single story view link on the first line when the body holds more than one copy', async () => {
|
|
1268
|
+
await runWithBody(`${storyViewLink}
|
|
1269
|
+
|
|
1270
|
+
Background text
|
|
1271
|
+
|
|
1272
|
+
${storyViewLink}`);
|
|
1273
|
+
|
|
1274
|
+
expect(mockIssueRepository.updateIssue.mock.calls).toHaveLength(1);
|
|
1275
|
+
expect(mockIssueRepository.updateIssue.mock.calls[0][0].body)
|
|
1276
|
+
.toBe(`${storyViewLink}
|
|
1277
|
+
|
|
1278
|
+
Background text`);
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
it('does not update the issue when the story view link is already the first line', async () => {
|
|
1282
|
+
await runWithBody(`${storyViewLink}
|
|
1283
|
+
|
|
1284
|
+
- [ ] Task 1`);
|
|
1285
|
+
|
|
1286
|
+
expect(mockIssueRepository.updateIssue).not.toHaveBeenCalled();
|
|
1287
|
+
});
|
|
1288
|
+
});
|
|
1289
|
+
|
|
1290
|
+
describe('story view link written for an earlier view id', () => {
|
|
1291
|
+
const urlOfStoryView =
|
|
1292
|
+
'https://github.com/users/TestUser/projects/48/views/48';
|
|
1293
|
+
const currentStoryViewLink = `${urlOfStoryView}?sliceBy%5Bvalue%5D=Story%201`;
|
|
1294
|
+
const earlierStoryViewLink =
|
|
1295
|
+
'https://github.com/users/TestUser/projects/48/views/44?sliceBy%5Bvalue%5D=Story%201';
|
|
1296
|
+
const otherStoryViewLink = `${urlOfStoryView}?sliceBy%5Bvalue%5D=Story%202`;
|
|
1297
|
+
|
|
1298
|
+
const runWithBody = async (body: string): Promise<void> => {
|
|
1299
|
+
jest.clearAllMocks();
|
|
1300
|
+
mockIssueRepository.getIssueByUrl.mockResolvedValue({
|
|
1301
|
+
...basicStoryIssue1,
|
|
1302
|
+
body,
|
|
1303
|
+
});
|
|
1304
|
+
const useCase = new ConvertCheckboxToIssueInStoryIssueUseCase(
|
|
1305
|
+
mockIssueRepository,
|
|
1306
|
+
);
|
|
1307
|
+
await useCase.run({
|
|
1308
|
+
project: singleStoryProject,
|
|
1309
|
+
issues: [basicStoryIssue1],
|
|
1310
|
+
cacheUsed: false,
|
|
1311
|
+
urlOfStoryView,
|
|
1312
|
+
storyObjectMap: singleStoryObjectMap,
|
|
1313
|
+
manager: 'ManagerName',
|
|
1314
|
+
createTaskFromStoryBodyCheckboxEnabled: false,
|
|
1315
|
+
});
|
|
1316
|
+
};
|
|
1317
|
+
|
|
1318
|
+
it('removes a story view link that names an earlier view id of the same project', async () => {
|
|
1319
|
+
await runWithBody(`${currentStoryViewLink}
|
|
1320
|
+
|
|
1321
|
+
${earlierStoryViewLink}
|
|
1322
|
+
|
|
1323
|
+
- [ ] Task 1`);
|
|
1324
|
+
|
|
1325
|
+
expect(mockIssueRepository.updateIssue.mock.calls).toHaveLength(1);
|
|
1326
|
+
expect(mockIssueRepository.updateIssue.mock.calls[0][0].body)
|
|
1327
|
+
.toBe(`${currentStoryViewLink}
|
|
1328
|
+
|
|
1329
|
+
- [ ] Task 1`);
|
|
1330
|
+
});
|
|
1331
|
+
|
|
1332
|
+
it('lifts a story view link that names an earlier view id to the current link on the first line', async () => {
|
|
1333
|
+
await runWithBody(`Background text
|
|
1334
|
+
|
|
1335
|
+
${earlierStoryViewLink}`);
|
|
1336
|
+
|
|
1337
|
+
expect(mockIssueRepository.updateIssue.mock.calls).toHaveLength(1);
|
|
1338
|
+
expect(mockIssueRepository.updateIssue.mock.calls[0][0].body)
|
|
1339
|
+
.toBe(`${currentStoryViewLink}
|
|
1340
|
+
|
|
1341
|
+
Background text`);
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1344
|
+
it('keeps a story view link that names a different story', async () => {
|
|
1345
|
+
await runWithBody(`${currentStoryViewLink}
|
|
1346
|
+
|
|
1347
|
+
${otherStoryViewLink}`);
|
|
1348
|
+
|
|
1349
|
+
expect(mockIssueRepository.updateIssue).not.toHaveBeenCalled();
|
|
1350
|
+
});
|
|
1351
|
+
});
|
|
1211
1352
|
});
|
|
1212
1353
|
|
|
1213
1354
|
describe('buildStoryViewLink', () => {
|
|
@@ -56,13 +56,12 @@ export class ConvertCheckboxToIssueInStoryIssueUseCase {
|
|
|
56
56
|
);
|
|
57
57
|
continue;
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
let newBody = this.bodyWithStoryViewLinkOnFirstLine(
|
|
60
|
+
freshStoryIssue.body,
|
|
60
61
|
input.urlOfStoryView,
|
|
61
62
|
storyOption.name,
|
|
62
63
|
);
|
|
63
|
-
|
|
64
|
-
if (!freshStoryIssue.body.includes(storyViewLink)) {
|
|
65
|
-
newBody = `${storyViewLink}\n\n${newBody}`;
|
|
64
|
+
if (newBody !== freshStoryIssue.body) {
|
|
66
65
|
await this.issueRepository.updateIssue({
|
|
67
66
|
...freshStoryIssue,
|
|
68
67
|
body: newBody,
|
|
@@ -115,9 +114,56 @@ export class ConvertCheckboxToIssueInStoryIssueUseCase {
|
|
|
115
114
|
}
|
|
116
115
|
}
|
|
117
116
|
};
|
|
117
|
+
bodyWithStoryViewLinkOnFirstLine = (
|
|
118
|
+
body: string,
|
|
119
|
+
urlOfStoryView: string,
|
|
120
|
+
storyName: string,
|
|
121
|
+
): string => {
|
|
122
|
+
const storyViewLink = this.buildStoryViewLink(urlOfStoryView, storyName);
|
|
123
|
+
const storyViewLinkPattern = this.buildStoryViewLinkPattern(
|
|
124
|
+
urlOfStoryView,
|
|
125
|
+
storyName,
|
|
126
|
+
);
|
|
127
|
+
const isStoryViewLinkLine = (line: string): boolean =>
|
|
128
|
+
storyViewLinkPattern.test(line);
|
|
129
|
+
const lines = body.split('\n');
|
|
130
|
+
const remainingLines: string[] = [];
|
|
131
|
+
for (let i = 0; i < lines.length; i++) {
|
|
132
|
+
if (!isStoryViewLinkLine(lines[i])) {
|
|
133
|
+
remainingLines.push(lines[i]);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (i + 1 < lines.length && lines[i + 1].trim() === '') {
|
|
137
|
+
i++;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (
|
|
141
|
+
remainingLines.length > 0 &&
|
|
142
|
+
remainingLines[remainingLines.length - 1].trim() === ''
|
|
143
|
+
) {
|
|
144
|
+
remainingLines.pop();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
while (remainingLines.length > 0 && remainingLines[0].trim() === '') {
|
|
148
|
+
remainingLines.shift();
|
|
149
|
+
}
|
|
150
|
+
return `${storyViewLink}\n\n${remainingLines.join('\n')}`;
|
|
151
|
+
};
|
|
118
152
|
buildStoryViewLink = (urlOfStoryView: string, storyName: string): string => {
|
|
119
153
|
return `${urlOfStoryView}?sliceBy%5Bvalue%5D=${encodeForURI(storyName)}`;
|
|
120
154
|
};
|
|
155
|
+
buildStoryViewLinkPattern = (
|
|
156
|
+
urlOfStoryView: string,
|
|
157
|
+
storyName: string,
|
|
158
|
+
): RegExp => {
|
|
159
|
+
const escapeForRegularExpression = (value: string): string =>
|
|
160
|
+
value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
161
|
+
const storyViewProjectUrl = urlOfStoryView.split('/views/')[0];
|
|
162
|
+
const storySliceQuery = `?sliceBy%5Bvalue%5D=${encodeForURI(storyName)}`;
|
|
163
|
+
return new RegExp(
|
|
164
|
+
`${escapeForRegularExpression(storyViewProjectUrl)}(/views/\\d+)?${escapeForRegularExpression(storySliceQuery)}(?![\\w%])`,
|
|
165
|
+
);
|
|
166
|
+
};
|
|
121
167
|
findCheckboxTextsNotCreatedIssue = (storyIssueBody: string): string[] => {
|
|
122
168
|
const regexToFindCheckboxes = /^- \[ ] (.*)$/gm;
|
|
123
169
|
const match = storyIssueBody.match(regexToFindCheckboxes);
|
|
@@ -15,7 +15,9 @@ export declare class ConvertCheckboxToIssueInStoryIssueUseCase {
|
|
|
15
15
|
manager: Member["name"];
|
|
16
16
|
createTaskFromStoryBodyCheckboxEnabled: boolean;
|
|
17
17
|
}) => Promise<void>;
|
|
18
|
+
bodyWithStoryViewLinkOnFirstLine: (body: string, urlOfStoryView: string, storyName: string) => string;
|
|
18
19
|
buildStoryViewLink: (urlOfStoryView: string, storyName: string) => string;
|
|
20
|
+
buildStoryViewLinkPattern: (urlOfStoryView: string, storyName: string) => RegExp;
|
|
19
21
|
findCheckboxTextsNotCreatedIssue: (storyIssueBody: string) => string[];
|
|
20
22
|
}
|
|
21
23
|
//# sourceMappingURL=ConvertCheckboxToIssueInStoryIssueUseCase.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvertCheckboxToIssueInStoryIssueUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,qBAAa,yCAAyC;IAElD,QAAQ,CAAC,eAAe,EAAE,IAAI,CAC5B,eAAe,EACb,gBAAgB,GAChB,aAAa,GACb,aAAa,GACb,eAAe,GACf,mBAAmB,CACtB;gBAPQ,eAAe,EAAE,IAAI,CAC5B,eAAe,EACb,gBAAgB,GAChB,aAAa,GACb,aAAa,GACb,eAAe,GACf,mBAAmB,CACtB;IAGH,GAAG,GAAU,OAAO;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,cAAc,CAAC;QAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,sCAAsC,EAAE,OAAO,CAAC;KACjD,KAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"ConvertCheckboxToIssueInStoryIssueUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,qBAAa,yCAAyC;IAElD,QAAQ,CAAC,eAAe,EAAE,IAAI,CAC5B,eAAe,EACb,gBAAgB,GAChB,aAAa,GACb,aAAa,GACb,eAAe,GACf,mBAAmB,CACtB;gBAPQ,eAAe,EAAE,IAAI,CAC5B,eAAe,EACb,gBAAgB,GAChB,aAAa,GACb,aAAa,GACb,eAAe,GACf,mBAAmB,CACtB;IAGH,GAAG,GAAU,OAAO;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,cAAc,CAAC;QAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,sCAAsC,EAAE,OAAO,CAAC;KACjD,KAAG,OAAO,CAAC,IAAI,CAAC,CAuFf;IACF,gCAAgC,GAC9B,MAAM,MAAM,EACZ,gBAAgB,MAAM,EACtB,WAAW,MAAM,KAChB,MAAM,CA8BP;IACF,kBAAkB,GAAI,gBAAgB,MAAM,EAAE,WAAW,MAAM,KAAG,MAAM,CAEtE;IACF,yBAAyB,GACvB,gBAAgB,MAAM,EACtB,WAAW,MAAM,KAChB,MAAM,CAQP;IACF,gCAAgC,GAAI,gBAAgB,MAAM,KAAG,MAAM,EAAE,CAcnE;CACH"}
|