-
Notifications
You must be signed in to change notification settings - Fork 36
Upgrade devDependencies and implement kernel plugin demo #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Vanessa219
merged 15 commits into
siyuan-note:main
from
Zuoqiu-Yingyi:feat/kernel-plugin
May 12, 2026
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
cae0262
chore(dependencies): Upgrade devDependencies and refresh pnpm lock
Zuoqiu-Yingyi 33174a3
docs: add kernel plugin demo design spec
Zuoqiu-Yingyi 1600518
docs: add kernel plugin demo implementation plan
Zuoqiu-Yingyi 24f2456
feat: implement kernel plugin demo with full API coverage and TSDoc
Zuoqiu-Yingyi d49d380
Add kernel build and split dev/build scripts
Zuoqiu-Yingyi 0ca1aec
Use explicit WebSocket/EventSource request types
Zuoqiu-Yingyi 8ef824e
ci(format): add dprint configuration and integrate into workspace
Zuoqiu-Yingyi 60120ce
style(dprint): Format code, docs and config tweaks
Zuoqiu-Yingyi 64ce68c
style(dprint): Prefer double quotes; simplify selector quoting
Zuoqiu-Yingyi 8f5de20
style(dprint): Enforce no-space around object properties
Zuoqiu-Yingyi d988d5f
chore(build): Add kernel.js to webpack copy patterns
Zuoqiu-Yingyi d8c3ed2
style(kernel): Add Chinese docs and clarify kernel API comments
Zuoqiu-Yingyi 5160d6b
feat(kenrel): Log globalThis properties for goja inspection
Zuoqiu-Yingyi 34bf828
fix: Potential fix for pull request finding
Zuoqiu-Yingyi 3a0cfaa
chore(build): Use npm-run-all for dev/build scripts
Zuoqiu-Yingyi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,10 @@ | |
| node_modules | ||
| .DS_Store | ||
| .eslintcache | ||
| .dprint | ||
| dist | ||
| package.zip | ||
| index.css | ||
| index.js | ||
| kernel.js | ||
| /i18n | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
733 changes: 733 additions & 0 deletions
733
docs/superpowers/plans/2026-05-09-kernel-plugin-demo.md
Large diffs are not rendered by default.
Oops, something went wrong.
146 changes: 146 additions & 0 deletions
146
docs/superpowers/specs/2026-05-09-kernel-plugin-demo-design.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| # Kernel Plugin Demo — Design Spec | ||
|
|
||
| **Date:** 2026-05-09\ | ||
| **Status:** Approved\ | ||
| **Scope:** `plugin-sample/src/kernel.ts` + `petal/kernel.d.ts` | ||
|
|
||
| --- | ||
|
|
||
| ## Goal | ||
|
|
||
| Implement a TypeScript reference demo of the kernel plugin API in `src/kernel.ts`. This file is the living, authoritative example for community developers. It will be updated alongside `petal/kernel.d.ts` whenever new kernel APIs are added. | ||
|
|
||
| --- | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### `src/kernel.ts` | ||
|
|
||
| Single file, single class `KernelPlugin`. Webpack compiles it to `kernel.js` (CommonJS2, executed inside the kernel's goja runtime). | ||
|
|
||
| ``` | ||
| /// <reference types="siyuan/kernel" /> | ||
|
|
||
| class KernelPlugin { | ||
| private readonly siyuan: ISiyuan | ||
| private ws: IWebSocket | null | ||
| private es: IEventSource | null | ||
|
|
||
| constructor() — wire lifecycle hooks + server/event handlers | ||
| onload() — siyuan.rpc.bind + siyuan.storage CRUD | ||
| onloaded() — siyuan.client.fetch (kernel REST API) | ||
| onrunning() — HTTP RPC loopback + WebSocket client + SSE client | ||
| onunload() — rpc.broadcast + ws/es cleanup | ||
| eventHandler() — siyuan.event.handler + siyuan.event.emit | ||
| httpHandler() — siyuan.server.private.http.handler → IHttpResponse | ||
| wsHandler() — siyuan.server.private.ws.handler (IServerWsRequest) | ||
| esHandler() — siyuan.server.private.es.handler (IServerEsRequest) | ||
| } | ||
|
|
||
| new KernelPlugin(); | ||
| ``` | ||
|
|
||
| ### `petal/kernel.d.ts` additions | ||
|
|
||
| The current `IServerRequestHandler<TRes>` hard-codes `IServerRequest` as the handler argument. WS and SSE server handlers receive an augmented request that also carries a `port` back-channel to the connected client. The following additions are required (all backward-compatible): | ||
|
|
||
| | Addition | Purpose | | ||
| | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | `IEsServerPort` | Server-side SSE port: `onopen`, `onclose`, `send(eventType: string, data: string): void` (synchronous — no `await` needed), `close(): void` | | ||
| | `IServerWsRequest extends IServerRequest` | Adds `port: IWebSocket` for WS server handlers | | ||
| | `IServerEsRequest extends IServerRequest` | Adds `port: IEsServerPort` for SSE server handlers | | ||
| | `IServerRequestHandler<TRes, TReq extends IServerRequest = IServerRequest>` | Second type param (default = `IServerRequest`) — backward-compatible. The `handler` field body is updated to `((request: TReq) => TRes \| Promise<TRes>) \| null` so the type parameter is actually applied to the handler argument | | ||
| | `IServerScope.ws` / `.es` updated | `IServerRequestHandler<void, IServerWsRequest>` / `IServerRequestHandler<void, IServerEsRequest>` | | ||
|
|
||
| --- | ||
|
|
||
| ## API Coverage | ||
|
|
||
| Every public API on `globalThis.siyuan` is exercised: | ||
|
|
||
| | Namespace | Demonstrated | | ||
| | ---------------- | -------------------------------------------------------------------------------- | | ||
| | `siyuan.plugin` | `name`, `version`, `platform`, `i18n`; all four lifecycle hooks | | ||
| | `siyuan.logger` | All five levels: `trace`, `debug`, `info`, `warn`, `error` | | ||
| | `console` | Sync logging; note difference vs `siyuan.logger` (sync, 3 levels, `util.format`) | | ||
| | `siyuan.storage` | `put`, `get` → `.text()` / `.json()` / `.arrayBuffer()`, `list`, `remove` | | ||
| | `siyuan.rpc` | `bind` (with description), `unbind`, `broadcast` | | ||
| | `siyuan.client` | `fetch` (HTTP RPC loopback), `socket` (WS client), `event` (SSE client) | | ||
| | `siyuan.event` | `handler` (receive), `emit` (publish) | | ||
| | `siyuan.server` | `private.http.handler`, `private.ws.handler`, `private.es.handler` | | ||
|
|
||
| --- | ||
|
|
||
| ## Comment Strategy (TSDoc) | ||
|
|
||
| ### Method-level TSDoc blocks | ||
|
|
||
| Every method gets a TSDoc block with: | ||
|
|
||
| * Summary line describing which API/feature it demonstrates | ||
| * `@remarks` for behavioral constraints (e.g. lifecycle state semantics, when RPC calls are accepted) | ||
| * `@example` snippet for non-obvious usage patterns (e.g. `ws.open()` must be called explicitly) | ||
|
|
||
| Example: | ||
|
|
||
| ```typescript | ||
| /** | ||
| * Demonstrates {@link IRpc}: registering, calling, and broadcasting RPC methods. | ||
| * | ||
| * @remarks | ||
| * `siyuan.rpc.bind` should be called in `onload` so methods are ready when the | ||
| * plugin reaches the `running` state. RPC calls are rejected with `-32002` if | ||
| * the plugin has not yet reached `running`. | ||
| */ | ||
| private async onload(): Promise<void> { ... } | ||
| ``` | ||
|
|
||
| ### Inline comments | ||
|
|
||
| Key constraints or non-obvious behavior are annotated at the call site: | ||
|
|
||
| ```typescript | ||
| // Assign all callbacks before calling open() — onopen fires only after | ||
| // the TCP/WebSocket handshake completes. | ||
| await this.ws.open(); | ||
| ``` | ||
|
|
||
| ### Class-level TSDoc | ||
|
|
||
| `KernelPlugin` gets a full class-level doc block explaining: | ||
|
|
||
| * purpose (living reference for the kernel plugin API) | ||
| * lifecycle state diagram reference | ||
| * how to update the file when new APIs are added | ||
|
|
||
| --- | ||
|
|
||
| ## Type Usage | ||
|
|
||
| | Location | Type | | ||
| | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | | ||
| | `this.siyuan` field | `ISiyuan` | | ||
| | `this.ws` field | `IWebSocket \| null` | | ||
| | `this.es` field | `IEventSource \| null` | | ||
| | `onload` / `onloaded` / `onrunning` / `onunload` | `() => Promise<void>` | | ||
| | `eventHandler` param | `IEventMessage` | | ||
| | `httpHandler` param | `IServerRequest` | | ||
| | `httpHandler` return | `IHttpResponse` | | ||
| | `wsHandler` param | `IServerWsRequest` | | ||
| | `esHandler` param | `IServerEsRequest` | | ||
| | `any` | Only where the underlying API type is already `any` (e.g. `IEventMessage.detail`, `IRpc.bind` fn args) | | ||
|
|
||
| --- | ||
|
|
||
| ## Files Changed | ||
|
|
||
| | File | Change | | ||
| | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | ||
| | `plugin-sample/src/kernel.ts` | Full implementation (was a one-line stub) | | ||
| | `petal/kernel.d.ts` | Add `IEsServerPort`, `IServerWsRequest`, `IServerEsRequest`; extend `IServerRequestHandler` generic; update `IServerScope` | | ||
|
|
||
| --- | ||
|
|
||
| ## Out of Scope | ||
|
|
||
| * No unit tests (kernel plugin runs inside goja; tested by loading in a live SiYuan instance) | ||
|
Zuoqiu-Yingyi marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| { | ||
| "$schema": "https://dprint.dev/schemas/v0.json", | ||
| "lineWidth": 120, | ||
| "indentWidth": 4, | ||
| "useTabs": false, | ||
| "newLineKind": "lf", | ||
| "includes": [ | ||
| "**/*.{ts,tsx,js,jsx,mjs,cjs}", | ||
| "**/*.{json,jsonc}", | ||
| "**/*.{css,scss}", | ||
| "**/*.{md,markdown}", | ||
| "**/*.{yaml,yml}" | ||
| ], | ||
| "excludes": [ | ||
| "**/.git", | ||
| "**/node_modules", | ||
| "**/dist", | ||
| "**/pnpm-lock.yaml", | ||
| "index.js", | ||
| "kernel.js", | ||
| "index.css" | ||
| ], | ||
| "typescript": { | ||
| "quoteStyle": "preferDouble", | ||
| "semiColons": "always", | ||
| "trailingCommas": "onlyMultiLine", | ||
| "operatorPosition": "sameLine", | ||
| "nextControlFlowPosition": "sameLine", | ||
| "spaceSurroundingProperties": false, | ||
| "importDeclaration.forceMultiLine": "whenMultiple", | ||
| "importDeclaration.sortNamedImports": "maintain" | ||
| }, | ||
| "json": { | ||
| "indentWidth": 2, | ||
| "trailingCommas": "never" | ||
| }, | ||
| "markdown": { | ||
| "textWrap": "maintain", | ||
| "unorderedListKind": "asterisks" | ||
| }, | ||
| "malva": { | ||
| "printWidth": 120, | ||
| "indentWidth": 2 | ||
| }, | ||
| "yaml": { | ||
| "printWidth": 120, | ||
| "indentWidth": 2 | ||
| }, | ||
| "plugins": [ | ||
| "https://plugins.dprint.dev/typescript-0.96.0.wasm", | ||
| "https://plugins.dprint.dev/json-0.21.3.wasm", | ||
| "https://plugins.dprint.dev/markdown-0.21.1.wasm", | ||
| "https://plugins.dprint.dev/g-plane/malva-v0.15.3.wasm", | ||
| "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.6.0.wasm" | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,54 +1,58 @@ | ||
| import { FlatCompat } from "@eslint/eslintrc"; | ||
| import js from "@eslint/js"; | ||
| import typescriptEslint from "@typescript-eslint/eslint-plugin"; | ||
| import globals from "globals"; | ||
| import tsParser from "@typescript-eslint/parser"; | ||
| import globals from "globals"; | ||
| import path from "node:path"; | ||
| import {fileURLToPath} from "node:url"; | ||
| import js from "@eslint/js"; | ||
| import {FlatCompat} from "@eslint/eslintrc"; | ||
| import { fileURLToPath } from "node:url"; | ||
|
|
||
| const __filename = fileURLToPath(import.meta.url); | ||
| const __dirname = path.dirname(__filename); | ||
| const compat = new FlatCompat({ | ||
| baseDirectory: __dirname, | ||
| recommendedConfig: js.configs.recommended, | ||
| allConfig: js.configs.all | ||
| allConfig: js.configs.all, | ||
| }); | ||
|
|
||
| export default [{ | ||
| ignores: [ | ||
| "dist", | ||
| "node_modules", | ||
| "index.js", | ||
| ], | ||
| }, ...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"), { | ||
| plugins: { | ||
| "@typescript-eslint": typescriptEslint, | ||
| export default [ | ||
| { | ||
| ignores: [ | ||
| "dist", | ||
| "node_modules", | ||
| "index.js", | ||
| ], | ||
| }, | ||
|
|
||
| languageOptions: { | ||
| globals: { | ||
| ...globals.node, | ||
| ...globals.browser, | ||
| ...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"), | ||
| { | ||
| plugins: { | ||
| "@typescript-eslint": typescriptEslint, | ||
| }, | ||
|
|
||
| parser: tsParser, | ||
| }, | ||
| languageOptions: { | ||
| globals: { | ||
| ...globals.node, | ||
| ...globals.browser, | ||
| }, | ||
|
|
||
| parser: tsParser, | ||
| }, | ||
|
|
||
| rules: { | ||
| semi: [2, "always"], | ||
| quotes: [2, "double", { | ||
| avoidEscape: true, | ||
| }], | ||
| "@typescript-eslint/no-unused-vars": ["warn", {caughtErrors: "none"}], | ||
| "no-async-promise-executor": "off", | ||
| "no-prototype-builtins": "off", | ||
| "no-useless-escape": "off", | ||
| "no-irregular-whitespace": "off", | ||
| "@typescript-eslint/ban-ts-comment": "off", | ||
| "@typescript-eslint/no-var-requires": "off", | ||
| "@typescript-eslint/explicit-function-return-type": "off", | ||
| "@typescript-eslint/explicit-module-boundary-types": "off", | ||
| "@typescript-eslint/no-explicit-any": "off", | ||
| "@typescript-eslint/no-require-imports": "off", | ||
| rules: { | ||
| semi: [2, "always"], | ||
| quotes: [2, "double", { | ||
| avoidEscape: true, | ||
| }], | ||
| "@typescript-eslint/no-unused-vars": ["warn", {caughtErrors: "none"}], | ||
| "no-async-promise-executor": "off", | ||
| "no-prototype-builtins": "off", | ||
| "no-useless-escape": "off", | ||
| "no-irregular-whitespace": "off", | ||
| "@typescript-eslint/ban-ts-comment": "off", | ||
| "@typescript-eslint/no-var-requires": "off", | ||
| "@typescript-eslint/explicit-function-return-type": "off", | ||
| "@typescript-eslint/explicit-module-boundary-types": "off", | ||
| "@typescript-eslint/no-explicit-any": "off", | ||
| "@typescript-eslint/no-require-imports": "off", | ||
| }, | ||
| }, | ||
| }]; | ||
| ]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.