@vetta-org/plugin-vite 0.0.5 → 0.2.0

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 (45) hide show
  1. package/dist/build-warning-filter.d.ts +8 -0
  2. package/dist/build-warning-filter.d.ts.map +1 -0
  3. package/dist/build-warning-filter.js +26 -0
  4. package/dist/build-warning-filter.js.map +1 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +83 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/dev-events.d.ts +23 -0
  10. package/dist/dev-events.d.ts.map +1 -0
  11. package/dist/dev-events.js +9 -0
  12. package/dist/dev-events.js.map +1 -0
  13. package/dist/dev-server.d.ts +9 -0
  14. package/dist/dev-server.d.ts.map +1 -0
  15. package/dist/dev-server.js +244 -0
  16. package/dist/dev-server.js.map +1 -0
  17. package/dist/dev-vite-plugins.d.ts +5 -0
  18. package/dist/dev-vite-plugins.d.ts.map +1 -0
  19. package/dist/dev-vite-plugins.js +144 -0
  20. package/dist/dev-vite-plugins.js.map +1 -0
  21. package/dist/host-theme.d.ts +5 -0
  22. package/dist/host-theme.d.ts.map +1 -0
  23. package/dist/host-theme.js +42 -0
  24. package/dist/host-theme.js.map +1 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +89 -4
  28. package/dist/index.js.map +1 -1
  29. package/dist/pack.d.ts +4 -0
  30. package/dist/pack.d.ts.map +1 -1
  31. package/dist/pack.js +45 -89
  32. package/dist/pack.js.map +1 -1
  33. package/dist/permission-contract.d.ts +13 -0
  34. package/dist/permission-contract.d.ts.map +1 -0
  35. package/dist/permission-contract.js +94 -0
  36. package/dist/permission-contract.js.map +1 -0
  37. package/dist/request-query.d.ts +8 -0
  38. package/dist/request-query.d.ts.map +1 -0
  39. package/dist/request-query.js +19 -0
  40. package/dist/request-query.js.map +1 -0
  41. package/dist/style-scope.d.ts +8 -0
  42. package/dist/style-scope.d.ts.map +1 -1
  43. package/dist/style-scope.js +102 -3
  44. package/dist/style-scope.js.map +1 -1
  45. package/package.json +13 -3
package/dist/pack.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
3
3
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
4
+ import { listPluginManifestResources, parsePluginManifest } from "@vetta-org/plugin-sdk/manifest";
5
+ import { parseVettaNpmPluginPackage } from "@vetta-org/plugin-sdk/npm-package";
6
+ import { assertPluginPermissionContract } from "./permission-contract.js";
7
+ export const VETTA_NPM_PLUGIN_ARCHIVE_PATH = "release/vetta-plugin.zip";
4
8
  const crcTable = new Uint32Array(256);
5
9
  for (let i = 0; i < 256; i += 1) {
6
10
  let value = i;
@@ -16,55 +20,6 @@ function readString(record, key) {
16
20
  const value = record[key];
17
21
  return typeof value === "string" ? value : undefined;
18
22
  }
19
- function readStringArray(record, key) {
20
- const value = record[key];
21
- if (!Array.isArray(value)) {
22
- return undefined;
23
- }
24
- const strings = value.filter((entry) => typeof entry === "string");
25
- return strings.length === value.length ? strings : undefined;
26
- }
27
- function readAgentManifest(record) {
28
- const agent = record.agent;
29
- if (!isRecord(agent)) {
30
- return undefined;
31
- }
32
- const systemPrompt = isRecord(agent.systemPrompt)
33
- ? {
34
- promptPaths: readStringArray(agent.systemPrompt, "promptPaths"),
35
- }
36
- : undefined;
37
- const mcpServersRaw = agent.mcpServers;
38
- const mcpServers = typeof mcpServersRaw === "string"
39
- ? mcpServersRaw
40
- : isRecord(mcpServersRaw)
41
- ? mcpServersRaw
42
- : undefined;
43
- return {
44
- systemPrompt,
45
- skillPaths: readStringArray(agent, "skillPaths"),
46
- mcpServers,
47
- };
48
- }
49
- function parsePluginManifest(value) {
50
- if (!isRecord(value)) {
51
- throw new Error("plugin.json must contain an object.");
52
- }
53
- const id = readString(value, "id");
54
- const version = readString(value, "version");
55
- const entry = readString(value, "entry");
56
- if (!id || !version || !entry) {
57
- throw new Error("plugin.json must define string id, version, and entry fields.");
58
- }
59
- return {
60
- id,
61
- version,
62
- entry,
63
- icon: readString(value, "icon"),
64
- agent: readAgentManifest(value),
65
- styles: readStringArray(value, "styles"),
66
- };
67
- }
68
23
  function validateAbilityDescriptor(value, pluginManifest) {
69
24
  if (!isRecord(value))
70
25
  throw new Error("ability.json must contain an object.");
@@ -75,18 +30,6 @@ function validateAbilityDescriptor(value, pluginManifest) {
75
30
  throw new Error("ability.json identity must match plugin.json id and version.");
76
31
  }
77
32
  }
78
- /** Iconify 图标名:`solar:magic-stick-3-bold` 这种 `<集合>:<图标>` 形态。 */
79
- const ICONIFY_ICON_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*:[a-z0-9]+(?:-[a-z0-9]+)*$/;
80
- /**
81
- * 与宿主 `isPassthroughIconRef`、服务端 `isPackagedIconPath` 保持同一判定:
82
- * Iconify 名与 http(s) 外链不落包,其余按包内相对路径打进 zip。
83
- */
84
- function isPackagedIconPath(icon) {
85
- return (icon !== "" &&
86
- !icon.startsWith("http://") &&
87
- !icon.startsWith("https://") &&
88
- !ICONIFY_ICON_PATTERN.test(icon));
89
- }
90
33
  function parseJsonObject(buffer, fileName) {
91
34
  const parsed = JSON.parse(buffer.toString("utf-8"));
92
35
  if (!isRecord(parsed)) {
@@ -240,12 +183,12 @@ async function collectRuntimeFiles(rootDir, manifestPath, distDir) {
240
183
  // optional presentation/ directory
241
184
  }
242
185
  }
243
- const federationManifestPath = resolve(rootDir, pluginManifest.entry);
244
- addFile(federationManifestPath);
245
- const federationManifest = parseJsonObject(await readFile(federationManifestPath), basename(federationManifestPath));
186
+ const runtimeEntryPath = resolve(rootDir, pluginManifest.entry);
187
+ addFile(runtimeEntryPath);
188
+ const federationManifest = parseJsonObject(await readFile(runtimeEntryPath), basename(runtimeEntryPath));
246
189
  const remoteEntry = readManifestRemoteEntry(federationManifest);
247
190
  if (remoteEntry) {
248
- addFile(resolve(dirname(federationManifestPath), remoteEntry));
191
+ addFile(resolve(dirname(runtimeEntryPath), remoteEntry));
249
192
  }
250
193
  const assetsDir = join(distDir, "assets");
251
194
  for (const file of await collectFiles(assetsDir)) {
@@ -264,34 +207,24 @@ async function collectRuntimeFiles(rootDir, manifestPath, distDir) {
264
207
  catch {
265
208
  // dist missing
266
209
  }
267
- for (const style of pluginManifest.styles ?? []) {
268
- addFile(resolve(rootDir, style));
269
- }
270
- // 包内相对路径图标:不打进 zip 的话,宿主 vetta-plugin:// 会 404、市场上传会被服务端拒绝。
271
- const icon = pluginManifest.icon?.trim();
272
- if (icon && isPackagedIconPath(icon)) {
273
- const iconPath = resolve(rootDir, icon);
274
- if (!existsSync(iconPath)) {
275
- throw new Error(`plugin.json icon file not found: ${icon}`);
276
- }
277
- addFile(iconPath);
278
- }
279
- for (const promptPath of pluginManifest.agent?.systemPrompt?.promptPaths ?? []) {
280
- for (const file of await collectPath(resolve(rootDir, promptPath))) {
281
- addFile(file.fullPath);
210
+ for (const resource of listPluginManifestResources(pluginManifest)) {
211
+ if (resource.field === "entry")
212
+ continue;
213
+ const resourcePath = resolve(rootDir, resource.path);
214
+ if (resource.kind === "file") {
215
+ if (!existsSync(resourcePath)) {
216
+ throw new Error(`plugin.json resource not found: ${resource.field} (${resource.path})`);
217
+ }
218
+ addFile(resourcePath);
219
+ continue;
282
220
  }
283
- }
284
- for (const skillPath of pluginManifest.agent?.skillPaths ?? []) {
285
- for (const file of await collectPath(resolve(rootDir, skillPath))) {
221
+ for (const file of await collectPath(resourcePath)) {
286
222
  addFile(file.fullPath);
287
223
  }
288
224
  }
289
225
  // Plugin-scoped MCP: include config file and conventional companion dirs when declared.
290
226
  const mcpServers = pluginManifest.agent?.mcpServers;
291
227
  if (mcpServers !== undefined) {
292
- if (typeof mcpServers === "string") {
293
- addFile(resolve(rootDir, mcpServers));
294
- }
295
228
  try {
296
229
  for (const file of await collectFiles(resolve(rootDir, "mcp"))) {
297
230
  addFile(file.fullPath);
@@ -339,9 +272,32 @@ export async function createVettaPluginPackage(options = {}) {
339
272
  const pluginManifest = parsePluginManifest(parseJsonObject(await readFile(manifestPath), basename(manifestPath)));
340
273
  const outputPath = join(releaseDir, `${pluginManifest.id}-${pluginManifest.version}.zip`);
341
274
  const files = await collectRuntimeFiles(rootDir, manifestPath, distDir);
342
- await rm(releaseDir, { recursive: true, force: true });
275
+ assertPluginPermissionContract(pluginManifest, await Promise.all(files
276
+ .filter((file) => /\.(?:c|m)?js$/u.test(file.archivePath))
277
+ .map(async (file) => ({ fileName: file.archivePath, code: await readFile(file.fullPath, "utf8") }))));
278
+ let npmOutputPath;
279
+ if (options.npmArchive === true) {
280
+ const packageManifest = parseVettaNpmPluginPackage(parseJsonObject(await readFile(resolve(rootDir, "package.json")), "package.json"));
281
+ if (packageManifest.version !== pluginManifest.version) {
282
+ throw new Error(`npm package version ${packageManifest.version} must match plugin version ${pluginManifest.version}.`);
283
+ }
284
+ if (packageManifest.vetta.pluginId !== pluginManifest.id) {
285
+ throw new Error(`npm package plugin id ${packageManifest.vetta.pluginId} must match plugin id ${pluginManifest.id}.`);
286
+ }
287
+ if (packageManifest.vetta.archive !== VETTA_NPM_PLUGIN_ARCHIVE_PATH) {
288
+ throw new Error(`npm package archive must be ${VETTA_NPM_PLUGIN_ARCHIVE_PATH}.`);
289
+ }
290
+ npmOutputPath = resolve(rootDir, VETTA_NPM_PLUGIN_ARCHIVE_PATH);
291
+ }
343
292
  await mkdir(releaseDir, { recursive: true });
344
- await writeFile(outputPath, await createZip(files));
345
- return { outputPath, files };
293
+ await rm(outputPath, { force: true });
294
+ const archive = await createZip(files);
295
+ await writeFile(outputPath, archive);
296
+ if (npmOutputPath && npmOutputPath !== outputPath) {
297
+ await mkdir(dirname(npmOutputPath), { recursive: true });
298
+ await rm(npmOutputPath, { force: true });
299
+ await writeFile(npmOutputPath, archive);
300
+ }
301
+ return { outputPath, npmOutputPath, files };
346
302
  }
347
303
  //# sourceMappingURL=pack.js.map
package/dist/pack.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pack.js","sourceRoot":"","sources":["../src/pack.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join, relative, resolve, sep } from \"node:path\";\n\nexport interface VettaPluginPackageFile {\n\tfullPath: string;\n\tarchivePath: string;\n}\n\nexport interface VettaPluginPackageResult {\n\toutputPath: string;\n\tfiles: VettaPluginPackageFile[];\n}\n\nexport interface CreateVettaPluginPackageOptions {\n\trootDir?: string;\n\tmanifestPath?: string;\n\treleaseDir?: string;\n\tdistDir?: string;\n}\n\ninterface PluginManifest {\n\tid: string;\n\tversion: string;\n\tentry: string;\n\tstyles?: string[];\n\t/** 三态:Iconify 名 / `http(s)://` 外链 / 包内相对路径(只有后者需要打包)。 */\n\ticon?: string;\n\tagent?: {\n\t\tsystemPrompt?: {\n\t\t\tpromptPaths?: string[];\n\t\t};\n\t\tskillPaths?: string[];\n\t\t/** Relative path to `.mcp.json` or present as object (inline). */\n\t\tmcpServers?: string | Record<string, unknown>;\n\t};\n}\n\nconst crcTable = new Uint32Array(256);\nfor (let i = 0; i < 256; i += 1) {\n\tlet value = i;\n\tfor (let bit = 0; bit < 8; bit += 1) {\n\t\tvalue = value & 1 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;\n\t}\n\tcrcTable[i] = value >>> 0;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction readString(record: Record<string, unknown>, key: string): string | undefined {\n\tconst value = record[key];\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction readStringArray(record: Record<string, unknown>, key: string): string[] | undefined {\n\tconst value = record[key];\n\tif (!Array.isArray(value)) {\n\t\treturn undefined;\n\t}\n\tconst strings = value.filter((entry): entry is string => typeof entry === \"string\");\n\treturn strings.length === value.length ? strings : undefined;\n}\n\nfunction readAgentManifest(record: Record<string, unknown>): PluginManifest[\"agent\"] {\n\tconst agent = record.agent;\n\tif (!isRecord(agent)) {\n\t\treturn undefined;\n\t}\n\tconst systemPrompt = isRecord(agent.systemPrompt)\n\t\t? {\n\t\t\t\tpromptPaths: readStringArray(agent.systemPrompt, \"promptPaths\"),\n\t\t\t}\n\t\t: undefined;\n\tconst mcpServersRaw = agent.mcpServers;\n\tconst mcpServers =\n\t\ttypeof mcpServersRaw === \"string\"\n\t\t\t? mcpServersRaw\n\t\t\t: isRecord(mcpServersRaw)\n\t\t\t\t? mcpServersRaw\n\t\t\t\t: undefined;\n\treturn {\n\t\tsystemPrompt,\n\t\tskillPaths: readStringArray(agent, \"skillPaths\"),\n\t\tmcpServers,\n\t};\n}\n\nfunction parsePluginManifest(value: unknown): PluginManifest {\n\tif (!isRecord(value)) {\n\t\tthrow new Error(\"plugin.json must contain an object.\");\n\t}\n\n\tconst id = readString(value, \"id\");\n\tconst version = readString(value, \"version\");\n\tconst entry = readString(value, \"entry\");\n\tif (!id || !version || !entry) {\n\t\tthrow new Error(\"plugin.json must define string id, version, and entry fields.\");\n\t}\n\n\treturn {\n\t\tid,\n\t\tversion,\n\t\tentry,\n\t\ticon: readString(value, \"icon\"),\n\t\tagent: readAgentManifest(value),\n\t\tstyles: readStringArray(value, \"styles\"),\n\t};\n}\n\nfunction validateAbilityDescriptor(value: unknown, pluginManifest: PluginManifest): void {\n\tif (!isRecord(value)) throw new Error(\"ability.json must contain an object.\");\n\tif (\n\t\tvalue.schemaVersion !== 1 ||\n\t\tvalue.type !== \"plugin\" ||\n\t\tvalue.slug !== pluginManifest.id ||\n\t\tvalue.version !== pluginManifest.version\n\t) {\n\t\tthrow new Error(\"ability.json identity must match plugin.json id and version.\");\n\t}\n}\n\n/** Iconify 图标名:`solar:magic-stick-3-bold` 这种 `<集合>:<图标>` 形态。 */\nconst ICONIFY_ICON_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*:[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/**\n * 与宿主 `isPassthroughIconRef`、服务端 `isPackagedIconPath` 保持同一判定:\n * Iconify 名与 http(s) 外链不落包,其余按包内相对路径打进 zip。\n */\nfunction isPackagedIconPath(icon: string): boolean {\n\treturn (\n\t\ticon !== \"\" &&\n\t\t!icon.startsWith(\"http://\") &&\n\t\t!icon.startsWith(\"https://\") &&\n\t\t!ICONIFY_ICON_PATTERN.test(icon)\n\t);\n}\n\nfunction parseJsonObject(buffer: Buffer, fileName: string): Record<string, unknown> {\n\tconst parsed = JSON.parse(buffer.toString(\"utf-8\")) as unknown;\n\tif (!isRecord(parsed)) {\n\t\tthrow new Error(`${fileName} must contain an object.`);\n\t}\n\treturn parsed;\n}\n\nfunction crc32(buffer: Buffer): number {\n\tlet value = 0xffffffff;\n\tfor (const byte of buffer) {\n\t\tvalue = crcTable[(value ^ byte) & 0xff] ^ (value >>> 8);\n\t}\n\treturn (value ^ 0xffffffff) >>> 0;\n}\n\nfunction writeUInt16(value: number): Buffer {\n\tconst buffer = Buffer.allocUnsafe(2);\n\tbuffer.writeUInt16LE(value, 0);\n\treturn buffer;\n}\n\nfunction writeUInt32(value: number): Buffer {\n\tconst buffer = Buffer.allocUnsafe(4);\n\tbuffer.writeUInt32LE(value >>> 0, 0);\n\treturn buffer;\n}\n\nfunction archivePathFromRoot(rootDir: string, fullPath: string): string {\n\tconst archivePath = relative(rootDir, fullPath).replace(/\\\\/g, \"/\");\n\tif (!archivePath || archivePath.startsWith(\"..\") || archivePath.includes(`${sep}..${sep}`)) {\n\t\tthrow new Error(`File is outside plugin root: ${fullPath}`);\n\t}\n\treturn archivePath;\n}\n\nasync function collectFiles(dir: string): Promise<VettaPluginPackageFile[]> {\n\tconst entries = await readdir(dir, { withFileTypes: true });\n\tconst files: VettaPluginPackageFile[] = [];\n\tfor (const entry of entries) {\n\t\tconst fullPath = join(dir, entry.name);\n\t\tif (entry.isDirectory()) {\n\t\t\tfiles.push(...(await collectFiles(fullPath)));\n\t\t} else if (entry.isFile()) {\n\t\t\tfiles.push({ fullPath, archivePath: \"\" });\n\t\t}\n\t}\n\treturn files;\n}\n\nasync function collectPath(path: string): Promise<VettaPluginPackageFile[]> {\n\tconst info = await stat(path);\n\tif (info.isDirectory()) {\n\t\treturn collectFiles(path);\n\t}\n\tif (info.isFile()) {\n\t\treturn [{ fullPath: path, archivePath: \"\" }];\n\t}\n\treturn [];\n}\n\nasync function createZip(files: VettaPluginPackageFile[]): Promise<Buffer> {\n\tconst localParts: Buffer[] = [];\n\tconst centralParts: Buffer[] = [];\n\tlet offset = 0;\n\n\tfor (const file of files) {\n\t\tconst data = await readFile(file.fullPath);\n\t\tconst name = Buffer.from(file.archivePath.replace(/\\\\/g, \"/\"));\n\t\tconst checksum = crc32(data);\n\t\tconst localHeader = Buffer.concat([\n\t\t\twriteUInt32(0x04034b50),\n\t\t\twriteUInt16(20),\n\t\t\twriteUInt16(0),\n\t\t\twriteUInt16(0),\n\t\t\twriteUInt16(0),\n\t\t\twriteUInt16(0),\n\t\t\twriteUInt32(checksum),\n\t\t\twriteUInt32(data.length),\n\t\t\twriteUInt32(data.length),\n\t\t\twriteUInt16(name.length),\n\t\t\twriteUInt16(0),\n\t\t\tname,\n\t\t]);\n\t\tlocalParts.push(localHeader, data);\n\n\t\tcentralParts.push(\n\t\t\tBuffer.concat([\n\t\t\t\twriteUInt32(0x02014b50),\n\t\t\t\twriteUInt16(20),\n\t\t\t\twriteUInt16(20),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt32(checksum),\n\t\t\t\twriteUInt32(data.length),\n\t\t\t\twriteUInt32(data.length),\n\t\t\t\twriteUInt16(name.length),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt32(0),\n\t\t\t\twriteUInt32(offset),\n\t\t\t\tname,\n\t\t\t]),\n\t\t);\n\t\toffset += localHeader.length + data.length;\n\t}\n\n\tconst centralDirectory = Buffer.concat(centralParts);\n\tconst endOfCentralDirectory = Buffer.concat([\n\t\twriteUInt32(0x06054b50),\n\t\twriteUInt16(0),\n\t\twriteUInt16(0),\n\t\twriteUInt16(files.length),\n\t\twriteUInt16(files.length),\n\t\twriteUInt32(centralDirectory.length),\n\t\twriteUInt32(offset),\n\t\twriteUInt16(0),\n\t]);\n\n\treturn Buffer.concat([...localParts, centralDirectory, endOfCentralDirectory]);\n}\n\nfunction readManifestRemoteEntry(manifest: Record<string, unknown>): string | undefined {\n\tconst metaData = manifest.metaData;\n\tif (!isRecord(metaData)) {\n\t\treturn undefined;\n\t}\n\tconst remoteEntry = metaData.remoteEntry;\n\tif (!isRecord(remoteEntry)) {\n\t\treturn undefined;\n\t}\n\tconst name = readString(remoteEntry, \"name\");\n\tif (!name) {\n\t\treturn undefined;\n\t}\n\tconst path = readString(remoteEntry, \"path\") ?? \"\";\n\treturn path ? `${path.replace(/\\/$/, \"\")}/${name}` : name;\n}\n\nasync function collectRuntimeFiles(\n\trootDir: string,\n\tmanifestPath: string,\n\tdistDir: string,\n): Promise<VettaPluginPackageFile[]> {\n\tconst pluginManifest = parsePluginManifest(parseJsonObject(await readFile(manifestPath), basename(manifestPath)));\n\tconst packageFiles = new Map<string, VettaPluginPackageFile>();\n\tconst addFile = (fullPath: string) => {\n\t\tconst resolved = resolve(fullPath);\n\t\tconst archivePath = archivePathFromRoot(rootDir, resolved);\n\t\tpackageFiles.set(archivePath, { fullPath: resolved, archivePath });\n\t};\n\n\taddFile(manifestPath);\n\n\t// 插件详情跟随插件包发布;ability.json 缺省兼容,存在时必须与 plugin.json 身份一致。\n\tconst abilityDescriptorPath = resolve(rootDir, \"ability.json\");\n\tif (existsSync(abilityDescriptorPath)) {\n\t\tvalidateAbilityDescriptor(\n\t\t\tparseJsonObject(await readFile(abilityDescriptorPath), basename(abilityDescriptorPath)),\n\t\t\tpluginManifest,\n\t\t);\n\t\taddFile(abilityDescriptorPath);\n\t\t// 约定的展示资源目录;内联 blocks 可引用其中的图片,随包整体带上。\n\t\ttry {\n\t\t\tfor (const file of await collectFiles(resolve(rootDir, \"presentation\"))) {\n\t\t\t\taddFile(file.fullPath);\n\t\t\t}\n\t\t} catch {\n\t\t\t// optional presentation/ directory\n\t\t}\n\t}\n\n\tconst federationManifestPath = resolve(rootDir, pluginManifest.entry);\n\taddFile(federationManifestPath);\n\n\tconst federationManifest = parseJsonObject(await readFile(federationManifestPath), basename(federationManifestPath));\n\tconst remoteEntry = readManifestRemoteEntry(federationManifest);\n\tif (remoteEntry) {\n\t\taddFile(resolve(dirname(federationManifestPath), remoteEntry));\n\t}\n\n\tconst assetsDir = join(distDir, \"assets\");\n\tfor (const file of await collectFiles(assetsDir)) {\n\t\taddFile(file.fullPath);\n\t}\n\n\t// Vite cssCodeSplit emits extra files like dist/style2.css for async chunks;\n\t// include all dist-root CSS so preload-helper can fetch them (not only styles[]).\n\ttry {\n\t\tfor (const file of await collectFiles(distDir)) {\n\t\t\tconst rel = relative(distDir, file.fullPath).replace(/\\\\/g, \"/\");\n\t\t\tif (rel.endsWith(\".css\") && !rel.includes(\"/\")) {\n\t\t\t\taddFile(file.fullPath);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// dist missing\n\t}\n\n\tfor (const style of pluginManifest.styles ?? []) {\n\t\taddFile(resolve(rootDir, style));\n\t}\n\n\t// 包内相对路径图标:不打进 zip 的话,宿主 vetta-plugin:// 会 404、市场上传会被服务端拒绝。\n\tconst icon = pluginManifest.icon?.trim();\n\tif (icon && isPackagedIconPath(icon)) {\n\t\tconst iconPath = resolve(rootDir, icon);\n\t\tif (!existsSync(iconPath)) {\n\t\t\tthrow new Error(`plugin.json icon file not found: ${icon}`);\n\t\t}\n\t\taddFile(iconPath);\n\t}\n\n\tfor (const promptPath of pluginManifest.agent?.systemPrompt?.promptPaths ?? []) {\n\t\tfor (const file of await collectPath(resolve(rootDir, promptPath))) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t}\n\n\tfor (const skillPath of pluginManifest.agent?.skillPaths ?? []) {\n\t\tfor (const file of await collectPath(resolve(rootDir, skillPath))) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t}\n\n\t// Plugin-scoped MCP: include config file and conventional companion dirs when declared.\n\tconst mcpServers = pluginManifest.agent?.mcpServers;\n\tif (mcpServers !== undefined) {\n\t\tif (typeof mcpServers === \"string\") {\n\t\t\taddFile(resolve(rootDir, mcpServers));\n\t\t}\n\t\ttry {\n\t\t\tfor (const file of await collectFiles(resolve(rootDir, \"mcp\"))) {\n\t\t\t\taddFile(file.fullPath);\n\t\t\t}\n\t\t} catch {\n\t\t\t// optional mcp/ directory\n\t\t}\n\t}\n\n\t// Helper scripts (plugin workbench etc.): always pack scripts/ when present.\n\ttry {\n\t\tfor (const file of await collectFiles(resolve(rootDir, \"scripts\"))) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t} catch {\n\t\t// optional scripts/ directory\n\t}\n\n\t// Handbook / agent docs beside skills (not always listed in skillPaths).\n\ttry {\n\t\tfor (const file of await collectFiles(resolve(rootDir, \"agent/docs\"))) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t} catch {\n\t\t// optional agent/docs\n\t}\n\n\t// Plugin i18n catalogs (ADR-0033): bundle locales/<lang>.json so the host can\n\t// load them alongside the manifest. Optional — absent for single-language plugins.\n\ttry {\n\t\tfor (const file of await collectFiles(resolve(rootDir, \"locales\"))) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t} catch {\n\t\t// no locales/ directory — nothing to bundle\n\t}\n\n\treturn [...packageFiles.values()].sort((a, b) => a.archivePath.localeCompare(b.archivePath));\n}\n\nexport async function createVettaPluginPackage(\n\toptions: CreateVettaPluginPackageOptions = {},\n): Promise<VettaPluginPackageResult> {\n\tconst rootDir = resolve(options.rootDir ?? process.cwd());\n\tconst manifestPath = resolve(rootDir, options.manifestPath ?? \"plugin.json\");\n\tconst releaseDir = resolve(rootDir, options.releaseDir ?? \"release\");\n\tconst distDir = resolve(rootDir, options.distDir ?? \"dist\");\n\tconst pluginManifest = parsePluginManifest(parseJsonObject(await readFile(manifestPath), basename(manifestPath)));\n\tconst outputPath = join(releaseDir, `${pluginManifest.id}-${pluginManifest.version}.zip`);\n\tconst files = await collectRuntimeFiles(rootDir, manifestPath, distDir);\n\n\tawait rm(releaseDir, { recursive: true, force: true });\n\tawait mkdir(releaseDir, { recursive: true });\n\tawait writeFile(outputPath, await createZip(files));\n\n\treturn { outputPath, files };\n}\n"]}
1
+ {"version":3,"file":"pack.js","sourceRoot":"","sources":["../src/pack.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join, relative, resolve, sep } from \"node:path\";\nimport { listPluginManifestResources, parsePluginManifest, type PluginManifest } from \"@vetta-org/plugin-sdk/manifest\";\nimport { parseVettaNpmPluginPackage } from \"@vetta-org/plugin-sdk/npm-package\";\nimport { assertPluginPermissionContract } from \"./permission-contract.js\";\n\nexport interface VettaPluginPackageFile {\n\tfullPath: string;\n\tarchivePath: string;\n}\n\nexport interface VettaPluginPackageResult {\n\toutputPath: string;\n\tnpmOutputPath?: string;\n\tfiles: VettaPluginPackageFile[];\n}\n\nexport interface CreateVettaPluginPackageOptions {\n\trootDir?: string;\n\tmanifestPath?: string;\n\treleaseDir?: string;\n\tdistDir?: string;\n\t/** Also write the stable npm distribution artifact `release/vetta-plugin.zip`. */\n\tnpmArchive?: boolean;\n}\n\nexport const VETTA_NPM_PLUGIN_ARCHIVE_PATH = \"release/vetta-plugin.zip\";\n\nconst crcTable = new Uint32Array(256);\nfor (let i = 0; i < 256; i += 1) {\n\tlet value = i;\n\tfor (let bit = 0; bit < 8; bit += 1) {\n\t\tvalue = value & 1 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;\n\t}\n\tcrcTable[i] = value >>> 0;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction readString(record: Record<string, unknown>, key: string): string | undefined {\n\tconst value = record[key];\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction validateAbilityDescriptor(value: unknown, pluginManifest: PluginManifest): void {\n\tif (!isRecord(value)) throw new Error(\"ability.json must contain an object.\");\n\tif (\n\t\tvalue.schemaVersion !== 1 ||\n\t\tvalue.type !== \"plugin\" ||\n\t\tvalue.slug !== pluginManifest.id ||\n\t\tvalue.version !== pluginManifest.version\n\t) {\n\t\tthrow new Error(\"ability.json identity must match plugin.json id and version.\");\n\t}\n}\n\nfunction parseJsonObject(buffer: Buffer, fileName: string): Record<string, unknown> {\n\tconst parsed = JSON.parse(buffer.toString(\"utf-8\")) as unknown;\n\tif (!isRecord(parsed)) {\n\t\tthrow new Error(`${fileName} must contain an object.`);\n\t}\n\treturn parsed;\n}\n\nfunction crc32(buffer: Buffer): number {\n\tlet value = 0xffffffff;\n\tfor (const byte of buffer) {\n\t\tvalue = crcTable[(value ^ byte) & 0xff] ^ (value >>> 8);\n\t}\n\treturn (value ^ 0xffffffff) >>> 0;\n}\n\nfunction writeUInt16(value: number): Buffer {\n\tconst buffer = Buffer.allocUnsafe(2);\n\tbuffer.writeUInt16LE(value, 0);\n\treturn buffer;\n}\n\nfunction writeUInt32(value: number): Buffer {\n\tconst buffer = Buffer.allocUnsafe(4);\n\tbuffer.writeUInt32LE(value >>> 0, 0);\n\treturn buffer;\n}\n\nfunction archivePathFromRoot(rootDir: string, fullPath: string): string {\n\tconst archivePath = relative(rootDir, fullPath).replace(/\\\\/g, \"/\");\n\tif (!archivePath || archivePath.startsWith(\"..\") || archivePath.includes(`${sep}..${sep}`)) {\n\t\tthrow new Error(`File is outside plugin root: ${fullPath}`);\n\t}\n\treturn archivePath;\n}\n\nasync function collectFiles(dir: string): Promise<VettaPluginPackageFile[]> {\n\tconst entries = await readdir(dir, { withFileTypes: true });\n\tconst files: VettaPluginPackageFile[] = [];\n\tfor (const entry of entries) {\n\t\tconst fullPath = join(dir, entry.name);\n\t\tif (entry.isDirectory()) {\n\t\t\tfiles.push(...(await collectFiles(fullPath)));\n\t\t} else if (entry.isFile()) {\n\t\t\tfiles.push({ fullPath, archivePath: \"\" });\n\t\t}\n\t}\n\treturn files;\n}\n\nasync function collectPath(path: string): Promise<VettaPluginPackageFile[]> {\n\tconst info = await stat(path);\n\tif (info.isDirectory()) {\n\t\treturn collectFiles(path);\n\t}\n\tif (info.isFile()) {\n\t\treturn [{ fullPath: path, archivePath: \"\" }];\n\t}\n\treturn [];\n}\n\nasync function createZip(files: VettaPluginPackageFile[]): Promise<Buffer> {\n\tconst localParts: Buffer[] = [];\n\tconst centralParts: Buffer[] = [];\n\tlet offset = 0;\n\n\tfor (const file of files) {\n\t\tconst data = await readFile(file.fullPath);\n\t\tconst name = Buffer.from(file.archivePath.replace(/\\\\/g, \"/\"));\n\t\tconst checksum = crc32(data);\n\t\tconst localHeader = Buffer.concat([\n\t\t\twriteUInt32(0x04034b50),\n\t\t\twriteUInt16(20),\n\t\t\twriteUInt16(0),\n\t\t\twriteUInt16(0),\n\t\t\twriteUInt16(0),\n\t\t\twriteUInt16(0),\n\t\t\twriteUInt32(checksum),\n\t\t\twriteUInt32(data.length),\n\t\t\twriteUInt32(data.length),\n\t\t\twriteUInt16(name.length),\n\t\t\twriteUInt16(0),\n\t\t\tname,\n\t\t]);\n\t\tlocalParts.push(localHeader, data);\n\n\t\tcentralParts.push(\n\t\t\tBuffer.concat([\n\t\t\t\twriteUInt32(0x02014b50),\n\t\t\t\twriteUInt16(20),\n\t\t\t\twriteUInt16(20),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt32(checksum),\n\t\t\t\twriteUInt32(data.length),\n\t\t\t\twriteUInt32(data.length),\n\t\t\t\twriteUInt16(name.length),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt16(0),\n\t\t\t\twriteUInt32(0),\n\t\t\t\twriteUInt32(offset),\n\t\t\t\tname,\n\t\t\t]),\n\t\t);\n\t\toffset += localHeader.length + data.length;\n\t}\n\n\tconst centralDirectory = Buffer.concat(centralParts);\n\tconst endOfCentralDirectory = Buffer.concat([\n\t\twriteUInt32(0x06054b50),\n\t\twriteUInt16(0),\n\t\twriteUInt16(0),\n\t\twriteUInt16(files.length),\n\t\twriteUInt16(files.length),\n\t\twriteUInt32(centralDirectory.length),\n\t\twriteUInt32(offset),\n\t\twriteUInt16(0),\n\t]);\n\n\treturn Buffer.concat([...localParts, centralDirectory, endOfCentralDirectory]);\n}\n\nfunction readManifestRemoteEntry(manifest: Record<string, unknown>): string | undefined {\n\tconst metaData = manifest.metaData;\n\tif (!isRecord(metaData)) {\n\t\treturn undefined;\n\t}\n\tconst remoteEntry = metaData.remoteEntry;\n\tif (!isRecord(remoteEntry)) {\n\t\treturn undefined;\n\t}\n\tconst name = readString(remoteEntry, \"name\");\n\tif (!name) {\n\t\treturn undefined;\n\t}\n\tconst path = readString(remoteEntry, \"path\") ?? \"\";\n\treturn path ? `${path.replace(/\\/$/, \"\")}/${name}` : name;\n}\n\nasync function collectRuntimeFiles(\n\trootDir: string,\n\tmanifestPath: string,\n\tdistDir: string,\n): Promise<VettaPluginPackageFile[]> {\n\tconst pluginManifest = parsePluginManifest(parseJsonObject(await readFile(manifestPath), basename(manifestPath)));\n\tconst packageFiles = new Map<string, VettaPluginPackageFile>();\n\tconst addFile = (fullPath: string) => {\n\t\tconst resolved = resolve(fullPath);\n\t\tconst archivePath = archivePathFromRoot(rootDir, resolved);\n\t\tpackageFiles.set(archivePath, { fullPath: resolved, archivePath });\n\t};\n\n\taddFile(manifestPath);\n\n\t// 插件详情跟随插件包发布;ability.json 缺省兼容,存在时必须与 plugin.json 身份一致。\n\tconst abilityDescriptorPath = resolve(rootDir, \"ability.json\");\n\tif (existsSync(abilityDescriptorPath)) {\n\t\tvalidateAbilityDescriptor(\n\t\t\tparseJsonObject(await readFile(abilityDescriptorPath), basename(abilityDescriptorPath)),\n\t\t\tpluginManifest,\n\t\t);\n\t\taddFile(abilityDescriptorPath);\n\t\t// 约定的展示资源目录;内联 blocks 可引用其中的图片,随包整体带上。\n\t\ttry {\n\t\t\tfor (const file of await collectFiles(resolve(rootDir, \"presentation\"))) {\n\t\t\t\taddFile(file.fullPath);\n\t\t\t}\n\t\t} catch {\n\t\t\t// optional presentation/ directory\n\t\t}\n\t}\n\n\tconst runtimeEntryPath = resolve(rootDir, pluginManifest.entry);\n\taddFile(runtimeEntryPath);\n\n\tconst federationManifest = parseJsonObject(await readFile(runtimeEntryPath), basename(runtimeEntryPath));\n\tconst remoteEntry = readManifestRemoteEntry(federationManifest);\n\tif (remoteEntry) {\n\t\taddFile(resolve(dirname(runtimeEntryPath), remoteEntry));\n\t}\n\n\tconst assetsDir = join(distDir, \"assets\");\n\tfor (const file of await collectFiles(assetsDir)) {\n\t\taddFile(file.fullPath);\n\t}\n\n\t// Vite cssCodeSplit emits extra files like dist/style2.css for async chunks;\n\t// include all dist-root CSS so preload-helper can fetch them (not only styles[]).\n\ttry {\n\t\tfor (const file of await collectFiles(distDir)) {\n\t\t\tconst rel = relative(distDir, file.fullPath).replace(/\\\\/g, \"/\");\n\t\t\tif (rel.endsWith(\".css\") && !rel.includes(\"/\")) {\n\t\t\t\taddFile(file.fullPath);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// dist missing\n\t}\n\n\tfor (const resource of listPluginManifestResources(pluginManifest)) {\n\t\tif (resource.field === \"entry\") continue;\n\t\tconst resourcePath = resolve(rootDir, resource.path);\n\t\tif (resource.kind === \"file\") {\n\t\t\tif (!existsSync(resourcePath)) {\n\t\t\t\tthrow new Error(`plugin.json resource not found: ${resource.field} (${resource.path})`);\n\t\t\t}\n\t\t\taddFile(resourcePath);\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const file of await collectPath(resourcePath)) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t}\n\n\t// Plugin-scoped MCP: include config file and conventional companion dirs when declared.\n\tconst mcpServers = pluginManifest.agent?.mcpServers;\n\tif (mcpServers !== undefined) {\n\t\ttry {\n\t\t\tfor (const file of await collectFiles(resolve(rootDir, \"mcp\"))) {\n\t\t\t\taddFile(file.fullPath);\n\t\t\t}\n\t\t} catch {\n\t\t\t// optional mcp/ directory\n\t\t}\n\t}\n\n\t// Helper scripts (plugin workbench etc.): always pack scripts/ when present.\n\ttry {\n\t\tfor (const file of await collectFiles(resolve(rootDir, \"scripts\"))) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t} catch {\n\t\t// optional scripts/ directory\n\t}\n\n\t// Handbook / agent docs beside skills (not always listed in skillPaths).\n\ttry {\n\t\tfor (const file of await collectFiles(resolve(rootDir, \"agent/docs\"))) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t} catch {\n\t\t// optional agent/docs\n\t}\n\n\t// Plugin i18n catalogs (ADR-0033): bundle locales/<lang>.json so the host can\n\t// load them alongside the manifest. Optional — absent for single-language plugins.\n\ttry {\n\t\tfor (const file of await collectFiles(resolve(rootDir, \"locales\"))) {\n\t\t\taddFile(file.fullPath);\n\t\t}\n\t} catch {\n\t\t// no locales/ directory — nothing to bundle\n\t}\n\n\treturn [...packageFiles.values()].sort((a, b) => a.archivePath.localeCompare(b.archivePath));\n}\n\nexport async function createVettaPluginPackage(\n\toptions: CreateVettaPluginPackageOptions = {},\n): Promise<VettaPluginPackageResult> {\n\tconst rootDir = resolve(options.rootDir ?? process.cwd());\n\tconst manifestPath = resolve(rootDir, options.manifestPath ?? \"plugin.json\");\n\tconst releaseDir = resolve(rootDir, options.releaseDir ?? \"release\");\n\tconst distDir = resolve(rootDir, options.distDir ?? \"dist\");\n\tconst pluginManifest = parsePluginManifest(parseJsonObject(await readFile(manifestPath), basename(manifestPath)));\n\tconst outputPath = join(releaseDir, `${pluginManifest.id}-${pluginManifest.version}.zip`);\n\tconst files = await collectRuntimeFiles(rootDir, manifestPath, distDir);\n\tassertPluginPermissionContract(\n\t\tpluginManifest,\n\t\tawait Promise.all(\n\t\t\tfiles\n\t\t\t\t.filter((file) => /\\.(?:c|m)?js$/u.test(file.archivePath))\n\t\t\t\t.map(async (file) => ({ fileName: file.archivePath, code: await readFile(file.fullPath, \"utf8\") })),\n\t\t),\n\t);\n\tlet npmOutputPath: string | undefined;\n\tif (options.npmArchive === true) {\n\t\tconst packageManifest = parseVettaNpmPluginPackage(\n\t\t\tparseJsonObject(await readFile(resolve(rootDir, \"package.json\")), \"package.json\"),\n\t\t);\n\t\tif (packageManifest.version !== pluginManifest.version) {\n\t\t\tthrow new Error(\n\t\t\t\t`npm package version ${packageManifest.version} must match plugin version ${pluginManifest.version}.`,\n\t\t\t);\n\t\t}\n\t\tif (packageManifest.vetta.pluginId !== pluginManifest.id) {\n\t\t\tthrow new Error(\n\t\t\t\t`npm package plugin id ${packageManifest.vetta.pluginId} must match plugin id ${pluginManifest.id}.`,\n\t\t\t);\n\t\t}\n\t\tif (packageManifest.vetta.archive !== VETTA_NPM_PLUGIN_ARCHIVE_PATH) {\n\t\t\tthrow new Error(`npm package archive must be ${VETTA_NPM_PLUGIN_ARCHIVE_PATH}.`);\n\t\t}\n\t\tnpmOutputPath = resolve(rootDir, VETTA_NPM_PLUGIN_ARCHIVE_PATH);\n\t}\n\n\tawait mkdir(releaseDir, { recursive: true });\n\tawait rm(outputPath, { force: true });\n\tconst archive = await createZip(files);\n\tawait writeFile(outputPath, archive);\n\tif (npmOutputPath && npmOutputPath !== outputPath) {\n\t\tawait mkdir(dirname(npmOutputPath), { recursive: true });\n\t\tawait rm(npmOutputPath, { force: true });\n\t\tawait writeFile(npmOutputPath, archive);\n\t}\n\n\treturn { outputPath, npmOutputPath, files };\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { PluginManifest, PluginPermission } from "@vetta-org/plugin-sdk/manifest";
2
+ export interface PluginRuntimeChunk {
3
+ fileName: string;
4
+ code: string;
5
+ }
6
+ export interface PluginPermissionContractViolation {
7
+ capability: string;
8
+ fileName: string;
9
+ missingPermissions: PluginPermission[];
10
+ }
11
+ export declare function findPluginPermissionContractViolations(manifest: PluginManifest, chunks: readonly PluginRuntimeChunk[]): PluginPermissionContractViolation[];
12
+ export declare function assertPluginPermissionContract(manifest: PluginManifest, chunks: readonly PluginRuntimeChunk[]): void;
13
+ //# sourceMappingURL=permission-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-contract.d.ts","sourceRoot":"","sources":["../src/permission-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAEvF,MAAM,WAAW,kBAAkB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iCAAiC;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;CACvC;AAmDD,wBAAgB,sCAAsC,CACrD,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,SAAS,kBAAkB,EAAE,GACnC,iCAAiC,EAAE,CA8CrC;AAED,wBAAgB,8BAA8B,CAC7C,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,SAAS,kBAAkB,EAAE,GACnC,IAAI,CAUN","sourcesContent":["import type { PluginManifest, PluginPermission } from \"@vetta-org/plugin-sdk/manifest\";\n\nexport interface PluginRuntimeChunk {\n\tfileName: string;\n\tcode: string;\n}\n\nexport interface PluginPermissionContractViolation {\n\tcapability: string;\n\tfileName: string;\n\tmissingPermissions: PluginPermission[];\n}\n\ninterface BundleCapabilityRule {\n\tcapability: string;\n\tpermissions: readonly PluginPermission[];\n\tpatterns: readonly RegExp[];\n}\n\nconst BUNDLE_CAPABILITY_RULES: readonly BundleCapabilityRule[] = [\n\t{\n\t\tcapability: \"dynamic system prompt provider registration\",\n\t\tpermissions: [\"agent.systemPrompt.write\"],\n\t\tpatterns: [/(?:\\.|\\[\\s*[\"'])registerSystemPromptProvider(?:[\"']\\s*\\])?\\s*\\(/u],\n\t},\n\t{\n\t\tcapability: \"dynamic runtime tool availability\",\n\t\tpermissions: [\"agent.tools.control\"],\n\t\tpatterns: [\n\t\t\t/(?:\\btype|[\"']type[\"'])\\s*:\\s*[\"']setToolEnabled[\"']/u,\n\t\t\t/(?:\\.tools|\\[\\s*[\"']tools[\"']\\s*\\])(?:\\.(?:setEnabled|enable|disable)|\\[\\s*[\"'](?:setEnabled|enable|disable)[\"']\\s*\\])\\s*\\(/u,\n\t\t],\n\t},\n\t{\n\t\tcapability: \"Agent continuation\",\n\t\tpermissions: [\"agent.continuation.register\"],\n\t\tpatterns: [\n\t\t\t/(?:\\.|\\[\\s*[\"'])registerContinuationProvider(?:[\"']\\s*\\])?\\s*\\(/u,\n\t\t\t/(?:\\btype|[\"']type[\"'])\\s*:\\s*[\"']requestContinuation[\"']/u,\n\t\t\t/(?:\\.continuation|\\[\\s*[\"']continuation[\"']\\s*\\])(?:\\.request|\\[\\s*[\"']request[\"']\\s*\\])\\s*\\(/u,\n\t\t],\n\t},\n\t{\n\t\tcapability: \"Agent tool registration\",\n\t\tpermissions: [\"agent.tools.register\", \"agent.toolHandler.execute\"],\n\t\tpatterns: [/(?:\\.|\\[\\s*[\"'])registerTool(?:[\"']\\s*\\])?\\s*\\(/u],\n\t},\n\t{\n\t\tcapability: \"Agent hook registration\",\n\t\tpermissions: [\"agent.hooks.register\", \"agent.hookHandler.execute\"],\n\t\tpatterns: [/(?:\\.|\\[\\s*[\"'])registerHook(?:[\"']\\s*\\])?\\s*\\(/u],\n\t},\n];\n\nfunction missingPermissions(\n\tmanifest: PluginManifest,\n\trequired: readonly PluginPermission[],\n): PluginPermission[] {\n\tconst declared = new Set(manifest.permissions ?? []);\n\treturn required.filter((permission) => !declared.has(permission));\n}\n\nexport function findPluginPermissionContractViolations(\n\tmanifest: PluginManifest,\n\tchunks: readonly PluginRuntimeChunk[],\n): PluginPermissionContractViolation[] {\n\tconst violations: PluginPermissionContractViolation[] = [];\n\tfor (const rule of BUNDLE_CAPABILITY_RULES) {\n\t\tconst chunk = chunks.find((candidate) => rule.patterns.some((pattern) => pattern.test(candidate.code)));\n\t\tif (!chunk) continue;\n\t\tconst missing = missingPermissions(manifest, rule.permissions);\n\t\tif (missing.length === 0) continue;\n\t\tviolations.push({\n\t\t\tcapability: rule.capability,\n\t\t\tfileName: chunk.fileName,\n\t\t\tmissingPermissions: missing,\n\t\t});\n\t}\n\n\tconst manifestRequirements: Array<{\n\t\tactive: boolean;\n\t\tcapability: string;\n\t\tpermission: PluginPermission;\n\t}> = [\n\t\t{\n\t\t\tactive: manifest.agent?.toolPolicy !== undefined,\n\t\t\tcapability: \"plugin.json#agent.toolPolicy\",\n\t\t\tpermission: \"agent.tools.control\",\n\t\t},\n\t\t{\n\t\t\tactive: (manifest.agent?.skillPaths?.length ?? 0) > 0,\n\t\t\tcapability: \"plugin.json#agent.skillPaths\",\n\t\t\tpermission: \"agent.skills.control\",\n\t\t},\n\t\t{\n\t\t\tactive: manifest.agent?.mcpServers !== undefined,\n\t\t\tcapability: \"plugin.json#agent.mcpServers\",\n\t\t\tpermission: \"agent.mcp.control\",\n\t\t},\n\t];\n\tfor (const requirement of manifestRequirements) {\n\t\tif (!requirement.active) continue;\n\t\tconst missing = missingPermissions(manifest, [requirement.permission]);\n\t\tif (missing.length === 0) continue;\n\t\tviolations.push({\n\t\t\tcapability: requirement.capability,\n\t\t\tfileName: \"plugin.json\",\n\t\t\tmissingPermissions: missing,\n\t\t});\n\t}\n\treturn violations;\n}\n\nexport function assertPluginPermissionContract(\n\tmanifest: PluginManifest,\n\tchunks: readonly PluginRuntimeChunk[],\n): void {\n\tconst violations = findPluginPermissionContractViolations(manifest, chunks);\n\tif (violations.length === 0) return;\n\tconst details = violations.map(\n\t\t(violation) =>\n\t\t\t`- ${violation.capability} in ${violation.fileName} requires ${violation.missingPermissions\n\t\t\t\t.map((permission) => JSON.stringify(permission))\n\t\t\t\t.join(\" and \")}`,\n\t);\n\tthrow new Error(`Plugin ${JSON.stringify(manifest.id)} permission contract failed:\\n${details.join(\"\\n\")}`);\n}\n"]}
@@ -0,0 +1,94 @@
1
+ const BUNDLE_CAPABILITY_RULES = [
2
+ {
3
+ capability: "dynamic system prompt provider registration",
4
+ permissions: ["agent.systemPrompt.write"],
5
+ patterns: [/(?:\.|\[\s*["'])registerSystemPromptProvider(?:["']\s*\])?\s*\(/u],
6
+ },
7
+ {
8
+ capability: "dynamic runtime tool availability",
9
+ permissions: ["agent.tools.control"],
10
+ patterns: [
11
+ /(?:\btype|["']type["'])\s*:\s*["']setToolEnabled["']/u,
12
+ /(?:\.tools|\[\s*["']tools["']\s*\])(?:\.(?:setEnabled|enable|disable)|\[\s*["'](?:setEnabled|enable|disable)["']\s*\])\s*\(/u,
13
+ ],
14
+ },
15
+ {
16
+ capability: "Agent continuation",
17
+ permissions: ["agent.continuation.register"],
18
+ patterns: [
19
+ /(?:\.|\[\s*["'])registerContinuationProvider(?:["']\s*\])?\s*\(/u,
20
+ /(?:\btype|["']type["'])\s*:\s*["']requestContinuation["']/u,
21
+ /(?:\.continuation|\[\s*["']continuation["']\s*\])(?:\.request|\[\s*["']request["']\s*\])\s*\(/u,
22
+ ],
23
+ },
24
+ {
25
+ capability: "Agent tool registration",
26
+ permissions: ["agent.tools.register", "agent.toolHandler.execute"],
27
+ patterns: [/(?:\.|\[\s*["'])registerTool(?:["']\s*\])?\s*\(/u],
28
+ },
29
+ {
30
+ capability: "Agent hook registration",
31
+ permissions: ["agent.hooks.register", "agent.hookHandler.execute"],
32
+ patterns: [/(?:\.|\[\s*["'])registerHook(?:["']\s*\])?\s*\(/u],
33
+ },
34
+ ];
35
+ function missingPermissions(manifest, required) {
36
+ const declared = new Set(manifest.permissions ?? []);
37
+ return required.filter((permission) => !declared.has(permission));
38
+ }
39
+ export function findPluginPermissionContractViolations(manifest, chunks) {
40
+ const violations = [];
41
+ for (const rule of BUNDLE_CAPABILITY_RULES) {
42
+ const chunk = chunks.find((candidate) => rule.patterns.some((pattern) => pattern.test(candidate.code)));
43
+ if (!chunk)
44
+ continue;
45
+ const missing = missingPermissions(manifest, rule.permissions);
46
+ if (missing.length === 0)
47
+ continue;
48
+ violations.push({
49
+ capability: rule.capability,
50
+ fileName: chunk.fileName,
51
+ missingPermissions: missing,
52
+ });
53
+ }
54
+ const manifestRequirements = [
55
+ {
56
+ active: manifest.agent?.toolPolicy !== undefined,
57
+ capability: "plugin.json#agent.toolPolicy",
58
+ permission: "agent.tools.control",
59
+ },
60
+ {
61
+ active: (manifest.agent?.skillPaths?.length ?? 0) > 0,
62
+ capability: "plugin.json#agent.skillPaths",
63
+ permission: "agent.skills.control",
64
+ },
65
+ {
66
+ active: manifest.agent?.mcpServers !== undefined,
67
+ capability: "plugin.json#agent.mcpServers",
68
+ permission: "agent.mcp.control",
69
+ },
70
+ ];
71
+ for (const requirement of manifestRequirements) {
72
+ if (!requirement.active)
73
+ continue;
74
+ const missing = missingPermissions(manifest, [requirement.permission]);
75
+ if (missing.length === 0)
76
+ continue;
77
+ violations.push({
78
+ capability: requirement.capability,
79
+ fileName: "plugin.json",
80
+ missingPermissions: missing,
81
+ });
82
+ }
83
+ return violations;
84
+ }
85
+ export function assertPluginPermissionContract(manifest, chunks) {
86
+ const violations = findPluginPermissionContractViolations(manifest, chunks);
87
+ if (violations.length === 0)
88
+ return;
89
+ const details = violations.map((violation) => `- ${violation.capability} in ${violation.fileName} requires ${violation.missingPermissions
90
+ .map((permission) => JSON.stringify(permission))
91
+ .join(" and ")}`);
92
+ throw new Error(`Plugin ${JSON.stringify(manifest.id)} permission contract failed:\n${details.join("\n")}`);
93
+ }
94
+ //# sourceMappingURL=permission-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-contract.js","sourceRoot":"","sources":["../src/permission-contract.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PluginManifest, PluginPermission } from \"@vetta-org/plugin-sdk/manifest\";\n\nexport interface PluginRuntimeChunk {\n\tfileName: string;\n\tcode: string;\n}\n\nexport interface PluginPermissionContractViolation {\n\tcapability: string;\n\tfileName: string;\n\tmissingPermissions: PluginPermission[];\n}\n\ninterface BundleCapabilityRule {\n\tcapability: string;\n\tpermissions: readonly PluginPermission[];\n\tpatterns: readonly RegExp[];\n}\n\nconst BUNDLE_CAPABILITY_RULES: readonly BundleCapabilityRule[] = [\n\t{\n\t\tcapability: \"dynamic system prompt provider registration\",\n\t\tpermissions: [\"agent.systemPrompt.write\"],\n\t\tpatterns: [/(?:\\.|\\[\\s*[\"'])registerSystemPromptProvider(?:[\"']\\s*\\])?\\s*\\(/u],\n\t},\n\t{\n\t\tcapability: \"dynamic runtime tool availability\",\n\t\tpermissions: [\"agent.tools.control\"],\n\t\tpatterns: [\n\t\t\t/(?:\\btype|[\"']type[\"'])\\s*:\\s*[\"']setToolEnabled[\"']/u,\n\t\t\t/(?:\\.tools|\\[\\s*[\"']tools[\"']\\s*\\])(?:\\.(?:setEnabled|enable|disable)|\\[\\s*[\"'](?:setEnabled|enable|disable)[\"']\\s*\\])\\s*\\(/u,\n\t\t],\n\t},\n\t{\n\t\tcapability: \"Agent continuation\",\n\t\tpermissions: [\"agent.continuation.register\"],\n\t\tpatterns: [\n\t\t\t/(?:\\.|\\[\\s*[\"'])registerContinuationProvider(?:[\"']\\s*\\])?\\s*\\(/u,\n\t\t\t/(?:\\btype|[\"']type[\"'])\\s*:\\s*[\"']requestContinuation[\"']/u,\n\t\t\t/(?:\\.continuation|\\[\\s*[\"']continuation[\"']\\s*\\])(?:\\.request|\\[\\s*[\"']request[\"']\\s*\\])\\s*\\(/u,\n\t\t],\n\t},\n\t{\n\t\tcapability: \"Agent tool registration\",\n\t\tpermissions: [\"agent.tools.register\", \"agent.toolHandler.execute\"],\n\t\tpatterns: [/(?:\\.|\\[\\s*[\"'])registerTool(?:[\"']\\s*\\])?\\s*\\(/u],\n\t},\n\t{\n\t\tcapability: \"Agent hook registration\",\n\t\tpermissions: [\"agent.hooks.register\", \"agent.hookHandler.execute\"],\n\t\tpatterns: [/(?:\\.|\\[\\s*[\"'])registerHook(?:[\"']\\s*\\])?\\s*\\(/u],\n\t},\n];\n\nfunction missingPermissions(\n\tmanifest: PluginManifest,\n\trequired: readonly PluginPermission[],\n): PluginPermission[] {\n\tconst declared = new Set(manifest.permissions ?? []);\n\treturn required.filter((permission) => !declared.has(permission));\n}\n\nexport function findPluginPermissionContractViolations(\n\tmanifest: PluginManifest,\n\tchunks: readonly PluginRuntimeChunk[],\n): PluginPermissionContractViolation[] {\n\tconst violations: PluginPermissionContractViolation[] = [];\n\tfor (const rule of BUNDLE_CAPABILITY_RULES) {\n\t\tconst chunk = chunks.find((candidate) => rule.patterns.some((pattern) => pattern.test(candidate.code)));\n\t\tif (!chunk) continue;\n\t\tconst missing = missingPermissions(manifest, rule.permissions);\n\t\tif (missing.length === 0) continue;\n\t\tviolations.push({\n\t\t\tcapability: rule.capability,\n\t\t\tfileName: chunk.fileName,\n\t\t\tmissingPermissions: missing,\n\t\t});\n\t}\n\n\tconst manifestRequirements: Array<{\n\t\tactive: boolean;\n\t\tcapability: string;\n\t\tpermission: PluginPermission;\n\t}> = [\n\t\t{\n\t\t\tactive: manifest.agent?.toolPolicy !== undefined,\n\t\t\tcapability: \"plugin.json#agent.toolPolicy\",\n\t\t\tpermission: \"agent.tools.control\",\n\t\t},\n\t\t{\n\t\t\tactive: (manifest.agent?.skillPaths?.length ?? 0) > 0,\n\t\t\tcapability: \"plugin.json#agent.skillPaths\",\n\t\t\tpermission: \"agent.skills.control\",\n\t\t},\n\t\t{\n\t\t\tactive: manifest.agent?.mcpServers !== undefined,\n\t\t\tcapability: \"plugin.json#agent.mcpServers\",\n\t\t\tpermission: \"agent.mcp.control\",\n\t\t},\n\t];\n\tfor (const requirement of manifestRequirements) {\n\t\tif (!requirement.active) continue;\n\t\tconst missing = missingPermissions(manifest, [requirement.permission]);\n\t\tif (missing.length === 0) continue;\n\t\tviolations.push({\n\t\t\tcapability: requirement.capability,\n\t\t\tfileName: \"plugin.json\",\n\t\t\tmissingPermissions: missing,\n\t\t});\n\t}\n\treturn violations;\n}\n\nexport function assertPluginPermissionContract(\n\tmanifest: PluginManifest,\n\tchunks: readonly PluginRuntimeChunk[],\n): void {\n\tconst violations = findPluginPermissionContractViolations(manifest, chunks);\n\tif (violations.length === 0) return;\n\tconst details = violations.map(\n\t\t(violation) =>\n\t\t\t`- ${violation.capability} in ${violation.fileName} requires ${violation.missingPermissions\n\t\t\t\t.map((permission) => JSON.stringify(permission))\n\t\t\t\t.join(\" and \")}`,\n\t);\n\tthrow new Error(`Plugin ${JSON.stringify(manifest.id)} permission contract failed:\\n${details.join(\"\\n\")}`);\n}\n"]}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * These Vite queries expose the requested file as a JavaScript value rather
3
+ * than executing the file as a module or applying it as a stylesheet. Their
4
+ * internal loader relationships are implementation details, not dependencies
5
+ * that a consumer would request separately.
6
+ */
7
+ export declare function hasOpaqueResourceQuery(id: string): boolean;
8
+ //# sourceMappingURL=request-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-query.d.ts","sourceRoot":"","sources":["../src/request-query.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAQ1D","sourcesContent":["const OPAQUE_RESOURCE_QUERY_KEYS = new Set([\"inline\", \"raw\", \"url\"]);\n\n/**\n * These Vite queries expose the requested file as a JavaScript value rather\n * than executing the file as a module or applying it as a stylesheet. Their\n * internal loader relationships are implementation details, not dependencies\n * that a consumer would request separately.\n */\nexport function hasOpaqueResourceQuery(id: string): boolean {\n\tconst queryIndex = id.indexOf(\"?\");\n\tif (queryIndex === -1) return false;\n\tconst query = new URLSearchParams(id.slice(queryIndex + 1));\n\tfor (const key of OPAQUE_RESOURCE_QUERY_KEYS) {\n\t\tif (query.has(key)) return true;\n\t}\n\treturn false;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ const OPAQUE_RESOURCE_QUERY_KEYS = new Set(["inline", "raw", "url"]);
2
+ /**
3
+ * These Vite queries expose the requested file as a JavaScript value rather
4
+ * than executing the file as a module or applying it as a stylesheet. Their
5
+ * internal loader relationships are implementation details, not dependencies
6
+ * that a consumer would request separately.
7
+ */
8
+ export function hasOpaqueResourceQuery(id) {
9
+ const queryIndex = id.indexOf("?");
10
+ if (queryIndex === -1)
11
+ return false;
12
+ const query = new URLSearchParams(id.slice(queryIndex + 1));
13
+ for (const key of OPAQUE_RESOURCE_QUERY_KEYS) {
14
+ if (query.has(key))
15
+ return true;
16
+ }
17
+ return false;
18
+ }
19
+ //# sourceMappingURL=request-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-query.js","sourceRoot":"","sources":["../src/request-query.ts"],"names":[],"mappings":"AAAA,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAErE;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,EAAU,EAAW;IAC3D,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,UAAU,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5D,KAAK,MAAM,GAAG,IAAI,0BAA0B,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACjC,CAAC;IACD,OAAO,KAAK,CAAC;AAAA,CACb","sourcesContent":["const OPAQUE_RESOURCE_QUERY_KEYS = new Set([\"inline\", \"raw\", \"url\"]);\n\n/**\n * These Vite queries expose the requested file as a JavaScript value rather\n * than executing the file as a module or applying it as a stylesheet. Their\n * internal loader relationships are implementation details, not dependencies\n * that a consumer would request separately.\n */\nexport function hasOpaqueResourceQuery(id: string): boolean {\n\tconst queryIndex = id.indexOf(\"?\");\n\tif (queryIndex === -1) return false;\n\tconst query = new URLSearchParams(id.slice(queryIndex + 1));\n\tfor (const key of OPAQUE_RESOURCE_QUERY_KEYS) {\n\t\tif (query.has(key)) return true;\n\t}\n\treturn false;\n}\n"]}
@@ -1,3 +1,11 @@
1
1
  import type { Plugin } from "vite";
2
+ export declare function scopePluginCss(css: string, pluginId: string): string;
3
+ /**
4
+ * Vite can import a CSS file as a JavaScript resource module via queries such
5
+ * as `?raw`. Those requests keep the `.css` pathname, but their transform
6
+ * input is JavaScript and must not be parsed by PostCSS. Other queries such as
7
+ * `?direct` and HMR timestamps still represent stylesheet requests.
8
+ */
9
+ export declare function isPluginStylesheetRequest(id: string): boolean;
2
10
  export declare function createPluginStyleScopePlugin(): Plugin;
3
11
  //# sourceMappingURL=style-scope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"style-scope.d.ts","sourceRoot":"","sources":["../src/style-scope.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAmGnC,wBAAgB,4BAA4B,IAAI,MAAM,CAiBrD","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport postcss, { type AtRule, type Container, type Node, type Rule } from \"postcss\";\nimport selectorParser from \"postcss-selector-parser\";\nimport type { Plugin } from \"vite\";\n\nconst PLUGIN_ROOT_ATTRIBUTE = \"data-vetta-plugin-root\";\nconst PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;\nconst KEYFRAMES_PATTERN = /(?:^|-)keyframes$/i;\n\nfunction createPluginRootAttribute(pluginId: string) {\n\treturn selectorParser.attribute({\n\t\tattribute: PLUGIN_ROOT_ATTRIBUTE,\n\t\toperator: \"=\",\n\t\tquoteMark: '\"',\n\t\traws: {},\n\t\tvalue: pluginId,\n\t});\n}\n\nfunction isInsideKeyframes(rule: Rule): boolean {\n\tlet parent: Node | undefined = rule.parent;\n\twhile (parent) {\n\t\tif (\n\t\t\tparent.type === \"atrule\" &&\n\t\t\t\"name\" in parent &&\n\t\t\ttypeof parent.name === \"string\" &&\n\t\t\tKEYFRAMES_PATTERN.test(parent.name)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tparent = parent.parent;\n\t}\n\treturn false;\n}\n\nfunction replacePluginRootSelectors(selector: string): string {\n\treturn selectorParser((selectors) => {\n\t\tselectors.walkPseudos((pseudo) => {\n\t\t\tif (pseudo.value === \":root\") {\n\t\t\t\tpseudo.replaceWith(selectorParser.pseudo({ value: \":scope\" }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pseudo.value === \":host\") {\n\t\t\t\tconst hostArgumentNodes =\n\t\t\t\t\tpseudo.nodes.length === 1 ? pseudo.nodes[0].nodes.map((node) => node.clone()) : [];\n\t\t\t\tpseudo.replaceWith(selectorParser.pseudo({ value: \":scope\" }), ...hostArgumentNodes);\n\t\t\t}\n\t\t});\n\t}).processSync(selector);\n}\n\nfunction isKeyframesAtRule(node: Node): boolean {\n\treturn node.type === \"atrule\" && KEYFRAMES_PATTERN.test((node as AtRule).name);\n}\n\nfunction createScopeRule(pluginId: string): AtRule {\n\treturn postcss.atRule({\n\t\tname: \"scope\",\n\t\tparams: `(${createPluginRootAttribute(pluginId).toString()})`,\n\t});\n}\n\nfunction scopeRulesInContainer(container: Container, pluginId: string): void {\n\tif (!container.nodes) return;\n\tlet currentScope: AtRule | undefined;\n\tfor (const node of [...container.nodes]) {\n\t\tif (node.type === \"rule\") {\n\t\t\tif (!currentScope) {\n\t\t\t\tcurrentScope = createScopeRule(pluginId);\n\t\t\t\tnode.before(currentScope);\n\t\t\t}\n\t\t\tcurrentScope.append(node);\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrentScope = undefined;\n\t\tif (node.type === \"atrule\" && !isKeyframesAtRule(node)) {\n\t\t\tconst atRule = node as AtRule;\n\t\t\tif (atRule.nodes) scopeRulesInContainer(atRule, pluginId);\n\t\t}\n\t}\n}\n\nfunction scopePluginCss(css: string, pluginId: string): string {\n\tconst root = postcss.parse(css);\n\troot.walkRules((rule) => {\n\t\tif (isInsideKeyframes(rule)) return;\n\t\trule.selector = replacePluginRootSelectors(rule.selector);\n\t});\n\tscopeRulesInContainer(root, pluginId);\n\treturn root.toString();\n}\n\nfunction readPluginId(rootDir: string): string {\n\tconst manifestPath = join(rootDir, \"plugin.json\");\n\tconst manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as { id?: unknown };\n\tif (typeof manifest.id !== \"string\" || !PLUGIN_ID_PATTERN.test(manifest.id)) {\n\t\tthrow new Error(`Invalid plugin id in ${manifestPath}`);\n\t}\n\treturn manifest.id;\n}\n\nexport function createPluginStyleScopePlugin(): Plugin {\n\tlet pluginId = \"\";\n\treturn {\n\t\tname: \"vetta-plugin-style-scope\",\n\t\tapply: \"build\",\n\t\tenforce: \"post\",\n\t\tconfigResolved(config) {\n\t\t\tpluginId = readPluginId(config.root);\n\t\t},\n\t\tgenerateBundle(_options, bundle) {\n\t\t\tfor (const output of Object.values(bundle)) {\n\t\t\t\tif (output.type !== \"asset\" || !output.fileName.endsWith(\".css\")) continue;\n\t\t\t\tconst css = typeof output.source === \"string\" ? output.source : Buffer.from(output.source).toString(\"utf8\");\n\t\t\t\toutput.source = scopePluginCss(css, pluginId);\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"style-scope.d.ts","sourceRoot":"","sources":["../src/style-scope.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AA+JnC,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQpE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAK7D;AAWD,wBAAgB,4BAA4B,IAAI,MAAM,CAyBrD","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport postcss, { type AtRule, type Container, type Node, type Rule } from \"postcss\";\nimport selectorParser from \"postcss-selector-parser\";\nimport type { Plugin } from \"vite\";\nimport { hasOpaqueResourceQuery } from \"./request-query.js\";\n\nconst PLUGIN_ROOT_ATTRIBUTE = \"data-vetta-plugin-root\";\nconst PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;\nconst KEYFRAMES_PATTERN = /(?:^|-)keyframes$/i;\nconst ICONIFY_CLASS_PATTERN = /^icon-\\[[a-z0-9]+(?:-[a-z0-9]+)*--[a-z0-9]+(?:-[a-z0-9]+)*\\]$/u;\nconst ICONIFY_DECLARATION_VALUES: Readonly<Record<string, string>> = {\n\twidth: \"1em\",\n\theight: \"1em\",\n\t\"-webkit-mask-image\": \"var(--svg)\",\n\t\"mask-image\": \"var(--svg)\",\n\t\"background-color\": \"currentColor\",\n\tdisplay: \"inline-block\",\n\t\"-webkit-mask-size\": \"100% 100%\",\n\t\"mask-size\": \"100% 100%\",\n\t\"-webkit-mask-repeat\": \"no-repeat\",\n\t\"mask-repeat\": \"no-repeat\",\n};\nconst ICONIFY_SVG_VALUE_PATTERN = /^url\\((?:\"|')?data:image\\/svg\\+xml,/u;\n/**\n * 全局化的 Iconify 规则要放进一个嵌套 layer:插件样式表在宿主之后加载,\n * 而 `icon-[…]{width:1em;height:1em}` 与宿主的 `.w-4/.h-4` 同特异性,\n * 直接全局化会让宿主里任何同名图标退化成 1em(字号),把相邻文字挤偏。\n * 同一 layer 内「未嵌套的规则」优先于其子 layer,因此包一层即可让显式尺寸工具类稳定胜出,\n * 同时保留插件自身不写尺寸时的 1em 默认值。\n */\nconst ICONIFY_LAYER_NAME = \"vetta-plugin-icons\";\n\nfunction createPluginRootAttribute(pluginId: string) {\n\treturn selectorParser.attribute({\n\t\tattribute: PLUGIN_ROOT_ATTRIBUTE,\n\t\toperator: \"=\",\n\t\tquoteMark: '\"',\n\t\traws: {},\n\t\tvalue: pluginId,\n\t});\n}\n\nfunction isInsideKeyframes(rule: Rule): boolean {\n\tlet parent: Node | undefined = rule.parent;\n\twhile (parent) {\n\t\tif (\n\t\t\tparent.type === \"atrule\" &&\n\t\t\t\"name\" in parent &&\n\t\t\ttypeof parent.name === \"string\" &&\n\t\t\tKEYFRAMES_PATTERN.test(parent.name)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tparent = parent.parent;\n\t}\n\treturn false;\n}\n\nfunction replacePluginRootSelectors(selector: string): string {\n\treturn selectorParser((selectors) => {\n\t\tselectors.walkPseudos((pseudo) => {\n\t\t\tif (pseudo.value === \":root\") {\n\t\t\t\tpseudo.replaceWith(selectorParser.pseudo({ value: \":scope\" }));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pseudo.value === \":host\") {\n\t\t\t\tconst hostArgumentNodes =\n\t\t\t\t\tpseudo.nodes.length === 1 ? pseudo.nodes[0].nodes.map((node) => node.clone()) : [];\n\t\t\t\tpseudo.replaceWith(selectorParser.pseudo({ value: \":scope\" }), ...hostArgumentNodes);\n\t\t\t}\n\t\t});\n\t}).processSync(selector);\n}\n\nfunction isKeyframesAtRule(node: Node): boolean {\n\treturn node.type === \"atrule\" && KEYFRAMES_PATTERN.test((node as AtRule).name);\n}\n\nfunction hasOnlyIconifySelectors(rule: Rule): boolean {\n\tlet selectorCount = 0;\n\tlet valid = true;\n\tselectorParser((selectors) => {\n\t\tselectors.each((selector) => {\n\t\t\tselectorCount += 1;\n\t\t\tconst nodes = selector.nodes.filter((node) => node.type !== \"comment\");\n\t\t\tconst candidate = nodes[0];\n\t\t\tif (\n\t\t\t\tnodes.length !== 1 ||\n\t\t\t\tcandidate?.type !== \"class\" ||\n\t\t\t\t!ICONIFY_CLASS_PATTERN.test(candidate.value)\n\t\t\t) {\n\t\t\t\tvalid = false;\n\t\t\t}\n\t\t});\n\t}).processSync(rule.selector);\n\treturn valid && selectorCount > 0;\n}\n\nfunction hasOnlyIconifyDeclarations(rule: Rule): boolean {\n\tlet hasSvg = false;\n\tlet hasMask = false;\n\tfor (const node of rule.nodes) {\n\t\tif (node.type !== \"decl\") return false;\n\t\tif (node.prop === \"--svg\") {\n\t\t\tif (!ICONIFY_SVG_VALUE_PATTERN.test(node.value)) return false;\n\t\t\thasSvg = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ICONIFY_DECLARATION_VALUES[node.prop] !== node.value) return false;\n\t\tif (node.prop === \"mask-image\" || node.prop === \"-webkit-mask-image\") hasMask = true;\n\t}\n\treturn hasSvg && hasMask;\n}\n\nfunction isSafeGlobalIconifyRule(rule: Rule): boolean {\n\treturn hasOnlyIconifySelectors(rule) && hasOnlyIconifyDeclarations(rule);\n}\n\nfunction createScopeRule(pluginId: string): AtRule {\n\treturn postcss.atRule({\n\t\tname: \"scope\",\n\t\tparams: `(${createPluginRootAttribute(pluginId).toString()})`,\n\t});\n}\n\nfunction createIconifyLayerRule(): AtRule {\n\treturn postcss.atRule({ name: \"layer\", params: ICONIFY_LAYER_NAME });\n}\n\nfunction scopeRulesInContainer(container: Container, pluginId: string): void {\n\tif (!container.nodes) return;\n\tlet currentScope: AtRule | undefined;\n\tlet currentIconifyLayer: AtRule | undefined;\n\tfor (const node of [...container.nodes]) {\n\t\tif (node.type === \"rule\") {\n\t\t\tif (isSafeGlobalIconifyRule(node)) {\n\t\t\t\tcurrentScope = undefined;\n\t\t\t\tif (!currentIconifyLayer) {\n\t\t\t\t\tcurrentIconifyLayer = createIconifyLayerRule();\n\t\t\t\t\tnode.before(currentIconifyLayer);\n\t\t\t\t}\n\t\t\t\tcurrentIconifyLayer.append(node);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcurrentIconifyLayer = undefined;\n\t\t\tif (!currentScope) {\n\t\t\t\tcurrentScope = createScopeRule(pluginId);\n\t\t\t\tnode.before(currentScope);\n\t\t\t}\n\t\t\tcurrentScope.append(node);\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrentScope = undefined;\n\t\tcurrentIconifyLayer = undefined;\n\t\tif (node.type === \"atrule\" && !isKeyframesAtRule(node)) {\n\t\t\tconst atRule = node as AtRule;\n\t\t\tif (atRule.nodes) scopeRulesInContainer(atRule, pluginId);\n\t\t}\n\t}\n}\n\nexport function scopePluginCss(css: string, pluginId: string): string {\n\tconst root = postcss.parse(css);\n\troot.walkRules((rule) => {\n\t\tif (isInsideKeyframes(rule)) return;\n\t\trule.selector = replacePluginRootSelectors(rule.selector);\n\t});\n\tscopeRulesInContainer(root, pluginId);\n\treturn root.toString();\n}\n\n/**\n * Vite can import a CSS file as a JavaScript resource module via queries such\n * as `?raw`. Those requests keep the `.css` pathname, but their transform\n * input is JavaScript and must not be parsed by PostCSS. Other queries such as\n * `?direct` and HMR timestamps still represent stylesheet requests.\n */\nexport function isPluginStylesheetRequest(id: string): boolean {\n\tconst queryIndex = id.indexOf(\"?\");\n\tconst pathname = queryIndex === -1 ? id : id.slice(0, queryIndex);\n\tif (!pathname.endsWith(\".css\")) return false;\n\treturn !hasOpaqueResourceQuery(id);\n}\n\nfunction readPluginId(rootDir: string): string {\n\tconst manifestPath = join(rootDir, \"plugin.json\");\n\tconst manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as { id?: unknown };\n\tif (typeof manifest.id !== \"string\" || !PLUGIN_ID_PATTERN.test(manifest.id)) {\n\t\tthrow new Error(`Invalid plugin id in ${manifestPath}`);\n\t}\n\treturn manifest.id;\n}\n\nexport function createPluginStyleScopePlugin(): Plugin {\n\tlet pluginId = \"\";\n\tlet command: \"build\" | \"serve\" = \"build\";\n\treturn {\n\t\tname: \"vetta-plugin-style-scope\",\n\t\tenforce: \"pre\",\n\t\tconfigResolved(config) {\n\t\t\tpluginId = readPluginId(config.root);\n\t\t\tcommand = config.command;\n\t\t},\n\t\ttransform(code, id) {\n\t\t\tif (command !== \"serve\" || !isPluginStylesheetRequest(id)) return;\n\t\t\treturn {\n\t\t\t\tcode: scopePluginCss(code, pluginId),\n\t\t\t\tmap: null,\n\t\t\t};\n\t\t},\n\t\tgenerateBundle(_options, bundle) {\n\t\t\tfor (const output of Object.values(bundle)) {\n\t\t\t\tif (output.type !== \"asset\" || !output.fileName.endsWith(\".css\")) continue;\n\t\t\t\tconst css = typeof output.source === \"string\" ? output.source : Buffer.from(output.source).toString(\"utf8\");\n\t\t\t\toutput.source = scopePluginCss(css, pluginId);\n\t\t\t}\n\t\t},\n\t};\n}\n"]}