@vetta-org/plugin-vite 0.0.4 → 0.1.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.
- package/dist/build-warning-filter.d.ts +8 -0
- package/dist/build-warning-filter.d.ts.map +1 -0
- package/dist/build-warning-filter.js +26 -0
- package/dist/build-warning-filter.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +83 -0
- package/dist/cli.js.map +1 -0
- package/dist/dev-events.d.ts +23 -0
- package/dist/dev-events.d.ts.map +1 -0
- package/dist/dev-events.js +9 -0
- package/dist/dev-events.js.map +1 -0
- package/dist/dev-server.d.ts +9 -0
- package/dist/dev-server.d.ts.map +1 -0
- package/dist/dev-server.js +239 -0
- package/dist/dev-server.js.map +1 -0
- package/dist/dev-vite-plugins.d.ts +5 -0
- package/dist/dev-vite-plugins.d.ts.map +1 -0
- package/dist/dev-vite-plugins.js +144 -0
- package/dist/dev-vite-plugins.js.map +1 -0
- package/dist/host-theme.d.ts +5 -0
- package/dist/host-theme.d.ts.map +1 -0
- package/dist/host-theme.js +42 -0
- package/dist/host-theme.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +97 -4
- package/dist/index.js.map +1 -1
- package/dist/pack.d.ts +4 -0
- package/dist/pack.d.ts.map +1 -1
- package/dist/pack.js +68 -87
- package/dist/pack.js.map +1 -1
- package/dist/permission-contract.d.ts +13 -0
- package/dist/permission-contract.d.ts.map +1 -0
- package/dist/permission-contract.js +94 -0
- package/dist/permission-contract.js.map +1 -0
- package/dist/request-query.d.ts +8 -0
- package/dist/request-query.d.ts.map +1 -0
- package/dist/request-query.js +19 -0
- package/dist/request-query.js.map +1 -0
- package/dist/style-scope.d.ts +8 -0
- package/dist/style-scope.d.ts.map +1 -1
- package/dist/style-scope.js +102 -3
- package/dist/style-scope.js.map +1 -1
- 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,66 +20,15 @@ function readString(record, key) {
|
|
|
16
20
|
const value = record[key];
|
|
17
21
|
return typeof value === "string" ? value : undefined;
|
|
18
22
|
}
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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.");
|
|
23
|
+
function validateAbilityDescriptor(value, pluginManifest) {
|
|
24
|
+
if (!isRecord(value))
|
|
25
|
+
throw new Error("ability.json must contain an object.");
|
|
26
|
+
if (value.schemaVersion !== 1 ||
|
|
27
|
+
value.type !== "plugin" ||
|
|
28
|
+
value.slug !== pluginManifest.id ||
|
|
29
|
+
value.version !== pluginManifest.version) {
|
|
30
|
+
throw new Error("ability.json identity must match plugin.json id and version.");
|
|
58
31
|
}
|
|
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
|
-
/** Iconify 图标名:`solar:magic-stick-3-bold` 这种 `<集合>:<图标>` 形态。 */
|
|
69
|
-
const ICONIFY_ICON_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*:[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
70
|
-
/**
|
|
71
|
-
* 与宿主 `isPassthroughIconRef`、服务端 `isPackagedIconPath` 保持同一判定:
|
|
72
|
-
* Iconify 名与 http(s) 外链不落包,其余按包内相对路径打进 zip。
|
|
73
|
-
*/
|
|
74
|
-
function isPackagedIconPath(icon) {
|
|
75
|
-
return (icon !== "" &&
|
|
76
|
-
!icon.startsWith("http://") &&
|
|
77
|
-
!icon.startsWith("https://") &&
|
|
78
|
-
!ICONIFY_ICON_PATTERN.test(icon));
|
|
79
32
|
}
|
|
80
33
|
function parseJsonObject(buffer, fileName) {
|
|
81
34
|
const parsed = JSON.parse(buffer.toString("utf-8"));
|
|
@@ -215,12 +168,27 @@ async function collectRuntimeFiles(rootDir, manifestPath, distDir) {
|
|
|
215
168
|
packageFiles.set(archivePath, { fullPath: resolved, archivePath });
|
|
216
169
|
};
|
|
217
170
|
addFile(manifestPath);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
171
|
+
// 插件详情跟随插件包发布;ability.json 缺省兼容,存在时必须与 plugin.json 身份一致。
|
|
172
|
+
const abilityDescriptorPath = resolve(rootDir, "ability.json");
|
|
173
|
+
if (existsSync(abilityDescriptorPath)) {
|
|
174
|
+
validateAbilityDescriptor(parseJsonObject(await readFile(abilityDescriptorPath), basename(abilityDescriptorPath)), pluginManifest);
|
|
175
|
+
addFile(abilityDescriptorPath);
|
|
176
|
+
// 约定的展示资源目录;内联 blocks 可引用其中的图片,随包整体带上。
|
|
177
|
+
try {
|
|
178
|
+
for (const file of await collectFiles(resolve(rootDir, "presentation"))) {
|
|
179
|
+
addFile(file.fullPath);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// optional presentation/ directory
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const runtimeEntryPath = resolve(rootDir, pluginManifest.entry);
|
|
187
|
+
addFile(runtimeEntryPath);
|
|
188
|
+
const federationManifest = parseJsonObject(await readFile(runtimeEntryPath), basename(runtimeEntryPath));
|
|
221
189
|
const remoteEntry = readManifestRemoteEntry(federationManifest);
|
|
222
190
|
if (remoteEntry) {
|
|
223
|
-
addFile(resolve(dirname(
|
|
191
|
+
addFile(resolve(dirname(runtimeEntryPath), remoteEntry));
|
|
224
192
|
}
|
|
225
193
|
const assetsDir = join(distDir, "assets");
|
|
226
194
|
for (const file of await collectFiles(assetsDir)) {
|
|
@@ -239,34 +207,24 @@ async function collectRuntimeFiles(rootDir, manifestPath, distDir) {
|
|
|
239
207
|
catch {
|
|
240
208
|
// dist missing
|
|
241
209
|
}
|
|
242
|
-
for (const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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;
|
|
251
220
|
}
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
for (const promptPath of pluginManifest.agent?.systemPrompt?.promptPaths ?? []) {
|
|
255
|
-
for (const file of await collectPath(resolve(rootDir, promptPath))) {
|
|
256
|
-
addFile(file.fullPath);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
for (const skillPath of pluginManifest.agent?.skillPaths ?? []) {
|
|
260
|
-
for (const file of await collectPath(resolve(rootDir, skillPath))) {
|
|
221
|
+
for (const file of await collectPath(resourcePath)) {
|
|
261
222
|
addFile(file.fullPath);
|
|
262
223
|
}
|
|
263
224
|
}
|
|
264
225
|
// Plugin-scoped MCP: include config file and conventional companion dirs when declared.
|
|
265
226
|
const mcpServers = pluginManifest.agent?.mcpServers;
|
|
266
227
|
if (mcpServers !== undefined) {
|
|
267
|
-
if (typeof mcpServers === "string") {
|
|
268
|
-
addFile(resolve(rootDir, mcpServers));
|
|
269
|
-
}
|
|
270
228
|
try {
|
|
271
229
|
for (const file of await collectFiles(resolve(rootDir, "mcp"))) {
|
|
272
230
|
addFile(file.fullPath);
|
|
@@ -314,9 +272,32 @@ export async function createVettaPluginPackage(options = {}) {
|
|
|
314
272
|
const pluginManifest = parsePluginManifest(parseJsonObject(await readFile(manifestPath), basename(manifestPath)));
|
|
315
273
|
const outputPath = join(releaseDir, `${pluginManifest.id}-${pluginManifest.version}.zip`);
|
|
316
274
|
const files = await collectRuntimeFiles(rootDir, manifestPath, distDir);
|
|
317
|
-
|
|
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
|
+
}
|
|
318
292
|
await mkdir(releaseDir, { recursive: true });
|
|
319
|
-
await
|
|
320
|
-
|
|
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 };
|
|
321
302
|
}
|
|
322
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\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\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"]}
|
package/dist/style-scope.d.ts
CHANGED
|
@@ -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;
|
|
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"]}
|