-
Notifications
You must be signed in to change notification settings - Fork 0
/
pushTasks.ts
57 lines (52 loc) · 1.87 KB
/
pushTasks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { TaskBlock, toString } from "./task.ts";
import { format, toTitle } from "./diary.ts";
import { oneByOne, OneByOneResult } from "./utils.ts";
import { isSameDay } from "./deps/date-fns.ts";
import { patch, Socket } from "./deps/scrapbox-websocket.ts";
export interface PushTasksOptions {
/** 書き込みに使うSocket */
socket: Socket;
}
export interface PushTasksResult {
/** 書き込み先の日付ページの日付 */ date: Date;
/** 書き込んだタスクの数 */ size: number;
}
/** 任意個のタスクを特定プロジェクトの日付ページに書き込む
*
* @param project 書き込み先プロジェクト
* @param tasks 書き込むタスク (インデントでぶら下げた行をlinesに入れられる)
* @param init
* @return 書き込みの成否が入ったasync iterator
*/
export async function* pushTasks(
project: string,
tasks: readonly TaskBlock[],
init: PushTasksOptions,
): AsyncGenerator<OneByOneResult<PushTasksResult>, void, void> {
const stacks = [...tasks];
const promises = [] as Promise<PushTasksResult>[];
while (stacks.length > 0) {
const task = stacks.shift();
if (!task) break;
// taskと同じ日付のtaskを集める
const date = task.base;
const tasks_ = [task];
for (let i = 0; i < stacks.length; i++) {
if (!isSameDay(stacks[i].base, date)) continue;
// stacksからtasks_に移動する
tasks_.push(...stacks.splice(i, 1));
i--;
}
// 非同期に書き込む
promises.push((async () => {
await patch(project, toTitle(date), (lines) =>
format([
...lines.map((line) => line.text),
...tasks_.flatMap((task) => [toString(task), ...task.lines ?? []]),
]), init);
return { date, size: tasks_.length };
})());
}
// 書き込みの成否と書き込み先の日付を返す
yield* oneByOne(promises);
}