@stealthscale/vite-config-specimen 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,6 +37,13 @@ The package's example spec renders each `**/*.example.tsx` file without pressing
37
37
  `layers()` excludes those files from coverage too. Their event handlers would otherwise count as
38
38
  uncovered functions.
39
39
 
40
+ `layers()` also publishes the package's catalogue pages through the specimen plugin's `pages()`,
41
+ which it adds to `pack.plugins` with the entries that `pack.published()` states. The declarations
42
+ cover those entries alone, and the export map leaves out the pages directory. The pack writes the
43
+ pages, their props and the pages file into `dist/pages/`, and the specimen plugin's README lists the
44
+ files. A package publishes its `locales` directory beside `dist`, so a product shows the pages'
45
+ words.
46
+
40
47
  ## An application that shows a catalogue
41
48
 
42
49
  Add `specimen.catalogue()` to whichever tier the application already builds on.
@@ -54,12 +61,25 @@ export default defineConfig(import.meta.dirname, {
54
61
  });
55
62
  ```
56
63
 
57
- `patterns` has no default. A pattern resolves against the application root, and an application that
58
- shows a catalogue of a workspace's components sits beside those components rather than above them.
64
+ `patterns` finds the specimens of the workspace's packages and has no default. A pattern resolves
65
+ against the application root, and an application that shows a catalogue of a workspace's components
66
+ is beside those components rather than above them. The index also lists the pages that the installed
67
+ packages publish, so a product in another repository states no patterns.
59
68
 
60
- State `props` to have each page carry what its components accept, resolved out of their types. Left
61
- out, nothing loads a compiler. Every member of `Options` reaches the plugin as written, and the
62
- plugin's README documents what a page then gets.
69
+ ```ts
70
+ export default defineConfig(import.meta.dirname, {
71
+ extends: [react.layers(), i18n.layers(), product.app(), specimen.catalogue()],
72
+ });
73
+ ```
74
+
75
+ Such a product installs `@stealthscale/plugin-catalogue`, the component packages whose pages it
76
+ lists, and each package in the `requires` of their pages files: the specimen kit, `lucide-react`,
77
+ `react-dom` and the component packages that the examples compose.
78
+
79
+ State `props` to have each source page carry what its components accept, resolved out of their
80
+ types. Left out, nothing loads a compiler. An installed page has its published props either way.
81
+ Every member of `Options` reaches the plugin as written, and the plugin's README documents what a
82
+ page then gets.
63
83
 
64
84
  `catalogue()` adds the index plugin, and every specimen as an entry the dependency scan walks before
65
85
  the server starts. A specimen is reached through a dynamic import the scan does not follow, so
@@ -68,6 +88,12 @@ without the entries the first page a reader opens re-optimises and reloads the c
68
88
  Naming the entries stops Vite working the entries out for itself, which is why `**/*.html` is named
69
89
  beside them.
70
90
 
91
+ `catalogue()` also adds `@stealthscale/plugin-catalogue` and the modules under `dist/pages/` to
92
+ `ssr.noExternal`. A spec runner loads an installed package with Node's own loader, which resolves
93
+ neither the catalogue's `virtual:specimen-index` nor an import of a page that its package does not
94
+ declare. Vite copies the setting into the server environment, and the spec runner then loads those
95
+ modules through the application's plugins.
96
+
71
97
  ## The stylesheet a catalogue needs
72
98
 
73
99
  An application drawn on `@stealthscale/theme` states `static: "*"` in its `theme.config.ts`.
@@ -89,6 +115,7 @@ Add `specimen.workspace()` to the root configuration.
89
115
 
90
116
  ```ts
91
117
  import * as specimen from "@stealthscale/vite-config-specimen";
118
+
92
119
  import { defineConfig } from "./packages/vite-config/src/preset/workspace.ts";
93
120
 
94
121
  export default defineConfig(import.meta.dirname, { extends: [specimen.workspace()] });
@@ -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.11"},{"type":"application","name":"vite","version":"8.3.1"},{"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":"testing-config","group":"@stealthscale","version":"0.5.0","bom-ref":"pkg:npm/%40stealthscale/testing-config@0.5.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.5.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":"vite-config-core","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-core@0.3.0","description":"Composes presets, contributions, removals and overrides into one Vite configuration.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-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#packages/vite-config-core","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-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":"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.6.0","bom-ref":"pkg:npm/%40stealthscale/vite-config@0.6.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.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/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-specimen","group":"@stealthscale","version":"0.1.0","bom-ref":"pkg:npm/%40stealthscale/vite-plugin-specimen@0.1.0","description":"Indexes specimen files from their source, so a catalogue lists every page without loading one.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-plugin-specimen@0.1.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-specimen","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-specimen#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.3","bom-ref":"pkg:npm/%40types/node@26.6.3","description":"TypeScript definitions for node","hashes":[{"alg":"SHA-512","content":"76ca8c410a1e4cbaaef70ca70c3d34ab9ef798dceca3721d40e01f1d126a2c27260853e81a8f40d5b0e951cbfff6d9caa44ad05aff6e29e19f977ec4212d3662"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/node@26.6.3","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.1","bom-ref":"pkg:npm/%40vitest/coverage-v8@5.0.1","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"V8 coverage provider for Vitest","hashes":[{"alg":"SHA-512","content":"1510bc0028ae742ddd23a313a65cd14985870d19c8bf620f7dbcece0576824db0c6a5ff7e6c595f21c087d5f1972acd23f2fae5c778c54e36df4212ab4e535ef"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40vitest/coverage-v8@5.0.1","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.0.0","bom-ref":"pkg:npm/%40voidzero-dev/vite-plus-core@1.0.0","author":"VoidZero Inc.","description":"The Unified Toolchain for the Web","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40voidzero-dev/vite-plus-core@1.0.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.1","bom-ref":"pkg:npm/vitest@5.0.1","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"Next generation testing framework powered by Vite","hashes":[{"alg":"SHA-512","content":"880f799506ca124bebb5391d0209d66d77db8a95a28967bf8439763f9b4c8ba585c03efa1b43715c01a9fccf4439c62ea5e18946beb0a6931cec2a00e354d08e"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/vitest@5.0.1","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-config-specimen","group":"@stealthscale","version":"0.1.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-specimen@0.1.0","description":"Configures an application that shows a catalogue, and the workspace root the specimens sit under.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-specimen@0.1.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-specimen","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-specimen#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-config-specimen@0.1.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":"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":"vite-config-core","group":"@stealthscale","version":"0.4.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-core@0.4.0","description":"Composes presets, contributions, removals and overrides into one Vite configuration.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-core@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-config-core","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-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":"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-specimen","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-plugin-specimen@0.3.0","description":"Indexes specimen files from their source, so a catalogue lists every page without loading one.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-plugin-specimen@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-specimen","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-specimen#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-config-specimen","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-specimen@0.3.0","description":"Configures an application that shows a catalogue, and the workspace root the specimens sit under.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-specimen@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-specimen","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-specimen#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-config-specimen@0.3.0"}]}
package/dist/index.d.mts CHANGED
@@ -2,14 +2,15 @@ import { Contribution, Layer } from "@stealthscale/vite-config-core";
2
2
  import { Options } from "@stealthscale/vite-plugin-specimen";
3
3
  //#region src/catalogue.d.ts
4
4
  /**
5
- * Returns the index layer and the crawl layers, in the order they run.
5
+ * Returns the index layer, the crawl layers and the layer that loads the catalogue in a spec, in
6
+ * the order they run.
6
7
  *
7
8
  * @remarks
8
9
  * An array and not a tier, because a catalogue is an ordinary application first: it picks the
9
10
  * tier its framework calls for, and these layers extend it.
10
- * @param stated - Where the specimens are. `Options` documents every member.
11
+ * @param stated - Where the workspace's specimens are. `Options` documents every member.
11
12
  */
12
- export declare function catalogue(stated: Options): readonly Layer[];
13
+ export declare function catalogue(stated?: Options): readonly Layer[];
13
14
  //#endregion
14
15
  //#region src/crawled.d.ts
15
16
  /**
@@ -38,7 +39,8 @@ export declare function indexed(stated: Options): Contribution;
38
39
  //#endregion
39
40
  //#region src/layers.d.ts
40
41
  /**
41
- * Returns the coverage exclusions for the specimen and example files of a package.
42
+ * Returns the coverage exclusions for the specimen and example files of a package, and the layers
43
+ * that publish the package's pages when it is packed.
42
44
  *
43
45
  * @remarks
44
46
  * The function returns a layer list, not a tier, so a component package can add it to whichever
package/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { contribute, located, named } from "@stealthscale/vite-config-core";
1
+ import { appended, contribute, located, named, override, preset } from "@stealthscale/vite-config-core";
2
2
  import { deps, lint, test } from "@stealthscale/vite-config";
3
+ import "vite";
3
4
  //#region src/specimens.ts
4
5
  /**
5
6
  * Names the files every layer of this package treats as specimens, and renames a contribution a
@@ -95,17 +96,52 @@ function indexed(stated) {
95
96
  });
96
97
  }
97
98
  //#endregion
99
+ //#region src/inlined.ts
100
+ /**
101
+ * Loads the catalogue and the published pages through the application's plugins in a spec.
102
+ *
103
+ * @remarks
104
+ * The catalogue's published module imports the index, which only the specimen plugin serves, and
105
+ * a published page imports packages that only the application's root installs. A spec runner
106
+ * loads an installed package with Node's own loader, which resolves neither. Vite copies
107
+ * `ssr.noExternal` into the server environment, and the spec runner then loads the modules that
108
+ * the list matches through the application's plugins.
109
+ */
110
+ /**
111
+ * The package of the catalogue plugin.
112
+ */
113
+ const CATALOGUE = "@stealthscale/plugin-catalogue";
114
+ /**
115
+ * Matches a module of an installed package's published pages.
116
+ */
117
+ const PUBLISHED = /[\\/]dist[\\/]pages[\\/]/u;
118
+ /**
119
+ * Returns the layer that loads the catalogue and the published pages through the application's
120
+ * plugins.
121
+ */
122
+ function inlined() {
123
+ return preset({
124
+ config: { ssr: { noExternal: [CATALOGUE, PUBLISHED] } },
125
+ name: "specimen.inlined"
126
+ });
127
+ }
128
+ //#endregion
98
129
  //#region src/catalogue.ts
99
130
  /**
100
- * Returns the index layer and the crawl layers, in the order they run.
131
+ * Returns the index layer, the crawl layers and the layer that loads the catalogue in a spec, in
132
+ * the order they run.
101
133
  *
102
134
  * @remarks
103
135
  * An array and not a tier, because a catalogue is an ordinary application first: it picks the
104
136
  * tier its framework calls for, and these layers extend it.
105
- * @param stated - Where the specimens are. `Options` documents every member.
137
+ * @param stated - Where the workspace's specimens are. `Options` documents every member.
106
138
  */
107
- function catalogue(stated) {
108
- return [indexed(stated), ...crawled(stated.patterns)];
139
+ function catalogue(stated = {}) {
140
+ return [
141
+ indexed(stated),
142
+ ...crawled(stated.patterns ?? []),
143
+ inlined()
144
+ ];
109
145
  }
110
146
  //#endregion
111
147
  //#region src/examples.ts
@@ -159,6 +195,87 @@ function uncapped(files = EXAMPLES) {
159
195
  }));
160
196
  }
161
197
  //#endregion
198
+ //#region src/published.ts
199
+ /**
200
+ * Matches the name that the packer gives a page's chunk, which it would otherwise publish as a
201
+ * subpath of the package.
202
+ */
203
+ const PAGE_EXPORTS = /^pages\//u;
204
+ /**
205
+ * Returns the packer's configuration where the composed configuration states one object, and
206
+ * undefined otherwise.
207
+ */
208
+ function packOf(composed) {
209
+ const { pack } = composed;
210
+ return pack === void 0 || Array.isArray(pack) ? void 0 : pack;
211
+ }
212
+ /**
213
+ * Returns the packer's entries, keyed by their names, as the composed configuration states them.
214
+ *
215
+ * @remarks
216
+ * `pack.published()` states the entries as an object. Any other form of the setting gives no
217
+ * entries, and the plugin then groups none of the package's modules as an entry's own.
218
+ */
219
+ function entriesOf(pack) {
220
+ const entry = pack?.entry;
221
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return {};
222
+ return Object.fromEntries(Object.entries(entry).filter((pair) => typeof pair[1] === "string"));
223
+ }
224
+ /**
225
+ * Limits the declarations to the package's entries.
226
+ *
227
+ * @remarks
228
+ * The declarations plugin emits a declaration file for every entry of the bundle, and every page
229
+ * is an entry. A page's declarations would bundle the types of the packages that it imports
230
+ * without a declaration, so the plugin is given the package's own entries.
231
+ */
232
+ function declared(composed, pack, entries) {
233
+ if (pack === void 0 || pack.dts === void 0 || pack.dts === false || entries.length === 0) return composed;
234
+ const stated = typeof pack.dts === "object" ? pack.dts : {};
235
+ return {
236
+ ...composed,
237
+ pack: {
238
+ ...pack,
239
+ dts: {
240
+ ...stated,
241
+ entry: [...entries]
242
+ }
243
+ }
244
+ };
245
+ }
246
+ /**
247
+ * Builds the packer's plugin with the package's directory and its entries.
248
+ */
249
+ async function packing(context, entries) {
250
+ return (await loaded()).pages({
251
+ entries,
252
+ root: context.at
253
+ });
254
+ }
255
+ /**
256
+ * Returns the layers that publish a package's catalogue pages with its components.
257
+ *
258
+ * @remarks
259
+ * The plugin is an override because it reads the entries that the composed configuration states.
260
+ * The packer publishes every entry of the bundle as a subpath, and a page's chunk is an entry, so
261
+ * the export map leaves out the pages directory.
262
+ */
263
+ function published() {
264
+ return [override({
265
+ because: "a product in another repository lists a package's pages from what the package publishes, and only the pack can build the pages with the package's own modules",
266
+ name: "specimen.published",
267
+ refine: (context, composed) => {
268
+ const pack = packOf(composed);
269
+ const entries = entriesOf(pack);
270
+ const limited = declared(composed, pack, Object.values(entries));
271
+ return appended(limited, "pack.plugins", packing(context, entries));
272
+ }
273
+ }), preset({
274
+ config: { pack: { exports: { exclude: [PAGE_EXPORTS] } } },
275
+ name: "specimen.published(exports)"
276
+ })];
277
+ }
278
+ //#endregion
162
279
  //#region src/uncounted.ts
163
280
  /**
164
281
  * Stops counting the specimens a package holds towards its coverage.
@@ -181,7 +298,8 @@ function uncounted(files = SPECIMENS) {
181
298
  //#endregion
182
299
  //#region src/layers.ts
183
300
  /**
184
- * Returns the coverage exclusions for the specimen and example files of a package.
301
+ * Returns the coverage exclusions for the specimen and example files of a package, and the layers
302
+ * that publish the package's pages when it is packed.
185
303
  *
186
304
  * @remarks
187
305
  * The function returns a layer list, not a tier, so a component package can add it to whichever
@@ -190,7 +308,11 @@ function uncounted(files = SPECIMENS) {
190
308
  * @param files - Specimen globs. Defaults to every `*.specimen.tsx` file in the package.
191
309
  */
192
310
  function layers(files = SPECIMENS) {
193
- return [...uncounted(files), ...unmeasured()];
311
+ return [
312
+ ...uncounted(files),
313
+ ...unmeasured(),
314
+ ...published()
315
+ ];
194
316
  }
195
317
  //#endregion
196
318
  //#region src/workspace.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stealthscale/vite-config-specimen",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Configures an application that shows a catalogue, and the workspace root the specimens sit under.",
5
5
  "keywords": [
6
6
  "catalogue",
@@ -34,22 +34,22 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@arethetypeswrong/core": "^0.18",
37
- "@stealthscale/testing-config": "^0.5.0",
38
- "@stealthscale/vite-config": "^0.6.0",
39
- "@stealthscale/vite-config-core": "^0.3.0",
37
+ "@stealthscale/testing-config": "^0.6.0",
38
+ "@stealthscale/vite-config": "^0.8.0",
39
+ "@stealthscale/vite-config-core": "^0.4.0",
40
40
  "@stealthscale/vite-config-typescript": "^0.3.0",
41
- "@stealthscale/vite-plugin-specimen": "^0.1.0",
41
+ "@stealthscale/vite-plugin-specimen": "^0.3.0",
42
42
  "@types/node": "^26.6",
43
- "@vitest/coverage-v8": "5.0.1",
43
+ "@vitest/coverage-v8": "5.0.3",
44
44
  "publint": "^0.3",
45
45
  "typescript": "^7.0",
46
- "vite": "npm:@voidzero-dev/vite-plus-core@1.0.0",
47
- "vitest": "5.0.1"
46
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
47
+ "vitest": "5.0.3"
48
48
  },
49
49
  "peerDependencies": {
50
- "@stealthscale/vite-config": "^0.6.0",
51
- "@stealthscale/vite-config-core": "^0.3.0",
52
- "@stealthscale/vite-plugin-specimen": "^0.1.0",
50
+ "@stealthscale/vite-config": "^0.8.0",
51
+ "@stealthscale/vite-config-core": "^0.4.0",
52
+ "@stealthscale/vite-plugin-specimen": "^0.3.0",
53
53
  "vite": "^8.3"
54
54
  },
55
55
  "engines": {