@marko/run 0.0.1-beta7 → 0.0.1-beta8
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 +204 -49
- package/dist/adapter/index.cjs +27 -6
- package/dist/adapter/index.js +27 -6
- package/dist/adapter/middleware.cjs +12 -2
- package/dist/adapter/middleware.d.ts +2 -0
- package/dist/adapter/middleware.js +12 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/vite/index.cjs +1 -1
- package/dist/vite/index.js +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
</a>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
|
-
`@marko/run`
|
|
18
|
+
`@marko/run` will help you get up and *running* with [Marko](https://markojs.com)
|
|
19
19
|
|
|
20
20
|
- Vite plugin that encapsulates [`@marko/vite`](https://github.com/marko-js/vite)
|
|
21
21
|
- CLI to simplify build modes
|
|
@@ -36,10 +36,12 @@ The package provides a command line tool `marko-run` which can be run using scri
|
|
|
36
36
|
|
|
37
37
|
### Getting Started / Zero Config
|
|
38
38
|
|
|
39
|
+
|
|
40
|
+
|
|
39
41
|
`marko-run` makes it easy to get started without little to no config. The package ships with a default Vite config and node-based adapter that means a minimal project start can be:
|
|
40
42
|
1. Install `@marko/run`
|
|
41
43
|
2. Create file `src/routes/+page.marko`
|
|
42
|
-
3. Run `npx marko-run
|
|
44
|
+
3. Run `npx marko-run`
|
|
43
45
|
4. Open browser to `http://localhost:3000`
|
|
44
46
|
|
|
45
47
|
### Commands
|
|
@@ -48,6 +50,11 @@ The package provides a command line tool `marko-run` which can be run using scri
|
|
|
48
50
|
```bash
|
|
49
51
|
> npx marko-run dev
|
|
50
52
|
```
|
|
53
|
+
or (default command)
|
|
54
|
+
```bash
|
|
55
|
+
> npx marko-run
|
|
56
|
+
```
|
|
57
|
+
|
|
51
58
|
|
|
52
59
|
**`build`** - Create a production build
|
|
53
60
|
```bash
|
|
@@ -58,11 +65,6 @@ The package provides a command line tool `marko-run` which can be run using scri
|
|
|
58
65
|
```bash
|
|
59
66
|
> npx marko-run serve
|
|
60
67
|
```
|
|
61
|
-
or (default command)
|
|
62
|
-
```bash
|
|
63
|
-
> npx marko-run
|
|
64
|
-
```
|
|
65
|
-
|
|
66
68
|
## Vite Plugin
|
|
67
69
|
|
|
68
70
|
This package’s Vite plugin discovers your route files, generates the routing code, and registers the `@marko/vite` plugin to compile your `.marko` files.
|
|
@@ -73,15 +75,36 @@ import { defineConfig } from "vite";
|
|
|
73
75
|
import marko from "@marko/run/vite"; // Import the Vite plugin
|
|
74
76
|
|
|
75
77
|
export default defineConfig({
|
|
76
|
-
plugins: [marko()]
|
|
78
|
+
plugins: [marko()] // Register the Vite plugin
|
|
77
79
|
})
|
|
78
80
|
```
|
|
79
81
|
|
|
80
82
|
## Adapters
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
Adapters provide the means to change the development, build and preview process to fit different deployment platforms and runtimes while allowing authors to write idiomatic code.
|
|
85
|
+
|
|
86
|
+
### Configure
|
|
87
|
+
|
|
88
|
+
Specify your adapter in the Vite config when registering the `@marko/run` plugin
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
// vite.config.ts
|
|
92
|
+
import { defineConfig } from "vite";
|
|
93
|
+
import marko from "@marko/run/vite";
|
|
94
|
+
import netlify from "@makor/run-adapter-netlify" // Import the adapter
|
|
95
|
+
|
|
96
|
+
export default defineConfig({
|
|
97
|
+
plugins: [marko({
|
|
98
|
+
adapter: netlify({ edge: true }) // Configure and apply the adapter
|
|
99
|
+
})]
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Adapter List
|
|
83
104
|
|
|
84
|
-
|
|
105
|
+
- ### [@marko/run-adapter-node](./packages/adapters/node/README.md)
|
|
106
|
+
- ### [@marko/run-adapter-netlify](./packages/adapters/netlify/README.md)
|
|
107
|
+
- ### [@marko/run-adapter-static](./packages/adapters/static/README.md)
|
|
85
108
|
|
|
86
109
|
## Runtime
|
|
87
110
|
|
|
@@ -91,18 +114,52 @@ Generally, when using an adapter, this runtime will be abstracted away.
|
|
|
91
114
|
<!-- TODO: Split fetch and match + invoke in two sections and explain why you might use one or the other -->
|
|
92
115
|
|
|
93
116
|
```ts
|
|
94
|
-
import
|
|
117
|
+
import * as Run from '@marko/run/router`;
|
|
95
118
|
```
|
|
96
119
|
|
|
97
|
-
###
|
|
120
|
+
### Emdedding in Existing Server
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
### `Run.fetch`
|
|
98
125
|
|
|
99
126
|
```ts
|
|
100
127
|
async function fetch<T>(request: Request, platform: T) => Promise<Response | void>;
|
|
101
128
|
```
|
|
102
129
|
|
|
130
|
+
|
|
131
|
+
|
|
103
132
|
This asynchronous function takes a [WHATWG `Request` object](https://fetch.spec.whatwg.org/#request-class) object and an object containing any platform specific data you may want access to and returns the [WHATWG `Response` object](https://fetch.spec.whatwg.org/#response-class) from executing any matched route files or undefined if the request was explicitly not handled. If no route matches the requested path, a `404` status code response will be returned. If an error occurs a `500` status code response will be returned.
|
|
104
133
|
|
|
105
|
-
|
|
134
|
+
Express example:
|
|
135
|
+
```ts
|
|
136
|
+
import express from "express";
|
|
137
|
+
import * as Run from "@marko/run/router";
|
|
138
|
+
|
|
139
|
+
express()
|
|
140
|
+
.use(async (req, res, next) => {
|
|
141
|
+
const request = // ...code to create a WHATWG Request from `req`
|
|
142
|
+
|
|
143
|
+
const response = await Run.fetch(request, {
|
|
144
|
+
req,
|
|
145
|
+
res
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (response) {
|
|
149
|
+
// ...code to apply response to `res`
|
|
150
|
+
} else {
|
|
151
|
+
next();
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
.listen(3000);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
### Other APIs
|
|
159
|
+
|
|
160
|
+
In some cases you might want more control over when route matching and invokation (creating a response) occur. For instance you may have middleware in your server which need to know if there is a matched route. The runtime provides these additional methods
|
|
161
|
+
|
|
162
|
+
### `Run.match`
|
|
106
163
|
|
|
107
164
|
```ts
|
|
108
165
|
interface interface Route {
|
|
@@ -118,12 +175,49 @@ This synchronous function takes an HTTP method and path name, then returns an ob
|
|
|
118
175
|
- `params` - a `{ key: value }` collection of any path parameters for the route
|
|
119
176
|
- `meta` - metadata for the route
|
|
120
177
|
|
|
121
|
-
### `invoke`
|
|
178
|
+
### `Run.invoke`
|
|
122
179
|
|
|
123
180
|
```ts
|
|
124
181
|
async function invoke<T>(route: Route, request: Request, platform: T) => Promise<Response | void>;
|
|
125
182
|
```
|
|
126
|
-
This asynchronous function takes a route object returned by [match](#match) the request and platform data and returns a response in the same way the [fetch](#fetch) does.
|
|
183
|
+
This asynchronous function takes a route object returned by [Run.match](#Run.match) the request and platform data and returns a response in the same way the [Run.fetch](#Run.fetch) does.
|
|
184
|
+
|
|
185
|
+
Express example:
|
|
186
|
+
```ts
|
|
187
|
+
import express from "express";
|
|
188
|
+
import * as Run from "@marko/run/router";
|
|
189
|
+
|
|
190
|
+
express()
|
|
191
|
+
.use((req, res) => {
|
|
192
|
+
const matchedRoute = Run.match(req.method, req.path);
|
|
193
|
+
if (matchedRoute) {
|
|
194
|
+
req.match = matchedRoute;
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// ...other middleware
|
|
199
|
+
|
|
200
|
+
.use(async (req, res, next) => {
|
|
201
|
+
// Check if a route was previously matched
|
|
202
|
+
if (!req.match) {
|
|
203
|
+
next();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const request = // ...code to create a WHATWG Request from `req`
|
|
208
|
+
const response = await Run.invoke(req.match, request, {
|
|
209
|
+
req,
|
|
210
|
+
res
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
if (response) {
|
|
214
|
+
// ...code to apply response to `res`
|
|
215
|
+
} else {
|
|
216
|
+
next();
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
.listen(3000);
|
|
220
|
+
```
|
|
127
221
|
|
|
128
222
|
|
|
129
223
|
|
|
@@ -184,26 +278,35 @@ Typically, these will be `.js` or `.ts` files depending on your project. Like pa
|
|
|
184
278
|
<details>
|
|
185
279
|
<summary>More Info</summary>
|
|
186
280
|
|
|
187
|
-
- Valid exports are functions named `
|
|
188
|
-
-
|
|
189
|
-
-
|
|
190
|
-
-
|
|
281
|
+
- Valid exports are functions named `GET`, `POST`, `PUT`, or `DELETE`.
|
|
282
|
+
- Exports can be one of the following
|
|
283
|
+
- Handler function (see below)
|
|
284
|
+
- Array of handler functions - will be composed by calling them in order
|
|
285
|
+
- Promise that resolves to a handler function or array of handler functions
|
|
286
|
+
- Handler functions are synchronous or asynchronous functions that
|
|
287
|
+
- Receives a `context` and `next` argument,
|
|
288
|
+
- The `context` argument contains the WHATWG request object, path parameters, URL, and route metadata.
|
|
289
|
+
- The `next` argument will call the page for get requests where applicable or return a `204` response.
|
|
290
|
+
- Return a WHATWG response, throw a WHATWG response, return undefined. If the function return's undefined the `next` argument with be automatically called and used as the response.
|
|
191
291
|
|
|
192
292
|
```js
|
|
193
|
-
export function
|
|
293
|
+
export function POST(context, next) {
|
|
194
294
|
const { request, params, url, meta } = context;
|
|
195
295
|
return new Response('Successfully updated', { status: 200 });
|
|
196
296
|
}
|
|
197
297
|
|
|
198
|
-
export function
|
|
199
|
-
|
|
298
|
+
export function PUT(context, next) {
|
|
299
|
+
// `next` will be called for you by the runtime
|
|
200
300
|
}
|
|
201
301
|
|
|
202
|
-
export function
|
|
203
|
-
|
|
302
|
+
export async function GET(context, next) {
|
|
303
|
+
// do something before calling `next`
|
|
304
|
+
const response = await next();
|
|
305
|
+
// do something with the response from `next`
|
|
306
|
+
return response;
|
|
204
307
|
}
|
|
205
308
|
|
|
206
|
-
export function
|
|
309
|
+
export function DELETE(context, next) {
|
|
207
310
|
return new Response('Successfully removed', { status: 204 });
|
|
208
311
|
}
|
|
209
312
|
```
|
|
@@ -219,18 +322,23 @@ These files are like layouts, but for handlers. Middleware get called before han
|
|
|
219
322
|
<details>
|
|
220
323
|
<summary>More Info</summary>
|
|
221
324
|
|
|
222
|
-
Expects a `default` export that
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
325
|
+
- Expects a `default` export that can be one of the following
|
|
326
|
+
- Handler function (see below)
|
|
327
|
+
- Array of handler functions - will be composed by calling them in order
|
|
328
|
+
- Promise that resolves to a handler function or array of handler functions
|
|
329
|
+
- Handler functions are synchronous or asynchronous functions that
|
|
330
|
+
- Receives a `context` and `next` argument,
|
|
331
|
+
- The `context` argument contains the WHATWG request object, path parameters, URL, and route metadata.
|
|
332
|
+
- The `next` argument will call the page for get requests where applicable or return a `204` response.
|
|
333
|
+
- Return a WHATWG response, throw a WHATWG response, return undefined. If the function return's undefined the `next` argument with be automatically called and used as the response.
|
|
226
334
|
|
|
227
335
|
```ts
|
|
228
336
|
export default async function(context, next) {
|
|
229
|
-
const requestName = `${
|
|
337
|
+
const requestName = `${context.request.method} ${context.url.href}`;
|
|
230
338
|
let success = true;
|
|
231
339
|
console.log(`${requestName} request started`)
|
|
232
340
|
try {
|
|
233
|
-
return await next(); // Wait for subsequent middleware
|
|
341
|
+
return await next(); // Wait for subsequent middleware, handler and page
|
|
234
342
|
} catch (err) {
|
|
235
343
|
success = false;
|
|
236
344
|
throw err;
|
|
@@ -243,7 +351,9 @@ These files are like layouts, but for handlers. Middleware get called before han
|
|
|
243
351
|
|
|
244
352
|
#### `+meta.*`
|
|
245
353
|
|
|
246
|
-
These files represent metadata to attach to the route. This metadata will be automatically provided on the the route `context` when invoking a route.
|
|
354
|
+
These files represent static metadata to attach to the route. This metadata will be automatically provided on the the route `context` when invoking a route.
|
|
355
|
+
|
|
356
|
+
|
|
247
357
|
|
|
248
358
|
### Special Files
|
|
249
359
|
|
|
@@ -271,9 +381,21 @@ Responses with this page will have a `500` status code.
|
|
|
271
381
|
|
|
272
382
|
### Execution Order
|
|
273
383
|
|
|
274
|
-
|
|
384
|
+
Given the following routes directory structure
|
|
275
385
|
|
|
276
|
-
|
|
386
|
+
<pre>
|
|
387
|
+
routes/
|
|
388
|
+
about/
|
|
389
|
+
+handler.js
|
|
390
|
+
+layout.marko
|
|
391
|
+
+middleware.js
|
|
392
|
+
+page.marko
|
|
393
|
+
+layout.marko
|
|
394
|
+
+middleware.js
|
|
395
|
+
+page.marko
|
|
396
|
+
</pre>
|
|
397
|
+
|
|
398
|
+
When the path `"/about"` is requested, the routable files execute in the following order:
|
|
277
399
|
|
|
278
400
|
1. Middlewares from root-most to leaf-most
|
|
279
401
|
2. Handler
|
|
@@ -282,21 +404,21 @@ For a matched route, the routable files execute in the following order:
|
|
|
282
404
|
|
|
283
405
|
```mermaid
|
|
284
406
|
sequenceDiagram
|
|
285
|
-
participant
|
|
286
|
-
participant
|
|
287
|
-
participant
|
|
288
|
-
participant
|
|
289
|
-
participant
|
|
290
|
-
participant
|
|
291
|
-
Note over
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
407
|
+
participant MW1 as routes/+middleware.js
|
|
408
|
+
participant MW2 as routes/about/+middleware.js
|
|
409
|
+
participant H as routes/about/+handler.js
|
|
410
|
+
participant L1 as routes/+layout.marko
|
|
411
|
+
participant L2 as routes/about/+layout.marko
|
|
412
|
+
participant P as routes/about/+page.marko
|
|
413
|
+
Note over L1,P: Combined at build-time as a single component
|
|
414
|
+
MW1->>MW2: next()
|
|
415
|
+
MW2->>H: next()
|
|
416
|
+
H->>L1: next()
|
|
417
|
+
L1->L2: ${input.renderBody}
|
|
418
|
+
L2->P: ${input.renderBody}
|
|
419
|
+
L1-->>H: Stream Response
|
|
420
|
+
H-->>MW2: Response
|
|
421
|
+
MW2-->>MW1: Response
|
|
300
422
|
```
|
|
301
423
|
|
|
302
424
|
### Path Structure
|
|
@@ -347,3 +469,36 @@ Within the _routes directory_, the directory structure will determine the path t
|
|
|
347
469
|
|
|
348
470
|
## TypeScript
|
|
349
471
|
|
|
472
|
+
|
|
473
|
+
### Global Namespace
|
|
474
|
+
marko/run provides a global namespace `MarkoRun` with the folling types:
|
|
475
|
+
|
|
476
|
+
**`MarkoRun.Handler`** - Type that represents a handler function to be exported by a +handler or +middleware file
|
|
477
|
+
|
|
478
|
+
**`MarkoRun.CurrentRoute`** - Type of the route's params and meta data
|
|
479
|
+
|
|
480
|
+
**`MarkoRun.CurrentContext`** - Type of the request context object in a handler and `out.global` in your Marko files
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
### Generated Types
|
|
484
|
+
If a [TSConfig](https://www.typescriptlang.org/tsconfig) file is discovered in the project root, the Vite plugin will automatically generate a .d.ts file which provides more specific types for each of your middleware, handlers, layouts and pages. This file will be generated at `.marko-run/routes.d.ts` whenever the project is built - including dev.
|
|
485
|
+
> **Note** TypeScript will not include this file by default. If you are not using the [Marko VSCode plugin](https://marketplace.visualstudio.com/items?itemName=Marko-JS.marko-vscode) and you will need to [add it in your tsconfig](https://www.typescriptlang.org/tsconfig#include).
|
|
486
|
+
|
|
487
|
+
These types are replaced with more specific versions per routeable file:
|
|
488
|
+
|
|
489
|
+
**`MarkoRun.Handler`**
|
|
490
|
+
- Overrides context with specific MarkoRun.CurrentContext
|
|
491
|
+
|
|
492
|
+
**`MarkoRun.CurrentRoute`**
|
|
493
|
+
- Adds specific parameters and meta types
|
|
494
|
+
- In middleware and layouts which are used in many routes, this type will be a union of all possible routes that file will see
|
|
495
|
+
|
|
496
|
+
**`MarkoRun.CurrentContext`**
|
|
497
|
+
- In middleware and layouts which are used in many routes, this type will be a union of all possible routes that file will see.
|
|
498
|
+
- When an adapter is used, it can provide types for the platform
|
|
499
|
+
|
|
500
|
+
## Beta Roadmap
|
|
501
|
+
|
|
502
|
+
- Error handling
|
|
503
|
+
- Error component
|
|
504
|
+
- Redirect component
|
package/dist/adapter/index.cjs
CHANGED
|
@@ -95,7 +95,7 @@ function getOrigin(req, protocol, host, trustProxy) {
|
|
|
95
95
|
return `${protocol}://${host}`;
|
|
96
96
|
}
|
|
97
97
|
function createMiddleware(fetch2, options = {}) {
|
|
98
|
-
const { trustProxy = process.env.TRUST_PROXY === "1" } = options;
|
|
98
|
+
const { trustProxy = process.env.TRUST_PROXY === "1", devServer } = options;
|
|
99
99
|
let { origin = process.env.ORIGIN } = options;
|
|
100
100
|
let protocol;
|
|
101
101
|
let host;
|
|
@@ -179,7 +179,17 @@ function createMiddleware(fetch2, options = {}) {
|
|
|
179
179
|
res.off("error", cancel);
|
|
180
180
|
reader.cancel(error).catch(() => {
|
|
181
181
|
});
|
|
182
|
-
|
|
182
|
+
if (error) {
|
|
183
|
+
if (process.env.NODE_ENV !== "production" && devServer) {
|
|
184
|
+
res.end();
|
|
185
|
+
devServer.ws.send({
|
|
186
|
+
type: "error",
|
|
187
|
+
err: { message: error.message, stack: error.stack || "" }
|
|
188
|
+
});
|
|
189
|
+
} else {
|
|
190
|
+
res.destroy(error);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
183
193
|
}
|
|
184
194
|
async function write() {
|
|
185
195
|
try {
|
|
@@ -206,6 +216,7 @@ function createMiddleware(fetch2, options = {}) {
|
|
|
206
216
|
}
|
|
207
217
|
|
|
208
218
|
// src/adapter/dev-server.ts
|
|
219
|
+
var fixedErrors = /* @__PURE__ */ new WeakSet();
|
|
209
220
|
function createViteDevMiddleware(devServer, load, factory) {
|
|
210
221
|
let value;
|
|
211
222
|
let middleware;
|
|
@@ -218,10 +229,16 @@ function createViteDevMiddleware(devServer, load, factory) {
|
|
|
218
229
|
}
|
|
219
230
|
await middleware(req, res, next);
|
|
220
231
|
} catch (err) {
|
|
232
|
+
res.statusCode = 500;
|
|
221
233
|
if (err instanceof Error) {
|
|
222
|
-
|
|
234
|
+
if (!fixedErrors.has(err)) {
|
|
235
|
+
fixedErrors.add(err);
|
|
236
|
+
devServer.ssrFixStacktrace(err);
|
|
237
|
+
}
|
|
238
|
+
res.end(err.stack);
|
|
239
|
+
} else {
|
|
240
|
+
res.end();
|
|
223
241
|
}
|
|
224
|
-
return next == null ? void 0 : next();
|
|
225
242
|
}
|
|
226
243
|
};
|
|
227
244
|
}
|
|
@@ -229,12 +246,16 @@ async function createDevServer(configFile) {
|
|
|
229
246
|
const devServer = await (0, import_vite.createServer)({
|
|
230
247
|
configFile,
|
|
231
248
|
appType: "custom",
|
|
232
|
-
server: { middlewareMode: true }
|
|
249
|
+
server: { middlewareMode: true },
|
|
250
|
+
resolve: {
|
|
251
|
+
dedupe: ["marko"],
|
|
252
|
+
conditions: ["worker"]
|
|
253
|
+
}
|
|
233
254
|
});
|
|
234
255
|
const middleware = createViteDevMiddleware(
|
|
235
256
|
devServer,
|
|
236
257
|
async () => await devServer.ssrLoadModule("@marko/run/router"),
|
|
237
|
-
(module2) => createMiddleware(module2.fetch)
|
|
258
|
+
(module2) => createMiddleware(module2.fetch, { devServer })
|
|
238
259
|
);
|
|
239
260
|
return devServer.middlewares.use(middleware);
|
|
240
261
|
}
|
package/dist/adapter/index.js
CHANGED
|
@@ -63,7 +63,7 @@ function getOrigin(req, protocol, host, trustProxy) {
|
|
|
63
63
|
return `${protocol}://${host}`;
|
|
64
64
|
}
|
|
65
65
|
function createMiddleware(fetch2, options = {}) {
|
|
66
|
-
const { trustProxy = process.env.TRUST_PROXY === "1" } = options;
|
|
66
|
+
const { trustProxy = process.env.TRUST_PROXY === "1", devServer } = options;
|
|
67
67
|
let { origin = process.env.ORIGIN } = options;
|
|
68
68
|
let protocol;
|
|
69
69
|
let host;
|
|
@@ -147,7 +147,17 @@ function createMiddleware(fetch2, options = {}) {
|
|
|
147
147
|
res.off("error", cancel);
|
|
148
148
|
reader.cancel(error).catch(() => {
|
|
149
149
|
});
|
|
150
|
-
|
|
150
|
+
if (error) {
|
|
151
|
+
if (process.env.NODE_ENV !== "production" && devServer) {
|
|
152
|
+
res.end();
|
|
153
|
+
devServer.ws.send({
|
|
154
|
+
type: "error",
|
|
155
|
+
err: { message: error.message, stack: error.stack || "" }
|
|
156
|
+
});
|
|
157
|
+
} else {
|
|
158
|
+
res.destroy(error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
151
161
|
}
|
|
152
162
|
async function write() {
|
|
153
163
|
try {
|
|
@@ -174,6 +184,7 @@ function createMiddleware(fetch2, options = {}) {
|
|
|
174
184
|
}
|
|
175
185
|
|
|
176
186
|
// src/adapter/dev-server.ts
|
|
187
|
+
var fixedErrors = /* @__PURE__ */ new WeakSet();
|
|
177
188
|
function createViteDevMiddleware(devServer, load, factory) {
|
|
178
189
|
let value;
|
|
179
190
|
let middleware;
|
|
@@ -186,10 +197,16 @@ function createViteDevMiddleware(devServer, load, factory) {
|
|
|
186
197
|
}
|
|
187
198
|
await middleware(req, res, next);
|
|
188
199
|
} catch (err) {
|
|
200
|
+
res.statusCode = 500;
|
|
189
201
|
if (err instanceof Error) {
|
|
190
|
-
|
|
202
|
+
if (!fixedErrors.has(err)) {
|
|
203
|
+
fixedErrors.add(err);
|
|
204
|
+
devServer.ssrFixStacktrace(err);
|
|
205
|
+
}
|
|
206
|
+
res.end(err.stack);
|
|
207
|
+
} else {
|
|
208
|
+
res.end();
|
|
191
209
|
}
|
|
192
|
-
return next == null ? void 0 : next();
|
|
193
210
|
}
|
|
194
211
|
};
|
|
195
212
|
}
|
|
@@ -197,12 +214,16 @@ async function createDevServer(configFile) {
|
|
|
197
214
|
const devServer = await createServer({
|
|
198
215
|
configFile,
|
|
199
216
|
appType: "custom",
|
|
200
|
-
server: { middlewareMode: true }
|
|
217
|
+
server: { middlewareMode: true },
|
|
218
|
+
resolve: {
|
|
219
|
+
dedupe: ["marko"],
|
|
220
|
+
conditions: ["worker"]
|
|
221
|
+
}
|
|
201
222
|
});
|
|
202
223
|
const middleware = createViteDevMiddleware(
|
|
203
224
|
devServer,
|
|
204
225
|
async () => await devServer.ssrLoadModule("@marko/run/router"),
|
|
205
|
-
(module) => createMiddleware(module.fetch)
|
|
226
|
+
(module) => createMiddleware(module.fetch, { devServer })
|
|
206
227
|
);
|
|
207
228
|
return devServer.middlewares.use(middleware);
|
|
208
229
|
}
|
|
@@ -83,7 +83,7 @@ function getOrigin(req, protocol, host, trustProxy) {
|
|
|
83
83
|
return `${protocol}://${host}`;
|
|
84
84
|
}
|
|
85
85
|
function createMiddleware(fetch2, options = {}) {
|
|
86
|
-
const { trustProxy = process.env.TRUST_PROXY === "1" } = options;
|
|
86
|
+
const { trustProxy = process.env.TRUST_PROXY === "1", devServer } = options;
|
|
87
87
|
let { origin = process.env.ORIGIN } = options;
|
|
88
88
|
let protocol;
|
|
89
89
|
let host;
|
|
@@ -167,7 +167,17 @@ function createMiddleware(fetch2, options = {}) {
|
|
|
167
167
|
res.off("error", cancel);
|
|
168
168
|
reader.cancel(error).catch(() => {
|
|
169
169
|
});
|
|
170
|
-
|
|
170
|
+
if (error) {
|
|
171
|
+
if (process.env.NODE_ENV !== "production" && devServer) {
|
|
172
|
+
res.end();
|
|
173
|
+
devServer.ws.send({
|
|
174
|
+
type: "error",
|
|
175
|
+
err: { message: error.message, stack: error.stack || "" }
|
|
176
|
+
});
|
|
177
|
+
} else {
|
|
178
|
+
res.destroy(error);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
171
181
|
}
|
|
172
182
|
async function write() {
|
|
173
183
|
try {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Fetch } from "../runtime";
|
|
2
2
|
import type { IncomingMessage, ServerResponse } from "http";
|
|
3
|
+
import type { ViteDevServer } from "vite";
|
|
3
4
|
declare module "net" {
|
|
4
5
|
interface Socket {
|
|
5
6
|
encrypted?: boolean;
|
|
@@ -46,6 +47,7 @@ export interface NodeAdapterOptions {
|
|
|
46
47
|
* is set to `1`, otherwise false.
|
|
47
48
|
*/
|
|
48
49
|
trustProxy?: boolean;
|
|
50
|
+
devServer?: ViteDevServer;
|
|
49
51
|
}
|
|
50
52
|
export declare function getOrigin(req: IncomingMessage, protocol?: string, host?: string, trustProxy?: boolean): string;
|
|
51
53
|
/**
|
|
@@ -56,7 +56,7 @@ function getOrigin(req, protocol, host, trustProxy) {
|
|
|
56
56
|
return `${protocol}://${host}`;
|
|
57
57
|
}
|
|
58
58
|
function createMiddleware(fetch2, options = {}) {
|
|
59
|
-
const { trustProxy = process.env.TRUST_PROXY === "1" } = options;
|
|
59
|
+
const { trustProxy = process.env.TRUST_PROXY === "1", devServer } = options;
|
|
60
60
|
let { origin = process.env.ORIGIN } = options;
|
|
61
61
|
let protocol;
|
|
62
62
|
let host;
|
|
@@ -140,7 +140,17 @@ function createMiddleware(fetch2, options = {}) {
|
|
|
140
140
|
res.off("error", cancel);
|
|
141
141
|
reader.cancel(error).catch(() => {
|
|
142
142
|
});
|
|
143
|
-
|
|
143
|
+
if (error) {
|
|
144
|
+
if (process.env.NODE_ENV !== "production" && devServer) {
|
|
145
|
+
res.end();
|
|
146
|
+
devServer.ws.send({
|
|
147
|
+
type: "error",
|
|
148
|
+
err: { message: error.message, stack: error.stack || "" }
|
|
149
|
+
});
|
|
150
|
+
} else {
|
|
151
|
+
res.destroy(error);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
144
154
|
}
|
|
145
155
|
async function write() {
|
|
146
156
|
try {
|
package/dist/cli/index.mjs
CHANGED
|
@@ -98,12 +98,12 @@ var defaultPort = +process.env.PORT || 3e3;
|
|
|
98
98
|
var defaultConfigFileBases = ["serve.config", "vite.config"];
|
|
99
99
|
var defaultConfigFileExts = [".js", ".cjs", ".mjs", ".ts", ".mts"];
|
|
100
100
|
var prog = sade("marko-run").version("0.0.1").option("-c, --config", `Provide path to a Vite config file (by default looks for a file starting with ${defaultConfigFileBases.join(" or ")} with one of these extensions: ${defaultConfigFileExts.join(", ")})`).option("-e, --env", "Provide path to a dotenv file");
|
|
101
|
-
prog.command("serve [entry]"
|
|
101
|
+
prog.command("serve [entry]").describe("Start a production-like server for already-built app files").option("-o, --output", "Directory to serve files from, and write asset files to if `--build` (default: )").option("-p, --port", "Port the server should listen on (defaults: `$PORT` env variable or 3000)").option("-f, --file", "Output file to start").action(async (entry, opts) => {
|
|
102
102
|
const config2 = await getViteConfig(cwd, opts.config);
|
|
103
103
|
await build(entry, config2, opts.output, false, opts.env);
|
|
104
104
|
await preview(opts.entry, config2, opts.port, opts.output, opts.env);
|
|
105
105
|
});
|
|
106
|
-
prog.command("dev [entry]").describe("Start development server in watch mode").option("-p, --port", "Port the dev server should listen on (defaults: 'preview.port' in config, or `$PORT` env variable, or 3000)").example("dev --config vite.config.js").action(async (entry, opts) => {
|
|
106
|
+
prog.command("dev [entry]", "", { default: true }).describe("Start development server in watch mode").option("-p, --port", "Port the dev server should listen on (defaults: 'preview.port' in config, or `$PORT` env variable, or 3000)").example("dev --config vite.config.js").action(async (entry, opts) => {
|
|
107
107
|
const cmd = opts._.length ? `${entry} ${opts._.join(" ")}` : entry ? `node ${entry}` : void 0;
|
|
108
108
|
const config2 = await getViteConfig(cwd, opts.config);
|
|
109
109
|
await dev(cmd, config2, opts.port, opts.env);
|
package/dist/vite/index.cjs
CHANGED
|
@@ -703,8 +703,8 @@ export async function invoke(route, request, platform, url = new URL(request.url
|
|
|
703
703
|
request,
|
|
704
704
|
platform
|
|
705
705
|
};
|
|
706
|
+
const buildInput = createInput(context);
|
|
706
707
|
try {
|
|
707
|
-
const buildInput = createInput(context);
|
|
708
708
|
if (route) {
|
|
709
709
|
context.params = route.params;
|
|
710
710
|
context.meta = route.meta;
|
package/dist/vite/index.js
CHANGED
|
@@ -666,8 +666,8 @@ export async function invoke(route, request, platform, url = new URL(request.url
|
|
|
666
666
|
request,
|
|
667
667
|
platform
|
|
668
668
|
};
|
|
669
|
+
const buildInput = createInput(context);
|
|
669
670
|
try {
|
|
670
|
-
const buildInput = createInput(context);
|
|
671
671
|
if (route) {
|
|
672
672
|
context.params = route.params;
|
|
673
673
|
context.meta = route.meta;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marko/run",
|
|
3
|
-
"version": "0.0.1-
|
|
3
|
+
"version": "0.0.1-beta8",
|
|
4
4
|
"description": "File-based routing for Marko based on Vite",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "Ryan Turnquist <rturnq@gmail.com>",
|
|
@@ -69,7 +69,8 @@
|
|
|
69
69
|
"dist"
|
|
70
70
|
],
|
|
71
71
|
"peerDependencies": {
|
|
72
|
-
"@marko/vite": "^2.3.9"
|
|
72
|
+
"@marko/vite": "^2.3.9",
|
|
73
|
+
"marko": "^5"
|
|
73
74
|
},
|
|
74
75
|
"devDependencies": {
|
|
75
76
|
"@babel/types": "^7.19.0",
|