@stealthscale/vite-plugin-product 0.3.0 → 0.3.2

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/README.md CHANGED
@@ -228,9 +228,11 @@ release.
228
228
  the package. The entry of an ES module exports `*` and its default export. The entry of a CommonJS
229
229
  module exports the names that Node's `require` returns.
230
230
  - The client build runs a first build of the same configuration without the entries, and records the
231
- chunk of each module. The second build places each recorded module in the chunk of the same name,
232
- and each recorded CommonJS module in a chunk beside it, named with `-cjs`. Rolldown builds the
233
- code that only the entries need into chunks that only the entries import.
231
+ chunk of each module. The first build keeps every export of each module of a provided package that
232
+ states its side effects, because the entries make the second build keep them. It also records the
233
+ modules that those exports import. The second build places each recorded module in the chunk of
234
+ the same name, and each recorded CommonJS module in a chunk beside it, named with `-cjs`. Rolldown
235
+ builds the code that only the entries need into chunks that only the entries import.
234
236
  - The build writes `.product/provided.json`. The file contains the URL of each provided entry and
235
237
  the URLs of the chunks that the entry imports, without the chunks of the page's startup. It also
236
238
  contains the installed version of each provided package and the page's fallback `language`. The
@@ -1 +1 @@
1
- {"$schema":"http://cyclonedx.org/schema/bom-1.7.schema.json","bomFormat":"CycloneDX","specVersion":"1.7","version":1,"metadata":{"lifecycles":[{"phase":"build"}],"tools":{"components":[{"type":"application","name":"rolldown","version":"1.2.12"},{"type":"application","name":"vite","version":"8.3.3"},{"type":"library","name":"core","group":"@arethetypeswrong","version":"0.18.5","bom-ref":"pkg:npm/%40arethetypeswrong/core@0.18.5","author":"Andrew Branch","description":"The API behind arethetypeswrong.github.io","hashes":[{"alg":"SHA-512","content":"f72b63cc6c318e6f54cfb23d6af7dbb79be542deae93db914444b3263aabce797a58abc8e9dc184e8faf277534d96aeafe64778aa97f3f386f1e129d2480230d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40arethetypeswrong/core@0.18.5","externalReferences":[{"url":"https://github.com/arethetypeswrong/arethetypeswrong.github.io.git#packages/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=20"}]},{"type":"library","name":"sdk-core","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/sdk-core@0.3.0","description":"Declares the contracts and manifests of plugins, evaluates their conditions, and resolves a product from them, without loading another package at run time.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/sdk-core@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#sdk/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/sdk/core#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"testing-config","group":"@stealthscale","version":"0.6.0","bom-ref":"pkg:npm/%40stealthscale/testing-config@0.6.0","description":"Lists every part of the house contract a config, plugin or library package breaks.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/testing-config@0.6.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/testing-config","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/testing-config#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"testing","group":"@stealthscale","version":"0.4.0","bom-ref":"pkg:npm/%40stealthscale/testing@0.4.0","description":"Supplies the scratch workspaces, manifests, element measurements and plugin drivers a specification needs.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/testing@0.4.0","externalReferences":[{"url":"git+https://github.com/stealth-scale/scale.git#packages/testing","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-typescript","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","description":"Sets the TypeScript options every stealthscale package compiles with.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config-typescript","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config-typescript#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config","group":"@stealthscale","version":"0.8.0","bom-ref":"pkg:npm/%40stealthscale/vite-config@0.8.0","description":"Configures a package from five Vite+ tiers and a named layer for every block.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config@0.8.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-plugin-base","group":"@stealthscale","version":"0.4.0","bom-ref":"pkg:npm/%40stealthscale/vite-plugin-base@0.4.0","description":"Turns a name and one write step into a bundler plugin that reads the module graph.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-plugin-base@0.4.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-plugin-base","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-plugin-base#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-plugin-i18n","group":"@stealthscale","version":"0.3.1","bom-ref":"pkg:npm/%40stealthscale/vite-plugin-i18n@0.3.1","description":"Finds every catalogue an application can reach, types their keys, and answers the module it loads them from.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-plugin-i18n@0.3.1","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-plugin-i18n","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-plugin-i18n#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"node","group":"@types","version":"26.6.4","bom-ref":"pkg:npm/%40types/node@26.6.4","description":"TypeScript definitions for node","hashes":[{"alg":"SHA-512","content":"95d54f0c2ce3edfb1a199acb07436e1ee4ef25cb0d6accac040a8ca25aff720c6b2ddd716eac48af75c988f9c71c9502c63e6c345d6f9d18fd6969eb561e4972"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/node@26.6.4","externalReferences":[{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped.git#types/node","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"coverage-v8","group":"@vitest","version":"5.0.3","bom-ref":"pkg:npm/%40vitest/coverage-v8@5.0.3","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"V8 coverage provider for Vitest","hashes":[{"alg":"SHA-512","content":"fa496ccb3ec1bd3d6f094dbc6647f39acd486bbf170f4578d54dc552d45a6b74bebceaff117bcad4ee81bd50fb9754731239ba48e351d9ac9b3af0c37fdbb499"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40vitest/coverage-v8@5.0.3","externalReferences":[{"url":"https://github.com/vitest-dev/vitest/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/vitest-dev/vitest.git#packages/coverage-v8","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://vitest.dev/guide/coverage","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"vite-plus-core","group":"@voidzero-dev","version":"1.1.0","bom-ref":"pkg:npm/%40voidzero-dev/vite-plus-core@1.1.0","author":"VoidZero Inc.","description":"The Unified Toolchain for the Web","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40voidzero-dev/vite-plus-core@1.1.0","externalReferences":[{"url":"https://github.com/voidzero-dev/vite-plus/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/voidzero-dev/vite-plus.git#packages/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://viteplus.dev/guide","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^20.19.0 || ^22.18.0 || >=24.11.0"}]},{"type":"library","name":"typescript","version":"7.0.2","bom-ref":"pkg:npm/typescript@7.0.2","author":"Microsoft Corp.","description":"TypeScript is a language for application scale JavaScript development","hashes":[{"alg":"SHA-512","content":"f0561abbdea8dcd28e85b8ca8bfa8dbc6fd6e63873c646dd9b9b23f406d9ff94f9b16aa7de12602df1b1dbbb11299593bf2cc23fc74b4414dfe6d05349155434"}],"licenses":[{"license":{"id":"Apache-2.0"}}],"purl":"pkg:npm/typescript@7.0.2","externalReferences":[{"url":"https://github.com/microsoft/TypeScript/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/microsoft/TypeScript.git","type":"vcs","comment":"as detected from PackageJson property \"repository.url\""},{"url":"https://www.typescriptlang.org/","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=16.20.0"}]},{"type":"library","name":"vitest","version":"5.0.3","bom-ref":"pkg:npm/vitest@5.0.3","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"Next generation testing framework powered by Vite","hashes":[{"alg":"SHA-512","content":"c4cc3ded2deb8ddb63e5d9156adee30aca96069bdc86cdd196941cb54ab0243d0a904464e34bf3d9f27bee50f05bf57387fa64d7c788b5803392876149eb378d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/vitest@5.0.3","externalReferences":[{"url":"https://github.com/vitest-dev/vitest/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/vitest-dev/vitest.git#packages/vitest","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://vitest.dev","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^22.12.0 || ^24.0.0 || >=26.0.0"}]}]},"component":{"type":"library","name":"vite-plugin-product","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-plugin-product@0.3.0","description":"Composes a product from its plugins while it builds: checks every plugin against the others, resolves the product, and serves it as virtual:product.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-plugin-product@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-plugin-product","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-plugin-product#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}],"evidence":{"licenses":[{"license":{"name":"file: LICENSE","text":{"content":"TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAyNiBTdGVhbHRoIFNjYWxlIEIuVi4KClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==","contentType":"text/plain","encoding":"base64"}}}]}},"supplier":{"name":"Stealth Scale B.V.","url":["https://stealthscale.io"]}},"components":[],"dependencies":[{"ref":"pkg:npm/%40stealthscale/vite-plugin-product@0.3.0"}]}
1
+ {"$schema":"http://cyclonedx.org/schema/bom-1.7.schema.json","bomFormat":"CycloneDX","specVersion":"1.7","version":1,"metadata":{"lifecycles":[{"phase":"build"}],"tools":{"components":[{"type":"application","name":"rolldown","version":"1.2.12"},{"type":"application","name":"vite","version":"8.3.3"},{"type":"library","name":"core","group":"@arethetypeswrong","version":"0.18.5","bom-ref":"pkg:npm/%40arethetypeswrong/core@0.18.5","author":"Andrew Branch","description":"The API behind arethetypeswrong.github.io","hashes":[{"alg":"SHA-512","content":"f72b63cc6c318e6f54cfb23d6af7dbb79be542deae93db914444b3263aabce797a58abc8e9dc184e8faf277534d96aeafe64778aa97f3f386f1e129d2480230d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40arethetypeswrong/core@0.18.5","externalReferences":[{"url":"https://github.com/arethetypeswrong/arethetypeswrong.github.io.git#packages/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=20"}]},{"type":"library","name":"sdk-core","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/sdk-core@0.3.0","description":"Declares the contracts and manifests of plugins, evaluates their conditions, and resolves a product from them, without loading another package at run time.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/sdk-core@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#sdk/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/sdk/core#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"testing-config","group":"@stealthscale","version":"0.6.0","bom-ref":"pkg:npm/%40stealthscale/testing-config@0.6.0","description":"Lists every part of the house contract a config, plugin or library package breaks.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/testing-config@0.6.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/testing-config","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/testing-config#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"testing","group":"@stealthscale","version":"0.4.0","bom-ref":"pkg:npm/%40stealthscale/testing@0.4.0","description":"Supplies the scratch workspaces, manifests, element measurements and plugin drivers a specification needs.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/testing@0.4.0","externalReferences":[{"url":"git+https://github.com/stealth-scale/scale.git#packages/testing","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-typescript","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","description":"Sets the TypeScript options every stealthscale package compiles with.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config-typescript","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config-typescript#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config","group":"@stealthscale","version":"0.8.0","bom-ref":"pkg:npm/%40stealthscale/vite-config@0.8.0","description":"Configures a package from five Vite+ tiers and a named layer for every block.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config@0.8.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-config","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-config#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-plugin-base","group":"@stealthscale","version":"0.5.1","bom-ref":"pkg:npm/%40stealthscale/vite-plugin-base@0.5.1","description":"Turns a name and one write step into a bundler plugin that reads the module graph.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-plugin-base@0.5.1","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-plugin-base","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-plugin-base#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-plugin-i18n","group":"@stealthscale","version":"0.4.0","bom-ref":"pkg:npm/%40stealthscale/vite-plugin-i18n@0.4.0","description":"Finds every catalogue an application can reach, types their keys, and answers the module it loads them from.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-plugin-i18n@0.4.0","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-plugin-i18n","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-plugin-i18n#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"node","group":"@types","version":"26.6.4","bom-ref":"pkg:npm/%40types/node@26.6.4","description":"TypeScript definitions for node","hashes":[{"alg":"SHA-512","content":"95d54f0c2ce3edfb1a199acb07436e1ee4ef25cb0d6accac040a8ca25aff720c6b2ddd716eac48af75c988f9c71c9502c63e6c345d6f9d18fd6969eb561e4972"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/node@26.6.4","externalReferences":[{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped.git#types/node","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"coverage-v8","group":"@vitest","version":"5.0.3","bom-ref":"pkg:npm/%40vitest/coverage-v8@5.0.3","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"V8 coverage provider for Vitest","hashes":[{"alg":"SHA-512","content":"fa496ccb3ec1bd3d6f094dbc6647f39acd486bbf170f4578d54dc552d45a6b74bebceaff117bcad4ee81bd50fb9754731239ba48e351d9ac9b3af0c37fdbb499"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40vitest/coverage-v8@5.0.3","externalReferences":[{"url":"https://github.com/vitest-dev/vitest/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/vitest-dev/vitest.git#packages/coverage-v8","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://vitest.dev/guide/coverage","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"vite-plus-core","group":"@voidzero-dev","version":"1.1.0","bom-ref":"pkg:npm/%40voidzero-dev/vite-plus-core@1.1.0","author":"VoidZero Inc.","description":"The Unified Toolchain for the Web","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40voidzero-dev/vite-plus-core@1.1.0","externalReferences":[{"url":"https://github.com/voidzero-dev/vite-plus/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/voidzero-dev/vite-plus.git#packages/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://viteplus.dev/guide","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^20.19.0 || ^22.18.0 || >=24.11.0"}]},{"type":"library","name":"typescript","version":"7.0.2","bom-ref":"pkg:npm/typescript@7.0.2","author":"Microsoft Corp.","description":"TypeScript is a language for application scale JavaScript development","hashes":[{"alg":"SHA-512","content":"f0561abbdea8dcd28e85b8ca8bfa8dbc6fd6e63873c646dd9b9b23f406d9ff94f9b16aa7de12602df1b1dbbb11299593bf2cc23fc74b4414dfe6d05349155434"}],"licenses":[{"license":{"id":"Apache-2.0"}}],"purl":"pkg:npm/typescript@7.0.2","externalReferences":[{"url":"https://github.com/microsoft/TypeScript/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/microsoft/TypeScript.git","type":"vcs","comment":"as detected from PackageJson property \"repository.url\""},{"url":"https://www.typescriptlang.org/","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=16.20.0"}]},{"type":"library","name":"vitest","version":"5.0.3","bom-ref":"pkg:npm/vitest@5.0.3","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"Next generation testing framework powered by Vite","hashes":[{"alg":"SHA-512","content":"c4cc3ded2deb8ddb63e5d9156adee30aca96069bdc86cdd196941cb54ab0243d0a904464e34bf3d9f27bee50f05bf57387fa64d7c788b5803392876149eb378d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/vitest@5.0.3","externalReferences":[{"url":"https://github.com/vitest-dev/vitest/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/vitest-dev/vitest.git#packages/vitest","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://vitest.dev","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^22.12.0 || ^24.0.0 || >=26.0.0"}]}]},"component":{"type":"library","name":"vite-plugin-product","group":"@stealthscale","version":"0.3.2","bom-ref":"pkg:npm/%40stealthscale/vite-plugin-product@0.3.2","description":"Composes a product from its plugins while it builds: checks every plugin against the others, resolves the product, and serves it as virtual:product.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-plugin-product@0.3.2","externalReferences":[{"url":"https://github.com/stealth-scale/scale/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/scale.git#packages/vite-plugin-product","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/scale/tree/main/packages/vite-plugin-product#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}],"evidence":{"licenses":[{"license":{"name":"file: LICENSE","text":{"content":"TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAyNiBTdGVhbHRoIFNjYWxlIEIuVi4KClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==","contentType":"text/plain","encoding":"base64"}}}]}},"supplier":{"name":"Stealth Scale B.V.","url":["https://stealthscale.io"]}},"components":[],"dependencies":[{"ref":"pkg:npm/%40stealthscale/vite-plugin-product@0.3.2"}]}
package/dist/index.d.mts CHANGED
@@ -107,9 +107,12 @@ export declare function product(options?: ProductOptions): Plugin;
107
107
  * Creates the plugin that provides the product's shared modules to the releases its page loads.
108
108
  *
109
109
  * @remarks
110
- * The client build first runs a build of the same configuration without the facades. It then
111
- * builds each module of that first build into the chunk of the same name, and each CommonJS
112
- * module into a chunk beside it. It emits each facade as an entry chunk that keeps its exports.
110
+ * The client build first runs a build of the same configuration without the facades. The first
111
+ * build keeps every export of each module of a provided package that it includes, as the facades
112
+ * make the client build keep them. A package qualifies where it states which of its files have
113
+ * side effects. The client build then builds each module of the first build into the chunk of the
114
+ * same name, and each CommonJS module into a chunk beside it. It emits each facade as an entry
115
+ * chunk that keeps its exports.
113
116
  * A facade imports its specifier, and the plugin resolves the specifier from the package that
114
117
  * depends on it, so the facade and the product share one module. Rolldown builds the code that
115
118
  * only the facades need into chunks that only the facades import. The plugin writes
package/dist/index.mjs CHANGED
@@ -3,33 +3,38 @@ import { build, normalizePath, parseSync } from "vite";
3
3
  import { PROVIDED_FILE, RELEASE_FILE, lineOf, releaseProblems, resolveProduct } from "@stealthscale/sdk-core";
4
4
  import { dependencies, exportTarget, importer, literal, manifestAt, owning, packageAt, quoted, text } from "@stealthscale/vite-plugin-base";
5
5
  import { LOCALES, cataloguesOf } from "@stealthscale/vite-plugin-i18n";
6
- import { dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
6
+ import { basename, dirname, extname, isAbsolute, join, matchesGlob, posix, relative, resolve, sep } from "node:path";
7
7
  import { validateHotkey } from "@tanstack/hotkeys";
8
8
  import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
9
9
  import { createHash } from "node:crypto";
10
10
  //#region src/page.ts
11
11
  /**
12
- * Writes the document and the entry of a page the plugin serves at `index.html`: a product's page
13
- * or a plugin's standalone page.
12
+ * Writes the document and the entry of the page that the plugin serves at `index.html`. The page
13
+ * is a product's page or a plugin's standalone page.
14
14
  */
15
15
  /**
16
16
  * The page's document, from the project root.
17
17
  */
18
18
  const DOCUMENT = "index.html";
19
19
  /**
20
- * The language of a document whose page states none.
20
+ * The language of a document whose page has no language.
21
21
  */
22
22
  const LANGUAGE = "en-US";
23
23
  /**
24
- * Returns the path of the page's document for a specifier that names it, and undefined for any
24
+ * Returns the path of the page's document for a specifier of the document, and undefined for any
25
25
  * other specifier.
26
26
  *
27
+ * @remarks
28
+ * The function compares the specifier after `normalizePath`. A build's default input is the
29
+ * document's path from `path.resolve`, which has backslashes on Windows.
27
30
  * @param root - The project root.
28
- * @param id - The specifier: `index.html`, `/index.html` or the document's path name the document.
31
+ * @param id - The specifier. The document's specifiers are `index.html`, `/index.html` and the
32
+ * document's path.
29
33
  */
30
34
  function documentIdOf(root, id) {
31
35
  const document = normalizePath(join(root, DOCUMENT));
32
- return id === DOCUMENT || id === `/${DOCUMENT}` || id === document ? document : void 0;
36
+ const file = normalizePath(id);
37
+ return file === DOCUMENT || file === `/${DOCUMENT}` || file === document ? document : void 0;
33
38
  }
34
39
  /**
35
40
  * Returns the specifier of a module by its path from the project root, such as `/src/glyphs.tsx`.
@@ -38,8 +43,8 @@ function rootedOf(path) {
38
43
  return posix.join("/", normalizePath(path));
39
44
  }
40
45
  /**
41
- * Returns the source of a page's document: its language and title, an element with the id `root`,
42
- * and the entry.
46
+ * Returns the source of a page's document. The document has its language and title, an element
47
+ * with the id `root`, and the entry.
43
48
  */
44
49
  function documentSource({ entry, language, title }) {
45
50
  return [
@@ -59,18 +64,18 @@ function documentSource({ entry, language, title }) {
59
64
  ].join("\n");
60
65
  }
61
66
  /**
62
- * Returns the source of a page's entry: the stylesheet and the static imports, every other module
63
- * through `import()`, and a call of the render function with the members.
67
+ * Returns the source of a page's entry. The entry imports the stylesheet and the static modules,
68
+ * imports every other module through `import()`, and calls the render function with the members.
64
69
  *
65
70
  * @remarks
66
71
  * The entry imports the stylesheet and modules without components statically, and the page's
67
72
  * other modules through `import()`. The bundled dev server installs the React refresh runtime in
68
- * the entry's own body, and a chunk the entry imports statically runs before that body, so a
69
- * component in a chunk the bundler shares between the entry and a lazy module would run before
70
- * the runtime and throw. Behind `import()`, every component runs after it. A module the entry
71
- * alone imports statically builds into the entry's chunk, so it adds no chunk of its own. The
72
- * entry awaits nothing at its top level, because a module with a top-level await makes the
73
- * bundler move every module it shares with a lazy module into a chunk of its own.
73
+ * the entry's own body. A chunk that the entry imports statically runs before that body, so a
74
+ * component in a chunk that the entry shares with a lazy module would run before the runtime and
75
+ * throw. A component that the entry imports through `import()` runs after the runtime. A module
76
+ * that only the entry imports statically builds into the entry's chunk, so it adds no chunk of
77
+ * its own. The entry does not await at its top level, because a module with a top-level await
78
+ * makes the bundler move every module it shares with a lazy module into a chunk of its own.
74
79
  * @param render - The name of the render function, which the first module exports.
75
80
  * @param modules - The modules the entry imports through `import()`, the render function's first.
76
81
  * @param members - The members of the object the render function receives.
@@ -428,22 +433,22 @@ function moduleOf(definition, product) {
428
433
  //#endregion
429
434
  //#region src/chunks.ts
430
435
  /**
431
- * Names the chunk each module of a product builds into: one chunk per plugin, which every page,
432
- * extension, command and settings section of the plugin shares, and under a build one chunk for the
433
- * other modules outside the application that the startup or a plugin imports statically.
436
+ * Names the chunk that each module of a product builds into.
434
437
  *
435
438
  * @remarks
436
- * The product imports each web package's main entry statically, through its definition. The main
437
- * entry and every module it imports statically build into the chunks the entry loads, because in
438
- * the plugin's chunk they would make the first load fetch the whole plugin. Groups that place a
439
- * module by its path alone make rolldown 1.2 build a module the groups leave into the chunk of a
440
- * lazy module that imports it, and export it from there to the chunks that need it. `import()` of
441
- * that lazy module then resolves to a namespace with the other module's exports as well. A module
442
- * outside every web package that one plugin's lazy modules alone import goes into the plugin's
443
- * chunk. Every other module outside the application that the startup or a plugin's modules import
444
- * statically goes into the `dependencies` chunk, so a lazy module's chunk contains the lazy
445
- * module alone. A module that only another `import()` loads, such as a page the application
446
- * loads on demand, keeps its own chunk, so it does not load with the startup.
439
+ * Each plugin has one chunk for its pages, extensions, commands and settings sections. A build
440
+ * also has one chunk for the other modules outside the application that the startup or a plugin
441
+ * imports statically. The product's definition imports the main entry of each web package
442
+ * statically. The main entry and every module it imports statically build into the chunks that
443
+ * the entry loads, because in the plugin's chunk they would make the first load fetch the whole
444
+ * plugin. Groups that place a module by its path alone make rolldown 1.2 build a module that no
445
+ * group takes into the chunk of a lazy module that imports it. Rolldown then exports the module
446
+ * from that chunk to the chunks that need it, and `import()` of the lazy module resolves to a
447
+ * namespace with the other module's exports as well. A module outside every web package that
448
+ * only one plugin's lazy modules import goes into the plugin's chunk. Every other module outside
449
+ * the application that the startup or a plugin's modules import statically goes into the
450
+ * `dependencies` chunk. A lazy module's chunk then contains the lazy module alone. A module that
451
+ * only another `import()` loads keeps its own chunk and does not load with the startup.
447
452
  */
448
453
  /**
449
454
  * Name of the chunk that a module outside the application builds into where the startup or a
@@ -451,12 +456,13 @@ function moduleOf(definition, product) {
451
456
  */
452
457
  const DEPENDENCIES = "dependencies";
453
458
  /**
454
- * Priority of the plugin chunks' group: above the shared chunk's 3, below the vendor chunk's 5.
459
+ * Priority of the plugin chunks' group. It is above the shared chunk's 3 and below the vendor
460
+ * chunk's 5.
455
461
  */
456
462
  const PRIORITY = 4;
457
463
  /**
458
- * Priority of the dependencies' group: below every other group's, so it claims only the modules
459
- * they leave.
464
+ * Priority of the dependencies' group. It is below the priority of every other group, so the group
465
+ * claims only the modules that the other groups leave.
460
466
  */
461
467
  const LAST = 1;
462
468
  /**
@@ -466,13 +472,18 @@ const INSTALLED = /(?:^|[\\/])node_modules[\\/]/u;
466
472
  /**
467
473
  * Returns the id of the plugin whose web package contains a module, or undefined for a module
468
474
  * outside every web package.
475
+ *
476
+ * @remarks
477
+ * The web packages' directories have forward slashes. The function compares the module's id
478
+ * after `normalizePath`, so an id with backslashes on Windows matches too.
469
479
  */
470
480
  function ownerOf(id, packages) {
471
- return Object.entries(packages).find(([, { directory }]) => id.startsWith(`${directory}${sep}`))?.[0];
481
+ const file = normalizePath(id);
482
+ return Object.entries(packages).find(([, { directory }]) => file.startsWith(`${directory}/`))?.[0];
472
483
  }
473
484
  /**
474
- * Returns true where the walk over a module's static importers meets a module the test accepts,
475
- * the module itself included.
485
+ * Returns true where the walk over a module's static importers meets a module that the test
486
+ * accepts. The walk starts at the module itself.
476
487
  */
477
488
  function leadsTo(id, chunking, ends) {
478
489
  const seen = /* @__PURE__ */ new Set();
@@ -492,28 +503,28 @@ function startup(id, info) {
492
503
  return id === RESOLVED || info?.isEntry === true;
493
504
  }
494
505
  /**
495
- * Returns true where an entry of the build or `virtual:product` imports a module statically,
496
- * directly or through other modules.
506
+ * Returns true where an entry of the build or `virtual:product` imports a module statically. The
507
+ * import may pass through other modules.
497
508
  *
498
509
  * @remarks
499
- * The walk follows each module's static importers back towards the entries, and ends at
500
- * `virtual:product`, because every module the product imports statically loads with it. The
501
- * standalone page's entry imports the product through `import()`, so no entry imports the
502
- * definition statically there. A dynamic import ends the walk elsewhere, because a module behind
503
- * one loads after the entry.
510
+ * The walk follows each module's static importers back towards the entries. It ends at
511
+ * `virtual:product`, because every module that the product imports statically loads with it. The
512
+ * standalone page's entry imports the product through `import()`, and no entry imports the
513
+ * definition statically there. A dynamic import ends the walk elsewhere, because the module that
514
+ * it imports loads after the entry.
504
515
  */
505
516
  function initial(id, chunking) {
506
517
  return leadsTo(id, chunking, startup);
507
518
  }
508
519
  /**
509
- * Returns the one plugin whose web package's modules import a module outside every web package,
510
- * directly or through other modules.
520
+ * Returns the one plugin whose web package's modules import a module outside every web package.
521
+ * The import may pass through other modules.
511
522
  *
512
523
  * @remarks
513
- * Returns undefined where an entry or `virtual:product` imports the module statically, where the
514
- * walk meets a module outside every web package that no module imports statically, such as a lazy
515
- * page of the application, or a module the build does not know, and where the modules of two
516
- * plugins import it.
524
+ * The function returns undefined in four cases. An entry or `virtual:product` imports the module
525
+ * statically. The walk meets a module outside every web package that no module imports
526
+ * statically, such as a lazy page of the application. The walk meets a module that the build does
527
+ * not know. The modules of two plugins import the module.
517
528
  */
518
529
  function soleOwnerOf(id, chunking, packages) {
519
530
  const owners = /* @__PURE__ */ new Set();
@@ -534,11 +545,13 @@ function soleOwnerOf(id, chunking, packages) {
534
545
  return owners.size === 1 ? sole : void 0;
535
546
  }
536
547
  /**
537
- * Returns the chunk a module builds into: `plugin-<id>` for a module of an installed plugin's web
538
- * package that no entry imports statically, and for a module outside every web package that only
539
- * that plugin's lazy modules import, and null for every other module.
548
+ * Returns the plugin chunk that a module builds into, or null for a module of no plugin chunk.
540
549
  *
541
- * @param id - The module's id, its absolute path.
550
+ * @remarks
551
+ * A module of an installed plugin's web package that no entry imports statically builds into
552
+ * `plugin-<id>`. A module outside every web package that only that plugin's lazy modules import
553
+ * builds into the same chunk.
554
+ * @param id - The module's id. A file's id is its absolute path.
542
555
  * @param chunking - The context rolldown passes a group's name function.
543
556
  * @param packages - Each installed plugin's web package, by plugin id.
544
557
  */
@@ -549,17 +562,17 @@ function pluginChunkOf(id, chunking, packages) {
549
562
  return sole === void 0 ? null : `plugin-${sole}`;
550
563
  }
551
564
  /**
552
- * Returns the chunk a module builds into where the groups with a higher priority leave it:
553
- * `dependencies` for a module outside the application that the startup or a plugin's modules import
554
- * statically, and null for every other module.
565
+ * Returns `dependencies` for a module outside the application that the startup or a plugin's
566
+ * modules import statically, and null for every other module.
555
567
  *
556
568
  * @remarks
557
- * A module of the application is a file under the project root and outside its `node_modules`. A
558
- * virtual module's id is not an absolute path. The walk over the module's static importers ends
559
- * at an entry, at `virtual:product` and at a module of an installed plugin's web package. A
560
- * module it does not meet is one that only another `import()` loads, such as a page the
561
- * application loads on demand, which keeps its own chunk.
562
- * @param id - The module's id, its absolute path for a file.
569
+ * The groups with a higher priority place a module first. A module of the application is a file
570
+ * under the project root and outside its `node_modules`. A virtual module's id is not an absolute
571
+ * path. The walk over the module's static importers ends at an entry, at `virtual:product` and at
572
+ * a module of an installed plugin's web package. A page that the application loads on demand is a
573
+ * module that only another `import()` loads. The walk does not meet such a module, and the module
574
+ * keeps its own chunk.
575
+ * @param id - The module's id. A file's id is its absolute path.
563
576
  * @param chunking - The context rolldown passes a group's name function.
564
577
  * @param root - The project root.
565
578
  * @param packages - Each installed plugin's web package, by plugin id.
@@ -572,16 +585,17 @@ function dependencyChunkOf(id, chunking, root, packages) {
572
585
  }
573
586
  /**
574
587
  * Returns the configuration whose groups build each installed plugin's lazy modules into a chunk
575
- * of its own, and under a build every other module outside the application that the startup or a
576
- * plugin imports statically into the `dependencies` chunk.
588
+ * of its own.
577
589
  *
578
590
  * @remarks
579
- * Both groups read the web packages the composition found, and the dependencies' group reads the
580
- * project root. Both are read when the bundler places a module, after the composition. A dev
581
- * server takes no dependencies' group: `import()` of a lazy module resolves to the module's own
582
- * exports there without it, and `vite-config` leaves out its library and shared groups there too,
583
- * whose chunks would run components before the React refresh runtime is installed.
584
- * @param placing - The web packages and the project root, which each group reads when the bundler
591
+ * A build also builds every other module outside the application that the startup or a plugin
592
+ * imports statically into the `dependencies` chunk. Both groups read the web packages that the
593
+ * composition found, and the dependencies' group also reads the project root. The bundler calls
594
+ * both groups after the composition, when it places a module. A dev server has no dependencies'
595
+ * group, because `import()` of a lazy module resolves to the module's own exports there without
596
+ * it. `vite-config` leaves out its library and shared groups on a dev server too. Their chunks
597
+ * would run components before the React refresh runtime is installed.
598
+ * @param placing - The web packages and the project root. Each group reads them when the bundler
585
599
  * places a module.
586
600
  * @param command - The command Vite runs under, `build` or `serve`.
587
601
  */
@@ -599,15 +613,16 @@ function chunked(placing, command) {
599
613
  //#endregion
600
614
  //#region src/discover.ts
601
615
  /**
602
- * Finds each installed plugin's web package and contract package among the modules the product's
603
- * definition loaded.
616
+ * Finds each installed plugin's web package and contract package among the modules that the
617
+ * evaluation of the product's definition loaded.
604
618
  *
605
619
  * @remarks
606
- * The definition imports every installed plugin's manifest, and each manifest names its contract,
607
- * so the modules its evaluation loaded already contain both. A package is the one that contains
608
- * the module defining the object, matched by identity. A manifest the definition builds itself,
609
- * which no module exports, belongs to the definition module's package. No package is imported for
610
- * the search alone, so no component package and no React is loaded in Node.
620
+ * The definition module imports the manifest of every installed plugin, and each manifest
621
+ * contains its contract. The modules of the evaluation therefore contain both. An object belongs
622
+ * to the package of the module that defines it, and the search matches objects by identity. No
623
+ * module exports a manifest that the definition module creates itself, so that manifest belongs
624
+ * to the package of the definition module. The search imports no package of its own, so Node does
625
+ * not load a component package or React.
611
626
  */
612
627
  /**
613
628
  * Returns true where a value is an object whose members can be read by name.
@@ -616,10 +631,11 @@ function isRecord(value) {
616
631
  return typeof value === "object" && value !== null;
617
632
  }
618
633
  /**
619
- * Returns each installed plugin the definition states with a readable manifest and contract.
634
+ * Returns each installed plugin of the definition that has a readable manifest and contract.
620
635
  *
621
636
  * @remarks
622
- * A definition of another shape installs nothing here, and the resolver's shape check reports it.
637
+ * The function returns no plugin for a definition of another shape. The resolver's shape check
638
+ * reports that definition.
623
639
  * @param definition - The definition's default export.
624
640
  */
625
641
  function installationsOf(definition) {
@@ -640,9 +656,9 @@ function installationsOf(definition) {
640
656
  *
641
657
  * @remarks
642
658
  * A module evaluates after every module it imports, and a module that re-exports an object
643
- * imports the module that defines it. The first module that exports an object, in evaluation
644
- * order, is therefore the one that defines it.
645
- * @param loaded - Every module the definition's evaluation loaded, in evaluation order.
659
+ * imports the module that defines it. The first module in evaluation order that exports an object
660
+ * is therefore the module that defines it.
661
+ * @param loaded - Every module that the evaluation of the definition loaded, in evaluation order.
646
662
  */
647
663
  function ownersOf(loaded) {
648
664
  const owners = /* @__PURE__ */ new Map();
@@ -653,13 +669,17 @@ function ownersOf(loaded) {
653
669
  return owners;
654
670
  }
655
671
  /**
656
- * Returns the package at a directory, or undefined where its manifest states no name.
672
+ * Returns the package at a directory, or undefined where its manifest has no name.
673
+ *
674
+ * @remarks
675
+ * The package's directory goes through `normalizePath`, so on Windows it has the forward slashes
676
+ * of a module id.
657
677
  */
658
678
  function packageIn(directory) {
659
679
  const manifest = directory === void 0 ? void 0 : manifestAt(directory);
660
680
  const name = manifest === void 0 ? void 0 : text(manifest, "name");
661
681
  return directory === void 0 || name === void 0 ? void 0 : {
662
- directory,
682
+ directory: normalizePath(directory),
663
683
  name
664
684
  };
665
685
  }
@@ -667,18 +687,21 @@ function packageIn(directory) {
667
687
  * Finds each installed plugin's web package and contract package.
668
688
  *
669
689
  * @remarks
670
- * A web package outside the product's own package and its dependencies is left out, so the
671
- * resolver reports the plugin. A contract package is recorded wherever it is, because the build
672
- * reads it to leave the plugin's own catalogue out of the namespaces another package publishes.
690
+ * The function leaves out a web package outside the product's own package and its dependencies,
691
+ * so the resolver reports the plugin. It records a contract package wherever it is, because the
692
+ * build reads it to leave the plugin's own catalogue out of the namespaces of other packages. The
693
+ * function compares directories after `normalizePath`, because on Windows the module runner and
694
+ * `realpathSync` write them with different separators.
673
695
  * @param definition - The definition's default export.
674
- * @param loaded - Every module the definition's evaluation loaded, in evaluation order.
675
- * @param root - The product's directory, whose dependencies are walked.
676
- * @param file - The definition module, whose package a manifest the definition builds belongs to.
696
+ * @param loaded - Every module that the evaluation of the definition loaded, in evaluation order.
697
+ * @param root - The product's directory. The walk over its dependencies starts there.
698
+ * @param file - The definition module. A manifest that the definition module creates belongs to the
699
+ * package of this module.
677
700
  */
678
701
  function discover(definition, loaded, root, file) {
679
702
  const owners = ownersOf(loaded);
680
703
  const own = owning(realpathSync(file));
681
- const depended = /* @__PURE__ */ new Set([realpathSync(root), ...dependencies(root).map(({ at }) => at)]);
704
+ const depended = new Set([realpathSync(root), ...dependencies(root).map(({ at }) => at)].map((at) => normalizePath(at)));
682
705
  const contracts = {};
683
706
  const packages = {};
684
707
  for (const { contract, manifest, pluginId } of installationsOf(definition)) {
@@ -1417,108 +1440,6 @@ function facadeOf(specifier, shape) {
1417
1440
  ].join("\n");
1418
1441
  }
1419
1442
  //#endregion
1420
- //#region src/provided/pinned.ts
1421
- /**
1422
- * Returns a map from the id of each module of the first build to the name of its chunk.
1423
- *
1424
- * @remarks
1425
- * The modules of a static entry's chunk have no pin. The second chunk of one name in file name
1426
- * order takes the name with `-2` appended, and the third takes it with `-3` appended.
1427
- * @param chunks - The chunks of the first build.
1428
- */
1429
- function pinnedOf(chunks) {
1430
- const counts = /* @__PURE__ */ new Map();
1431
- const pinned = /* @__PURE__ */ new Map();
1432
- const ordered = chunks.filter(({ isEntry }) => !isEntry).toSorted((one, two) => one.fileName.localeCompare(two.fileName));
1433
- for (const { modules, name } of ordered) {
1434
- const count = (counts.get(name) ?? 0) + 1;
1435
- const pin = count === 1 ? name : `${name}-${String(count)}`;
1436
- counts.set(name, count);
1437
- for (const id of Object.keys(modules)) pinned.set(id, pin);
1438
- }
1439
- return pinned;
1440
- }
1441
- /**
1442
- * Returns the code-splitting group that places each pinned module in the second build.
1443
- *
1444
- * @remarks
1445
- * A pinned chunk can import a chunk of the facades' code that imports it back. Rolldown defines a
1446
- * CommonJS module's wrapper at the top level of its chunk, and an ES module that imports it calls
1447
- * the wrapper at its own top level. In such a cycle a chunk can call a wrapper that is not
1448
- * defined yet. The group builds each pin's CommonJS modules into a chunk of their own. As long as
1449
- * those modules require only CommonJS modules, that chunk imports only rolldown's runtime and
1450
- * other such chunks. It then runs before every chunk that calls its wrappers.
1451
- * @param pins - Returns a map from the id of each module of the first build to its chunk once the
1452
- * first build has run.
1453
- */
1454
- function pinnedGroup(pins) {
1455
- return {
1456
- debugName: "pinned",
1457
- name: (id, chunking) => {
1458
- const pin = pins()?.get(id);
1459
- if (pin === void 0) return null;
1460
- return chunking.getModuleInfo(id)?.inputFormat === "cjs" ? `${pin}-cjs` : pin;
1461
- }
1462
- };
1463
- }
1464
- //#endregion
1465
- //#region src/provided/first.ts
1466
- /**
1467
- * Runs a product's first build: the build's own configuration without the facades, written
1468
- * nowhere, whose chunks the second build pins the product's modules to.
1469
- */
1470
- /**
1471
- * Name of the plugin that marks the first build, which leaves the facades out.
1472
- */
1473
- const FIRST_BUILD = "stealth:provided-first";
1474
- /**
1475
- * Returns true where a configuration's plugins mark the first build.
1476
- *
1477
- * @param plugins - The resolved plugins of a build.
1478
- */
1479
- function isFirstBuild(plugins) {
1480
- return plugins.some(({ name }) => name === FIRST_BUILD);
1481
- }
1482
- /**
1483
- * Returns a plugin option with every nested list flattened into one list.
1484
- */
1485
- function flattened(option) {
1486
- return Array.isArray(option) ? option.flatMap((one) => flattened(one)) : [option];
1487
- }
1488
- /**
1489
- * Returns the plugins a caller passed inline, with the second build's own facade plugin left out.
1490
- */
1491
- function inlinePlugins(plugins, own) {
1492
- return (plugins ?? []).flatMap((option) => flattened(option)).filter((one) => one !== own);
1493
- }
1494
- /**
1495
- * Returns the chunks of the first build of the configuration a second build resolved.
1496
- *
1497
- * @remarks
1498
- * The first build reads the same configuration file and the same inline configuration, with the
1499
- * plugin that marks it, without watching and without writing. A facade plugin of the first build
1500
- * reads the mark and adds nothing, so the first build places each module as the product's build
1501
- * does without facades.
1502
- * @param config - The second build's configuration file, inline configuration, mode and root.
1503
- * @param own - The second build's facade plugin, which a caller may have passed inline.
1504
- */
1505
- async function firstBuild(config, own) {
1506
- const { configFile, inlineConfig, mode, root } = config;
1507
- return [await build({
1508
- ...inlineConfig,
1509
- build: {
1510
- ...inlineConfig.build,
1511
- watch: null,
1512
- write: false
1513
- },
1514
- configFile: configFile ?? false,
1515
- logLevel: "silent",
1516
- mode,
1517
- plugins: [...inlinePlugins(inlineConfig.plugins, own), { name: FIRST_BUILD }],
1518
- root
1519
- })].flat().flatMap(({ output }) => output).filter((file) => file.type === "chunk");
1520
- }
1521
- //#endregion
1522
1443
  //#region src/provided/packages.ts
1523
1444
  /**
1524
1445
  * Lists the packages a page provides to the releases it loads, and the specifiers of each.
@@ -1666,6 +1587,235 @@ function importerOf(provided, specifier) {
1666
1587
  return owner === void 0 ? void 0 : join(owner.from, "package.json");
1667
1588
  }
1668
1589
  //#endregion
1590
+ //#region src/provided/kept.ts
1591
+ /**
1592
+ * Makes a product's first build keep every export of each module of a provided package that the
1593
+ * build includes.
1594
+ *
1595
+ * @remarks
1596
+ * A facade keeps every export of its specifier's module, so the second build keeps code that the
1597
+ * first build removed from a module the product uses. A published package bundles its components
1598
+ * into few modules, and the code that the first build removed imports modules that the first
1599
+ * build left out. Those modules have no pin, so rolldown builds them into a chunk of their own.
1600
+ * That chunk imports the pinned chunk that imports it. In such a cycle a module can read a
1601
+ * binding of the other chunk before that chunk has run. The first build therefore appends to each
1602
+ * module of a provided package a statement that passes the module's namespace to a global hook.
1603
+ * The statement keeps every export of a module that the build includes, so the first build places
1604
+ * the modules that those exports import. The statement adds no module to the build. The build
1605
+ * leaves out a module whose exports nothing uses when its package has a `sideEffects` field.
1606
+ */
1607
+ /**
1608
+ * The extensions of an ES module in any package.
1609
+ */
1610
+ const MODULES = /* @__PURE__ */ new Set([".mjs", ".mts"]);
1611
+ /**
1612
+ * The extensions of an ES module in a package that states `"type": "module"`.
1613
+ */
1614
+ const TYPED = /* @__PURE__ */ new Set([
1615
+ ".js",
1616
+ ".jsx",
1617
+ ".ts",
1618
+ ".tsx"
1619
+ ]);
1620
+ /**
1621
+ * The key of the global function that the kept statement passes a module's namespace to. No page
1622
+ * defines the function, because no page loads the first build's output.
1623
+ */
1624
+ const HOOK = "stealth.kept";
1625
+ /**
1626
+ * Returns the patterns of a package's files that have side effects, or undefined where the
1627
+ * manifest's `sideEffects` is neither false nor an array.
1628
+ */
1629
+ function effectsOf(sideEffects) {
1630
+ if (sideEffects === false) return [];
1631
+ if (!Array.isArray(sideEffects)) return void 0;
1632
+ return sideEffects.filter((pattern) => typeof pattern === "string");
1633
+ }
1634
+ /**
1635
+ * Returns the provided packages whose modules the first build keeps whole.
1636
+ *
1637
+ * @remarks
1638
+ * Each is an installed package whose `sideEffects` is false or a list of patterns. Its directory
1639
+ * goes through `normalizePath`, so on Windows it has the forward slashes of a module id.
1640
+ * @param packages - The packages the product provides.
1641
+ */
1642
+ function keptPackages(packages) {
1643
+ return packages.flatMap(({ from, name }) => {
1644
+ const directory = packageAt(name, from);
1645
+ const manifest = directory === void 0 ? void 0 : manifestAt(directory);
1646
+ const effects = effectsOf(manifest?.["sideEffects"]);
1647
+ return directory === void 0 || effects === void 0 ? [] : [{
1648
+ directory: normalizePath(directory),
1649
+ effects,
1650
+ typed: manifest?.["type"] === "module"
1651
+ }];
1652
+ });
1653
+ }
1654
+ /**
1655
+ * Returns true where a pattern of a package's `sideEffects` list matches a file at a path relative
1656
+ * to the package.
1657
+ *
1658
+ * @remarks
1659
+ * A pattern without a slash matches the file's name in any directory, as bundlers read the list.
1660
+ */
1661
+ function affects(pattern, path) {
1662
+ return matchesGlob(path, pattern.includes("/") ? pattern.replace(/^\.\//u, "") : `**/${pattern}`);
1663
+ }
1664
+ /**
1665
+ * Returns true for an ES module file of a kept package that no side-effect pattern of the package
1666
+ * matches. The first build keeps the exports of such a module whole.
1667
+ *
1668
+ * @remarks
1669
+ * A file below a `node_modules` directory inside the package belongs to another package. The
1670
+ * function compares the id after `normalizePath`, so an id with backslashes on Windows matches
1671
+ * too.
1672
+ * @param id - The module's id.
1673
+ * @param packages - The packages whose modules the first build keeps whole.
1674
+ */
1675
+ function isKept(id, packages) {
1676
+ const file = normalizePath(id);
1677
+ const owner = isAbsolute(file) ? packages.find(({ directory }) => file.startsWith(`${directory}/`)) : void 0;
1678
+ if (owner === void 0) return false;
1679
+ const path = file.slice(owner.directory.length + 1);
1680
+ const extension = extname(file);
1681
+ return (MODULES.has(extension) || owner.typed && TYPED.has(extension)) && !path.split("/").includes("node_modules") && !owner.effects.some((pattern) => affects(pattern, path));
1682
+ }
1683
+ /**
1684
+ * Returns a module's code with the statement that keeps its exports appended. The statement
1685
+ * imports the namespace of the module's own file and passes it to a global hook.
1686
+ *
1687
+ * @param code - The module's code.
1688
+ * @param id - The module's id, the absolute path of its file.
1689
+ */
1690
+ function keptSourceOf(code, id) {
1691
+ return [
1692
+ code,
1693
+ `import * as __stealthKept from ${quoted(`./${basename(id)}`)};`,
1694
+ `globalThis[Symbol.for(${quoted(HOOK)})]?.(__stealthKept);`,
1695
+ ""
1696
+ ].join("\n");
1697
+ }
1698
+ //#endregion
1699
+ //#region src/provided/pinned.ts
1700
+ /**
1701
+ * Returns a map from the id of each module of the first build to the name of its chunk.
1702
+ *
1703
+ * @remarks
1704
+ * The modules of a static entry's chunk have no pin. The second chunk of one name in file name
1705
+ * order takes the name with `-2` appended, and the third takes it with `-3` appended.
1706
+ * @param chunks - The chunks of the first build.
1707
+ */
1708
+ function pinnedOf(chunks) {
1709
+ const counts = /* @__PURE__ */ new Map();
1710
+ const pinned = /* @__PURE__ */ new Map();
1711
+ const ordered = chunks.filter(({ isEntry }) => !isEntry).toSorted((one, two) => one.fileName.localeCompare(two.fileName));
1712
+ for (const { modules, name } of ordered) {
1713
+ const count = (counts.get(name) ?? 0) + 1;
1714
+ const pin = count === 1 ? name : `${name}-${String(count)}`;
1715
+ counts.set(name, count);
1716
+ for (const id of Object.keys(modules)) pinned.set(id, pin);
1717
+ }
1718
+ return pinned;
1719
+ }
1720
+ /**
1721
+ * Returns the code-splitting group that places each pinned module in the second build.
1722
+ *
1723
+ * @remarks
1724
+ * A pinned chunk can import a chunk of the facades' code that imports it back. Rolldown defines a
1725
+ * CommonJS module's wrapper at the top level of its chunk, and an ES module that imports it calls
1726
+ * the wrapper at its own top level. In such a cycle a chunk can call a wrapper that is not
1727
+ * defined yet. The group builds each pin's CommonJS modules into a chunk of their own. As long as
1728
+ * those modules require only CommonJS modules, that chunk imports only rolldown's runtime and
1729
+ * other such chunks. It then runs before every chunk that calls its wrappers.
1730
+ * @param pins - Returns a map from the id of each module of the first build to its chunk once the
1731
+ * first build has run.
1732
+ */
1733
+ function pinnedGroup(pins) {
1734
+ return {
1735
+ debugName: "pinned",
1736
+ name: (id, chunking) => {
1737
+ const pin = pins()?.get(id);
1738
+ if (pin === void 0) return null;
1739
+ return chunking.getModuleInfo(id)?.inputFormat === "cjs" ? `${pin}-cjs` : pin;
1740
+ }
1741
+ };
1742
+ }
1743
+ //#endregion
1744
+ //#region src/provided/first.ts
1745
+ /**
1746
+ * Runs a product's first build: the build's own configuration without the facades, written
1747
+ * nowhere, whose chunks the second build pins the product's modules to.
1748
+ */
1749
+ /**
1750
+ * Name of the plugin that marks the first build, which leaves the facades out.
1751
+ */
1752
+ const FIRST_BUILD = "stealth:provided-first";
1753
+ /**
1754
+ * Returns true where a configuration's plugins mark the first build.
1755
+ *
1756
+ * @param plugins - The resolved plugins of a build.
1757
+ */
1758
+ function isFirstBuild(plugins) {
1759
+ return plugins.some(({ name }) => name === FIRST_BUILD);
1760
+ }
1761
+ /**
1762
+ * Returns a plugin option with every nested list flattened into one list.
1763
+ */
1764
+ function flattened(option) {
1765
+ return Array.isArray(option) ? option.flatMap((one) => flattened(one)) : [option];
1766
+ }
1767
+ /**
1768
+ * Returns the plugins a caller passed inline, with the second build's own facade plugin left out.
1769
+ */
1770
+ function inlinePlugins(plugins, own) {
1771
+ return (plugins ?? []).flatMap((option) => flattened(option)).filter((one) => one !== own);
1772
+ }
1773
+ /**
1774
+ * Returns the plugin that marks the first build and keeps every export of each module of a kept
1775
+ * package.
1776
+ */
1777
+ function markOf(kept) {
1778
+ return {
1779
+ name: FIRST_BUILD,
1780
+ /**
1781
+ * Appends the statement that keeps every export to each module of a kept package, and leaves
1782
+ * every other module alone.
1783
+ */
1784
+ transform(code, id) {
1785
+ return isKept(id, kept) ? keptSourceOf(code, id) : null;
1786
+ }
1787
+ };
1788
+ }
1789
+ /**
1790
+ * Returns the chunks of the first build of the configuration a second build resolved.
1791
+ *
1792
+ * @remarks
1793
+ * The first build reads the same configuration file and the same inline configuration, with the
1794
+ * plugin that marks it, without watching and without writing. A facade plugin of the first build
1795
+ * reads the mark and adds nothing. The plugin that marks the build keeps every export of each
1796
+ * module of a kept package that the build includes, as the facades make the second build keep
1797
+ * them. The first build therefore also places the modules that those exports import.
1798
+ * @param config - The second build's configuration file, inline configuration, mode and root.
1799
+ * @param own - The second build's facade plugin, which a caller may have passed inline.
1800
+ * @param kept - The provided packages whose modules the first build keeps whole.
1801
+ */
1802
+ async function firstBuild(config, own, kept) {
1803
+ const { configFile, inlineConfig, mode, root } = config;
1804
+ return [await build({
1805
+ ...inlineConfig,
1806
+ build: {
1807
+ ...inlineConfig.build,
1808
+ watch: null,
1809
+ write: false
1810
+ },
1811
+ configFile: configFile ?? false,
1812
+ logLevel: "silent",
1813
+ mode,
1814
+ plugins: [...inlinePlugins(inlineConfig.plugins, own), markOf(kept)],
1815
+ root
1816
+ })].flat().flatMap(({ output }) => output).filter((file) => file.type === "chunk");
1817
+ }
1818
+ //#endregion
1669
1819
  //#region src/provided/manifest.ts
1670
1820
  /**
1671
1821
  * Returns the paths of some chunks and of every chunk that they import statically. The given
@@ -1803,9 +1953,12 @@ async function facadeSourceOf(context, packages, id) {
1803
1953
  * Creates the plugin that provides the product's shared modules to the releases its page loads.
1804
1954
  *
1805
1955
  * @remarks
1806
- * The client build first runs a build of the same configuration without the facades. It then
1807
- * builds each module of that first build into the chunk of the same name, and each CommonJS
1808
- * module into a chunk beside it. It emits each facade as an entry chunk that keeps its exports.
1956
+ * The client build first runs a build of the same configuration without the facades. The first
1957
+ * build keeps every export of each module of a provided package that it includes, as the facades
1958
+ * make the client build keep them. A package qualifies where it states which of its files have
1959
+ * side effects. The client build then builds each module of the first build into the chunk of the
1960
+ * same name, and each CommonJS module into a chunk beside it. It emits each facade as an entry
1961
+ * chunk that keeps its exports.
1809
1962
  * A facade imports its specifier, and the plugin resolves the specifier from the package that
1810
1963
  * depends on it, so the facade and the product share one module. Rolldown builds the code that
1811
1964
  * only the facades need into chunks that only the facades import. The plugin writes
@@ -1830,7 +1983,7 @@ function provided() {
1830
1983
  async buildStart() {
1831
1984
  if (state.first || this.environment.config.consumer !== "client") return;
1832
1985
  state.language = languageOf(state.api);
1833
- state.pinned = pinnedOf(await firstBuild(this.environment.config, plugin));
1986
+ state.pinned = pinnedOf(await firstBuild(this.environment.config, plugin, keptPackages(state.packages)));
1834
1987
  for (const facade of facadesOf(state.packages)) this.emitFile(facade);
1835
1988
  },
1836
1989
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stealthscale/vite-plugin-product",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Composes a product from its plugins while it builds: checks every plugin against the others, resolves the product, and serves it as virtual:product.",
5
5
  "keywords": [
6
6
  "plugins",
@@ -43,8 +43,8 @@
43
43
  "@stealthscale/testing-config": "^0.6.0",
44
44
  "@stealthscale/vite-config": "^0.8.0",
45
45
  "@stealthscale/vite-config-typescript": "^0.3.0",
46
- "@stealthscale/vite-plugin-base": "^0.4.0",
47
- "@stealthscale/vite-plugin-i18n": "^0.3.1",
46
+ "@stealthscale/vite-plugin-base": "^0.5.1",
47
+ "@stealthscale/vite-plugin-i18n": "^0.4.0",
48
48
  "@types/node": "^26.6",
49
49
  "@vitest/coverage-v8": "5.0.3",
50
50
  "publint": "^0.3",
@@ -54,8 +54,8 @@
54
54
  },
55
55
  "peerDependencies": {
56
56
  "@stealthscale/sdk-core": "^0.3.0",
57
- "@stealthscale/vite-plugin-base": "^0.4.0",
58
- "@stealthscale/vite-plugin-i18n": "^0.3.1",
57
+ "@stealthscale/vite-plugin-base": "^0.5.1",
58
+ "@stealthscale/vite-plugin-i18n": "^0.4.0",
59
59
  "vite": "^8.3"
60
60
  },
61
61
  "engines": {