@koishi-ce/client 1.0.3 → 1.0.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.
Files changed (40) hide show
  1. package/app/home/welcome.vue +12 -6
  2. package/app/index.ts +8 -2
  3. package/app/layout/header.vue +12 -4
  4. package/app/layout/layout.vue +4 -1
  5. package/app/layout/menu-item.vue +3 -1
  6. package/app/settings/settings.vue +6 -4
  7. package/app/settings/theme.vue +4 -1
  8. package/app/status/loading.vue +4 -1
  9. package/app/theme/activity/button.vue +4 -1
  10. package/app/theme/activity/index.vue +12 -4
  11. package/app/theme/activity/item.vue +18 -4
  12. package/app/theme/activity/separator.vue +44 -12
  13. package/app/theme/index.ts +5 -1
  14. package/app/theme/index.vue +3 -1
  15. package/app/theme/menu/menu-item.vue +10 -4
  16. package/app/theme/menu/menu.vue +9 -4
  17. package/client/components/chat/overlay.vue +30 -8
  18. package/client/components/common/k-hint.vue +3 -1
  19. package/client/components/dynamic.vue +2 -1
  20. package/client/components/icons/index.ts +7 -2
  21. package/client/components/index.ts +8 -2
  22. package/client/components/link.ts +5 -2
  23. package/client/components/perms.vue +22 -5
  24. package/client/components/slot.ts +19 -4
  25. package/client/context.ts +12 -4
  26. package/client/data.ts +57 -26
  27. package/client/index.ts +2 -1
  28. package/client/plugins/action.ts +46 -13
  29. package/client/plugins/loader.ts +67 -45
  30. package/client/plugins/router.ts +34 -11
  31. package/client/plugins/setting.ts +45 -12
  32. package/client/plugins/theme.ts +21 -6
  33. package/client/utils.ts +7 -2
  34. package/lib/bin.mjs +3 -3
  35. package/lib/{client-CaTn_gVG.mjs → client-C97iYPCr.mjs} +1 -1
  36. package/lib/index.mjs +1 -1
  37. package/lib/{src-DXaM1Kgh.mjs → src-BOakssV3.mjs} +2 -2
  38. package/package.json +3 -3
  39. package/src/bin.ts +10 -3
  40. package/src/index.ts +59 -15
@@ -9,10 +9,23 @@
9
9
  * (经所有插件 schema 补全后的完整配置),二者双向同步(见文末类注释)。
10
10
  * 插件通过 `ctx.settings()` 注册设置分区、`ctx.schema()` 注册自定义控件。
11
11
  */
12
- import { type RemovableRef, useLocalStorage } from "@vueuse/core";
12
+ import {
13
+ type RemovableRef,
14
+ useLocalStorage,
15
+ } from "@vueuse/core";
13
16
  import { type Dict, remove } from "cosmokit";
14
- import { type Component, computed, markRaw, reactive, ref, watch } from "vue";
15
- import { Schema, SchemaBase } from "../../../components/client/index.ts";
17
+ import {
18
+ type Component,
19
+ computed,
20
+ markRaw,
21
+ reactive,
22
+ ref,
23
+ watch,
24
+ } from "vue";
25
+ import {
26
+ Schema,
27
+ SchemaBase,
28
+ } from "../../../components/client/index.ts";
16
29
  import type { Config } from "..";
17
30
  import type { Context } from "../context";
18
31
  import { insert, type Ordered, Service } from "../utils";
@@ -56,7 +69,10 @@ export let useStorage = <T extends object>(
56
69
  __version__?: number | undefined;
57
70
  };
58
71
  initial.__version__ = version;
59
- const storage = useLocalStorage(`koishi.console.${key}`, initial);
72
+ const storage = useLocalStorage(
73
+ `koishi.console.${key}`,
74
+ initial,
75
+ );
60
76
  if (storage.value.__version__ !== version) {
61
77
  storage.value = initial;
62
78
  }
@@ -87,7 +103,10 @@ export function createStorage<T extends object>(
87
103
  if (storage.value.version !== version) {
88
104
  storage.value = { version, data: initial };
89
105
  } else if (!Array.isArray(storage.value.data)) {
90
- storage.value.data = { ...initial, ...storage.value.data };
106
+ storage.value.data = {
107
+ ...initial,
108
+ ...storage.value.data,
109
+ };
91
110
  }
92
111
  return reactive<T>(storage.value["data"]);
93
112
  }
@@ -141,14 +160,19 @@ export default class SettingService extends Service {
141
160
  title: "通用设置",
142
161
  order: 1000,
143
162
  schema: Schema.object({
144
- locale: Schema.union(["zh-CN", "en-US"]).description("语言设置。"),
163
+ locale: Schema.union([
164
+ "zh-CN",
165
+ "en-US",
166
+ ]).description("语言设置。"),
145
167
  }).description("通用设置"),
146
168
  });
147
169
 
148
170
  // 汇总所有分区 schema 为一个相交对象,作为 resolved 的解释器
149
171
  const schema = computed(() => {
150
172
  const list: Schema[] = [];
151
- for (const settings of Object.values(ctx.internal.settings)) {
173
+ for (const settings of Object.values(
174
+ ctx.internal.settings,
175
+ )) {
152
176
  for (const options of settings) {
153
177
  if (options.schema) {
154
178
  list.push(options.schema);
@@ -186,7 +210,9 @@ export default class SettingService extends Service {
186
210
  ctx.effect(() => () => stop?.());
187
211
 
188
212
  // 原始存储或 schema 集合任一变化,都重新生成 resolved
189
- ctx.effect(() => watch(original, update, { deep: true }));
213
+ ctx.effect(() =>
214
+ watch(original, update, { deep: true }),
215
+ );
190
216
  ctx.effect(() => watch(schema, update));
191
217
  }
192
218
 
@@ -195,7 +221,9 @@ export default class SettingService extends Service {
195
221
  * 返回取消注册函数。
196
222
  */
197
223
  extendSchema(extension: SchemaBase.Extension) {
198
- const component = this.ctx.wrapComponent(extension.component);
224
+ const component = this.ctx.wrapComponent(
225
+ extension.component,
226
+ );
199
227
  if (component) extension.component = component;
200
228
  return this.ctx.effect(() => {
201
229
  SchemaBase.extensions.add(extension);
@@ -207,14 +235,19 @@ export default class SettingService extends Service {
207
235
  settings(options: SettingOptions) {
208
236
  markRaw(options);
209
237
  options.order ??= 0;
210
- const component = this.ctx.wrapComponent(options.component);
238
+ const component = this.ctx.wrapComponent(
239
+ options.component,
240
+ );
211
241
  if (component) options.component = component;
212
242
  return this.ctx.effect(() => {
213
- const list = (this.ctx.internal.settings[options.id] ||= []);
243
+ const list = (this.ctx.internal.settings[
244
+ options.id
245
+ ] ||= []);
214
246
  insert(list, options);
215
247
  return () => {
216
248
  remove(list, options);
217
- if (!list.length) delete this.ctx.internal.settings[options.id];
249
+ if (!list.length)
250
+ delete this.ctx.internal.settings[options.id];
218
251
  };
219
252
  });
220
253
  }
@@ -11,7 +11,13 @@
11
11
  */
12
12
  import { usePreferredDark } from "@vueuse/core";
13
13
  import type { Dict } from "cosmokit";
14
- import { type Component, computed, markRaw, reactive, watchEffect } from "vue";
14
+ import {
15
+ type Component,
16
+ computed,
17
+ markRaw,
18
+ reactive,
19
+ watchEffect,
20
+ } from "vue";
15
21
  import { Schema } from "../../../components/client/index.ts";
16
22
  import type { Context } from "../context";
17
23
  import { Service } from "../utils";
@@ -100,11 +106,15 @@ export default class ThemeService extends Service {
100
106
  watchEffect(
101
107
  () => {
102
108
  if (!config.value.theme) return;
103
- const root = window.document.querySelector("html");
109
+ const root =
110
+ window.document.querySelector("html");
104
111
  if (!root) return;
105
112
  // 把当前主题名写到 <html theme="...">,并同步 dark 类;
106
113
  // 主题样式与深色变量均由 CSS 依据这两个标记选择
107
- root.setAttribute("theme", config.value.theme[colorMode.value]);
114
+ root.setAttribute(
115
+ "theme",
116
+ config.value.theme[colorMode.value],
117
+ );
108
118
  if (colorMode.value === "dark") {
109
119
  root.classList.add("dark");
110
120
  } else {
@@ -123,16 +133,21 @@ export default class ThemeService extends Service {
123
133
  */
124
134
  theme(options: ThemeOptions) {
125
135
  markRaw(options);
126
- for (const [type, component] of Object.entries(options.components || {})) {
136
+ for (const [type, component] of Object.entries(
137
+ options.components || {},
138
+ )) {
127
139
  this.ctx.slot({
128
140
  type,
129
- disabled: () => config.value.theme[colorMode.value] !== options.id,
141
+ disabled: () =>
142
+ config.value.theme[colorMode.value] !==
143
+ options.id,
130
144
  component,
131
145
  });
132
146
  }
133
147
  return this.ctx.effect(() => {
134
148
  this.ctx.internal.themes[options.id] = options;
135
- return () => delete this.ctx.internal.themes[options.id];
149
+ return () =>
150
+ delete this.ctx.internal.themes[options.id];
136
151
  });
137
152
  }
138
153
  }
package/client/utils.ts CHANGED
@@ -24,13 +24,18 @@ export interface Ordered {
24
24
  * 按 order 升序将条目插入有序列表(相同 order 的后者排在后面)。
25
25
  * 同时 markRaw 标记条目,避免其被 Vue 深度代理。
26
26
  */
27
- export function insert<T extends Ordered>(list: T[], item: T) {
27
+ export function insert<T extends Ordered>(
28
+ list: T[],
29
+ item: T,
30
+ ) {
28
31
  markRaw(item);
29
32
  // order 为可选属性:任一侧缺失(undefined)时数值比较结果恒为 false,
30
33
  // 与原实现(直接比较)在所有输入下的求值结果一致,这里显式判空以通过严格空检查
31
34
  const index = list.findIndex(
32
35
  (a) =>
33
- a.order !== undefined && item.order !== undefined && a.order < item.order,
36
+ a.order !== undefined &&
37
+ item.order !== undefined &&
38
+ a.order < item.order,
34
39
  );
35
40
  if (index >= 0) {
36
41
  list.splice(index, 0, item);
package/lib/bin.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as build } from "./src-DXaM1Kgh.mjs";
2
+ import { t as build } from "./src-BOakssV3.mjs";
3
3
  import { existsSync } from "node:fs";
4
4
  import { resolve } from "node:path";
5
5
  //#endregion
@@ -16,7 +16,7 @@ import { resolve } from "node:path";
16
16
  const { version } = {
17
17
  name: "@koishi-ce/client",
18
18
  description: "Koishi Console Client",
19
- version: "1.0.3",
19
+ version: "1.0.4",
20
20
  type: "module",
21
21
  main: "client/index.ts",
22
22
  exports: {
@@ -104,7 +104,7 @@ async function main() {
104
104
  await build(resolve(process.cwd(), target));
105
105
  return;
106
106
  }
107
- await (await import("./client-CaTn_gVG.mjs")).default();
107
+ await (await import("./client-C97iYPCr.mjs")).default();
108
108
  return;
109
109
  }
110
110
  console.error(`Unknown command ${JSON.stringify(command)}.`);
@@ -70,7 +70,7 @@ async function build(root, config = {}, isClient = false) {
70
70
  }
71
71
  },
72
72
  plugins: [
73
- vue(),
73
+ vue({ template: { compilerOptions: { comments: false } } }),
74
74
  yaml(),
75
75
  ...config.plugins || []
76
76
  ],
package/lib/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as createServer, t as build } from "./src-DXaM1Kgh.mjs";
1
+ import { n as createServer, t as build } from "./src-BOakssV3.mjs";
2
2
  export { build, createServer };
@@ -82,7 +82,7 @@ async function build(root, config = {}) {
82
82
  }
83
83
  },
84
84
  plugins: [
85
- vue(),
85
+ vue({ template: { compilerOptions: { comments: false } } }),
86
86
  yaml(),
87
87
  (await import("unocss/vite")).default({ presets: [(await import("unocss/preset-mini")).default({ preflight: false })] })
88
88
  ],
@@ -130,7 +130,7 @@ async function createServer(baseDir, config = {}) {
130
130
  fs: { allow: [vite.searchForWorkspaceRoot(baseDir)] }
131
131
  },
132
132
  plugins: [
133
- vue(),
133
+ vue({ template: { compilerOptions: { comments: false } } }),
134
134
  yaml(),
135
135
  (await import("unocss/vite")).default({ presets: [(await import("unocss/preset-mini")).default({ preflight: false })] })
136
136
  ],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@koishi-ce/client",
3
3
  "description": "Koishi Console Client",
4
- "version": "1.0.3",
4
+ "version": "1.0.4",
5
5
  "type": "module",
6
6
  "main": "client/index.ts",
7
7
  "exports": {
@@ -64,7 +64,7 @@
64
64
  "vue-router": "^5.2.0"
65
65
  },
66
66
  "devDependencies": {
67
- "@koishi-ce/koishi": "^1.0.4",
68
- "@koishi-ce/plugin-console": "^1.0.3"
67
+ "@koishi-ce/koishi": "^1.0.6",
68
+ "@koishi-ce/plugin-console": "^1.0.4"
69
69
  }
70
70
  }
package/src/bin.ts CHANGED
@@ -36,7 +36,11 @@ Options:
36
36
 
37
37
  async function main() {
38
38
  const [command, ...args] = process.argv.slice(2);
39
- if (command === undefined || command === "-h" || command === "--help") {
39
+ if (
40
+ command === undefined ||
41
+ command === "-h" ||
42
+ command === "--help"
43
+ ) {
40
44
  console.log(help);
41
45
  return;
42
46
  }
@@ -47,7 +51,8 @@ async function main() {
47
51
  if (command === "build") {
48
52
  // root 缺省时:cwd 是插件目录则构建它,否则视为宿主总装
49
53
  const root = args.find((arg) => !arg.startsWith("-"));
50
- const target = root ?? (existsSync("client") ? "." : undefined);
54
+ const target =
55
+ root ?? (existsSync("client") ? "." : undefined);
51
56
  if (target !== undefined) {
52
57
  await build(resolve(process.cwd(), target));
53
58
  return;
@@ -56,7 +61,9 @@ async function main() {
56
61
  await host.default();
57
62
  return;
58
63
  }
59
- console.error(`Unknown command ${JSON.stringify(command)}.`);
64
+ console.error(
65
+ `Unknown command ${JSON.stringify(command)}.`,
66
+ );
60
67
  console.log(help);
61
68
  process.exitCode = 1;
62
69
  }
package/src/index.ts CHANGED
@@ -33,21 +33,32 @@ interface BuildResult {
33
33
  // 将全部工作区包名映射到其源码目录,行为对齐根 tsconfig 的 paths 别名。
34
34
  // 没有被任何工作区包依赖的插件(如 plugin-logger)不会出现在 node_modules
35
35
  // 的链接里,bundler 无法按包名解析,必须显式提供这层映射。
36
- async function collectWorkspaceAliases(): Promise<Record<string, string>> {
36
+ async function collectWorkspaceAliases(): Promise<
37
+ Record<string, string>
38
+ > {
37
39
  // 源码形态(src/)与产物形态(lib/)都在包根下一级,上跳四级到仓库根一致
38
- const repoRoot = resolve(import.meta.dir, "../../../..").replace(/\\/g, "/");
39
- const manifest = await Bun.file(`${repoRoot}/package.json`).json();
40
+ const repoRoot = resolve(
41
+ import.meta.dir,
42
+ "../../../..",
43
+ ).replace(/\\/g, "/");
44
+ const manifest = await Bun.file(
45
+ `${repoRoot}/package.json`,
46
+ ).json();
40
47
  const aliases: Record<string, string> = {};
41
48
  for (const pattern of manifest.workspaces ?? []) {
42
49
  // scanSync 产出的相对路径在 Windows 上是反斜杠,统一归一化为正斜杠
43
- const files = new Bun.Glob(`${pattern}/package.json`).scanSync({
50
+ const files = new Bun.Glob(
51
+ `${pattern}/package.json`,
52
+ ).scanSync({
44
53
  cwd: repoRoot,
45
54
  });
46
55
  for (const file of files) {
47
56
  const rel = file.replaceAll("\\", "/");
48
57
  const dir = `${repoRoot}/${rel.slice(0, -"/package.json".length)}`;
49
58
  try {
50
- const { name } = await Bun.file(`${dir}/package.json`).json();
59
+ const { name } = await Bun.file(
60
+ `${dir}/package.json`,
61
+ ).json();
51
62
  if (!name) continue;
52
63
  // 控制台前端语境下,裸包名对到浏览器端入口(替代上游 lib 的 browser
53
64
  // 导出条件);`<name>/src` 子路径对到源码目录,供共享代码引用;
@@ -56,9 +67,13 @@ async function collectWorkspaceAliases(): Promise<Record<string, string>> {
56
67
  // 上游与 npm 产物的 exports 均未声明它,同样靠仓库内别名解析)。
57
68
  // 子路径键必须先插入——别名解析按插入序取首个命中项
58
69
  const clientEntry = `${dir}/client/index.ts`;
59
- if (existsSync(`${dir}/src`)) aliases[`${name}/src`] = `${dir}/src`;
60
- if (existsSync(clientEntry)) aliases[`${name}/client`] = clientEntry;
61
- aliases[name] = existsSync(clientEntry) ? clientEntry : `${dir}/src`;
70
+ if (existsSync(`${dir}/src`))
71
+ aliases[`${name}/src`] = `${dir}/src`;
72
+ if (existsSync(clientEntry))
73
+ aliases[`${name}/client`] = clientEntry;
74
+ aliases[name] = existsSync(clientEntry)
75
+ ? clientEntry
76
+ : `${dir}/src`;
62
77
  } catch {}
63
78
  }
64
79
  }
@@ -72,7 +87,10 @@ const workspaceAliases = await collectWorkspaceAliases();
72
87
  // 类型面由根 tsconfig.client.json 的 paths 解析到 schemastery-vue-client.ts
73
88
  const runtimeShimPath = (
74
89
  workspaceAliases["@koishi-ce/components"] ?? ""
75
- ).replace(/client\/index\.ts$/, "client/schemastery-vue-runtime.ts");
90
+ ).replace(
91
+ /client\/index\.ts$/,
92
+ "client/schemastery-vue-runtime.ts",
93
+ );
76
94
 
77
95
  /**
78
96
  * 构建单个 webui 插件的前端产物。
@@ -80,7 +98,10 @@ const runtimeShimPath = (
80
98
  * @param root 插件目录(无 `client/` 子目录时视为该插件没有前端,直接跳过)
81
99
  * @param config 额外的 vite 配置,逐层合并覆盖下方默认值
82
100
  */
83
- export async function build(root: string, config: vite.UserConfig = {}) {
101
+ export async function build(
102
+ root: string,
103
+ config: vite.UserConfig = {},
104
+ ) {
84
105
  if (!existsSync(`${root}/client`)) return;
85
106
 
86
107
  // 插件可自带 `build/client.ts` 导出额外的 vite 配置覆盖下方默认值
@@ -88,7 +109,9 @@ export async function build(root: string, config: vite.UserConfig = {}) {
88
109
  // 如 analytics 的 fuck-echarts 符号遮蔽修补
89
110
  const overridePath = `${root}/build/client.ts`;
90
111
  if (existsSync(overridePath)) {
91
- const mod = await import(pathToFileURL(overridePath).href);
112
+ const mod = await import(
113
+ pathToFileURL(overridePath).href
114
+ );
92
115
  config = vite.mergeConfig(config, mod.default ?? mod);
93
116
  }
94
117
 
@@ -124,7 +147,9 @@ export async function build(root: string, config: vite.UserConfig = {}) {
124
147
  // 仓库侧无法根治,直接静默
125
148
  onwarn(warning, warn) {
126
149
  if (
127
- warning.message.includes("is being imported multiple times")
150
+ warning.message.includes(
151
+ "is being imported multiple times",
152
+ )
128
153
  ) {
129
154
  return;
130
155
  }
@@ -144,7 +169,16 @@ export async function build(root: string, config: vite.UserConfig = {}) {
144
169
  },
145
170
  },
146
171
  plugins: [
147
- vue(),
172
+ // 钉死剥离模板注释:注释写在 template 根元素之前时,SFC 会被
173
+ // 编译成多根 fragment,Vue 随之禁用 attribute 透传(外部传入的
174
+ // class 落不到 svg 上,侧栏图标因此丢掉尺寸类);生产语义本就
175
+ // 应剥注释,这里显式钉死,避免随 NODE_ENV 漂移。dev server
176
+ // 同步钉死,保证开发态与产物行为一致
177
+ vue({
178
+ template: {
179
+ compilerOptions: { comments: false },
180
+ },
181
+ }),
148
182
  yaml(),
149
183
  (
150
184
  await import("unocss/vite")
@@ -171,7 +205,8 @@ export async function build(root: string, config: vite.UserConfig = {}) {
171
205
  // 源码发布的组件库),其内部以 npm 名引用组件库;重定向到
172
206
  // 本仓库同版本(1.5.22)components 源码,避免 npm 版整套
173
207
  // 组件库被打进插件产物
174
- "@koishijs/components": workspaceAliases["@koishi-ce/components"],
208
+ "@koishijs/components":
209
+ workspaceAliases["@koishi-ce/components"],
175
210
  // 虚拟子路径的运行时载体(补齐真实包缺失的 SchemaBase
176
211
  // 具名导出);类型面由 tsconfig.client.json 的 paths
177
212
  // 解析到 schemastery-vue-client.ts
@@ -242,7 +277,16 @@ export async function createServer(
242
277
  },
243
278
  },
244
279
  plugins: [
245
- vue(),
280
+ // 钉死剥离模板注释:注释写在 template 根元素之前时,SFC 会被
281
+ // 编译成多根 fragment,Vue 随之禁用 attribute 透传(外部传入的
282
+ // class 落不到 svg 上,侧栏图标因此丢掉尺寸类);生产语义本就
283
+ // 应剥注释,这里显式钉死,避免随 NODE_ENV 漂移。dev server
284
+ // 同步钉死,保证开发态与产物行为一致
285
+ vue({
286
+ template: {
287
+ compilerOptions: { comments: false },
288
+ },
289
+ }),
246
290
  yaml(),
247
291
  (await import("unocss/vite")).default({
248
292
  presets: [