Scrapboxの書き込みAPI案
共同projectでこれをやるとWOMが発生してよくない影響が出るかもしれないが、個人projectでやる分には何の問題もないし、むしろ出来たほうがいろいろ便利 /nishio/nishio.iconさんも井戸端でそんなこと言ってた
ここではそのAPIの設計案を書き出す
提供する機能
任意projectのStreamの購読
interface example
code:ts
const listen = await listenStream("5f2f02f3c4a48d00237e1534");
while (true) {
const event = await listen();
console.info(event);
// ...
}
Promiseで包む処理を外部に切り出せる
socket.io-requestはtypescriptじゃなくて使いづらいので、ここから独自のError classとserver side対応を削ったものを自前で作る いや、Scrapboxのwebsocketを操作する低レイヤーlibraryに組み込んでしまうか
機能
timeoutで例外を投げる
server io disconnectやerror propertyが返ってきたら例外として処理する
送信と受信をともにPromiseで包む
送信と通信時のobjects全てに型をつける
code:mod.ts
import { socketIO } from "../userscript-socket-io/mod.ts";
import { getPromiseSettledAnytimes } from "../getpromisesettledanytimes/mod.ts";
export async function listenStream(projectId: string) {
const socket = await socketIO();
await new Promise((resolve, reject) => {
const onDisconnect = (message: string) => {
if (message !== "io server disconnect") return;
reject(message);
};
socket.emit("socket.io-request", {
method: "room:join",
data: {
pageId: null,
projectId,
projectUpdatesStream: true,
},
}, (e: unknown) => {
socket.off("disconnect", onDisconnect);
resolve(e);
});
socket.once("disconnect", onDisconnect);
});
socket.on("projectUpdatesStream:commit", resolve);
socket.on("projectUpdatesStream:event", resolve);
return waitForEvent;
}
任意projectの任意のpageの
更新購読
code:ts
for await (const event of listenPageUpdate(projectId, pageId)) {
//...
}
書き込み
編集
code:ts
// 内部で/api/pages/:projectName/:pageTitleを呼び出してpage idとcommit idを取得しておく
const {
update,
insert,
delete,
} = await joinPageRoom(projectName, pageTitle);
await updateLine(lineId, newText);
任意行の下へ挿入
削除
一個ずつ命令するの面倒だろうから、宣言的UIのようにページ全体を書き換えるような関数を用意してしまおうかな 現在のページ内容と更新後のページ内容とを比較し、差分だけcommitを作って更新する
これにより、変更する必要のない行のテロメアをそのままにできる
使う側も、何行目に挿入するとか考えなくてすむから楽
ページ削除
code:ts
await deletePage(projectId, pageId);
ピン留め/ピン留め解除
commit Idは自動で作る
conflict時の処理はどうする
まあ個人用途でしか考えてないし、conflict解決機能はつけなくてもいいと思う
他のuserのカーソル位置の更新購読
これは要らないかも?
任意projectの新規ページ作成
これはいらないか
普通の空ページのpage idをとってきてそこに書き込めばいい
まあこんなところか
実装