@jk2908/solas 0.4.4 → 0.5.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 +13 -0
- package/README.md +108 -10
- package/dist/adapters/bun.d.ts +12 -0
- package/dist/adapters/bun.js +39 -0
- package/dist/adapters/node.d.ts +11 -0
- package/dist/adapters/node.js +34 -0
- package/dist/index.js +15 -8
- package/dist/internal/browser-router/router.d.ts +1 -1
- package/dist/internal/browser-router/router.js +2 -2
- package/dist/internal/browser-router/shared.d.ts +1 -0
- package/dist/internal/browser-router/use-router.d.ts +1 -1
- package/dist/internal/build.js +14 -13
- package/dist/internal/codegen/config.js +3 -2
- package/dist/internal/codegen/environments.d.ts +2 -1
- package/dist/internal/codegen/environments.js +6 -4
- package/dist/internal/env/rsc.d.ts +1 -0
- package/dist/internal/env/rsc.js +1 -0
- package/dist/internal/http-router/router.js +8 -7
- package/dist/internal/postbuild.js +9 -8
- package/dist/internal/prerender.js +14 -13
- package/dist/internal/runtimes/bun.d.ts +9 -0
- package/dist/internal/runtimes/bun.js +33 -0
- package/dist/internal/runtimes/node.d.ts +9 -0
- package/dist/internal/runtimes/node.js +31 -0
- package/dist/internal/runtimes/runtime.d.ts +29 -0
- package/dist/internal/runtimes/runtime.js +32 -0
- package/dist/runtimes/bun.d.ts +13 -0
- package/dist/runtimes/bun.js +39 -0
- package/dist/solas.d.ts +4 -1
- package/dist/solas.js +27 -6
- package/dist/types.d.ts +6 -1
- package/dist/utils/compress.js +2 -2
- package/dist/utils/export-reader.js +69 -58
- package/package.json +9 -5
|
@@ -4,6 +4,7 @@ import { Compress } from '../utils/compress.js';
|
|
|
4
4
|
import { Logger } from '../utils/logger.js';
|
|
5
5
|
import { Solas } from '../solas.js';
|
|
6
6
|
import { Prerender } from './prerender.js';
|
|
7
|
+
import { Runtime } from './runtimes/runtime.js';
|
|
7
8
|
const logger = new Logger();
|
|
8
9
|
export async function postbuild(cwd = process.cwd()) {
|
|
9
10
|
const manifestPath = path.join(cwd, Solas.Config.GENERATED_DIR, 'build.json');
|
|
@@ -59,8 +60,8 @@ export async function postbuild(cwd = process.cwd()) {
|
|
|
59
60
|
if (artifact.mode === 'ppr') {
|
|
60
61
|
await fs.mkdir(artifactDir, { recursive: true });
|
|
61
62
|
const writes = [
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
Runtime.write(path.join(artifactDir, 'prelude.html'), artifact.html),
|
|
64
|
+
Runtime.write(path.join(artifactDir, 'metadata.json'), JSON.stringify({
|
|
64
65
|
schema: artifact.schema,
|
|
65
66
|
route: artifact.route,
|
|
66
67
|
createdAt: artifact.createdAt,
|
|
@@ -68,7 +69,7 @@ export async function postbuild(cwd = process.cwd()) {
|
|
|
68
69
|
})),
|
|
69
70
|
];
|
|
70
71
|
if (artifact.postponed !== undefined) {
|
|
71
|
-
writes.push(
|
|
72
|
+
writes.push(Runtime.write(path.join(artifactDir, 'postponed.json'), JSON.stringify(artifact.postponed)));
|
|
72
73
|
}
|
|
73
74
|
await Promise.all(writes);
|
|
74
75
|
artifactManifest[route] = {
|
|
@@ -82,13 +83,13 @@ export async function postbuild(cwd = process.cwd()) {
|
|
|
82
83
|
}
|
|
83
84
|
await fs.mkdir(artifactDir, { recursive: true });
|
|
84
85
|
await Promise.all([
|
|
85
|
-
|
|
86
|
+
Runtime.write(path.join(artifactDir, 'metadata.json'), JSON.stringify({
|
|
86
87
|
schema: artifact.schema,
|
|
87
88
|
route: artifact.route,
|
|
88
89
|
createdAt: artifact.createdAt,
|
|
89
90
|
mode: artifact.mode,
|
|
90
91
|
})),
|
|
91
|
-
|
|
92
|
+
Runtime.write(Prerender.Artifact.getFilePath(outDir, route, Prerender.Artifact.FULL_PRERENDER_FILENAME), artifact.html),
|
|
92
93
|
]);
|
|
93
94
|
artifactManifest[route] = {
|
|
94
95
|
mode: artifact.mode,
|
|
@@ -108,7 +109,7 @@ export async function postbuild(cwd = process.cwd()) {
|
|
|
108
109
|
artifacts: artifactManifest,
|
|
109
110
|
publicFiles: manifest.publicFiles,
|
|
110
111
|
};
|
|
111
|
-
await
|
|
112
|
+
await Runtime.write(Solas.Runtime.getManifestPath(outDir), JSON.stringify(runtimeManifest));
|
|
112
113
|
if (manifest.sitemapRoutes.length > 0 && manifest.url) {
|
|
113
114
|
const origin = manifest.url.replace(/\/$/, '');
|
|
114
115
|
const urls = manifest.sitemapRoutes
|
|
@@ -120,7 +121,7 @@ export async function postbuild(cwd = process.cwd()) {
|
|
|
120
121
|
urls,
|
|
121
122
|
'</urlset>',
|
|
122
123
|
].join('\n');
|
|
123
|
-
await
|
|
124
|
+
await Runtime.write(path.join(outDir, 'sitemap.xml'), sitemap);
|
|
124
125
|
logger.info('[sitemap]', `generated ${manifest.sitemapRoutes.length} urls`);
|
|
125
126
|
}
|
|
126
127
|
if (manifest.precompress) {
|
|
@@ -144,7 +145,7 @@ export async function postbuild(cwd = process.cwd()) {
|
|
|
144
145
|
normalisedPath.endsWith(`/${Prerender.Artifact.FULL_PRERENDER_FILENAME}`));
|
|
145
146
|
},
|
|
146
147
|
})) {
|
|
147
|
-
await
|
|
148
|
+
await Runtime.write(`${input}.br`, compressed);
|
|
148
149
|
logger.info('[precompress]', `${path.basename(input)}.br`);
|
|
149
150
|
}
|
|
150
151
|
}
|
|
@@ -4,6 +4,7 @@ import { BasePath } from '../utils/base-path.js';
|
|
|
4
4
|
import { Logger } from '../utils/logger.js';
|
|
5
5
|
import { Solas } from '../solas.js';
|
|
6
6
|
import { toPathPattern } from './http-router/utils.js';
|
|
7
|
+
import { Runtime as AdapterRuntime } from './runtimes/runtime.js';
|
|
7
8
|
const logger = new Logger();
|
|
8
9
|
export { Prerender };
|
|
9
10
|
var Prerender;
|
|
@@ -60,18 +61,18 @@ var Prerender;
|
|
|
60
61
|
* Load the postponed state for a given route from the file system, if it exists
|
|
61
62
|
*/
|
|
62
63
|
async function loadPostponedState(outDir, pathname) {
|
|
63
|
-
let
|
|
64
|
+
let filePath;
|
|
64
65
|
try {
|
|
65
|
-
|
|
66
|
+
filePath = path.join(getPath(outDir, pathname), 'postponed.json');
|
|
66
67
|
}
|
|
67
68
|
catch (err) {
|
|
68
69
|
logger.warn(`[prerender:artifacts] rejected postponed state path for ${pathname}`, Logger.print(err));
|
|
69
70
|
return null;
|
|
70
71
|
}
|
|
71
|
-
if (!(await
|
|
72
|
+
if (!(await AdapterRuntime.exists(filePath)))
|
|
72
73
|
return null;
|
|
73
74
|
try {
|
|
74
|
-
return JSON.parse(await
|
|
75
|
+
return JSON.parse(await AdapterRuntime.readText(filePath));
|
|
75
76
|
}
|
|
76
77
|
catch {
|
|
77
78
|
return null;
|
|
@@ -82,18 +83,18 @@ var Prerender;
|
|
|
82
83
|
* Load the prelude HTML for a given route from the file system, if it exists
|
|
83
84
|
*/
|
|
84
85
|
async function loadPrelude(outDir, pathname) {
|
|
85
|
-
let
|
|
86
|
+
let filePath;
|
|
86
87
|
try {
|
|
87
|
-
|
|
88
|
+
filePath = path.join(getPath(outDir, pathname), 'prelude.html');
|
|
88
89
|
}
|
|
89
90
|
catch (err) {
|
|
90
91
|
logger.warn(`[prerender:artifacts] rejected prelude path for ${pathname}`, Logger.print(err));
|
|
91
92
|
return null;
|
|
92
93
|
}
|
|
93
|
-
if (!(await
|
|
94
|
+
if (!(await AdapterRuntime.exists(filePath)))
|
|
94
95
|
return null;
|
|
95
96
|
try {
|
|
96
|
-
return await
|
|
97
|
+
return await AdapterRuntime.readText(filePath);
|
|
97
98
|
}
|
|
98
99
|
catch {
|
|
99
100
|
return null;
|
|
@@ -104,18 +105,18 @@ var Prerender;
|
|
|
104
105
|
* Load the prerender artifact metadata for a given route from the file system, if it exists and is valid
|
|
105
106
|
*/
|
|
106
107
|
async function loadMetadata(outDir, pathname) {
|
|
107
|
-
let
|
|
108
|
+
let filePath;
|
|
108
109
|
try {
|
|
109
|
-
|
|
110
|
+
filePath = path.join(getPath(outDir, pathname), 'metadata.json');
|
|
110
111
|
}
|
|
111
112
|
catch (err) {
|
|
112
113
|
logger.warn(`[prerender:artifacts] rejected metadata path for ${pathname}`, Logger.print(err));
|
|
113
114
|
return null;
|
|
114
115
|
}
|
|
115
|
-
if (!(await
|
|
116
|
+
if (!(await AdapterRuntime.exists(filePath)))
|
|
116
117
|
return null;
|
|
117
118
|
try {
|
|
118
|
-
const value = JSON.parse(await
|
|
119
|
+
const value = JSON.parse(await AdapterRuntime.readText(filePath));
|
|
119
120
|
if (!value || typeof value !== 'object')
|
|
120
121
|
return null;
|
|
121
122
|
const schema = value.schema;
|
|
@@ -270,7 +271,7 @@ var Prerender;
|
|
|
270
271
|
const params = await buildContext.exportReader.value(filePath, 'params', (v) => typeof v === 'function');
|
|
271
272
|
if (!params)
|
|
272
273
|
return [];
|
|
273
|
-
const resolved = await Promise.
|
|
274
|
+
const resolved = await Promise.resolve().then(() => params());
|
|
274
275
|
if (!Array.isArray(resolved))
|
|
275
276
|
return [];
|
|
276
277
|
return resolved;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RuntimeBase } from './runtime.js';
|
|
2
|
+
export declare class RuntimeBun extends RuntimeBase {
|
|
3
|
+
exists(filePath: string): Promise<boolean>;
|
|
4
|
+
readText(filePath: string): Promise<string>;
|
|
5
|
+
readBuffer(filePath: string): Promise<ArrayBuffer>;
|
|
6
|
+
mimeType(filePath: string): string;
|
|
7
|
+
write(filePath: string, content: string | NodeJS.ArrayBufferView): Promise<void>;
|
|
8
|
+
hash(value: string): string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { RuntimeBase } from './runtime.js';
|
|
2
|
+
export class RuntimeBun extends RuntimeBase {
|
|
3
|
+
async exists(filePath) {
|
|
4
|
+
return Bun.file(filePath).exists();
|
|
5
|
+
}
|
|
6
|
+
readText(filePath) {
|
|
7
|
+
return Bun.file(filePath).text();
|
|
8
|
+
}
|
|
9
|
+
readBuffer(filePath) {
|
|
10
|
+
return Bun.file(filePath).arrayBuffer();
|
|
11
|
+
}
|
|
12
|
+
mimeType(filePath) {
|
|
13
|
+
return Bun.file(filePath).type || 'application/octet-stream';
|
|
14
|
+
}
|
|
15
|
+
async write(filePath, content) {
|
|
16
|
+
// normalise wider arraybuffer views into a shape Bun.write accepts directly
|
|
17
|
+
await Bun.write(filePath, typeof content === 'string'
|
|
18
|
+
? content
|
|
19
|
+
: content instanceof Uint8Array
|
|
20
|
+
? content
|
|
21
|
+
: new Uint8Array(content.buffer, content.byteOffset, content.byteLength));
|
|
22
|
+
}
|
|
23
|
+
hash(value) {
|
|
24
|
+
const hash = Bun.hash(value);
|
|
25
|
+
// Bun.hash returns an integer-like value, so keep it in BigInt space and avoid
|
|
26
|
+
// precision loss. Clamp it to an unsigned 64-bit value before hex
|
|
27
|
+
// formatting. Pad to 16 chars to match the Node runtime
|
|
28
|
+
// output shape
|
|
29
|
+
return BigInt.asUintN(64, typeof hash === 'bigint' ? hash : BigInt(hash))
|
|
30
|
+
.toString(16)
|
|
31
|
+
.padStart(16, '0');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RuntimeBase } from './runtime.js';
|
|
2
|
+
export declare class RuntimeNode extends RuntimeBase {
|
|
3
|
+
exists(filePath: string): Promise<boolean>;
|
|
4
|
+
readText(filePath: string): Promise<string>;
|
|
5
|
+
readBuffer(filePath: string): Promise<ArrayBuffer>;
|
|
6
|
+
mimeType(filePath: string): string;
|
|
7
|
+
write(filePath: string, content: string | NodeJS.ArrayBufferView): Promise<void>;
|
|
8
|
+
hash(value: string): string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import { lookup } from 'mime-types';
|
|
4
|
+
import { RuntimeBase } from './runtime.js';
|
|
5
|
+
export class RuntimeNode extends RuntimeBase {
|
|
6
|
+
async exists(filePath) {
|
|
7
|
+
try {
|
|
8
|
+
await fs.access(filePath);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
readText(filePath) {
|
|
16
|
+
return fs.readFile(filePath, 'utf-8');
|
|
17
|
+
}
|
|
18
|
+
async readBuffer(filePath) {
|
|
19
|
+
const buffer = await fs.readFile(filePath);
|
|
20
|
+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
21
|
+
}
|
|
22
|
+
mimeType(filePath) {
|
|
23
|
+
return lookup(filePath) || 'application/octet-stream';
|
|
24
|
+
}
|
|
25
|
+
async write(filePath, content) {
|
|
26
|
+
await fs.writeFile(filePath, content);
|
|
27
|
+
}
|
|
28
|
+
hash(value) {
|
|
29
|
+
return createHash('sha256').update(value).digest('hex').slice(0, 16);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare namespace Runtime {
|
|
2
|
+
type Impl = {
|
|
3
|
+
exists: (filePath: string) => Promise<boolean>;
|
|
4
|
+
readText: (filePath: string) => Promise<string>;
|
|
5
|
+
readBuffer: (filePath: string) => Promise<ArrayBuffer>;
|
|
6
|
+
mimeType: (filePath: string) => string;
|
|
7
|
+
write: (filePath: string, content: string | NodeJS.ArrayBufferView) => Promise<void>;
|
|
8
|
+
hash: (value: string) => string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare abstract class RuntimeBase implements Runtime.Impl {
|
|
12
|
+
abstract exists(filePath: string): Promise<boolean>;
|
|
13
|
+
abstract readText(filePath: string): Promise<string>;
|
|
14
|
+
abstract readBuffer(filePath: string): Promise<ArrayBuffer>;
|
|
15
|
+
abstract mimeType(filePath: string): string;
|
|
16
|
+
abstract write(filePath: string, content: string | NodeJS.ArrayBufferView): Promise<void>;
|
|
17
|
+
abstract hash(value: string): string;
|
|
18
|
+
}
|
|
19
|
+
export declare class Runtime {
|
|
20
|
+
#private;
|
|
21
|
+
static set runtime(runtime: Runtime.Impl);
|
|
22
|
+
static get runtime(): Runtime.Impl;
|
|
23
|
+
static exists(filePath: string): Promise<boolean>;
|
|
24
|
+
static readText(filePath: string): Promise<string>;
|
|
25
|
+
static readBuffer(filePath: string): Promise<ArrayBuffer>;
|
|
26
|
+
static mimeType(filePath: string): string;
|
|
27
|
+
static write(filePath: string, content: string | NodeJS.ArrayBufferView): Promise<void>;
|
|
28
|
+
static hash(value: string): string;
|
|
29
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export class RuntimeBase {
|
|
2
|
+
}
|
|
3
|
+
export class Runtime {
|
|
4
|
+
static #runtime;
|
|
5
|
+
static set runtime(runtime) {
|
|
6
|
+
this.#runtime = runtime;
|
|
7
|
+
}
|
|
8
|
+
static get runtime() {
|
|
9
|
+
if (!this.#runtime) {
|
|
10
|
+
throw new Error('No runtime configured. Please set the runtime implementation before using runtime methods.');
|
|
11
|
+
}
|
|
12
|
+
return this.#runtime;
|
|
13
|
+
}
|
|
14
|
+
static exists(filePath) {
|
|
15
|
+
return this.runtime.exists(filePath);
|
|
16
|
+
}
|
|
17
|
+
static readText(filePath) {
|
|
18
|
+
return this.runtime.readText(filePath);
|
|
19
|
+
}
|
|
20
|
+
static readBuffer(filePath) {
|
|
21
|
+
return this.runtime.readBuffer(filePath);
|
|
22
|
+
}
|
|
23
|
+
static mimeType(filePath) {
|
|
24
|
+
return this.runtime.mimeType(filePath);
|
|
25
|
+
}
|
|
26
|
+
static write(filePath, content) {
|
|
27
|
+
return this.runtime.write(filePath, content);
|
|
28
|
+
}
|
|
29
|
+
static hash(value) {
|
|
30
|
+
return this.runtime.hash(value);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RuntimeBase } from '../internal/runtimes/runtime.js';
|
|
2
|
+
declare class BunAdapter extends RuntimeBase {
|
|
3
|
+
readonly name: "bun";
|
|
4
|
+
readonly module: string;
|
|
5
|
+
exists(filePath: string): Promise<boolean>;
|
|
6
|
+
readText(filePath: string): Promise<string>;
|
|
7
|
+
readBuffer(filePath: string): Promise<ArrayBuffer>;
|
|
8
|
+
mimeType(filePath: string): string;
|
|
9
|
+
write(filePath: string, content: string | NodeJS.ArrayBufferView): Promise<void>;
|
|
10
|
+
hash(value: string): string;
|
|
11
|
+
}
|
|
12
|
+
export default function bunAdapter(): BunAdapter;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RuntimeBase } from '../internal/runtimes/runtime.js';
|
|
2
|
+
import { Solas } from '../solas.js';
|
|
3
|
+
class BunAdapter extends RuntimeBase {
|
|
4
|
+
name = 'bun';
|
|
5
|
+
module = `${Solas.Config.PKG_NAME}/runtimes/bun`;
|
|
6
|
+
async exists(filePath) {
|
|
7
|
+
return Bun.file(filePath).exists();
|
|
8
|
+
}
|
|
9
|
+
readText(filePath) {
|
|
10
|
+
return Bun.file(filePath).text();
|
|
11
|
+
}
|
|
12
|
+
readBuffer(filePath) {
|
|
13
|
+
return Bun.file(filePath).arrayBuffer();
|
|
14
|
+
}
|
|
15
|
+
mimeType(filePath) {
|
|
16
|
+
return Bun.file(filePath).type || 'application/octet-stream';
|
|
17
|
+
}
|
|
18
|
+
async write(filePath, content) {
|
|
19
|
+
// normalise wider arraybuffer views into a shape Bun.write accepts directly
|
|
20
|
+
await Bun.write(filePath, typeof content === 'string'
|
|
21
|
+
? content
|
|
22
|
+
: content instanceof Uint8Array
|
|
23
|
+
? content
|
|
24
|
+
: new Uint8Array(content.buffer, content.byteOffset, content.byteLength));
|
|
25
|
+
}
|
|
26
|
+
hash(value) {
|
|
27
|
+
const hash = Bun.hash(value);
|
|
28
|
+
// Bun.hash returns an integer-like value, so keep it in BigInt space and avoid
|
|
29
|
+
// precision loss. Clamp it to an unsigned 64-bit value before hex
|
|
30
|
+
// formatting. Pad to 16 chars to match the Node adapter
|
|
31
|
+
// output shape
|
|
32
|
+
return BigInt.asUintN(64, typeof hash === 'bigint' ? hash : BigInt(hash))
|
|
33
|
+
.toString(16)
|
|
34
|
+
.padStart(16, '0');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export default function bunAdapter() {
|
|
38
|
+
return new BunAdapter();
|
|
39
|
+
}
|
package/dist/solas.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Prerender } from './internal/prerender.js';
|
|
2
|
-
import type { PluginConfig } from './types.js';
|
|
2
|
+
import type { PluginConfig, Runtime } from './types.js';
|
|
3
|
+
import { Runtime as InternalRuntime } from './internal/runtimes/runtime.js';
|
|
3
4
|
export declare namespace Solas {
|
|
4
5
|
interface Routes {
|
|
5
6
|
}
|
|
@@ -18,6 +19,7 @@ export declare namespace Solas {
|
|
|
18
19
|
const $: unique symbol;
|
|
19
20
|
const REQUEST_META_KEY: string;
|
|
20
21
|
const LOG_LEVELS: readonly ["debug", "info", "warn", "error", "fatal"];
|
|
22
|
+
const RUNTIMES: readonly ["auto", "node", "bun"];
|
|
21
23
|
const PRERENDER_MODES: readonly ["full", "ppr", false];
|
|
22
24
|
const TRAILING_SLASH_MODES: readonly ["always", "never", "ignore"];
|
|
23
25
|
const RUNTIME_MANIFEST = "runtime-manifest.json";
|
|
@@ -34,6 +36,7 @@ export declare namespace Solas {
|
|
|
34
36
|
artifacts: Prerender.Artifact.Manifest;
|
|
35
37
|
publicFiles: ReadonlySet<string>;
|
|
36
38
|
};
|
|
39
|
+
function create(runtime: Runtime): InternalRuntime.Impl;
|
|
37
40
|
function getManifestPath(outDir: string): string;
|
|
38
41
|
function loadManifest(outDir: string): Promise<Manifest | null>;
|
|
39
42
|
}
|
package/dist/solas.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { RuntimeBun } from './internal/runtimes/bun.js';
|
|
2
|
+
import { RuntimeNode } from './internal/runtimes/node.js';
|
|
3
|
+
import { Runtime as InternalRuntime } from './internal/runtimes/runtime.js';
|
|
1
4
|
export { Solas };
|
|
2
5
|
var Solas;
|
|
3
6
|
(function (Solas) {
|
|
@@ -17,10 +20,12 @@ var Solas;
|
|
|
17
20
|
Config.$ = Symbol(Config.SLUG);
|
|
18
21
|
Config.REQUEST_META_KEY = `__${Config.SLUG.toUpperCase()}__`;
|
|
19
22
|
Config.LOG_LEVELS = ['debug', 'info', 'warn', 'error', 'fatal'];
|
|
23
|
+
Config.RUNTIMES = ['auto', 'node', 'bun'];
|
|
20
24
|
Config.PRERENDER_MODES = ['full', 'ppr', false];
|
|
21
25
|
Config.TRAILING_SLASH_MODES = ['always', 'never', 'ignore'];
|
|
22
26
|
Config.RUNTIME_MANIFEST = 'runtime-manifest.json';
|
|
23
27
|
const CONFIG_KEYS = new Set([
|
|
28
|
+
'runtime',
|
|
24
29
|
'port',
|
|
25
30
|
'logger',
|
|
26
31
|
'metadata',
|
|
@@ -49,6 +54,11 @@ var Solas;
|
|
|
49
54
|
errors.push(`Unknown config key: ${key}`);
|
|
50
55
|
}
|
|
51
56
|
}
|
|
57
|
+
if ('runtime' in input &&
|
|
58
|
+
input.runtime !== undefined &&
|
|
59
|
+
!isRuntime(input.runtime)) {
|
|
60
|
+
errors.push("config.runtime must be 'auto', 'node', or 'bun'");
|
|
61
|
+
}
|
|
52
62
|
if ('url' in input && input.url !== undefined) {
|
|
53
63
|
if (typeof input.url !== 'string') {
|
|
54
64
|
errors.push('config.url must be a string');
|
|
@@ -161,6 +171,14 @@ var Solas;
|
|
|
161
171
|
Solas.getVersion = getVersion;
|
|
162
172
|
let Runtime;
|
|
163
173
|
(function (Runtime) {
|
|
174
|
+
function create(runtime) {
|
|
175
|
+
if (runtime === 'bun' ||
|
|
176
|
+
(runtime === 'auto' && typeof globalThis.Bun !== 'undefined')) {
|
|
177
|
+
return new RuntimeBun();
|
|
178
|
+
}
|
|
179
|
+
return new RuntimeNode();
|
|
180
|
+
}
|
|
181
|
+
Runtime.create = create;
|
|
164
182
|
const manifestCache = new Map();
|
|
165
183
|
function getManifestPath(outDir) {
|
|
166
184
|
return [outDir, Config.GENERATED_DIR, Config.RUNTIME_MANIFEST]
|
|
@@ -177,13 +195,13 @@ var Solas;
|
|
|
177
195
|
if (manifestCache.has(outDir)) {
|
|
178
196
|
return manifestCache.get(outDir) ?? null;
|
|
179
197
|
}
|
|
180
|
-
const
|
|
181
|
-
if (!(await
|
|
198
|
+
const manifestPath = getManifestPath(outDir);
|
|
199
|
+
if (!(await InternalRuntime.exists(manifestPath))) {
|
|
182
200
|
manifestCache.set(outDir, null);
|
|
183
201
|
return null;
|
|
184
202
|
}
|
|
185
203
|
try {
|
|
186
|
-
const value = JSON.parse(await
|
|
204
|
+
const value = JSON.parse(await InternalRuntime.readText(manifestPath));
|
|
187
205
|
if (!isRecord(value)) {
|
|
188
206
|
manifestCache.set(outDir, null);
|
|
189
207
|
return null;
|
|
@@ -230,12 +248,12 @@ var Solas;
|
|
|
230
248
|
return null;
|
|
231
249
|
}
|
|
232
250
|
}
|
|
233
|
-
const
|
|
251
|
+
const runtimeManifest = {
|
|
234
252
|
artifacts: artifacts,
|
|
235
253
|
publicFiles: new Set(publicFiles ?? []),
|
|
236
254
|
};
|
|
237
|
-
manifestCache.set(outDir,
|
|
238
|
-
return
|
|
255
|
+
manifestCache.set(outDir, runtimeManifest);
|
|
256
|
+
return runtimeManifest;
|
|
239
257
|
}
|
|
240
258
|
catch {
|
|
241
259
|
manifestCache.set(outDir, null);
|
|
@@ -255,3 +273,6 @@ var Solas;
|
|
|
255
273
|
function isRecord(value) {
|
|
256
274
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
257
275
|
}
|
|
276
|
+
function isRuntime(value) {
|
|
277
|
+
return typeof value === 'string' && new Set(Solas.Config.RUNTIMES).has(value);
|
|
278
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -9,8 +9,10 @@ import type { Metadata } from './internal/metadata.js';
|
|
|
9
9
|
import type { HttpException } from './internal/navigation/http-exception.js';
|
|
10
10
|
import { Solas } from './solas.js';
|
|
11
11
|
export type LogLevel = (typeof Solas.Config.LOG_LEVELS)[number];
|
|
12
|
+
export type Runtime = (typeof Solas.Config.RUNTIMES)[number];
|
|
12
13
|
type Origin = `http://${string}` | `https://${string}`;
|
|
13
14
|
type PluginConfigBase = {
|
|
15
|
+
runtime?: Runtime;
|
|
14
16
|
port?: number;
|
|
15
17
|
precompress?: boolean;
|
|
16
18
|
prerender?: Route.Prerender;
|
|
@@ -30,7 +32,10 @@ export type PluginConfig = PluginConfigBase & ({
|
|
|
30
32
|
url?: Origin;
|
|
31
33
|
sitemap?: false;
|
|
32
34
|
});
|
|
33
|
-
export type
|
|
35
|
+
export type ConfiguredPluginConfig = PluginConfig & {
|
|
36
|
+
runtime: Runtime;
|
|
37
|
+
};
|
|
38
|
+
export type RuntimeConfig = Omit<PluginConfig, 'runtime'> & {
|
|
34
39
|
precompress: NonNullable<PluginConfig['precompress']>;
|
|
35
40
|
trailingSlash: NonNullable<PluginConfig['trailingSlash']>;
|
|
36
41
|
trustedOrigins: NonNullable<PluginConfig['trustedOrigins']>;
|
package/dist/utils/compress.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from 'node:fs/promises';
|
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { brotliCompress } from 'node:zlib';
|
|
5
|
+
import { Runtime } from '../internal/runtimes/runtime.js';
|
|
5
6
|
export { Compress };
|
|
6
7
|
var Compress;
|
|
7
8
|
(function (Compress) {
|
|
@@ -25,8 +26,7 @@ var Compress;
|
|
|
25
26
|
return output;
|
|
26
27
|
}
|
|
27
28
|
async function compress(input) {
|
|
28
|
-
const
|
|
29
|
-
const buffer = Buffer.from(await file.arrayBuffer());
|
|
29
|
+
const buffer = Buffer.from(await Runtime.readBuffer(input));
|
|
30
30
|
const compressed = await new Promise((fulfill, reject) => {
|
|
31
31
|
brotliCompress(buffer, (err, res) => {
|
|
32
32
|
if (err) {
|