paseo-plugin-chat-view 0.1.0 → 0.1.1

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.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "paseo-plugin-chat-view",
3
- "version": "0.1.0",
4
- "license": "MIT",
3
+ "version": "0.1.1",
5
4
  "description": "Sticky questions and compact agent activity inside Paseo conversations",
5
+ "license": "MIT",
6
6
  "files": [
7
7
  "paseo-plugin.json",
8
8
  "index.client.tsx",
@@ -23,16 +23,18 @@
23
23
  "format": "oxfmt .",
24
24
  "format:check": "oxfmt --check ."
25
25
  },
26
- "devDependencies": {
26
+ "dependencies": {
27
27
  "@getpaseo/client": "0.10.3",
28
- "@getpaseo/plugin": "0.10.3",
29
28
  "@getpaseo/protocol": "0.10.3",
29
+ "prismjs": "^1.30.0"
30
+ },
31
+ "devDependencies": {
32
+ "@getpaseo/plugin": "0.10.3",
30
33
  "@types/node": "^22.20.5",
31
34
  "@types/prismjs": "^1.26.6",
32
35
  "@types/react": "~19.1.0",
33
36
  "oxfmt": "0.46.0",
34
37
  "oxlint": "1.61.0",
35
- "prismjs": "^1.30.0",
36
38
  "react": "19.1.0",
37
39
  "react-dom": "19.1.0",
38
40
  "react-native": "0.81.5",
@@ -0,0 +1,53 @@
1
+ import { expect, it } from "vitest";
2
+ import { readFile, readdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+
5
+ const runtimeRoot = new URL("..", import.meta.url).pathname;
6
+
7
+ /**
8
+ * 宿主用 `npm install --omit=dev` 安装插件,只装 `dependencies`。任何在源码里出现的
9
+ * 非宿主模块都必须列在 `dependencies` 里,否则安装后编译会报
10
+ * "Could not resolve type dependency"。宿主提供的模块见下表。
11
+ */
12
+ const HOST_PROVIDED = [
13
+ /^@getpaseo\/plugin(\/|$)/,
14
+ /^react(-dom|-native)?(\/|$)/,
15
+ /^zod(\/|$)/,
16
+ /^@tanstack\/react-query(\/|$)/,
17
+ /^node:/,
18
+ ];
19
+
20
+ async function* sourceFiles(directory: string): AsyncGenerator<string> {
21
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
22
+ const path = join(directory, entry.name);
23
+ if (entry.isDirectory()) yield* sourceFiles(path);
24
+ else if (/\.[jt]sx?$/.test(entry.name) && !/\.test\.[jt]sx?$/.test(entry.name)) yield path;
25
+ }
26
+ }
27
+
28
+ it("declares every non-host import as a runtime dependency", async () => {
29
+ const manifest = JSON.parse(await readFile(join(runtimeRoot, "package.json"), "utf8"));
30
+ const dependencies: Record<string, string> = manifest.dependencies ?? {};
31
+ const missing = new Map<string, string>();
32
+
33
+ const files = [join(runtimeRoot, "index.client.tsx"), join(runtimeRoot, "index.server.ts")];
34
+ for (const name of ["client", "server", "shared"]) {
35
+ for await (const file of sourceFiles(join(runtimeRoot, name))) files.push(file);
36
+ }
37
+ for (const file of files) {
38
+ const source = await readFile(file, "utf8");
39
+ // 只认行首的 import/export 与 require(),避免匹配注释里的引号文本。
40
+ const pattern =
41
+ /^(?:import|export)\s[^'"]*from\s*"([^"]+)"|^\s*import\s*"([^"]+)"|\brequire\(\s*"([^"]+)"\s*\)/gm;
42
+ for (const match of source.matchAll(pattern)) {
43
+ const specifier = match[1] ?? match[2] ?? match[3]!;
44
+ if (specifier.startsWith(".") || HOST_PROVIDED.some((rule) => rule.test(specifier))) continue;
45
+ const name = specifier.startsWith("@")
46
+ ? specifier.split("/").slice(0, 2).join("/")
47
+ : specifier.split("/")[0]!;
48
+ if (!(name in dependencies)) missing.set(name, file.slice(runtimeRoot.length));
49
+ }
50
+ }
51
+
52
+ expect([...missing]).toEqual([]);
53
+ });