Changes
18 changed files (+197/-47)
-
-
@@ -28,3 +28,8 @@ # YAML は 2 スペース以外のインデントを仕様レベルで読むことができない。[*.{yml,yaml}] indent_style = space indent_size = 2 # `gleam format` はインデントの設定ができない。 [*.gleam] indent_style = space indent_size = 2
-
-
-
@@ -5,3 +5,4 @@ # SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com># SPDX-License-Identifier: AGPL-3.0-only dprint 0.47.5 bun 1.1.38 gleam 1.6.3
-
-
-
-
@@ -6,6 +6,7 @@# 開発ガイド [bun]: https://bun.sh/ [gleam]: https://gleam.run/ [dprint]: https://dprint.dev/ ## 前提環境
-
@@ -13,6 +14,7 @@このプロジェクトを開発するにあたり以下のものが必要になる。 - [Bun][bun] v1.1.x - [Gleam][gleam] v1.6.x - [dprint][dprint] v0.47.x - [reuse tool](https://github.com/fsfe/reuse-tool) v4 以上
-
-
-
@@ -15,10 +15,17 @@ "commands": [{ "exts": ["proto"], "command": "bunx buf format {{file_path}}" }, { "exts": ["gleam"], "command": "gleam format --stdin" } ] }, "yaml": {}, "toml": { "useTabs": true }, "markup": { "useTabs": true },
-
@@ -29,6 +36,7 @@ "https://plugins.dprint.dev/biome-0.7.1.wasm","https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0", "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm", // "HTML, Vue, Svelte, Astro, Angular, Jinja, Twig, Nunjucks, and Vento files via markup_fmt." "https://plugins.dprint.dev/g-plane/markup_fmt-v0.18.0.wasm" "https://plugins.dprint.dev/g-plane/markup_fmt-v0.18.0.wasm", "https://plugins.dprint.dev/toml-0.6.3.wasm" ] }
-
-
-
@@ -6,3 +6,7 @@# What: ビルドされた PWA のページとアセット。 # Why: 編集するものではないため。 /dist # What: Gleam のビルドファイルや中間ファイルのディレクトリ。 # Why: ソースコードを基に毎回生成されるため。編集はしない。 /build
-
-
packages/pwa/gleam.toml (new)
-
@@ -0,0 +1,14 @@# Gleam のプロジェクトマニフェスト。 # # SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> # SPDX-License-Identifier: AGPL-3.0-only name = "yamori_pwa" version = "0.1.0" # Web フロントエンド用途のみのため、フラグを指定しなくてすむように固定する。 target = "javascript" [dependencies] gleam_stdlib = ">= 0.45.0 and < 1.0.0" gleam_json = ">= 2.1.0 and < 3.0.0"
-
-
-
@@ -0,0 +1,11 @@# This file was generated by Gleam # You typically do not need to edit this file packages = [ { name = "gleam_json", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "0A57FB5666E695FD2BEE74C0428A98B0FC11A395D2C7B4CDF5E22C5DD32C74C6" }, { name = "gleam_stdlib", version = "0.45.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "206FCE1A76974AECFC55AEBCD0217D59EDE4E408C016E2CFCCC8FF51278F186E" }, ] [requirements] gleam_json = { version = ">= 2.1.0 and < 3.0.0" } gleam_stdlib = { version = ">= 0.45.0 and < 1.0.0" }
-
-
-
@@ -0,0 +1,5 @@Gleam のロックファイル。 コンパイラが常に全書き換えする "仕様" のためヘッダを書いても消される。 SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> SPDX-License-Identifier: AGPL-3.0-only
-
-
-
@@ -13,6 +13,7 @@ "@yamori/proto": "workspace:*","idb": "^8.0.0" }, "devDependencies": { "@pocka/rollup-plugin-gleam": "^0.1.2", "@types/bun": "^1.1.14", "fake-indexeddb": "^6.0.0", "typescript": "^5.7.2",
-
-
-
@@ -0,0 +1,7 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import { ListResponse } from "@yamori/proto/yamori/workspace/v1/list_response_pb.js"; export function encode_list_request(): Uint8Array; export function decode_list_response(binary: Uint8Array): ListResponse;
-
-
-
@@ -0,0 +1,17 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import gleam/json import protobuf pub fn encode_list_request() -> protobuf.Binary { json.object([]) |> protobuf.encode(protobuf.list_request()) } pub fn decode_list_response( binary: protobuf.Binary, ) -> protobuf.Message(protobuf.ListResponse) { binary |> protobuf.decode(protobuf.list_response()) }
-
-
-
@@ -1,11 +1,8 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import { create, fromBinary, toBinary } from "@bufbuild/protobuf"; import { ListRequestSchema } from "@yamori/proto/yamori/workspace/v1/list_request_pb.js"; import { ListResponseSchema } from "@yamori/proto/yamori/workspace/v1/list_response_pb.js"; import { isValidMessage, type Message } from "./worker/message.ts"; import { encode_list_request, decode_list_response } from "./app.gleam"; const button = document.createElement("button"); button.textContent = "Send Message";
-
@@ -21,57 +18,64 @@ const worker = new Worker(new URL("./worker/main.ts", import.meta.url), {type: "module", }); interface RequestParameters { service: string; method: string; request: Uint8Array; } function request({ service, method, request }: RequestParameters): Promise<Uint8Array> { const id = crypto.randomUUID(); return new Promise((resolve) => { const handler = (event: MessageEvent) => { if (!isValidMessage(event.data) || event.data.id !== id) { return; } worker.removeEventListener("message", handler); if (event.data.service !== service || event.data.method !== method) { throw new Error( `Received response with incorrect service/method: expected=${service}.${method}, received=${event.data.service}/${event.data.method}`, ); } resolve(event.data.data); }; worker.addEventListener("message", handler); worker.postMessage( { id, service, method, data: request, } satisfies Message, { transfer: [request.buffer], }, ); }); } worker.addEventListener( "message", (ev) => { if (ev.data === "ready") { button.disabled = false; button.addEventListener("click", (ev) => { button.addEventListener("click", async (ev) => { ev.preventDefault(); const req = toBinary(ListRequestSchema, create(ListRequestSchema, {})); worker.postMessage( { service: "yamori.workspace.v1.KeyValueStorageBasedWorkspaceService", method: "List", data: req, } satisfies Message, { transfer: [req.buffer], }, ); }); worker.addEventListener("message", (ev) => { if (!isValidMessage(ev.data)) { console.warn("Invalid message sent from worker thread."); return; } switch (ev.data.service) { case "yamori.workspace.v1.KeyValueStorageBasedWorkspaceService": { switch (ev.data.method) { case "List": { const resp = fromBinary(ListResponseSchema, ev.data.data); const resp = await request({ service: "yamori.workspace.v1.KeyValueStorageBasedWorkspaceService", method: "List", request: encode_list_request(), }); output.textContent += "\n" + JSON.stringify(resp, null, 2); return; } default: { console.warn( `Unknown method name "${ev.data.method}" at ${ev.data.service}`, ); return; } } } default: { console.warn(`Unknown service name "${ev.data.service}"`); return; } } output.textContent += "\n" + JSON.stringify(decode_list_response(resp), null, 2); }); } },
-
-
-
@@ -0,0 +1,33 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import { create, fromBinary, toBinary, type DescMessage, type MessageInitShape, } from "@bufbuild/protobuf"; // TODO: Move these out to services/ or similar. import { ListRequestSchema } from "@yamori/proto/yamori/workspace/v1/list_request_pb.js"; import { ListResponseSchema } from "@yamori/proto/yamori/workspace/v1/list_response_pb.js"; export function ListRequest() { return ListRequestSchema; } export function ListResponse() { return ListResponseSchema; } export function decode<Message extends DescMessage>(binary: Uint8Array, schema: Message) { return fromBinary(schema, binary); } export function encode<Message extends DescMessage>( payload: MessageInitShape<Message>, schema: Message, ) { return toBinary(schema, create(schema, payload)); }
-
-
-
@@ -0,0 +1,26 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import gleam/json pub type Message(a) pub type Schema(a) pub type Binary @external(javascript, "./protobuf.ffi.ts", "decode") pub fn decode(binary: Binary, schema: Schema(a)) -> Message(a) @external(javascript, "./protobuf.ffi.ts", "encode") pub fn encode(payload: json.Json, schema: Schema(a)) -> Binary pub type ListRequest @external(javascript, "./protobuf.ffi.ts", "ListRequest") pub fn list_request() -> Schema(ListRequest) pub type ListResponse @external(javascript, "./protobuf.ffi.ts", "ListResponse") pub fn list_response() -> Schema(ListResponse)
-
-
-
@@ -5,6 +5,7 @@ // SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com>// SPDX-License-Identifier: AGPL-3.0-only export interface Message { id: unknown; service: string; method: string; data: Uint8Array;
-
@@ -12,6 +13,10 @@ }export function isValidMessage(x: unknown): x is Message { if (typeof x !== "object" || !x) { return false; } if (!("id" in x)) { return false; }
-
-
-
@@ -8,6 +8,7 @@ "noUnusedParameters": true,"strict": true, "allowImportingTsExtensions": true, "skipLibCheck": true, "allowArbitraryExtensions": true, "module": "ES2022", "moduleResolution": "Bundler", "noEmit": true,
-
-
-
@@ -4,6 +4,7 @@ //// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import { gleam } from "@pocka/rollup-plugin-gleam"; import { defineConfig } from "vite"; export default defineConfig({
-
@@ -12,4 +13,9 @@ build: {emptyOutDir: true, outDir: "../dist", }, plugins: [ gleam({ gleamToml: new URL("./gleam.toml", import.meta.url), }), ], });
-