@jk2908/solas 0.5.3 → 0.6.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/CHANGELOG.md +29 -0
- package/README.md +81 -85
- package/dist/config.d.ts +25 -0
- package/dist/config.js +152 -0
- package/dist/events.d.ts +4 -0
- package/dist/events.js +5 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +59 -37
- package/dist/internal/boundary-error.d.ts +4 -0
- package/dist/internal/boundary-error.js +8 -0
- package/dist/internal/browser-router/history.d.ts +46 -0
- package/dist/internal/browser-router/history.js +131 -0
- package/dist/internal/browser-router/link.d.ts +1 -1
- package/dist/internal/browser-router/link.js +1 -1
- package/dist/internal/browser-router/router.d.ts +6 -14
- package/dist/internal/browser-router/router.js +39 -13
- package/dist/internal/browser-router/shared.d.ts +183 -164
- package/dist/internal/browser-router/shared.js +49 -56
- package/dist/internal/browser-router/use-router.d.ts +1 -10
- package/dist/internal/browser-router/use-search-params.js +3 -3
- package/dist/internal/build.d.ts +108 -110
- package/dist/internal/build.js +569 -581
- package/dist/internal/codegen/config.js +3 -3
- package/dist/internal/codegen/environments.js +5 -6
- package/dist/internal/codegen/format.d.ts +6 -0
- package/dist/internal/codegen/format.js +24 -0
- package/dist/internal/codegen/manifest.js +2 -2
- package/dist/internal/codegen/maps.d.ts +1 -1
- package/dist/internal/codegen/maps.js +2 -2
- package/dist/internal/codegen/types.js +4 -4
- package/dist/internal/codegen/utils.js +2 -2
- package/dist/internal/env/request-context.js +1 -1
- package/dist/internal/env/rsc.d.ts +6 -4
- package/dist/internal/env/rsc.js +27 -25
- package/dist/internal/env/ssr.js +4 -4
- package/dist/internal/http-router/router.js +8 -8
- package/dist/internal/metadata.d.ts +1 -1
- package/dist/internal/metadata.js +1 -1
- package/dist/internal/navigation/http-exception-boundary.d.ts +1 -1
- package/dist/internal/navigation/redirect-boundary.d.ts +1 -1
- package/dist/internal/navigation/redirect.js +6 -6
- package/dist/internal/postbuild.js +18 -17
- package/dist/internal/prerender.d.ts +130 -138
- package/dist/internal/prerender.js +326 -354
- package/dist/internal/public-files.js +2 -4
- package/dist/internal/render/head.js +2 -2
- package/dist/internal/resolver.js +1 -1
- package/dist/internal/server/actions.js +2 -2
- package/dist/internal/ui/error-boundary.d.ts +1 -1
- package/dist/manifest.d.ts +7 -0
- package/dist/manifest.js +85 -0
- package/dist/prerender.d.ts +1 -1
- package/dist/prerender.js +1 -1
- package/dist/solas.d.ts +2 -46
- package/dist/solas.js +6 -266
- package/dist/types.d.ts +14 -21
- package/dist/types.js +1 -1
- package/dist/utils/base-path.d.ts +12 -14
- package/dist/utils/base-path.js +75 -82
- package/dist/utils/compress.d.ts +9 -11
- package/dist/utils/compress.js +59 -64
- package/dist/utils/context.d.ts +4 -6
- package/dist/utils/context.js +17 -22
- package/dist/utils/logger.js +2 -2
- package/dist/utils/time.d.ts +2 -4
- package/dist/utils/time.js +23 -29
- package/package.json +18 -8
- package/dist/runtimes/bun.d.ts +0 -13
- package/dist/runtimes/bun.js +0 -39
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- Removed the `Solas` runtime namespace exports (`Solas.Config`, `Solas.Runtime`, `Solas.Events`) from the `@jk2908/solas` entry. Runtime constants now live in dedicated internal modules, and generated code no longer reaches through the namespace.
|
|
8
|
+
- Removed the `@jk2908/solas/$` export path. Generated environment entries now import directly from `@jk2908/solas/env/rsc`.
|
|
9
|
+
- Removed the `port` config option from `solas()`. The development port now comes from Vite's `server.port`. `url` remains available as an optional public origin and now resolves from the `url` option → `VITE_APP_URL` → the Vite dev server `host`/`port`.
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- Generated `.solas` files are formatted with oxfmt before writing, and stale generated files are pruned when the codegen stops emitting them.
|
|
14
|
+
- Added a Vitest test suite covering unit, integration, and browser (React Testing Library) tests.
|
|
15
|
+
|
|
16
|
+
### Fixes
|
|
17
|
+
|
|
18
|
+
- Generated `entry.rsc.tsx` now emits valid code (`loadManifest` from `env/rsc`) instead of referencing an undefined `Config` import.
|
|
19
|
+
- Fixed the release pipeline by committing the postbuild measurement script.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Pinned `@vitejs/plugin-rsc` to `0.5.34`.
|
|
24
|
+
- Removed the Playwright e2e suite, fixtures, and scripts for now; unit, integration, and browser tests run through Vitest.
|
|
25
|
+
- Declared `engines.node` (`^20.19.0 || >=22.12.0`).
|
|
26
|
+
|
|
27
|
+
## 0.5.4 - 2026-06-08
|
|
28
|
+
|
|
29
|
+
- Add a BrowserRouterHistory API to sync app back/forward navigation with browser navigation.
|
|
30
|
+
- Expose BrowserRouterContext.history for gated use in client components
|
|
31
|
+
|
|
3
32
|
## 0.5.3 - 2026-06-06
|
|
4
33
|
|
|
5
34
|
- Ensured `createRuntime(...)` is exported from `@jk2908/solas/env/rsc` for generated RSC entry compatibility.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Solas is a minimal React meta-framework powered by Vite, created for experimenting with routing, streaming, and prerendering with React Server Components.
|
|
4
4
|
|
|
5
|
-
Solas is experimental and
|
|
5
|
+
Solas is experimental and under active development, so expect rough edges.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -201,13 +201,9 @@ That keeps your route params aligned across links, imperative navigation, metada
|
|
|
201
201
|
|
|
202
202
|
All Solas options are passed to `solas()` inside `defineConfig`.
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
Solas uses a runtime for filesystem access, mime lookup, and hashing.
|
|
207
|
-
|
|
208
|
-
This is not a deployment or packaging adapter. Platform adapters are not available yet.
|
|
204
|
+
### `runtime`
|
|
209
205
|
|
|
210
|
-
Use
|
|
206
|
+
Use `runtime` to select the runtime used by Solas server code.
|
|
211
207
|
|
|
212
208
|
Supported values are `'auto'`, `'node'`, and `'bun'`.
|
|
213
209
|
|
|
@@ -215,104 +211,45 @@ Supported values are `'auto'`, `'node'`, and `'bun'`.
|
|
|
215
211
|
|
|
216
212
|
If you already run Vite through Bun, `runtime: 'auto'` is usually enough and Solas will detect Bun automatically.
|
|
217
213
|
|
|
218
|
-
### Node runtime
|
|
219
|
-
|
|
220
|
-
If you want to pin Node explicitly, set `runtime: 'node'`:
|
|
221
|
-
|
|
222
|
-
```ts
|
|
223
|
-
import { defineConfig } from 'vite'
|
|
224
|
-
|
|
225
|
-
import solas from '@jk2908/solas'
|
|
226
|
-
import react from '@vitejs/plugin-react'
|
|
227
|
-
|
|
228
|
-
export default defineConfig({
|
|
229
|
-
plugins: [solas({ runtime: 'node' }), react()],
|
|
230
|
-
})
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
Use the normal Vite commands with the Node runtime:
|
|
234
|
-
|
|
235
|
-
```json
|
|
236
|
-
{
|
|
237
|
-
"scripts": {
|
|
238
|
-
"dev": "vite dev",
|
|
239
|
-
"build": "vite build",
|
|
240
|
-
"preview": "vite preview"
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### Bun runtime
|
|
246
|
-
|
|
247
|
-
If you want Solas runtime code to execute in Bun, set `runtime: 'bun'`:
|
|
248
|
-
|
|
249
|
-
```ts
|
|
250
|
-
import { defineConfig } from 'vite'
|
|
251
|
-
|
|
252
|
-
import solas from '@jk2908/solas'
|
|
253
|
-
import react from '@vitejs/plugin-react'
|
|
254
|
-
|
|
255
|
-
export default defineConfig({
|
|
256
|
-
plugins: [solas({ runtime: 'bun' }), react()],
|
|
257
|
-
})
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
When you use the Bun runtime, run Vite through Bun so the server/runtime code executes in a Bun process:
|
|
261
|
-
|
|
262
|
-
```json
|
|
263
|
-
{
|
|
264
|
-
"scripts": {
|
|
265
|
-
"dev": "bunx --bun vite dev",
|
|
266
|
-
"build": "bunx --bun vite build",
|
|
267
|
-
"preview": "bunx --bun vite preview"
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
214
|
### `url`
|
|
273
215
|
|
|
274
|
-
`url`
|
|
216
|
+
Use `url` to set the public origin for your app. It is optional.
|
|
275
217
|
|
|
276
|
-
Solas resolves
|
|
218
|
+
Solas resolves the origin in this order:
|
|
277
219
|
|
|
278
220
|
- the `url` option passed to `solas()`
|
|
279
221
|
- `VITE_APP_URL`
|
|
222
|
+
- the Vite dev server `host` and `port` (defaults to `http://localhost:8787`)
|
|
280
223
|
|
|
281
|
-
|
|
224
|
+
The resolved origin is exposed to your app as `import.meta.env.VITE_APP_URL` and is used for build-time prerender requests and `sitemap` URLs. When `url` is set, it is also used as a trusted origin for CSRF.
|
|
282
225
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
If you do want to set it explicitly, this is the shape:
|
|
226
|
+
You usually only need `url` in production, where the Vite dev server origin is meaningless. For example, to generate a `sitemap.xml` with real URLs:
|
|
286
227
|
|
|
287
228
|
```ts
|
|
288
229
|
export default defineConfig(({ mode }) => ({
|
|
289
230
|
plugins: [
|
|
290
231
|
solas({
|
|
291
|
-
url: mode === 'production' ? 'https://example.com' :
|
|
232
|
+
url: mode === 'production' ? 'https://example.com' : undefined,
|
|
233
|
+
sitemap: true,
|
|
292
234
|
}),
|
|
293
235
|
],
|
|
294
236
|
}))
|
|
295
237
|
```
|
|
296
238
|
|
|
297
|
-
If you prefer an environment variable, set
|
|
239
|
+
If you prefer an environment variable, set `VITE_APP_URL` instead:
|
|
298
240
|
|
|
299
241
|
```sh
|
|
300
242
|
VITE_APP_URL=https://example.com
|
|
301
243
|
```
|
|
302
244
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
Use `port` to change the development server port.
|
|
306
|
-
|
|
307
|
-
Default: `8787`
|
|
245
|
+
Set the development port with Vite's `server.port`:
|
|
308
246
|
|
|
309
247
|
```ts
|
|
310
248
|
export default defineConfig({
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
],
|
|
249
|
+
server: {
|
|
250
|
+
port: 4000,
|
|
251
|
+
},
|
|
252
|
+
plugins: [solas(), react()],
|
|
316
253
|
})
|
|
317
254
|
```
|
|
318
255
|
|
|
@@ -510,13 +447,13 @@ Use `sitemap` to generate a `sitemap.xml` at build time.
|
|
|
510
447
|
|
|
511
448
|
Default: `false`
|
|
512
449
|
|
|
513
|
-
When enabled, Solas writes a sitemap containing all routes with deterministic URLs: static routes, prerendered routes, and dynamic routes resolved via `params`. The origin for each URL comes from `
|
|
450
|
+
When enabled, Solas writes a sitemap containing all routes with deterministic URLs: static routes, prerendered routes, and dynamic routes resolved via `params`. The origin for each URL comes from the resolved origin (see Config > `url`).
|
|
514
451
|
|
|
515
452
|
```ts
|
|
516
453
|
export default defineConfig(({ mode }) => ({
|
|
517
454
|
plugins: [
|
|
518
455
|
solas({
|
|
519
|
-
url: mode === 'production' ? 'https://example.com' :
|
|
456
|
+
url: mode === 'production' ? 'https://example.com' : undefined,
|
|
520
457
|
sitemap: true,
|
|
521
458
|
}),
|
|
522
459
|
],
|
|
@@ -528,10 +465,9 @@ Routes with dynamic segments (`[id]`) or catch-all segments (`[...param]`) are o
|
|
|
528
465
|
To add routes that Solas cannot discover automatically (for example, catch-all routes backed by a CMS), pass an object with a `routes` function. The function receives the auto-discovered routes and returns the final list:
|
|
529
466
|
|
|
530
467
|
```ts
|
|
531
|
-
export default defineConfig(
|
|
468
|
+
export default defineConfig({
|
|
532
469
|
plugins: [
|
|
533
470
|
solas({
|
|
534
|
-
url: mode === 'production' ? 'https://example.com' : 'http://localhost:8787',
|
|
535
471
|
sitemap: {
|
|
536
472
|
async routes(existing) {
|
|
537
473
|
const posts = await getPosts()
|
|
@@ -540,7 +476,7 @@ export default defineConfig(({ mode }) => ({
|
|
|
540
476
|
},
|
|
541
477
|
}),
|
|
542
478
|
],
|
|
543
|
-
})
|
|
479
|
+
})
|
|
544
480
|
```
|
|
545
481
|
|
|
546
482
|
The `routes` function can be async. The callback also lets you filter routes:
|
|
@@ -581,6 +517,66 @@ export default defineConfig({
|
|
|
581
517
|
})
|
|
582
518
|
```
|
|
583
519
|
|
|
520
|
+
## Runtime
|
|
521
|
+
|
|
522
|
+
Solas uses a runtime for filesystem access, mime lookup, and hashing.
|
|
523
|
+
|
|
524
|
+
This is not a deployment or packaging adapter. Platform adapters are not available yet.
|
|
525
|
+
|
|
526
|
+
### Node runtime
|
|
527
|
+
|
|
528
|
+
If you want to pin Node explicitly, set `runtime: 'node'`:
|
|
529
|
+
|
|
530
|
+
```ts
|
|
531
|
+
import { defineConfig } from 'vite'
|
|
532
|
+
|
|
533
|
+
import solas from '@jk2908/solas'
|
|
534
|
+
import react from '@vitejs/plugin-react'
|
|
535
|
+
|
|
536
|
+
export default defineConfig({
|
|
537
|
+
plugins: [solas({ runtime: 'node' }), react()],
|
|
538
|
+
})
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
Use the normal Vite commands with the Node runtime:
|
|
542
|
+
|
|
543
|
+
```json
|
|
544
|
+
{
|
|
545
|
+
"scripts": {
|
|
546
|
+
"dev": "vite dev",
|
|
547
|
+
"build": "vite build",
|
|
548
|
+
"preview": "vite preview"
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Bun runtime
|
|
554
|
+
|
|
555
|
+
If you want Solas runtime code to execute in Bun, set `runtime: 'bun'`:
|
|
556
|
+
|
|
557
|
+
```ts
|
|
558
|
+
import { defineConfig } from 'vite'
|
|
559
|
+
|
|
560
|
+
import solas from '@jk2908/solas'
|
|
561
|
+
import react from '@vitejs/plugin-react'
|
|
562
|
+
|
|
563
|
+
export default defineConfig({
|
|
564
|
+
plugins: [solas({ runtime: 'bun' }), react()],
|
|
565
|
+
})
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
When you use the Bun runtime, run Vite through Bun so the server/runtime code executes in a Bun process:
|
|
569
|
+
|
|
570
|
+
```json
|
|
571
|
+
{
|
|
572
|
+
"scripts": {
|
|
573
|
+
"dev": "bunx --bun vite dev",
|
|
574
|
+
"build": "bunx --bun vite build",
|
|
575
|
+
"preview": "bunx --bun vite preview"
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
584
580
|
## Scripts
|
|
585
581
|
|
|
586
582
|
Add scripts to your app:
|
|
@@ -619,7 +615,7 @@ When available, Solas checks browser provenance using:
|
|
|
619
615
|
- `Origin`
|
|
620
616
|
- `Referer`
|
|
621
617
|
|
|
622
|
-
Solas also considers the effective request origin when your app is behind a proxy by using `X-Forwarded-Host
|
|
618
|
+
Solas also considers the effective request origin when your app is behind a proxy by using `X-Forwarded-Host` and `X-Forwarded-Proto`.
|
|
623
619
|
|
|
624
620
|
If you need to allow a trusted third-party browser POST source, configure it explicitly:
|
|
625
621
|
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PluginConfig } from './types.js';
|
|
2
|
+
export declare const NAME = "Solas";
|
|
3
|
+
export declare const SLUG: string;
|
|
4
|
+
export declare const PKG_NAME: string;
|
|
5
|
+
export declare const OUT_DIR = "dist";
|
|
6
|
+
export declare const APP_DIR = "app";
|
|
7
|
+
export declare const GENERATED_DIR: string;
|
|
8
|
+
export declare const ENTRY_RSC = "entry.rsc.tsx";
|
|
9
|
+
export declare const ENTRY_SSR = "entry.ssr.tsx";
|
|
10
|
+
export declare const ENTRY_BROWSER = "entry.browser.tsx";
|
|
11
|
+
export declare const ASSETS_DIR: string;
|
|
12
|
+
export declare const PUBLIC_DIR = "public";
|
|
13
|
+
export declare const $: unique symbol;
|
|
14
|
+
export declare const REQUEST_META_KEY: string;
|
|
15
|
+
export declare const LOG_LEVELS: readonly ["debug", "info", "warn", "error", "fatal"];
|
|
16
|
+
export declare const RUNTIMES: readonly ["auto", "node", "bun"];
|
|
17
|
+
export declare const PRERENDER_MODES: readonly ["full", "ppr", false];
|
|
18
|
+
export declare const TRAILING_SLASH_MODES: readonly ["always", "never", "ignore"];
|
|
19
|
+
export declare const RUNTIME_MANIFEST = "runtime-manifest.json";
|
|
20
|
+
/**
|
|
21
|
+
* Validate the plugin configuration object, throwing an error if invalid
|
|
22
|
+
* @param input - the unvalidated configuration object
|
|
23
|
+
* @return the typed and validated configuration object
|
|
24
|
+
*/
|
|
25
|
+
export declare function validate(input: unknown): PluginConfig;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as Config from './config.js';
|
|
2
|
+
export const NAME = 'Solas';
|
|
3
|
+
export const SLUG = NAME.toLowerCase();
|
|
4
|
+
export const PKG_NAME = `@jk2908/${SLUG}`;
|
|
5
|
+
export const OUT_DIR = 'dist';
|
|
6
|
+
export const APP_DIR = 'app';
|
|
7
|
+
export const GENERATED_DIR = `.${SLUG}`;
|
|
8
|
+
export const ENTRY_RSC = 'entry.rsc.tsx';
|
|
9
|
+
export const ENTRY_SSR = 'entry.ssr.tsx';
|
|
10
|
+
export const ENTRY_BROWSER = 'entry.browser.tsx';
|
|
11
|
+
export const ASSETS_DIR = `_${SLUG}`;
|
|
12
|
+
export const PUBLIC_DIR = 'public';
|
|
13
|
+
export const $ = Symbol(SLUG);
|
|
14
|
+
export const REQUEST_META_KEY = `__${SLUG.toUpperCase()}__`;
|
|
15
|
+
export const LOG_LEVELS = ['debug', 'info', 'warn', 'error', 'fatal'];
|
|
16
|
+
export const RUNTIMES = ['auto', 'node', 'bun'];
|
|
17
|
+
export const PRERENDER_MODES = ['full', 'ppr', false];
|
|
18
|
+
export const TRAILING_SLASH_MODES = ['always', 'never', 'ignore'];
|
|
19
|
+
export const RUNTIME_MANIFEST = 'runtime-manifest.json';
|
|
20
|
+
const CONFIG_KEYS = new Set([
|
|
21
|
+
'runtime',
|
|
22
|
+
'logger',
|
|
23
|
+
'metadata',
|
|
24
|
+
'precompress',
|
|
25
|
+
'prerender',
|
|
26
|
+
'sitemap',
|
|
27
|
+
'trustedOrigins',
|
|
28
|
+
'trailingSlash',
|
|
29
|
+
'url',
|
|
30
|
+
]);
|
|
31
|
+
const LOGGER_KEYS = new Set(['level']);
|
|
32
|
+
/**
|
|
33
|
+
* Validate the plugin configuration object, throwing an error if invalid
|
|
34
|
+
* @param input - the unvalidated configuration object
|
|
35
|
+
* @return the typed and validated configuration object
|
|
36
|
+
*/
|
|
37
|
+
export function validate(input) {
|
|
38
|
+
if (input === undefined)
|
|
39
|
+
return {};
|
|
40
|
+
const errors = [];
|
|
41
|
+
if (!isRecord(input)) {
|
|
42
|
+
throw new Error(`[${NAME}] Invalid config:\n- Expected plugin config to be an object`);
|
|
43
|
+
}
|
|
44
|
+
for (const key of Object.keys(input)) {
|
|
45
|
+
if (!CONFIG_KEYS.has(key)) {
|
|
46
|
+
errors.push(`Unknown config key: ${key}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if ('runtime' in input && input.runtime !== undefined && !isRuntime(input.runtime)) {
|
|
50
|
+
errors.push("runtime must be 'auto', 'node', or 'bun'");
|
|
51
|
+
}
|
|
52
|
+
if ('url' in input && input.url !== undefined) {
|
|
53
|
+
if (typeof input.url !== 'string') {
|
|
54
|
+
errors.push('url must be a string');
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
try {
|
|
58
|
+
const url = new URL(input.url);
|
|
59
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
60
|
+
errors.push('url must use http:// or https://');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
errors.push('url must be a valid URL');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if ('precompress' in input && input.precompress !== undefined) {
|
|
69
|
+
if (typeof input.precompress !== 'boolean') {
|
|
70
|
+
errors.push('precompress must be a boolean');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if ('trustedOrigins' in input && input.trustedOrigins !== undefined) {
|
|
74
|
+
if (!Array.isArray(input.trustedOrigins)) {
|
|
75
|
+
errors.push('trustedOrigins must be an array of origins');
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
for (const [index, value] of input.trustedOrigins.entries()) {
|
|
79
|
+
if (typeof value !== 'string') {
|
|
80
|
+
errors.push(`trustedOrigins[${index}] must be a string`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const url = new URL(value);
|
|
85
|
+
const canonical = value.replace(/\/$/, '');
|
|
86
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
87
|
+
errors.push(`trustedOrigins[${index}] must use http:// or https://`);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (canonical !== url.origin) {
|
|
91
|
+
errors.push(`trustedOrigins[${index}] must be an origin without a path, query, or hash`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
errors.push(`trustedOrigins[${index}] must be a valid URL origin`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if ('sitemap' in input && input.sitemap !== undefined && input.sitemap !== false) {
|
|
101
|
+
if (typeof input.sitemap !== 'boolean' && typeof input.sitemap !== 'object') {
|
|
102
|
+
errors.push('sitemap must be a boolean or an object with a routes function');
|
|
103
|
+
}
|
|
104
|
+
if (typeof input.sitemap === 'object' &&
|
|
105
|
+
input.sitemap !== null &&
|
|
106
|
+
typeof input.sitemap.routes !== 'function') {
|
|
107
|
+
errors.push('sitemap.routes must be a function');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if ('prerender' in input && input.prerender !== undefined) {
|
|
111
|
+
if (!new Set(PRERENDER_MODES).has(input.prerender)) {
|
|
112
|
+
errors.push("prerender must be 'full', 'ppr', or false");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if ('trailingSlash' in input && input.trailingSlash !== undefined) {
|
|
116
|
+
if (typeof input.trailingSlash !== 'string' ||
|
|
117
|
+
!new Set(TRAILING_SLASH_MODES).has(input.trailingSlash)) {
|
|
118
|
+
errors.push("trailingSlash must be 'always', 'never', or 'ignore'");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if ('metadata' in input && input.metadata !== undefined && !isRecord(input.metadata)) {
|
|
122
|
+
errors.push('metadata must be an object when provided');
|
|
123
|
+
}
|
|
124
|
+
if ('logger' in input && input.logger !== undefined) {
|
|
125
|
+
if (!isRecord(input.logger)) {
|
|
126
|
+
errors.push('logger must be an object when provided');
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
for (const key of Object.keys(input.logger)) {
|
|
130
|
+
if (!LOGGER_KEYS.has(key)) {
|
|
131
|
+
errors.push(`Unknown logger key: ${key}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if ('level' in input.logger && input.logger.level !== undefined) {
|
|
135
|
+
if (typeof input.logger.level !== 'string' ||
|
|
136
|
+
!new Set(LOG_LEVELS).has(input.logger.level)) {
|
|
137
|
+
errors.push('logger.level must be one of: debug, info, warn, error, fatal');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (errors.length > 0) {
|
|
143
|
+
throw new Error(`[${NAME}] Invalid config:\n- ${errors.join('\n- ')}`);
|
|
144
|
+
}
|
|
145
|
+
return input;
|
|
146
|
+
}
|
|
147
|
+
function isRecord(value) {
|
|
148
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
149
|
+
}
|
|
150
|
+
function isRuntime(value) {
|
|
151
|
+
return typeof value === 'string' && new Set(Config.RUNTIMES).has(value);
|
|
152
|
+
}
|
package/dist/events.d.ts
ADDED
package/dist/events.js
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,5 @@ import { type PluginOption } from 'vite';
|
|
|
2
2
|
import type { PluginConfig } from './types.js';
|
|
3
3
|
declare function solas(c?: PluginConfig): PluginOption[];
|
|
4
4
|
export default solas;
|
|
5
|
-
export
|
|
6
|
-
export { Solas } from './solas.js';
|
|
5
|
+
export * as Solas from './solas.js';
|
|
7
6
|
export type * from './types.js';
|