@evertondgn/solid-tooling 0.5.0 → 0.7.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 +543 -598
- package/app-env.d.ts +7 -0
- package/dist/architecture-plugin.mjs +1 -1
- package/dist/backend-plugin.mjs +139 -4
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +42 -0
- package/dist/{constants-Jqvtbvxu.mjs → constants-BZJm7ouk.mjs} +1 -1
- package/dist/css-filename-CEHQd2gz.mjs +40 -0
- package/dist/css-filename.mjs +1 -40
- package/dist/fmt-9dlUYOMk.mjs +34 -0
- package/dist/fmt.mjs +1 -34
- package/dist/i18n-generate.d.mts +1 -0
- package/dist/i18n-generate.mjs +23 -0
- package/dist/i18nPlugin-CS7Gob6R.mjs +109 -0
- package/dist/knip.d.mts +2 -1
- package/dist/knip.mjs +7 -2
- package/dist/{lint-UTfyg7AR.mjs → lint-ehdtTKfw.mjs} +33 -86
- package/dist/lint.mjs +1 -1
- package/dist/playwright-teardown.mjs +1 -1
- package/dist/playwright.d.mts +2 -1
- package/dist/playwright.mjs +4 -3
- package/dist/prepareMessages-BXmY6Ko2.mjs +222 -0
- package/dist/project-plugin.mjs +2 -2
- package/dist/protocol-DSNNUYja.mjs +18 -0
- package/dist/publication/read-llms-index.d.mts +12 -0
- package/dist/publication/read-llms-index.mjs +1 -0
- package/dist/publication-CRUTOB0B.mjs +885 -0
- package/dist/readLlmsIndex-Gj4iTxAk.mjs +27 -0
- package/dist/stylelint.mjs +2 -2
- package/dist/test-locale--tuH0Np5.mjs +3 -0
- package/dist/types-DHu2Z_ot.d.mts +49 -0
- package/dist/vite.d.mts +33 -7
- package/dist/vite.mjs +449 -88
- package/dist/vitest-BjLr7iLf.mjs +362 -0
- package/dist/vitest.d.mts +3 -7
- package/dist/vitest.mjs +1 -129
- package/lefthook.yml +3 -1
- package/node-env.d.ts +1 -0
- package/package.json +32 -39
- package/tsconfig.app.json +4 -9
- package/virtual-modules.d.ts +90 -0
package/README.md
CHANGED
|
@@ -1,74 +1,71 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Stylelint configs, the Vite+ application config, the commitlint config and the
|
|
5
|
-
Git hooks for SolidJS 2 applications built with
|
|
6
|
-
[Vite+](https://viteplus.dev/guide/).
|
|
7
|
-
|
|
8
|
-
The package contains the lint, format, TypeScript, test, build, dead code, CSS
|
|
9
|
-
lint, commit message and Git hook setup of
|
|
10
|
-
[boilerplate_solidjs](https://github.com/everton-dgn/boilerplate_solidjs), a
|
|
11
|
-
SolidJS application template. Applications created from it install the package
|
|
12
|
-
instead of copying the files, so a rule change reaches them through a version
|
|
13
|
-
update.
|
|
14
|
-
|
|
15
|
-
## Requirements
|
|
16
|
-
|
|
17
|
-
The application installs three packages next to this one:
|
|
18
|
-
|
|
19
|
-
| Package | Why |
|
|
20
|
-
| ---------------------- | ----------------------------------------------------------- |
|
|
21
|
-
| `vite-plus` | Runs lint and format, and provides the Oxlint plugin API |
|
|
22
|
-
| `@inlang/paraglide-js` | The preset registers its lint plugin, resolved from the app |
|
|
23
|
-
| `typescript` | The preset turns on type-aware linting and type checking |
|
|
1
|
+
[](https://www.npmjs.com/package/@evertondgn/solid-tooling)
|
|
2
|
+
[](https://github.com/everton-dgn/solidjs_base/actions/workflows/ci.yml)
|
|
3
|
+
[](https://github.com/everton-dgn/solidjs_base/blob/main/LICENSE)
|
|
24
4
|
|
|
25
|
-
|
|
26
|
-
exact versions the package is tested with. Install the versions listed in its
|
|
27
|
-
`peerDependencies`. `typescript` is not a peer dependency: the package is tested
|
|
28
|
-
with the version in its `devDependencies`.
|
|
29
|
-
|
|
30
|
-
`eslint-plugin-solid`, `stylelint` and `stylelint-use-nesting` come with the
|
|
31
|
-
package, so the application does not declare them.
|
|
32
|
-
|
|
33
|
-
Some entries need tools the application already runs:
|
|
5
|
+
# @evertondgn/solid-tooling
|
|
34
6
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
| `./commitlint` | `@commitlint/cli`, an optional peer dependency pinned the same way |
|
|
41
|
-
| `./lefthook.yml` | `lefthook`, an optional peer dependency pinned the same way |
|
|
7
|
+
<picture>
|
|
8
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/hero-dark.webp" />
|
|
9
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/hero-light.webp" />
|
|
10
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/hero-light.webp" alt="Solid Base for SolidJS 2 RC and Vite+. Build your Solid app. Stop rebuilding its foundation. Shared tooling and runtime beneath the SolidJS mark: languages, theme, server protection, SEO, assets and development tools. Install solid-tooling for development and solid-runtime for application features." width="800" />
|
|
11
|
+
</picture>
|
|
42
12
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
`unplugin-icons`. They are optional peer dependencies pinned like the others.
|
|
46
|
-
Install the versions listed in `peerDependencies` as direct dependencies of the
|
|
47
|
-
application: Bun applies `overrides` and `patchedDependencies` only from the
|
|
48
|
-
root `package.json`, and the Knip plugin of `unplugin-icons` only turns on with
|
|
49
|
-
a direct dependency.
|
|
13
|
+
**The lint rules, tests, Git hooks and whole Vite+ config of your SolidJS 2
|
|
14
|
+
apps, as one dev dependency.**
|
|
50
15
|
|
|
51
|
-
|
|
16
|
+
Applications copied from a starter carry its tooling with them, and every fix to
|
|
17
|
+
the base has to be repeated by hand in each copy. This package holds that
|
|
18
|
+
tooling: an Oxlint preset with rules for your project layout, Oxfmt, TypeScript
|
|
19
|
+
configs, three Vitest projects, Playwright, Knip, a Stylelint policy,
|
|
20
|
+
commitlint, Git hooks and `defineSolidApp`, which returns the whole
|
|
21
|
+
`vite.config.ts` of a [Vite+](https://viteplus.dev/guide/) application. The fix
|
|
22
|
+
arrives when you update the dependency.
|
|
52
23
|
|
|
53
|
-
|
|
54
|
-
|
|
24
|
+
> SolidJS 2 is still a release candidate. The package is tested with
|
|
25
|
+
> `2.0.0-rc.21`, and its Solid, Nitro, router and icon plugins are pinned to the
|
|
26
|
+
> versions tested together. A new version of one of them needs a package version
|
|
27
|
+
> tested with it.
|
|
55
28
|
|
|
56
29
|
```bash
|
|
57
30
|
vp add -D @evertondgn/solid-tooling
|
|
58
31
|
```
|
|
59
32
|
|
|
60
|
-
|
|
61
|
-
|
|
33
|
+
Built for applications that follow the
|
|
34
|
+
[boilerplate_solidjs](https://github.com/everton-dgn/boilerplate_solidjs)
|
|
35
|
+
layout. Start with lint and formatting in your existing Vite+ config, and adopt
|
|
36
|
+
the full application config when you are ready.
|
|
37
|
+
|
|
38
|
+
| Package | Role |
|
|
39
|
+
| --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
40
|
+
| [`@evertondgn/solid-tooling`](https://github.com/everton-dgn/solidjs_base/blob/main/packages/solid-tooling/README.md) | Config, lint rules, tests, Git hooks, catalog generation, icons and fonts |
|
|
41
|
+
| [`@evertondgn/solid-runtime`](https://github.com/everton-dgn/solidjs_base/blob/main/packages/solid-runtime/README.md) | Security headers, server errors, locale, theme, SEO, sitemaps, Markdown, env and fonts |
|
|
42
|
+
|
|
43
|
+
[Quick start](#quick-start) ·
|
|
44
|
+
[Less config](#the-configuration-you-stop-maintaining) ·
|
|
45
|
+
[Fewer dependencies](#fewer-tool-versions-in-each-manifest) ·
|
|
46
|
+
[App config](#your-application-config-in-one-call) ·
|
|
47
|
+
[Lint](#lint-rules-that-know-your-project) ·
|
|
48
|
+
[Tests](#tests-in-the-environment-each-one-needs) ·
|
|
49
|
+
[E2E](#end-to-end-tests-against-a-real-build) ·
|
|
50
|
+
[Knip](#unused-files-exports-and-dependencies) ·
|
|
51
|
+
[CSS](#a-css-policy-built-on-tokens) · [Hooks](#commit-messages-and-git-hooks) ·
|
|
52
|
+
[Entry points](#entry-points)
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
npm view @evertondgn/solid-tooling peerDependencies
|
|
65
|
-
vp add -D @inlang/paraglide-js@<version>
|
|
66
|
-
```
|
|
54
|
+
## Requirements
|
|
67
55
|
|
|
68
|
-
|
|
56
|
+
Install the exact Vite+ version listed in the package's `peerDependencies`. The
|
|
57
|
+
package supplies its build, test, type-check and hook tools. Applications keep
|
|
58
|
+
their own direct imports and the Vite+ overrides; see the
|
|
59
|
+
[dependency requirements](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/limits.md#requirements).
|
|
60
|
+
An application with translations also installs the required version of
|
|
61
|
+
`@inlang/paraglide-js` and its message-format plugin.
|
|
62
|
+
|
|
63
|
+
## Quick start
|
|
64
|
+
|
|
65
|
+
Add `fmt` and `lint` to your existing Vite+ config. The example shows only those
|
|
66
|
+
settings; keep your plugins and other options:
|
|
69
67
|
|
|
70
68
|
```ts
|
|
71
|
-
// vite.config.ts
|
|
72
69
|
import { fmt } from '@evertondgn/solid-tooling/fmt'
|
|
73
70
|
import { lint } from '@evertondgn/solid-tooling/lint'
|
|
74
71
|
import { defineConfig } from 'vite-plus'
|
|
@@ -76,8 +73,9 @@ import { defineConfig } from 'vite-plus'
|
|
|
76
73
|
export default defineConfig({ fmt, lint })
|
|
77
74
|
```
|
|
78
75
|
|
|
76
|
+
In `tsconfig.json`:
|
|
77
|
+
|
|
79
78
|
```json
|
|
80
|
-
// tsconfig.json
|
|
81
79
|
{
|
|
82
80
|
"extends": "@evertondgn/solid-tooling/tsconfig.base.json",
|
|
83
81
|
"compilerOptions": {
|
|
@@ -87,83 +85,112 @@ export default defineConfig({ fmt, lint })
|
|
|
87
85
|
}
|
|
88
86
|
```
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
## Tests
|
|
88
|
+
Check your code and format your files:
|
|
93
89
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
| Project | Files | Environment |
|
|
98
|
-
| --------- | -------------------------------- | ------------------------------------------------ |
|
|
99
|
-
| `node` | `src/**/*.node.test.{ts,tsx}` | Node, with stand-ins for the build-only modules |
|
|
100
|
-
| `dom` | `src/**/*.dom.test.{ts,tsx}` | happy-dom at `http://localhost/en` |
|
|
101
|
-
| `browser` | `src/**/*.browser.test.{ts,tsx}` | Chromium through Playwright, with the CSS loaded |
|
|
102
|
-
|
|
103
|
-
`defineSolidApp` from `./vite` already calls `solidTest`. An application that
|
|
104
|
-
builds its own Vite config calls it directly:
|
|
105
|
-
|
|
106
|
-
```ts
|
|
107
|
-
// vite.config.ts
|
|
108
|
-
import { solidTest } from '@evertondgn/solid-tooling/vitest'
|
|
109
|
-
import solid from '@solidjs/vite-plugin'
|
|
110
|
-
import { defineConfig } from 'vite-plus'
|
|
111
|
-
|
|
112
|
-
export default defineConfig({
|
|
113
|
-
test: solidTest({
|
|
114
|
-
root: import.meta.dirname,
|
|
115
|
-
plugins: () => [solid({ serverFunctions: true })]
|
|
116
|
-
})
|
|
117
|
-
})
|
|
90
|
+
```bash
|
|
91
|
+
vp check
|
|
92
|
+
vp fmt
|
|
118
93
|
```
|
|
119
94
|
|
|
120
|
-
|
|
121
|
-
projects need to compile components: Solid, routes, icons and i18n. The preset
|
|
122
|
-
calls it once per project, because each project starts its own Vite server and a
|
|
123
|
-
plugin instance keeps the state of one server. The preset also sets the coverage
|
|
124
|
-
thresholds, the reporters and the workers on CI, passes `BASE_URL_TEST`, `HOST`
|
|
125
|
-
and `PORT` to the tests when they are set, and resets the Paraglide locale
|
|
126
|
-
before each browser test.
|
|
127
|
-
|
|
128
|
-
The `node` project does not load the Solid and routing plugins, so a plugin of
|
|
129
|
-
the preset serves `server-only`, `virtual:file-routes` and
|
|
130
|
-
`virtual:solid-server-function-handler`. Knip does not know `server-only`, a
|
|
131
|
-
virtual module of `@solidjs/vite-plugin`: pass it in the `ignoreDependencies` of
|
|
132
|
-
[`defineKnipConfig`](#knip).
|
|
133
|
-
|
|
134
|
-
`definePlaywrightConfig` builds the Playwright config from the application root:
|
|
95
|
+
To see a rule of the package fire, create `src/helpers/export-list.ts`:
|
|
135
96
|
|
|
136
97
|
```ts
|
|
137
|
-
|
|
138
|
-
import { definePlaywrightConfig } from '@evertondgn/solid-tooling/playwright'
|
|
98
|
+
const example = 1
|
|
139
99
|
|
|
140
|
-
export
|
|
100
|
+
export { example }
|
|
141
101
|
```
|
|
142
102
|
|
|
143
|
-
|
|
144
|
-
for the fixture routes, `production` with `TEST_PRODUCTION_ROUTES=true`), starts
|
|
145
|
-
the preview, and checks the server log for private markers when the suite ends.
|
|
146
|
-
`TEST_PREBUILT=true` reuses an existing production build.
|
|
147
|
-
|
|
148
|
-
| Option | Default | Use |
|
|
149
|
-
| ---------------- | ----------------- | ---------------------------------------------------------------------- |
|
|
150
|
-
| `testDir` | `src/tests/pages` | Folder of the `*.e2e.test.ts` files |
|
|
151
|
-
| `fixtureServers` | none | Extra servers for the fixture routes, as `{ command, url }` |
|
|
152
|
-
| `suites` | none | Globs of serial suites: `serverLogs`, `markdown` and `publicationLoad` |
|
|
153
|
-
|
|
154
|
-
Each serial suite gets its own project: `markdown` runs with one worker,
|
|
155
|
-
`serverLogs` runs last as the teardown of the others, and `publicationLoad` runs
|
|
156
|
-
alone, against two servers, with `TEST_PUBLICATION_LOAD=true`.
|
|
103
|
+
Run `vp lint`. The preset reports the export list:
|
|
157
104
|
|
|
158
|
-
|
|
105
|
+
```text
|
|
106
|
+
src/helpers/export-list.ts:3:1: error project(no-export-list): Export on the declaration itself (export function, export const, export type) instead of using export { ... }. An export list is only allowed in a re-export with from.
|
|
107
|
+
```
|
|
159
108
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
109
|
+
<picture>
|
|
110
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/first-result-dark.webp" />
|
|
111
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/first-result-light.webp" />
|
|
112
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/first-result-light.webp" alt="The example ends with export { example } at line 3. vp lint reports project(no-export-list) at line 3, column 1 and asks for an export on the declaration. The corrected export const example = 1 passes that rule." width="800" />
|
|
113
|
+
</picture>
|
|
114
|
+
|
|
115
|
+
Replace the list with `export const example = 1` and the rule passes. `fmt` sets
|
|
116
|
+
80 columns, single quotes, no semicolons, no trailing commas, wrapped Markdown
|
|
117
|
+
prose and sorted imports. See the
|
|
118
|
+
[formatter](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/typescript-and-format.md#formatter)
|
|
119
|
+
and the
|
|
120
|
+
[TypeScript configs](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/typescript-and-format.md#typescript-base).
|
|
121
|
+
|
|
122
|
+
## The configuration you stop maintaining
|
|
123
|
+
|
|
124
|
+
<picture>
|
|
125
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/before-after-dark.webp" />
|
|
126
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/before-after-light.webp" />
|
|
127
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/before-after-light.webp" alt="About 87 percent fewer lines across five configuration areas, from 945 to 125: Vite 427 to 48, Playwright 173 to 17, Knip 129 to 40, TypeScript 45 to 9, and Stylelint 171 to an 11-line script. Each bar shows the fraction retained in the app." width="800" />
|
|
128
|
+
</picture>
|
|
129
|
+
|
|
130
|
+
The original starter kept 945 lines of configuration in five areas. The same
|
|
131
|
+
application on this package keeps 125, about 87% fewer. The shared
|
|
132
|
+
implementation lives in the package, where one fix serves every application.
|
|
133
|
+
|
|
134
|
+
| Configuration | Original lines | With the package |
|
|
135
|
+
| --------------------------------------------------------------------------------------------------------------- | -------------: | ---------------: |
|
|
136
|
+
| [Vite](https://github.com/everton-dgn/solidjs_base/blob/main/apps/boilerplate/vite.config.ts) | 427 | 48 |
|
|
137
|
+
| [Playwright](https://github.com/everton-dgn/solidjs_base/blob/main/apps/boilerplate/playwright.config.ts) | 173 | 17 |
|
|
138
|
+
| [Knip](https://github.com/everton-dgn/solidjs_base/blob/main/apps/boilerplate/tooling/knip.ts) | 129 | 40 |
|
|
139
|
+
| [TypeScript](https://github.com/everton-dgn/solidjs_base/blob/main/apps/boilerplate/tsconfig.json) | 45 | 9 |
|
|
140
|
+
| [Stylelint caller](https://github.com/everton-dgn/solidjs_base/blob/main/apps/boilerplate/tooling/css/check.ts) | 171 | 11 |
|
|
141
|
+
|
|
142
|
+
Counts include blank lines and comments. The baseline is the
|
|
143
|
+
[original starter at 6145493](https://github.com/everton-dgn/boilerplate_solidjs/tree/61454937472d0faa1b4fab985fd7c5da968aa9a6),
|
|
144
|
+
whose Playwright and Stylelint configs lived in `tooling/playwright.ts` and
|
|
145
|
+
`tooling/css/stylelint.config.mjs`. Compare its
|
|
146
|
+
[`vite.config.ts`](https://github.com/everton-dgn/boilerplate_solidjs/blob/61454937472d0faa1b4fab985fd7c5da968aa9a6/vite.config.ts)
|
|
147
|
+
with the application's. The Stylelint replacement is an application script that
|
|
148
|
+
calls the packaged policy.
|
|
149
|
+
|
|
150
|
+
<picture>
|
|
151
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/fix-once-dark.webp" />
|
|
152
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/fix-once-light.webp" />
|
|
153
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/fix-once-light.webp" alt="Copied tooling and runtime drift between applications A, B and C. With Solid Base, the apps keep thin configs and consume solid-tooling and solid-runtime. Shared fixes arrive through vp update; application-specific code stays with each app." width="800" />
|
|
154
|
+
</picture>
|
|
155
|
+
|
|
156
|
+
## Fewer tool versions in each manifest
|
|
157
|
+
|
|
158
|
+
<picture>
|
|
159
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/libraries-dark.webp" />
|
|
160
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/libraries-light.webp" />
|
|
161
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/libraries-light.webp" alt="Direct manifest declarations before and after: boilerplate 28 to 14, client-only 16 to 5, SSR plain 17 to 5, SSR i18n 19 to 7, lint consumer 6 to 3." width="800" />
|
|
162
|
+
</picture>
|
|
163
|
+
|
|
164
|
+
The package installs the build, test, type-check and hook tools it calls, at the
|
|
165
|
+
versions it tests, and runs them from its own installation, including with Bun's
|
|
166
|
+
isolated linker. Your manifest keeps only what your own code imports, plus Vite+
|
|
167
|
+
and its Vite alias.
|
|
168
|
+
|
|
169
|
+
| Application | Direct declarations before | Now | Fewer |
|
|
170
|
+
| ----------------------------------------------------------------------------------------------------------- | -------------------------: | --: | ----: |
|
|
171
|
+
| [Boilerplate copy](https://github.com/everton-dgn/solidjs_base/blob/main/apps/boilerplate/package.json) | 28 | 14 | 14 |
|
|
172
|
+
| [Client-only](https://github.com/everton-dgn/solidjs_base/blob/main/fixtures/apps/client-only/package.json) | 16 | 5 | 11 |
|
|
173
|
+
| [SSR plain](https://github.com/everton-dgn/solidjs_base/blob/main/fixtures/apps/ssr-plain/package.json) | 17 | 5 | 12 |
|
|
174
|
+
| [SSR i18n](https://github.com/everton-dgn/solidjs_base/blob/main/fixtures/apps/ssr-i18n/package.json) | 19 | 7 | 12 |
|
|
175
|
+
| [Lint consumer](https://github.com/everton-dgn/solidjs_base/blob/main/fixtures/consumer/package.json) | 6 | 3 | 3 |
|
|
176
|
+
|
|
177
|
+
Counts combine `dependencies` and `devDependencies`, without overrides or
|
|
178
|
+
transitive packages. The fixture counts leave out the two package tarballs that
|
|
179
|
+
the installed test harness adds.
|
|
180
|
+
|
|
181
|
+
Fewer declarations do not mean a smaller install. The tooling also installs the
|
|
182
|
+
tools of features you may not use: in the
|
|
183
|
+
[measurement of that decision](https://github.com/everton-dgn/solidjs_base/blob/main/docs/ADRs/0027-packaged-tool-dependencies.md),
|
|
184
|
+
the `node_modules` of a fresh client-only application grew by 8.41% with the
|
|
185
|
+
hoisted linker and 8.69% with the isolated one. Build audits check that these
|
|
186
|
+
tools stay out of the application bundles.
|
|
187
|
+
|
|
188
|
+
## Your application config in one call
|
|
189
|
+
|
|
190
|
+
With the application dependencies installed, `defineSolidApp()` supplies the
|
|
191
|
+
plugins, build settings, tasks, lint, format and three Vitest projects:
|
|
164
192
|
|
|
165
193
|
```ts
|
|
166
|
-
// vite.config.ts
|
|
167
194
|
import { defineSolidApp } from '@evertondgn/solid-tooling/vite'
|
|
168
195
|
|
|
169
196
|
import { SECURITY_HEADERS } from './src/middleware/securityHeaders/constants.ts'
|
|
@@ -171,130 +198,160 @@ import { SECURITY_HEADERS } from './src/middleware/securityHeaders/constants.ts'
|
|
|
171
198
|
export default defineSolidApp({
|
|
172
199
|
root: import.meta.dirname,
|
|
173
200
|
middleware: './src/middleware/index.ts',
|
|
174
|
-
securityHeaders: SECURITY_HEADERS
|
|
175
|
-
staticPaths: ['/favicon/**']
|
|
201
|
+
securityHeaders: SECURITY_HEADERS
|
|
176
202
|
})
|
|
177
203
|
```
|
|
178
204
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
`
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
`
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
`inputs` from the workspace root, and `lint-css`, `dead-code-project` and
|
|
268
|
-
`typecheck-node` depend on the tasks in `dependsOn`:
|
|
269
|
-
|
|
270
|
-
```ts
|
|
271
|
-
workspace: {
|
|
272
|
-
dependsOn: ['@evertondgn/solid-tooling#build'],
|
|
273
|
-
inputs: ['packages/solid-tooling/dist/**']
|
|
274
|
-
}
|
|
275
|
-
```
|
|
205
|
+
That call registers the Solid plugin with SSR and server functions, file-system
|
|
206
|
+
routing with route types, icons, Nitro with the Vercel preset, the headers of
|
|
207
|
+
the static files, Lightning CSS with content-hashed CSS Modules class names, and
|
|
208
|
+
the dev server and preview on the `HOST` and `PORT` of `.env`. You keep your
|
|
209
|
+
middleware and header values. The plugins are package dependencies pinned to the
|
|
210
|
+
tested versions.
|
|
211
|
+
|
|
212
|
+
<picture>
|
|
213
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/only-what-you-use-dark.webp" />
|
|
214
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/only-what-you-use-light.webp" />
|
|
215
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/only-what-you-use-light.webp" alt="A client-only vite.config.ts with defineSolidApp, root and ssr: false. No translation project, theme imports, env.ts, fonts option or SEO are needed, and the build has client output only, with no Nitro or server bundle." width="800" />
|
|
216
|
+
</picture>
|
|
217
|
+
|
|
218
|
+
Each feature turns on only when the application uses it:
|
|
219
|
+
|
|
220
|
+
| Feature | Selection |
|
|
221
|
+
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
222
|
+
| Client-only build | Set `ssr: false` and omit SSR options such as `middleware` and `securityHeaders`; the build has no Nitro or server bundle and accepts a relative `./` base |
|
|
223
|
+
| Publication headers | Set `seo.markdown`, `seo.llms` and `seo.sitemap` one by one; `seo.llmsFull` also needs `seo.llms` and `seo.markdown.static` |
|
|
224
|
+
| Translations | `project.inlang/settings.json` enables the generation task and browser test setup; the lint plugin loads only where Paraglide resolves |
|
|
225
|
+
|
|
226
|
+
When the standard does not fit, change it without a fork: `extend` adds plugins
|
|
227
|
+
and Nitro modules, `tasks` adds or replaces a `vp run` task, `routeRules`,
|
|
228
|
+
`publicAssets` and `staticPaths` adjust Nitro and the static headers,
|
|
229
|
+
`workspace` places the app in a monorepo, and `mergeConfig` merges anything else
|
|
230
|
+
over the result.
|
|
231
|
+
|
|
232
|
+
The preset also defines the `vp run` tasks of the boilerplate layout:
|
|
233
|
+
`i18n-generate`, `lint-css`, `dead-code-project`, `lint-project`,
|
|
234
|
+
`check-project`, `typecheck-node` and `test-tooling`. The `knip`, `tsc`,
|
|
235
|
+
`playwright`, `lefthook` and `commitlint` tasks run the package-owned binaries,
|
|
236
|
+
including with an isolated installation. See
|
|
237
|
+
[all options and extension points](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/app-config.md)
|
|
238
|
+
and the
|
|
239
|
+
[known limits](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/limits.md#known-limits).
|
|
240
|
+
|
|
241
|
+
## Lint rules that know your project
|
|
242
|
+
|
|
243
|
+
The preset turns on the Oxlint plugins `import`, `jsx-a11y`, `node`, `oxc`,
|
|
244
|
+
`promise`, `typescript`, `unicorn` and `vitest`, the `solid` and `vite-plus`
|
|
245
|
+
plugins and three plugins of this package, plus `paraglide` when it resolves.
|
|
246
|
+
Type-aware rules and type checking are on. Warnings fail the run, and an unused
|
|
247
|
+
disable directive is an error. Every rule is listed by name, so an Oxlint update
|
|
248
|
+
does not add rules on its own.
|
|
249
|
+
|
|
250
|
+
The rules of this package catch what a generic preset cannot see:
|
|
251
|
+
|
|
252
|
+
| Rule | What it enforces |
|
|
253
|
+
| ---------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
254
|
+
| `project/css-modules-import` | A CSS Module is imported as the default binding `S` |
|
|
255
|
+
| `project/css-filename` | A CSS file is named `styles.module.css`, or `camelCase.css` inside `src/theme/` |
|
|
256
|
+
| `project/test-filename` | A test sits in `__tests__` next to its module, named after it and its environment |
|
|
257
|
+
| `project/no-export-list` | Exports sit on the declaration |
|
|
258
|
+
| `project/seo-module` | A route `seo.ts` exports only `seo` and imports no route values |
|
|
259
|
+
| `architecture/layer-imports` | Lower layers do not import upper ones, and production code does not import tests or `tooling/` |
|
|
260
|
+
| `backend/*` | No `console`, `fetch` only in `requestJson`, no Node transports, no `node_modules` paths in imports |
|
|
261
|
+
|
|
262
|
+
<picture>
|
|
263
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/layers-dark.webp" />
|
|
264
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/layers-light.webp" />
|
|
265
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/layers-light.webp" alt="architecture/layer-imports: imports only point down, from routes and entry files through organisms, molecules, atoms and primitives to the base layer. Below, vp lint on a copy of the boilerplate where the PageBadge atom imports a molecule: src/components/atoms/PageBadge/index.tsx:3:1: error architecture(layer-imports): Layer atoms must not depend on molecules (src/components/molecules/PageHero/index.tsx). See the layer rules in docs/architecture.md. Production code cannot import tests or tooling/ either." width="800" />
|
|
266
|
+
</picture>
|
|
267
|
+
|
|
268
|
+
The layer rule keeps the dependency direction of the UI. The base layer
|
|
269
|
+
(`@types`, `constants`, `helpers`, `data`, `infra`, `theme`, `i18n` and
|
|
270
|
+
`paraglide/`) imports no primitives, components, routes or entry files.
|
|
271
|
+
Primitives import no components or routes. Atoms do not import molecules or
|
|
272
|
+
organisms, and molecules do not import organisms. An import in the wrong
|
|
273
|
+
direction fails `vp lint` before review.
|
|
274
|
+
|
|
275
|
+
The backend rules keep outgoing requests in one module. Inside `src/`, `fetch`,
|
|
276
|
+
`XMLHttpRequest`, `WebSocket` and `EventSource` are refused outside
|
|
277
|
+
`src/infra/server/requestJson/index.ts`, `console` is refused, and the server
|
|
278
|
+
error configurator can only be imported in its setup file. See
|
|
279
|
+
[all rules and customization](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/lint.md).
|
|
280
|
+
|
|
281
|
+
## Tests in the environment each one needs
|
|
282
|
+
|
|
283
|
+
<picture>
|
|
284
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/vitest-projects-dark.webp" />
|
|
285
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/vitest-projects-light.webp" />
|
|
286
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/vitest-projects-light.webp" alt="The three Vitest projects of solidTest with their file globs and environments. In apps/boilerplate, 185 tests passed: 68 node tests in 12 files, 87 dom tests with happy-dom in 13 files and 30 browser tests with Chromium in 7 files. Coverage thresholds: 80% for lines, functions and statements, 75% for branches." width="800" />
|
|
287
|
+
</picture>
|
|
288
|
+
|
|
289
|
+
The file name picks the environment, so a server test, a component test and a
|
|
290
|
+
real-browser test live in the same repository with no extra config. In the
|
|
291
|
+
boilerplate, `vp test run` passed 185 tests in 32 files: 68 `node` tests in 12
|
|
292
|
+
files, 87 `dom` in 13 and 30 `browser` in 7.
|
|
276
293
|
|
|
277
|
-
|
|
294
|
+
| Project | Files | Environment |
|
|
295
|
+
| --------- | -------------------------------- | ------------------------------------------------ |
|
|
296
|
+
| `node` | `src/**/*.node.test.{ts,tsx}` | Node, with stand-ins for the build-only modules |
|
|
297
|
+
| `dom` | `src/**/*.dom.test.{ts,tsx}` | happy-dom, at the URL of `domUrl` |
|
|
298
|
+
| `browser` | `src/**/*.browser.test.{ts,tsx}` | Chromium through Playwright, with the CSS loaded |
|
|
278
299
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
300
|
+
The preset sets coverage thresholds of 80% for lines, functions and statements
|
|
301
|
+
and 75% for branches, the reporters and the CI workers. It resets the Paraglide
|
|
302
|
+
locale before each browser test and resolves packages that ship TypeScript
|
|
303
|
+
source, such as the runtime, under the `solid` condition. `defineSolidApp`
|
|
304
|
+
already calls `solidTest`; an application with its own Vite config imports it
|
|
305
|
+
from `./vitest`. See
|
|
306
|
+
[Vitest and Playwright](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/testing.md).
|
|
307
|
+
|
|
308
|
+
## End-to-end tests against a real build
|
|
309
|
+
|
|
310
|
+
<picture>
|
|
311
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/e2e-coverage-dark.webp" />
|
|
312
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/e2e-coverage-light.webp" />
|
|
313
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/e2e-coverage-light.webp" alt="The Playwright inventory of apps/boilerplate: 319 E2E cases across 15 areas, 164 in the E2E build and 155 in the production build. AgentReadiness 77, I18n 40, Home 36, SeoIndexes 29, Markdown 27, BackendError 25, BuildOutput 22, OutsideError 18, Hydration 18, UiKit 8, OutdatedPage 7, StructuredData 6, FragmentCss 2, LateRedirect 2 and NotFound 2. Enumerated with playwright test --list, without running them." width="800" />
|
|
314
|
+
</picture>
|
|
315
|
+
|
|
316
|
+
`definePlaywrightConfig` reads `BASE_URL_TEST` from `.env.test`, builds the
|
|
317
|
+
application, starts the preview and runs the suite against it: `e2e` mode for
|
|
318
|
+
the fixture routes, or the production build with `TEST_PRODUCTION_ROUTES=true`.
|
|
319
|
+
`TEST_PREBUILT=true` reuses an existing production build. Serial suites run in
|
|
320
|
+
their own projects: `markdown` with one worker, `publicationLoad` alone against
|
|
321
|
+
two servers, and `serverLogs` last, as the teardown of the others.
|
|
322
|
+
|
|
323
|
+
When the suite ends, `./playwright-teardown` checks the server log for private
|
|
324
|
+
markers, so a test run also fails when a server error leaks its details into the
|
|
325
|
+
log.
|
|
326
|
+
|
|
327
|
+
In the boilerplate, `vp run playwright test --list` counts 319 cases in 15 page
|
|
328
|
+
areas, 164 in 26 files for the E2E build and 155 in 12 files for the production
|
|
329
|
+
build; the figure above breaks them down by area.
|
|
282
330
|
|
|
283
331
|
```ts
|
|
284
|
-
|
|
285
|
-
import {
|
|
286
|
-
|
|
287
|
-
const app = defineSolidApp({ root: import.meta.dirname, securityHeaders })
|
|
332
|
+
// playwright.config.ts
|
|
333
|
+
import { definePlaywrightConfig } from '@evertondgn/solid-tooling/playwright'
|
|
288
334
|
|
|
289
|
-
export default
|
|
290
|
-
mergeConfig(app(env), { server: { strictPort: true } })
|
|
291
|
-
)
|
|
335
|
+
export default definePlaywrightConfig({ root: import.meta.dirname })
|
|
292
336
|
```
|
|
293
337
|
|
|
294
|
-
##
|
|
338
|
+
## Unused files, exports and dependencies
|
|
339
|
+
|
|
340
|
+
<picture>
|
|
341
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/dead-code-dark.webp" />
|
|
342
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/dead-code-light.webp" />
|
|
343
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/dead-code-light.webp" alt="Knip output on a copy of the boilerplate with an unused file, dependency and export added. Unused files (1): src/helpers/formatPrice/index.ts. Unused dependencies (1): date-fns at package.json:45:6. Unused exports (1): THEME_COOKIE_NAME at src/constants/theme.ts:6:14. The first pass fails, so vp run dead-code-project stops before the --strict pass." width="800" />
|
|
344
|
+
</picture>
|
|
295
345
|
|
|
296
|
-
|
|
297
|
-
|
|
346
|
+
A helper nobody calls, an export nobody imports and a dependency nobody uses
|
|
347
|
+
stop the push, and the report says where each one is. `defineKnipConfig` from
|
|
348
|
+
`./knip` gives Knip the entries of a Solid app: the server and client entries,
|
|
349
|
+
the middleware, `env.ts`, the Paraglide runtime, and every page and HTTP handler
|
|
350
|
+
that file-system routing finds. It turns off Knip's own routing plugin, which
|
|
351
|
+
takes every file of `src/routes/` as an entry, so an unused helper next to a
|
|
352
|
+
route is reported. Configuration hints are errors, and
|
|
353
|
+
`vp run dead-code-project` runs Knip twice, the second time with `--strict`. The
|
|
354
|
+
`pre-push` hook below runs it before the code leaves your machine.
|
|
298
355
|
|
|
299
356
|
```ts
|
|
300
357
|
// tooling/knip.ts
|
|
@@ -308,124 +365,50 @@ export default defineKnipConfig({
|
|
|
308
365
|
})
|
|
309
366
|
```
|
|
310
367
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
| Option | Default | Use |
|
|
334
|
-
| -------------------- | ----------------- | -------------------------------------------------------------- |
|
|
335
|
-
| `root` | required | The application folder |
|
|
336
|
-
| `configFile` | `tooling/knip.ts` | Path of the config file, relative to `root` |
|
|
337
|
-
| `entry` | none | More entries, such as a public API that only test fixtures use |
|
|
338
|
-
| `solidPluginImport` | `'lazy'` | `'static'` when `vite.config.ts` imports `solid()` statically |
|
|
339
|
-
| `ignoreBinaries` | none | Passed to Knip as is |
|
|
340
|
-
| `ignoreDependencies` | none | Passed to Knip as is |
|
|
341
|
-
| `ignoreIssues` | none | Passed to Knip, merged with the entry for `configFile` |
|
|
342
|
-
| `exclude` | none | Issue types to leave out, such as `catalogReferences` |
|
|
343
|
-
|
|
344
|
-
Knip adds the file given to `--config` to the entries in production mode, and
|
|
345
|
-
`--strict` only accepts `dependencies` there, so it reports this package as an
|
|
346
|
-
unlisted dependency of the config file. The config ignores `unlisted` issues in
|
|
347
|
-
`configFile` only: an import of this package from `src/` is still reported. An
|
|
348
|
-
application that keeps the config somewhere else passes its path in
|
|
349
|
-
`configFile`.
|
|
350
|
-
|
|
351
|
-
Nothing that depends on the application is a default. An ignore that matches
|
|
352
|
-
nothing is a configuration hint too, so `server-only` and the binaries of the
|
|
353
|
-
scripts are options. For a key without an option, wrap the function:
|
|
354
|
-
|
|
355
|
-
```ts
|
|
356
|
-
const configure = defineKnipConfig({ root })
|
|
357
|
-
|
|
358
|
-
export default async function configureKnip() {
|
|
359
|
-
return { ...(await configure()), ignoreUnresolved: ['virtual:example'] }
|
|
360
|
-
}
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
## CSS lint
|
|
364
|
-
|
|
365
|
-
`checkCss(root)` lints `src/**/*.css` with Stylelint and the CSS policy of the
|
|
366
|
-
boilerplate, and checks the name of every CSS file in `src/` as
|
|
367
|
-
`project/css-filename` does for imports: `styles.module.css`, or `camelCase.css`
|
|
368
|
-
inside `src/theme/`. It returns the report and whether anything failed:
|
|
369
|
-
|
|
370
|
-
```ts
|
|
371
|
-
// tooling/css/check.ts
|
|
372
|
-
import path from 'node:path'
|
|
373
|
-
import process from 'node:process'
|
|
374
|
-
|
|
375
|
-
import { checkCss } from '@evertondgn/solid-tooling/stylelint'
|
|
376
|
-
|
|
377
|
-
const { report, hasErrors } = await checkCss(
|
|
378
|
-
path.resolve(import.meta.dirname, '../..')
|
|
379
|
-
)
|
|
380
|
-
|
|
381
|
-
process.stdout.write(report)
|
|
382
|
-
if (hasErrors) process.exitCode = 1
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
`defineStylelintConfig(root)` returns the Stylelint config that `checkCss` uses.
|
|
386
|
-
The policy:
|
|
387
|
-
|
|
388
|
-
- Classes use snake_case, nesting goes at most two levels deep, and adjacent
|
|
389
|
-
state selectors and media queries are nested (`stylelint-use-nesting`).
|
|
390
|
-
- Unknown or invalid properties, values, units, selectors, at-rules and media
|
|
391
|
-
features are errors, as are deprecated and unmatchable selectors.
|
|
392
|
-
- Outside `src/theme/`, colors, gradients, radii, shadows, font sizes and
|
|
393
|
-
weights and `z-index` come from tokens with `var()`, from the matching token
|
|
394
|
-
family. Literal colors, color functions and system colors are errors.
|
|
395
|
-
- Inside `src/theme/`, the token rules are off, so the theme can define the
|
|
396
|
-
values with `oklch()`, `oklab()`, `color-mix()`, `light-dark()` and system
|
|
397
|
-
colors. Hex, named colors and the `rgb()`, `hsl()`, `hwb()`, `lab()`, `lch()`
|
|
398
|
-
and `color()` functions are still errors there.
|
|
399
|
-
- `var()` and animation names resolve against `src/theme/tokens/**/*.css` and
|
|
400
|
-
`src/theme/class/animation.css`. Stylelint stops the whole run when a
|
|
401
|
-
reference matches no file, so each one is passed only when it exists.
|
|
402
|
-
- An exception needs a `stylelint-disable` comment with the reason after `--`.
|
|
403
|
-
|
|
404
|
-
`stylelint` and `stylelint-use-nesting` are dependencies of this package. The
|
|
405
|
-
config passes the plugin by a path resolved from the package, because Stylelint
|
|
406
|
-
looks up a plugin name from the application and its working directory, where it
|
|
407
|
-
is not installed.
|
|
368
|
+
## A CSS policy built on tokens
|
|
369
|
+
|
|
370
|
+
<picture>
|
|
371
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/css-tokens-dark.webp" />
|
|
372
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/css-tokens-light.webp" />
|
|
373
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/css-tokens-light.webp" alt="In styles.module.css, color: #0b1525 is refused with the Stylelint message to use only var() tokens, and color: var(--color-foreground) passes. The token files of the boilerplate define 36 color, 11 font, 7 shadow, 6 grid, 5 radius and 3 z-index custom properties." width="800" />
|
|
374
|
+
</picture>
|
|
375
|
+
|
|
376
|
+
Outside `src/theme/`, colors, gradients, radii, shadows, font sizes and weights
|
|
377
|
+
and `z-index` must come from tokens with `var()`, from the matching token
|
|
378
|
+
family. A literal color is an error, so the palette is defined in the theme
|
|
379
|
+
files. Inside `src/theme/`, the theme defines the values with `oklch()`,
|
|
380
|
+
`oklab()`, `color-mix()` and `light-dark()`.
|
|
381
|
+
|
|
382
|
+
The policy also requires snake_case classes and at most two levels of nesting,
|
|
383
|
+
refuses unknown properties, values, units and selectors, checks that each
|
|
384
|
+
`var()` resolves to a token file, and accepts an exception only with a
|
|
385
|
+
`stylelint-disable` comment that gives the reason. `checkCss(root)` from
|
|
386
|
+
`./stylelint` runs it and checks CSS file names; the boilerplate's caller has 11
|
|
387
|
+
lines. The boilerplate's token files define 36 color, 11 font, 7 shadow, 6 grid,
|
|
388
|
+
5 radius and 3 z-index custom properties. See
|
|
389
|
+
[Knip and CSS](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/knip-and-css.md).
|
|
408
390
|
|
|
409
391
|
## Commit messages and Git hooks
|
|
410
392
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
393
|
+
<picture>
|
|
394
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/git-hooks-dark.webp" />
|
|
395
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/git-hooks-light.webp" />
|
|
396
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/git-hooks-light.webp" alt="The shared lefthook.yml: commit-msg runs commitlint with Conventional Commits and a 100-character header; pre-commit runs check:fix on the staged files and the kingfisher secret scan when installed, and skips merge and rebase; pre-push runs check:ci, typecheck:node and test:ci, then test:tooling and dead-code in parallel, and stops at the first failure." width="800" />
|
|
397
|
+
</picture>
|
|
416
398
|
|
|
417
|
-
|
|
418
|
-
// .commitlintrc
|
|
419
|
-
{ "extends": ["@evertondgn/solid-tooling/commitlint"] }
|
|
420
|
-
```
|
|
399
|
+
The shared hooks check a change before it reaches the remote:
|
|
421
400
|
|
|
422
|
-
|
|
423
|
-
|
|
401
|
+
| Hook | Jobs |
|
|
402
|
+
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
403
|
+
| `commit-msg` | `commitlint` on the message |
|
|
404
|
+
| `pre-commit` | `check:fix` on the staged files, staged again after the fix, and `scan:secrets --staged` when `kingfisher` is installed. Skipped in merge and rebase |
|
|
405
|
+
| `pre-push` | `check:ci`, `typecheck:node` and `test:ci` in order, then `test:tooling` and `dead-code` together; the first failure stops |
|
|
424
406
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
407
|
+
`./commitlint` applies the Conventional Commits rules with the header limited to
|
|
408
|
+
100 characters and a blank line before the footer. Lefthook and the commitlint
|
|
409
|
+
CLI come with the package, so the application declares neither. Extend the
|
|
410
|
+
shared file from `.lefthook.yml`, and override a shared job by name in
|
|
411
|
+
`lefthook-local.yml`, committed for everyone or kept on one machine:
|
|
429
412
|
|
|
430
413
|
```yaml
|
|
431
414
|
# .lefthook.yml
|
|
@@ -433,268 +416,230 @@ extends:
|
|
|
433
416
|
- node_modules/@evertondgn/solid-tooling/lefthook.yml
|
|
434
417
|
```
|
|
435
418
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
- `
|
|
517
|
-
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
`
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
only module that may call `console.error`.
|
|
541
|
-
- `fetch`, `XMLHttpRequest`, `WebSocket` and `EventSource` are not allowed.
|
|
542
|
-
`src/infra/server/requestJson/index.ts` is the only module that may call
|
|
543
|
-
`fetch`.
|
|
544
|
-
- The Node transports (`http`, `https`, `http2`, `net`, `tls`, `undici`) cannot
|
|
545
|
-
be imported.
|
|
546
|
-
- `markSafeError` and `SAFE_ERROR` can only be imported in
|
|
547
|
-
`src/infra/server/publicErrors/index.ts`.
|
|
548
|
-
- `configureServerErrors` from `@solidjs/web`, the
|
|
549
|
-
`@solidjs/web/server-functions` subpath and `observeRenderFailures` from the
|
|
550
|
-
application's `renderIntegrity` module can only be imported in
|
|
551
|
-
`src/infra/server/configureServerErrors/index.ts`.
|
|
552
|
-
- A relative import goes up at most three levels. Use `@/` beyond that.
|
|
553
|
-
|
|
554
|
-
Test files and `.d.ts` files are exempt from all of these except the relative
|
|
555
|
-
import limit.
|
|
556
|
-
|
|
557
|
-
## Changing the preset
|
|
558
|
-
|
|
559
|
-
`lint` and `fmt` are plain objects. Spread them and replace what the application
|
|
560
|
-
needs:
|
|
419
|
+
See
|
|
420
|
+
[Commit messages and Git hooks](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/commits-and-hooks.md).
|
|
421
|
+
|
|
422
|
+
## Translations, icons and fonts as data
|
|
423
|
+
|
|
424
|
+
<picture>
|
|
425
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/i18n-dark.webp" />
|
|
426
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/i18n-light.webp" />
|
|
427
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/i18n-light.webp" alt="A project.inlang settings excerpt with base locale fr and locales fr, de, it and ja. Catalogs stay beside each feature; validation, compilation and localization produce translated pages, URL helpers, redirects, cookies and navigation. Without a translation project, URLs stay unprefixed." width="800" />
|
|
428
|
+
</picture>
|
|
429
|
+
|
|
430
|
+
With `project.inlang/settings.json`, the packaged generator reads the catalogs
|
|
431
|
+
beside each feature, `src/**/i18n/<locale>.json`, and compiles Paraglide in
|
|
432
|
+
development, builds and tests. A missing translation, a duplicate ID or an
|
|
433
|
+
invalid message fails with the file and the key. The locales come from your
|
|
434
|
+
settings, with no fixed set. Without the file, no generator or i18n plugin
|
|
435
|
+
enters the build.
|
|
436
|
+
|
|
437
|
+
<picture>
|
|
438
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/icons-dark.webp" />
|
|
439
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/icons-light.webp" />
|
|
440
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/icons-light.webp" alt="solid.svg in src/assets/images becomes a Solid component. The icons option maps the my-images collection to that folder, the component imports ~icons/my-images/solid, and the preset adds aria-hidden=true; the icon-only control supplies its accessible label." width="800" />
|
|
441
|
+
</picture>
|
|
442
|
+
|
|
443
|
+
Icons from Iconify collections, or your own SVG folders mapped with the `icons`
|
|
444
|
+
option, become Solid components through `unplugin-icons`, with `aria-hidden` on
|
|
445
|
+
every icon. The application does not declare the plugin.
|
|
446
|
+
|
|
447
|
+
<picture>
|
|
448
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/fonts-dark.webp" />
|
|
449
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/fonts-light.webp" />
|
|
450
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/fonts-light.webp" alt="One font asset list in defineSolidApp produces external @font-face CSS with content-hashed URLs, deduplicated files and matching preload links. SSR renders FontLinks in the Document; client-only apps receive the links in index.html; without fonts, nothing is generated." width="800" />
|
|
451
|
+
</picture>
|
|
452
|
+
|
|
453
|
+
Pass a data-only `fonts` array to `defineSolidApp` to generate external
|
|
454
|
+
`@font-face` CSS and matching preloads for application-owned files. SSR uses
|
|
455
|
+
`FontLinks` from `@evertondgn/solid-runtime/fonts/font-links` in the Document
|
|
456
|
+
head; client-only applications receive both links in `index.html`, also with a
|
|
457
|
+
relative `./` base for `file://` and app shells. Leave `fonts` out and nothing
|
|
458
|
+
is generated. Typography tokens stay in the app. See the
|
|
459
|
+
[font API and migration examples](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/fonts.md).
|
|
460
|
+
|
|
461
|
+
## SEO configured as data
|
|
462
|
+
|
|
463
|
+
<picture>
|
|
464
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/seo-dark.webp" />
|
|
465
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/seo-light.webp" />
|
|
466
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/seo-light.webp" alt="Three independent SEO parts. Head: createSeo with inherited route metadata, canonical and social tags and escaped JSON-LD. Robots: an explicit route with a serializable crawl policy. Sitemap: createSitemapRoutes with arrays or bounded partition reads under the shared publication controller. All work with or without i18n." width="800" />
|
|
467
|
+
</picture>
|
|
468
|
+
|
|
469
|
+
Robots, sitemap headers, Markdown and the llms indexes are options of
|
|
470
|
+
`defineSolidApp` written as plain data, validated when the config loads. None of
|
|
471
|
+
them turns on another. Only `llmsFull` has prerequisites: the full file is built
|
|
472
|
+
from the static Markdown, so it needs `llms` and `markdown: { static: true }`,
|
|
473
|
+
and the config fails to load without them. The site URL becomes required once
|
|
474
|
+
`seo` is set, as an HTTP(S) origin with no path, query, fragment or credentials;
|
|
475
|
+
leave `seo` out and no origin is read.
|
|
476
|
+
|
|
477
|
+
For SSR,
|
|
478
|
+
`seo: { robots: { groups, sitemapPaths, cacheControl }, sitemap: true }`
|
|
479
|
+
configures the runtime robots route using serializable data. `originEnv`
|
|
480
|
+
defaults to `VITE_SITE_URL`. The preset validates it when SEO is enabled or the
|
|
481
|
+
runtime origin entry is imported.
|
|
482
|
+
|
|
483
|
+
Pass `site` directly to the runtime `createSeo` primitive. A meta/JSON-LD-only
|
|
484
|
+
application can omit `seo`, provide its own `site.url` and omit robots entirely.
|
|
485
|
+
Client-only applications omit both the option and runtime SEO imports. There are
|
|
486
|
+
no `siteModule`, `sourcesModule` or `editorialModule` path options.
|
|
487
|
+
`seo.sitemap` controls only the static `/sitemap.xml` and `/sitemaps/pages/**`
|
|
488
|
+
header rules. Install the runtime factory in explicit application route files,
|
|
489
|
+
and list the root in `robots.sitemapPaths` to advertise it. To remove sitemap,
|
|
490
|
+
remove its routes and server binding, omit its array metadata, omit
|
|
491
|
+
`sitemapPaths`, and omit or disable `seo.sitemap`. Robots can stay enabled. The
|
|
492
|
+
preset does not discover executable source registries or install routes. See the
|
|
493
|
+
[runtime SEO API](https://github.com/everton-dgn/solidjs_base/blob/main/packages/solid-runtime/README.md#optional-seo)
|
|
494
|
+
for factories, the one-line route and examples with and without translations.
|
|
495
|
+
|
|
496
|
+
### Publication artifacts
|
|
497
|
+
|
|
498
|
+
Crawlers get files, not renders. The build writes what you turn on: a `.md` copy
|
|
499
|
+
of each opted-in page with `markdown: { static: true }`, `llms.txt` with `llms`,
|
|
500
|
+
`llms-full.txt` with `llmsFull`, and the sitemap XML with
|
|
501
|
+
`sitemap: { static: true }`. A bad artifact fails the build instead of reaching
|
|
502
|
+
production: a `.md` file that is empty, not UTF-8 or still an HTML document, an
|
|
503
|
+
index or sitemap file over its byte budget, an `llms.txt` whose link to
|
|
504
|
+
`llms-full.txt` disagrees with the files built, a static page that resolves to
|
|
505
|
+
another route, or a Markdown list or sitemap inventory from a different build
|
|
506
|
+
than the SSR bundle. Your config needs no `extend` callback for this.
|
|
507
|
+
`publication/read-llms-index` exposes the compiled index reader for artifact
|
|
508
|
+
checks in Node. See
|
|
509
|
+
[ADR 0034](https://github.com/everton-dgn/solidjs_base/blob/main/docs/ADRs/0034-runtime-markdown-publication.md)
|
|
510
|
+
for the feature options, defaults, disabled-resource behavior and scale.
|
|
511
|
+
|
|
512
|
+
## Optional environment validation
|
|
513
|
+
|
|
514
|
+
<picture>
|
|
515
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/env-dark.webp" />
|
|
516
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/env-light.webp" />
|
|
517
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/env-light.webp" alt="An optional env.ts spreads serverEnv: HOST string or undefined, PORT number or undefined, BASE_URL_TEST string or undefined. Server virtual imports validate at initialization and fail the build from client code. Public client values validate at build time with inferred types and no validator shipped. No env requirements? Omit env.ts." width="800" />
|
|
518
|
+
</picture>
|
|
519
|
+
|
|
520
|
+
A missing or malformed value fails where it enters: when the server code that
|
|
521
|
+
imports it loads, or at build time for a public value. An SSR application can
|
|
522
|
+
add `env.ts` with the preset's optional validators:
|
|
561
523
|
|
|
562
524
|
```ts
|
|
563
|
-
|
|
564
|
-
import { fmt } from '@evertondgn/solid-tooling/fmt'
|
|
565
|
-
import { lint } from '@evertondgn/solid-tooling/lint'
|
|
566
|
-
import { defineConfig } from 'vite-plus'
|
|
525
|
+
import { serverEnv } from '@evertondgn/solid-runtime/env'
|
|
567
526
|
|
|
568
|
-
|
|
569
|
-
fmt,
|
|
570
|
-
lint: {
|
|
571
|
-
...lint,
|
|
572
|
-
ignorePatterns: [...(lint.ignorePatterns ?? []), 'generated/**'],
|
|
573
|
-
rules: { ...lint.rules, 'eslint/max-params': 'off' }
|
|
574
|
-
}
|
|
575
|
-
})
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
Do not replace `lint.jsPlugins`. It registers the JavaScript plugins listed
|
|
579
|
-
above, and a rule whose plugin is missing from it fails to resolve.
|
|
527
|
+
const env = { server: { ...serverEnv } }
|
|
580
528
|
|
|
581
|
-
|
|
582
|
-
keep the existing ones:
|
|
583
|
-
|
|
584
|
-
```ts
|
|
585
|
-
overrides: [
|
|
586
|
-
...(lint.overrides ?? []),
|
|
587
|
-
{
|
|
588
|
-
files: ['src/tests/pages/Checkout/**'],
|
|
589
|
-
rules: { 'project/test-filename': 'off' }
|
|
590
|
-
}
|
|
591
|
-
]
|
|
529
|
+
export default env
|
|
592
530
|
```
|
|
593
531
|
|
|
532
|
+
`HOST`, `PORT` and `BASE_URL_TEST` are optional; `PORT` produces a number.
|
|
533
|
+
Declare the runtime package in `dependencies` and keep the tooling in
|
|
534
|
+
`devDependencies`: Knip treats `env.ts` as production code. Extend `server` and
|
|
535
|
+
`client` with the application's own Standard Schema validators. The runtime
|
|
536
|
+
supplies Valibot for its fragment; declare a validator library in the
|
|
537
|
+
application only when its own code imports it. The optional SEO configuration
|
|
538
|
+
validates `VITE_SITE_URL` separately. An application without `env.ts` keeps
|
|
539
|
+
working, including client-only applications with no site URL.
|
|
540
|
+
|
|
541
|
+
The Solid plugin generates inferred types and rejects server env imports in the
|
|
542
|
+
client graph. The server virtual module bundles the fragment and validator; env
|
|
543
|
+
validation adds neither to the client. See the
|
|
544
|
+
[environment guide](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/app-config.md#optional-environment-validation)
|
|
545
|
+
for extension examples, boot validation and type generation.
|
|
546
|
+
|
|
547
|
+
## How it is verified
|
|
548
|
+
|
|
549
|
+
<picture>
|
|
550
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/verified-dark.webp" />
|
|
551
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/verified-light.webp" />
|
|
552
|
+
<img src="https://raw.githubusercontent.com/everton-dgn/solidjs_base/main/docs/assets/readme/verified-light.webp" alt="Current revision: 1,186 Vitest tests passed, 1,001 in the runtime and 185 in the boilerplate app; 319 E2E cases listed, 164 for the E2E build and 155 for the production build. Before each release the tarball is installed in a separate application and its exports and lint rules are checked. Release workflows publish with trusted publishing and signed npm provenance, with no stored npm token." width="800" />
|
|
553
|
+
</picture>
|
|
554
|
+
|
|
555
|
+
At this revision, 1,186 Vitest tests passed: 1,001 in 100 files of the runtime
|
|
556
|
+
package and 185 in 32 files of the boilerplate app. `playwright test --list`
|
|
557
|
+
counts 319 E2E cases in the app, 164 for the E2E build and 155 for the
|
|
558
|
+
production build.
|
|
559
|
+
|
|
560
|
+
- The package's own tests, `vp run test`, run with `node --test` against
|
|
561
|
+
fixtures in temporary folders: 268 `test` and `it` calls in 39 files, counted
|
|
562
|
+
in source.
|
|
563
|
+
- The tarball test packs the package, installs it in a separate application
|
|
564
|
+
outside the workspace and checks that lint applies the plugins, that the
|
|
565
|
+
application extends the shared hooks and commitlint config, and that the
|
|
566
|
+
fixture declares the workspace versions.
|
|
567
|
+
- The installed scenarios install the packed tooling and runtime in the
|
|
568
|
+
[three fixture applications](https://github.com/everton-dgn/solidjs_base/tree/main/fixtures/apps)
|
|
569
|
+
with Bun's `hoisted` and `isolated` linkers and build them. The matrix
|
|
570
|
+
enumerates 14 application cases: 3 client-only, 9 SSR and 2 translated SSR.
|
|
571
|
+
They fail when a disabled feature leaves its modules in the bundle.
|
|
572
|
+
- The runtime package is linted with this package's preset, loaded from its
|
|
573
|
+
sources.
|
|
574
|
+
|
|
575
|
+
`vp run validate` at the root runs the build, checks, dead code, package tests,
|
|
576
|
+
tarball tests and installed scenarios, as the publish job does. CI selects jobs
|
|
577
|
+
by changed paths, and a package change runs the packages and the complete
|
|
578
|
+
boilerplate app. The workflow publishes to npm through trusted publishing, with
|
|
579
|
+
signed provenance and no stored npm token. See the
|
|
580
|
+
[CI coverage](https://github.com/everton-dgn/solidjs_base/blob/main/docs/development.md#ci)
|
|
581
|
+
and the
|
|
582
|
+
[release process](https://github.com/everton-dgn/solidjs_base/blob/main/docs/releasing.md).
|
|
583
|
+
|
|
594
584
|
## Entry points
|
|
595
585
|
|
|
596
|
-
| Entry
|
|
597
|
-
|
|
|
598
|
-
| `./
|
|
599
|
-
| `./
|
|
600
|
-
| `./
|
|
601
|
-
| `./tsconfig.
|
|
602
|
-
| `./
|
|
603
|
-
| `./
|
|
604
|
-
| `./
|
|
605
|
-
| `./vitest
|
|
606
|
-
| `./
|
|
607
|
-
| `./
|
|
608
|
-
| `./
|
|
609
|
-
| `./
|
|
610
|
-
| `./
|
|
611
|
-
| `./
|
|
612
|
-
| `./
|
|
613
|
-
| `./
|
|
614
|
-
| `./
|
|
615
|
-
| `./
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
586
|
+
| Entry | Content |
|
|
587
|
+
| ------------------------------- | -------------------------------------------------------------------------------- |
|
|
588
|
+
| `./vite` | `defineSolidApp(options)`, the whole `vite.config.ts` of an application |
|
|
589
|
+
| `./lint` | `lint`: the lint preset, with the plugins below registered |
|
|
590
|
+
| `./fmt` | `fmt`: the formatter config |
|
|
591
|
+
| `./tsconfig.base.json` | Compiler options, without application paths |
|
|
592
|
+
| `./tsconfig.app.json` | The base plus packaged type references and the boilerplate `include` |
|
|
593
|
+
| `./app-env` | Type references loaded by `tsconfig.app.json` |
|
|
594
|
+
| `./virtual-modules` | Declarations of the `virtual:solid-app/*` modules, loaded by `tsconfig.app.json` |
|
|
595
|
+
| `./vitest` | `solidTest(options)`, the `test` block of `vite.config.ts` |
|
|
596
|
+
| `./vitest-setup/browser` | Setup file of the browser project, loaded by `./vitest` |
|
|
597
|
+
| `./playwright` | `definePlaywrightConfig(options)`, the Playwright config |
|
|
598
|
+
| `./playwright-teardown` | Server log check, loaded by `./playwright` |
|
|
599
|
+
| `./project-plugin` | The `project` rules |
|
|
600
|
+
| `./backend-plugin` | The `backend` rules |
|
|
601
|
+
| `./architecture-plugin` | The `architecture` rule |
|
|
602
|
+
| `./solid-plugin` | Re-export of `eslint-plugin-solid`, resolved from the package |
|
|
603
|
+
| `./css-filename` | `cssFilenameError(path)`, the CSS naming check, for a script outside lint |
|
|
604
|
+
| `./knip` | `defineKnipConfig(options)`, the Knip config |
|
|
605
|
+
| `./stylelint` | `checkCss(root)` and `defineStylelintConfig(root)`, the CSS lint |
|
|
606
|
+
| `./commitlint` | The commitlint config |
|
|
607
|
+
| `./lefthook.yml` | The Git hooks, extended from the application's `.lefthook.yml` |
|
|
608
|
+
| `./cli` | Command entry for packaged Knip, TypeScript, Playwright, Lefthook and commitlint |
|
|
609
|
+
| `./i18n-generate` | Compiled catalog generator executed by the preset's `i18n-generate` task |
|
|
610
|
+
| `./publication/read-llms-index` | Compiled reader of the llms index, for artifact checks in Node |
|
|
611
|
+
| `./package.json` | The package manifest |
|
|
612
|
+
|
|
613
|
+
Your editor and `tsc` know the test globals, the jest-dom matchers, the Solid
|
|
614
|
+
plugin and routing modules and every `virtual:solid-app/*` module with no local
|
|
615
|
+
`.d.ts`: `tsconfig.app.json` loads `./app-env`, which references
|
|
616
|
+
`./virtual-modules`. An application with its own TypeScript config adds
|
|
617
|
+
`@evertondgn/solid-tooling/app-env` to `types`.
|
|
618
|
+
|
|
619
|
+
Your application keeps its pages, components, translations, theme, `App`,
|
|
620
|
+
`Document`, entries and middleware. The plugin entries exist because Oxlint
|
|
621
621
|
loads plugins by specifier, from the application; the setup and teardown entries
|
|
622
|
-
are loaded by the test presets.
|
|
622
|
+
are loaded by the test presets. The
|
|
623
|
+
[entry-point reference](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/README.md#entry-points)
|
|
624
|
+
describes each one.
|
|
623
625
|
|
|
624
|
-
##
|
|
626
|
+
## Guides
|
|
625
627
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
628
|
+
- [Lint rules and customization](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/lint.md)
|
|
629
|
+
- [Application config, plugins and tasks](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/app-config.md)
|
|
630
|
+
- [Vitest and Playwright](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/testing.md)
|
|
631
|
+
- [Knip and CSS](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/knip-and-css.md)
|
|
632
|
+
- [Commit messages and Git hooks](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/commits-and-hooks.md)
|
|
633
|
+
- [TypeScript and formatting](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/typescript-and-format.md)
|
|
634
|
+
- [Requirements, limits and versions](https://github.com/everton-dgn/solidjs_base/blob/main/docs/tooling/limits.md)
|
|
629
635
|
|
|
630
|
-
##
|
|
631
|
-
|
|
632
|
-
`tsconfig.base.json` targets ES2024 with bundler resolution, keeps JSX for the
|
|
633
|
-
Solid compiler (`jsxImportSource: @solidjs/web`), emits nothing and turns on the
|
|
634
|
-
unused code and unchecked index checks. It has no `paths`, `include` or `types`.
|
|
635
|
-
|
|
636
|
-
`tsconfig.app.json` extends the base with the `types` of a boilerplate
|
|
637
|
-
application and an `include` resolved from the application folder with
|
|
638
|
-
`${configDir}`, which needs TypeScript 5.5 or later. Each entry of `types` comes
|
|
639
|
-
from a package the application installs:
|
|
640
|
-
|
|
641
|
-
| Entry of `types` | Package |
|
|
642
|
-
| --------------------------------------- | --------------------------- |
|
|
643
|
-
| `node` | `@types/node` |
|
|
644
|
-
| `vite/client` | `vite` |
|
|
645
|
-
| `vite-plus/test/globals` | `vite-plus` |
|
|
646
|
-
| `@testing-library/jest-dom/vitest` | `@testing-library/jest-dom` |
|
|
647
|
-
| `@solidjs/vite-plugin/boundary-modules` | `@solidjs/vite-plugin` |
|
|
648
|
-
| `@solidjs/vite-plugin/virtual-modules` | `@solidjs/vite-plugin` |
|
|
649
|
-
|
|
650
|
-
The application still declares its `paths`:
|
|
651
|
-
|
|
652
|
-
```json
|
|
653
|
-
{
|
|
654
|
-
"extends": "@evertondgn/solid-tooling/tsconfig.app.json",
|
|
655
|
-
"compilerOptions": {
|
|
656
|
-
"paths": { "@/*": ["./src/*"], "@paraglide/*": ["./paraglide/*"] }
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
```
|
|
660
|
-
|
|
661
|
-
Playwright reads the `tsconfig.json` of the test files with its own loader,
|
|
662
|
-
which does not expand `${configDir}`, so paths declared in the package would
|
|
663
|
-
break the `@/` imports of the end-to-end tests.
|
|
664
|
-
|
|
665
|
-
## Known limits
|
|
666
|
-
|
|
667
|
-
- The package ships compiled JavaScript. Node refuses to run TypeScript from
|
|
668
|
-
`node_modules`, and Vite+ loads `vite.config.ts` in Node.
|
|
669
|
-
- `project/test-filename` has no options. Test folders without a module, such as
|
|
670
|
-
the page tests in `src/tests/pages/`, are listed inside the package with the
|
|
671
|
-
names used in boilerplate_solidjs. For any other folder of that kind, turn the
|
|
672
|
-
rule off in `lint.overrides`, as shown in
|
|
673
|
-
[Changing the preset](#changing-the-preset).
|
|
674
|
-
- The Paraglide plugin is always registered, so `@inlang/paraglide-js` has to be
|
|
675
|
-
installed even in an application without translations.
|
|
676
|
-
- Some rule messages point to `docs/architecture.md` and `AGENTS.md`. Those
|
|
677
|
-
files belong to the application created from boilerplate_solidjs.
|
|
678
|
-
- The test presets expect the boilerplate layout: tests named by suffix
|
|
679
|
-
(`.node.test`, `.dom.test`, `.browser.test`, `.e2e.test`), page tests in
|
|
680
|
-
`src/tests/pages/`, Paraglide output in `paraglide/` and `.env.test` at the
|
|
681
|
-
root.
|
|
682
|
-
- The Knip and CSS configs expect the same layout: pages in `src/routes/`,
|
|
683
|
-
fixture routes in `src/tests/fixtures/` and the theme in `src/theme/`.
|
|
684
|
-
- The Knip config ignores every unlisted dependency in its own file, not only
|
|
685
|
-
this package.
|
|
686
|
-
- `./vite` expects the same layout: its tasks run scripts in `tooling/`, and the
|
|
687
|
-
Markdown rules need the locale prefix of the Paraglide `urlPatterns` in every
|
|
688
|
-
URL. Nitro always uses the `vercel` preset. The plugin packages are pinned, so
|
|
689
|
-
a new version of Solid, Nitro, the router or the icons plugin needs a package
|
|
690
|
-
version tested with it.
|
|
691
|
-
|
|
692
|
-
## Versions
|
|
636
|
+
## Versions and license
|
|
693
637
|
|
|
694
638
|
The package follows semantic versioning. Below 1.0.0, a breaking change raises
|
|
695
|
-
the minor version.
|
|
696
|
-
[changelog](https://github.com/everton-dgn/solidjs_base/blob/main/packages/solid-tooling/CHANGELOG.md)
|
|
697
|
-
|
|
698
|
-
|
|
639
|
+
the minor version. Read the
|
|
640
|
+
[changelog](https://github.com/everton-dgn/solidjs_base/blob/main/packages/solid-tooling/CHANGELOG.md)
|
|
641
|
+
for each release, and the
|
|
642
|
+
[Solid Base overview](https://github.com/everton-dgn/solidjs_base/blob/main/README.md)
|
|
643
|
+
for both packages together.
|
|
699
644
|
|
|
700
|
-
MIT
|
|
645
|
+
[MIT](https://github.com/everton-dgn/solidjs_base/blob/main/LICENSE)
|