@vetta-org/plugin-vite 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,WAAW,CAAC;AAE3F,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CAAC,+BAA+B,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9G,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,4BAA4B;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;CAC9C;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,4BAA4B,GAAG,uBAAuB,CAiChH;AA6DD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,YAAY,EAAE,CAa3F","sourcesContent":["import { federation, type ModuleFederationOptions } from \"@module-federation/vite\";\nimport type { Plugin, PluginOption } from \"vite\";\nimport { type CreateVettaPluginPackageOptions, createVettaPluginPackage } from \"./pack.js\";\n\nexport interface VettaPluginPackageOptions extends Omit<CreateVettaPluginPackageOptions, \"rootDir\" | \"distDir\"> {\n\tenabled?: boolean;\n}\n\nexport interface VettaPluginFederationOptions {\n\tname: string;\n\texpose?: string;\n\tentry?: string;\n\tmanifestFileName?: string;\n\tremoteEntryFileName?: string;\n\tshared?: ModuleFederationOptions[\"shared\"];\n\tpackage?: boolean | VettaPluginPackageOptions;\n}\n\nexport function createVettaPluginFederationConfig(options: VettaPluginFederationOptions): ModuleFederationOptions {\n\tconst expose = options.expose ?? \"./plugin\";\n\tconst entry = options.entry ?? \"./src/index.tsx\";\n\treturn {\n\t\tname: options.name,\n\t\tfilename: options.remoteEntryFileName ?? \"remoteEntry.js\",\n\t\texposes: {\n\t\t\t[expose]: entry,\n\t\t},\n\t\tmanifest: {\n\t\t\tfileName: options.manifestFileName ?? \"mf-manifest.json\",\n\t\t},\n\t\tdts: false,\n\t\tshared: {\n\t\t\treact: {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t\"react-dom\": {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t// Match host plugin-shared-modules (tldraw remotes may require this subpath).\n\t\t\t\"react-dom/client\": {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t...options.shared,\n\t\t},\n\t};\n}\n\nfunction createBuildDefaultsPlugin(entry: string): Plugin {\n\treturn {\n\t\tname: \"vetta-plugin-build-defaults\",\n\t\tapply: \"build\",\n\t\tconfig() {\n\t\t\treturn {\n\t\t\t\tbuild: {\n\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\tinput: entry,\n\t\t\t\t\t\texternal: [\"@vetta-org/plugin-sdk\"],\n\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\tassetFileNames(assetInfo) {\n\t\t\t\t\t\t\t\treturn assetInfo.names.some((name) => name.endsWith(\".css\"))\n\t\t\t\t\t\t\t\t\t? \"style.css\"\n\t\t\t\t\t\t\t\t\t: \"assets/[name]-[hash][extname]\";\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpaths: {\n\t\t\t\t\t\t\t\t\"@vetta-org/plugin-sdk\": \"vetta-host://plugin-sdk\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction createPackagePlugin(options: VettaPluginPackageOptions): Plugin {\n\tlet rootDir = \"\";\n\tlet distDir = \"\";\n\tlet buildFailed = false;\n\n\treturn {\n\t\tname: \"vetta-plugin-package\",\n\t\tapply: \"build\",\n\t\tbuildStart() {\n\t\t\tbuildFailed = false;\n\t\t},\n\t\tbuildEnd(error) {\n\t\t\tbuildFailed = error !== undefined;\n\t\t},\n\t\tconfigResolved(config) {\n\t\t\trootDir = config.root;\n\t\t\tdistDir = config.build.outDir;\n\t\t},\n\t\tasync closeBundle() {\n\t\t\tif (options.enabled === false || buildFailed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst result = await createVettaPluginPackage({\n\t\t\t\t...options,\n\t\t\t\trootDir,\n\t\t\t\tdistDir,\n\t\t\t});\n\t\t\tconsole.log(`[vetta-plugin-vite] Wrote ${result.outputPath} with ${result.files.length} runtime files`);\n\t\t},\n\t};\n}\n\nexport function vettaPluginFederation(options: VettaPluginFederationOptions): PluginOption[] {\n\tconst packageOptions = typeof options.package === \"object\" ? options.package : {};\n\tconst entry = options.entry ?? \"./src/index.tsx\";\n\tconst plugins: PluginOption[] = [\n\t\tcreateBuildDefaultsPlugin(entry),\n\t\t...federation(createVettaPluginFederationConfig(options)),\n\t];\n\t// VETTA_PLUGIN_DEV_WATCH=1:宿主 dev 热更新的 `vite build --watch` 只需要 dist,\n\t// 跳过每次增量重建都重打 zip(closeBundle 在 watch 模式每轮都会触发)。\n\tif (options.package !== false && process.env.VETTA_PLUGIN_DEV_WATCH !== \"1\") {\n\t\tplugins.push(createPackagePlugin(packageOptions));\n\t}\n\treturn plugins;\n}\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,EAAE,KAAK,+BAA+B,EAA4B,MAAM,WAAW,CAAC;AAG3F,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CAAC,+BAA+B,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9G,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,4BAA4B;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;CAC9C;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,4BAA4B,GAAG,uBAAuB,CAiChH;AA6DD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,YAAY,EAAE,CAc3F","sourcesContent":["import { federation, type ModuleFederationOptions } from \"@module-federation/vite\";\nimport type { Plugin, PluginOption } from \"vite\";\nimport { type CreateVettaPluginPackageOptions, createVettaPluginPackage } from \"./pack.js\";\nimport { createPluginStyleScopePlugin } from \"./style-scope.js\";\n\nexport interface VettaPluginPackageOptions extends Omit<CreateVettaPluginPackageOptions, \"rootDir\" | \"distDir\"> {\n\tenabled?: boolean;\n}\n\nexport interface VettaPluginFederationOptions {\n\tname: string;\n\texpose?: string;\n\tentry?: string;\n\tmanifestFileName?: string;\n\tremoteEntryFileName?: string;\n\tshared?: ModuleFederationOptions[\"shared\"];\n\tpackage?: boolean | VettaPluginPackageOptions;\n}\n\nexport function createVettaPluginFederationConfig(options: VettaPluginFederationOptions): ModuleFederationOptions {\n\tconst expose = options.expose ?? \"./plugin\";\n\tconst entry = options.entry ?? \"./src/index.tsx\";\n\treturn {\n\t\tname: options.name,\n\t\tfilename: options.remoteEntryFileName ?? \"remoteEntry.js\",\n\t\texposes: {\n\t\t\t[expose]: entry,\n\t\t},\n\t\tmanifest: {\n\t\t\tfileName: options.manifestFileName ?? \"mf-manifest.json\",\n\t\t},\n\t\tdts: false,\n\t\tshared: {\n\t\t\treact: {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t\"react-dom\": {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t// Match host plugin-shared-modules (tldraw remotes may require this subpath).\n\t\t\t\"react-dom/client\": {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t...options.shared,\n\t\t},\n\t};\n}\n\nfunction createBuildDefaultsPlugin(entry: string): Plugin {\n\treturn {\n\t\tname: \"vetta-plugin-build-defaults\",\n\t\tapply: \"build\",\n\t\tconfig() {\n\t\t\treturn {\n\t\t\t\tbuild: {\n\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\tinput: entry,\n\t\t\t\t\t\texternal: [\"@vetta-org/plugin-sdk\"],\n\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\tassetFileNames(assetInfo) {\n\t\t\t\t\t\t\t\treturn assetInfo.names.some((name) => name.endsWith(\".css\"))\n\t\t\t\t\t\t\t\t\t? \"style.css\"\n\t\t\t\t\t\t\t\t\t: \"assets/[name]-[hash][extname]\";\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpaths: {\n\t\t\t\t\t\t\t\t\"@vetta-org/plugin-sdk\": \"vetta-host://plugin-sdk\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction createPackagePlugin(options: VettaPluginPackageOptions): Plugin {\n\tlet rootDir = \"\";\n\tlet distDir = \"\";\n\tlet buildFailed = false;\n\n\treturn {\n\t\tname: \"vetta-plugin-package\",\n\t\tapply: \"build\",\n\t\tbuildStart() {\n\t\t\tbuildFailed = false;\n\t\t},\n\t\tbuildEnd(error) {\n\t\t\tbuildFailed = error !== undefined;\n\t\t},\n\t\tconfigResolved(config) {\n\t\t\trootDir = config.root;\n\t\t\tdistDir = config.build.outDir;\n\t\t},\n\t\tasync closeBundle() {\n\t\t\tif (options.enabled === false || buildFailed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst result = await createVettaPluginPackage({\n\t\t\t\t...options,\n\t\t\t\trootDir,\n\t\t\t\tdistDir,\n\t\t\t});\n\t\t\tconsole.log(`[vetta-plugin-vite] Wrote ${result.outputPath} with ${result.files.length} runtime files`);\n\t\t},\n\t};\n}\n\nexport function vettaPluginFederation(options: VettaPluginFederationOptions): PluginOption[] {\n\tconst packageOptions = typeof options.package === \"object\" ? options.package : {};\n\tconst entry = options.entry ?? \"./src/index.tsx\";\n\tconst plugins: PluginOption[] = [\n\t\tcreateBuildDefaultsPlugin(entry),\n\t\t...federation(createVettaPluginFederationConfig(options)),\n\t\tcreatePluginStyleScopePlugin(),\n\t];\n\t// VETTA_PLUGIN_DEV_WATCH=1:宿主 dev 热更新的 `vite build --watch` 只需要 dist,\n\t// 跳过每次增量重建都重打 zip(closeBundle 在 watch 模式每轮都会触发)。\n\tif (options.package !== false && process.env.VETTA_PLUGIN_DEV_WATCH !== \"1\") {\n\t\tplugins.push(createPackagePlugin(packageOptions));\n\t}\n\treturn plugins;\n}\n"]}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { federation } from "@module-federation/vite";
2
2
  import { createVettaPluginPackage } from "./pack.js";
3
+ import { createPluginStyleScopePlugin } from "./style-scope.js";
3
4
  export function createVettaPluginFederationConfig(options) {
4
5
  const expose = options.expose ?? "./plugin";
5
6
  const entry = options.entry ?? "./src/index.tsx";
@@ -96,6 +97,7 @@ export function vettaPluginFederation(options) {
96
97
  const plugins = [
97
98
  createBuildDefaultsPlugin(entry),
98
99
  ...federation(createVettaPluginFederationConfig(options)),
100
+ createPluginStyleScopePlugin(),
99
101
  ];
100
102
  // VETTA_PLUGIN_DEV_WATCH=1:宿主 dev 热更新的 `vite build --watch` 只需要 dist,
101
103
  // 跳过每次增量重建都重打 zip(closeBundle 在 watch 模式每轮都会触发)。
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { federation, type ModuleFederationOptions } from \"@module-federation/vite\";\nimport type { Plugin, PluginOption } from \"vite\";\nimport { type CreateVettaPluginPackageOptions, createVettaPluginPackage } from \"./pack.js\";\n\nexport interface VettaPluginPackageOptions extends Omit<CreateVettaPluginPackageOptions, \"rootDir\" | \"distDir\"> {\n\tenabled?: boolean;\n}\n\nexport interface VettaPluginFederationOptions {\n\tname: string;\n\texpose?: string;\n\tentry?: string;\n\tmanifestFileName?: string;\n\tremoteEntryFileName?: string;\n\tshared?: ModuleFederationOptions[\"shared\"];\n\tpackage?: boolean | VettaPluginPackageOptions;\n}\n\nexport function createVettaPluginFederationConfig(options: VettaPluginFederationOptions): ModuleFederationOptions {\n\tconst expose = options.expose ?? \"./plugin\";\n\tconst entry = options.entry ?? \"./src/index.tsx\";\n\treturn {\n\t\tname: options.name,\n\t\tfilename: options.remoteEntryFileName ?? \"remoteEntry.js\",\n\t\texposes: {\n\t\t\t[expose]: entry,\n\t\t},\n\t\tmanifest: {\n\t\t\tfileName: options.manifestFileName ?? \"mf-manifest.json\",\n\t\t},\n\t\tdts: false,\n\t\tshared: {\n\t\t\treact: {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t\"react-dom\": {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t// Match host plugin-shared-modules (tldraw remotes may require this subpath).\n\t\t\t\"react-dom/client\": {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t...options.shared,\n\t\t},\n\t};\n}\n\nfunction createBuildDefaultsPlugin(entry: string): Plugin {\n\treturn {\n\t\tname: \"vetta-plugin-build-defaults\",\n\t\tapply: \"build\",\n\t\tconfig() {\n\t\t\treturn {\n\t\t\t\tbuild: {\n\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\tinput: entry,\n\t\t\t\t\t\texternal: [\"@vetta-org/plugin-sdk\"],\n\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\tassetFileNames(assetInfo) {\n\t\t\t\t\t\t\t\treturn assetInfo.names.some((name) => name.endsWith(\".css\"))\n\t\t\t\t\t\t\t\t\t? \"style.css\"\n\t\t\t\t\t\t\t\t\t: \"assets/[name]-[hash][extname]\";\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpaths: {\n\t\t\t\t\t\t\t\t\"@vetta-org/plugin-sdk\": \"vetta-host://plugin-sdk\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction createPackagePlugin(options: VettaPluginPackageOptions): Plugin {\n\tlet rootDir = \"\";\n\tlet distDir = \"\";\n\tlet buildFailed = false;\n\n\treturn {\n\t\tname: \"vetta-plugin-package\",\n\t\tapply: \"build\",\n\t\tbuildStart() {\n\t\t\tbuildFailed = false;\n\t\t},\n\t\tbuildEnd(error) {\n\t\t\tbuildFailed = error !== undefined;\n\t\t},\n\t\tconfigResolved(config) {\n\t\t\trootDir = config.root;\n\t\t\tdistDir = config.build.outDir;\n\t\t},\n\t\tasync closeBundle() {\n\t\t\tif (options.enabled === false || buildFailed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst result = await createVettaPluginPackage({\n\t\t\t\t...options,\n\t\t\t\trootDir,\n\t\t\t\tdistDir,\n\t\t\t});\n\t\t\tconsole.log(`[vetta-plugin-vite] Wrote ${result.outputPath} with ${result.files.length} runtime files`);\n\t\t},\n\t};\n}\n\nexport function vettaPluginFederation(options: VettaPluginFederationOptions): PluginOption[] {\n\tconst packageOptions = typeof options.package === \"object\" ? options.package : {};\n\tconst entry = options.entry ?? \"./src/index.tsx\";\n\tconst plugins: PluginOption[] = [\n\t\tcreateBuildDefaultsPlugin(entry),\n\t\t...federation(createVettaPluginFederationConfig(options)),\n\t];\n\t// VETTA_PLUGIN_DEV_WATCH=1:宿主 dev 热更新的 `vite build --watch` 只需要 dist,\n\t// 跳过每次增量重建都重打 zip(closeBundle 在 watch 模式每轮都会触发)。\n\tif (options.package !== false && process.env.VETTA_PLUGIN_DEV_WATCH !== \"1\") {\n\t\tplugins.push(createPackagePlugin(packageOptions));\n\t}\n\treturn plugins;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { federation, type ModuleFederationOptions } from \"@module-federation/vite\";\nimport type { Plugin, PluginOption } from \"vite\";\nimport { type CreateVettaPluginPackageOptions, createVettaPluginPackage } from \"./pack.js\";\nimport { createPluginStyleScopePlugin } from \"./style-scope.js\";\n\nexport interface VettaPluginPackageOptions extends Omit<CreateVettaPluginPackageOptions, \"rootDir\" | \"distDir\"> {\n\tenabled?: boolean;\n}\n\nexport interface VettaPluginFederationOptions {\n\tname: string;\n\texpose?: string;\n\tentry?: string;\n\tmanifestFileName?: string;\n\tremoteEntryFileName?: string;\n\tshared?: ModuleFederationOptions[\"shared\"];\n\tpackage?: boolean | VettaPluginPackageOptions;\n}\n\nexport function createVettaPluginFederationConfig(options: VettaPluginFederationOptions): ModuleFederationOptions {\n\tconst expose = options.expose ?? \"./plugin\";\n\tconst entry = options.entry ?? \"./src/index.tsx\";\n\treturn {\n\t\tname: options.name,\n\t\tfilename: options.remoteEntryFileName ?? \"remoteEntry.js\",\n\t\texposes: {\n\t\t\t[expose]: entry,\n\t\t},\n\t\tmanifest: {\n\t\t\tfileName: options.manifestFileName ?? \"mf-manifest.json\",\n\t\t},\n\t\tdts: false,\n\t\tshared: {\n\t\t\treact: {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t\"react-dom\": {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t// Match host plugin-shared-modules (tldraw remotes may require this subpath).\n\t\t\t\"react-dom/client\": {\n\t\t\t\tsingleton: true,\n\t\t\t\timport: false,\n\t\t\t\trequiredVersion: \"*\",\n\t\t\t},\n\t\t\t...options.shared,\n\t\t},\n\t};\n}\n\nfunction createBuildDefaultsPlugin(entry: string): Plugin {\n\treturn {\n\t\tname: \"vetta-plugin-build-defaults\",\n\t\tapply: \"build\",\n\t\tconfig() {\n\t\t\treturn {\n\t\t\t\tbuild: {\n\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\tinput: entry,\n\t\t\t\t\t\texternal: [\"@vetta-org/plugin-sdk\"],\n\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\tassetFileNames(assetInfo) {\n\t\t\t\t\t\t\t\treturn assetInfo.names.some((name) => name.endsWith(\".css\"))\n\t\t\t\t\t\t\t\t\t? \"style.css\"\n\t\t\t\t\t\t\t\t\t: \"assets/[name]-[hash][extname]\";\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpaths: {\n\t\t\t\t\t\t\t\t\"@vetta-org/plugin-sdk\": \"vetta-host://plugin-sdk\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction createPackagePlugin(options: VettaPluginPackageOptions): Plugin {\n\tlet rootDir = \"\";\n\tlet distDir = \"\";\n\tlet buildFailed = false;\n\n\treturn {\n\t\tname: \"vetta-plugin-package\",\n\t\tapply: \"build\",\n\t\tbuildStart() {\n\t\t\tbuildFailed = false;\n\t\t},\n\t\tbuildEnd(error) {\n\t\t\tbuildFailed = error !== undefined;\n\t\t},\n\t\tconfigResolved(config) {\n\t\t\trootDir = config.root;\n\t\t\tdistDir = config.build.outDir;\n\t\t},\n\t\tasync closeBundle() {\n\t\t\tif (options.enabled === false || buildFailed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst result = await createVettaPluginPackage({\n\t\t\t\t...options,\n\t\t\t\trootDir,\n\t\t\t\tdistDir,\n\t\t\t});\n\t\t\tconsole.log(`[vetta-plugin-vite] Wrote ${result.outputPath} with ${result.files.length} runtime files`);\n\t\t},\n\t};\n}\n\nexport function vettaPluginFederation(options: VettaPluginFederationOptions): PluginOption[] {\n\tconst packageOptions = typeof options.package === \"object\" ? options.package : {};\n\tconst entry = options.entry ?? \"./src/index.tsx\";\n\tconst plugins: PluginOption[] = [\n\t\tcreateBuildDefaultsPlugin(entry),\n\t\t...federation(createVettaPluginFederationConfig(options)),\n\t\tcreatePluginStyleScopePlugin(),\n\t];\n\t// VETTA_PLUGIN_DEV_WATCH=1:宿主 dev 热更新的 `vite build --watch` 只需要 dist,\n\t// 跳过每次增量重建都重打 zip(closeBundle 在 watch 模式每轮都会触发)。\n\tif (options.package !== false && process.env.VETTA_PLUGIN_DEV_WATCH !== \"1\") {\n\t\tplugins.push(createPackagePlugin(packageOptions));\n\t}\n\treturn plugins;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../src/pack.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,sBAAsB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,sBAAsB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,+BAA+B;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAgVD,wBAAsB,wBAAwB,CAC7C,OAAO,GAAE,+BAAoC,GAC3C,OAAO,CAAC,wBAAwB,CAAC,CAcnC","sourcesContent":["import { 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\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\tagent: readAgentManifest(value),\n\t\tstyles: readStringArray(value, \"styles\"),\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\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.d.ts","sourceRoot":"","sources":["../src/pack.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,sBAAsB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,sBAAsB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,+BAA+B;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AA6WD,wBAAsB,wBAAwB,CAC7C,OAAO,GAAE,+BAAoC,GAC3C,OAAO,CAAC,wBAAwB,CAAC,CAcnC","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"]}
package/dist/pack.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { existsSync } from "node:fs";
1
2
  import { mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
2
3
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
3
4
  const crcTable = new Uint32Array(256);
@@ -59,10 +60,23 @@ function parsePluginManifest(value) {
59
60
  id,
60
61
  version,
61
62
  entry,
63
+ icon: readString(value, "icon"),
62
64
  agent: readAgentManifest(value),
63
65
  styles: readStringArray(value, "styles"),
64
66
  };
65
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
+ }
66
80
  function parseJsonObject(buffer, fileName) {
67
81
  const parsed = JSON.parse(buffer.toString("utf-8"));
68
82
  if (!isRecord(parsed)) {
@@ -228,6 +242,15 @@ async function collectRuntimeFiles(rootDir, manifestPath, distDir) {
228
242
  for (const style of pluginManifest.styles ?? []) {
229
243
  addFile(resolve(rootDir, style));
230
244
  }
245
+ // 包内相对路径图标:不打进 zip 的话,宿主 vetta-plugin:// 会 404、市场上传会被服务端拒绝。
246
+ const icon = pluginManifest.icon?.trim();
247
+ if (icon && isPackagedIconPath(icon)) {
248
+ const iconPath = resolve(rootDir, icon);
249
+ if (!existsSync(iconPath)) {
250
+ throw new Error(`plugin.json icon file not found: ${icon}`);
251
+ }
252
+ addFile(iconPath);
253
+ }
231
254
  for (const promptPath of pluginManifest.agent?.systemPrompt?.promptPaths ?? []) {
232
255
  for (const file of await collectPath(resolve(rootDir, promptPath))) {
233
256
  addFile(file.fullPath);
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 { 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\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\tagent: readAgentManifest(value),\n\t\tstyles: readStringArray(value, \"styles\"),\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\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\";\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"]}
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from "vite";
2
+ export declare function createPluginStyleScopePlugin(): Plugin;
3
+ //# sourceMappingURL=style-scope.d.ts.map
@@ -0,0 +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"]}
@@ -0,0 +1,111 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import postcss from "postcss";
4
+ import selectorParser from "postcss-selector-parser";
5
+ const PLUGIN_ROOT_ATTRIBUTE = "data-vetta-plugin-root";
6
+ const PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
7
+ const KEYFRAMES_PATTERN = /(?:^|-)keyframes$/i;
8
+ function createPluginRootAttribute(pluginId) {
9
+ return selectorParser.attribute({
10
+ attribute: PLUGIN_ROOT_ATTRIBUTE,
11
+ operator: "=",
12
+ quoteMark: '"',
13
+ raws: {},
14
+ value: pluginId,
15
+ });
16
+ }
17
+ function isInsideKeyframes(rule) {
18
+ let parent = rule.parent;
19
+ while (parent) {
20
+ if (parent.type === "atrule" &&
21
+ "name" in parent &&
22
+ typeof parent.name === "string" &&
23
+ KEYFRAMES_PATTERN.test(parent.name)) {
24
+ return true;
25
+ }
26
+ parent = parent.parent;
27
+ }
28
+ return false;
29
+ }
30
+ function replacePluginRootSelectors(selector) {
31
+ return selectorParser((selectors) => {
32
+ selectors.walkPseudos((pseudo) => {
33
+ if (pseudo.value === ":root") {
34
+ pseudo.replaceWith(selectorParser.pseudo({ value: ":scope" }));
35
+ return;
36
+ }
37
+ if (pseudo.value === ":host") {
38
+ const hostArgumentNodes = pseudo.nodes.length === 1 ? pseudo.nodes[0].nodes.map((node) => node.clone()) : [];
39
+ pseudo.replaceWith(selectorParser.pseudo({ value: ":scope" }), ...hostArgumentNodes);
40
+ }
41
+ });
42
+ }).processSync(selector);
43
+ }
44
+ function isKeyframesAtRule(node) {
45
+ return node.type === "atrule" && KEYFRAMES_PATTERN.test(node.name);
46
+ }
47
+ function createScopeRule(pluginId) {
48
+ return postcss.atRule({
49
+ name: "scope",
50
+ params: `(${createPluginRootAttribute(pluginId).toString()})`,
51
+ });
52
+ }
53
+ function scopeRulesInContainer(container, pluginId) {
54
+ if (!container.nodes)
55
+ return;
56
+ let currentScope;
57
+ for (const node of [...container.nodes]) {
58
+ if (node.type === "rule") {
59
+ if (!currentScope) {
60
+ currentScope = createScopeRule(pluginId);
61
+ node.before(currentScope);
62
+ }
63
+ currentScope.append(node);
64
+ continue;
65
+ }
66
+ currentScope = undefined;
67
+ if (node.type === "atrule" && !isKeyframesAtRule(node)) {
68
+ const atRule = node;
69
+ if (atRule.nodes)
70
+ scopeRulesInContainer(atRule, pluginId);
71
+ }
72
+ }
73
+ }
74
+ function scopePluginCss(css, pluginId) {
75
+ const root = postcss.parse(css);
76
+ root.walkRules((rule) => {
77
+ if (isInsideKeyframes(rule))
78
+ return;
79
+ rule.selector = replacePluginRootSelectors(rule.selector);
80
+ });
81
+ scopeRulesInContainer(root, pluginId);
82
+ return root.toString();
83
+ }
84
+ function readPluginId(rootDir) {
85
+ const manifestPath = join(rootDir, "plugin.json");
86
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
87
+ if (typeof manifest.id !== "string" || !PLUGIN_ID_PATTERN.test(manifest.id)) {
88
+ throw new Error(`Invalid plugin id in ${manifestPath}`);
89
+ }
90
+ return manifest.id;
91
+ }
92
+ export function createPluginStyleScopePlugin() {
93
+ let pluginId = "";
94
+ return {
95
+ name: "vetta-plugin-style-scope",
96
+ apply: "build",
97
+ enforce: "post",
98
+ configResolved(config) {
99
+ pluginId = readPluginId(config.root);
100
+ },
101
+ generateBundle(_options, bundle) {
102
+ for (const output of Object.values(bundle)) {
103
+ if (output.type !== "asset" || !output.fileName.endsWith(".css"))
104
+ continue;
105
+ const css = typeof output.source === "string" ? output.source : Buffer.from(output.source).toString("utf8");
106
+ output.source = scopePluginCss(css, pluginId);
107
+ }
108
+ },
109
+ };
110
+ }
111
+ //# sourceMappingURL=style-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-scope.js","sourceRoot":"","sources":["../src/style-scope.ts"],"names":[],"mappings":"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","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vetta-org/plugin-vite",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -22,7 +22,9 @@
22
22
  "build": "tsgo -p tsconfig.build.json"
23
23
  },
24
24
  "dependencies": {
25
- "@module-federation/vite": "^1.16.6"
25
+ "@module-federation/vite": "^1.16.6",
26
+ "postcss": "^8.5.15",
27
+ "postcss-selector-parser": "^7.1.4"
26
28
  },
27
29
  "peerDependencies": {
28
30
  "vite": "^7.0.0"