@marko/run 0.0.1-beta1

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.
Files changed (43) hide show
  1. package/README.md +267 -0
  2. package/dist/adapter/default-entry.mjs +18 -0
  3. package/dist/adapter/dev-server.d.ts +4 -0
  4. package/dist/adapter/index.cjs +159 -0
  5. package/dist/adapter/index.d.ts +4 -0
  6. package/dist/adapter/index.js +126 -0
  7. package/dist/adapter/server-old.d.ts +3 -0
  8. package/dist/adapter/server.d.ts +6 -0
  9. package/dist/adapters/node/index.d.ts +5 -0
  10. package/dist/adapters/node/server.d.ts +3 -0
  11. package/dist/adapters/static/crawler.d.ts +9 -0
  12. package/dist/adapters/static/default-entry.mjs +1 -0
  13. package/dist/adapters/static/index.cjs +371 -0
  14. package/dist/adapters/static/index.d.ts +5 -0
  15. package/dist/adapters/static/index.js +341 -0
  16. package/dist/adapters/static/server.d.ts +3 -0
  17. package/dist/cli/default.config.mjs +7 -0
  18. package/dist/cli/index.mjs +223 -0
  19. package/dist/runtime/index.cjs +34 -0
  20. package/dist/runtime/index.d.ts +2 -0
  21. package/dist/runtime/index.js +7 -0
  22. package/dist/runtime/request.d.ts +4 -0
  23. package/dist/runtime/router.cjs +39 -0
  24. package/dist/runtime/router.d.ts +4 -0
  25. package/dist/runtime/router.js +12 -0
  26. package/dist/runtime/types.d.ts +22 -0
  27. package/dist/vite/codegen/index.d.ts +5 -0
  28. package/dist/vite/codegen/writer.d.ts +20 -0
  29. package/dist/vite/constants.d.ts +19 -0
  30. package/dist/vite/index.cjs +1394 -0
  31. package/dist/vite/index.d.ts +3 -0
  32. package/dist/vite/index.js +1359 -0
  33. package/dist/vite/plugin.d.ts +3 -0
  34. package/dist/vite/routes/builder.d.ts +7 -0
  35. package/dist/vite/routes/routeTrie.d.ts +2 -0
  36. package/dist/vite/routes/walk.d.ts +14 -0
  37. package/dist/vite/types.d.ts +62 -0
  38. package/dist/vite/utils/ast.d.ts +1 -0
  39. package/dist/vite/utils/config.d.ts +3 -0
  40. package/dist/vite/utils/log.d.ts +3 -0
  41. package/dist/vite/utils/route.d.ts +3 -0
  42. package/dist/vite/utils/server.d.ts +7 -0
  43. package/package.json +93 -0
package/README.md ADDED
@@ -0,0 +1,267 @@
1
+ <h1 align="center">
2
+ <!-- Logo -->
3
+ <img src="https://user-images.githubusercontent.com/4985201/115444712-ca550500-a1c9-11eb-9897-238ece59129c.png" height="118"/>
4
+ <br/>
5
+ @marko/run
6
+ <br/>
7
+
8
+ <!-- Language -->
9
+ <a href="http://typescriptlang.org">
10
+ <img src="https://img.shields.io/badge/%3C%2F%3E-typescript-blue.svg" alt="TypeScript"/>
11
+ </a>
12
+ </h1>
13
+
14
+ Vite plugin for Marko with these features
15
+ - Encapsulates [@marko/vite](https://github.com/marko-js/vite)
16
+ - File-based routing with layouts and middleware
17
+ - Efficient routing using a compiled static trie
18
+ - Designed with web standards to run anywhere
19
+
20
+ ## Intallation
21
+
22
+ ```
23
+ npm install @marko/run
24
+ ```
25
+
26
+ ## Vite Plugin
27
+
28
+ This package provides both a Vite plugin and a runtime import. The Vite plugin is responsible for discovering your route files, generating the routing code and registering the @marko/vite plugin which builds your .marko files.
29
+
30
+ ```ts
31
+ // vite.config.ts
32
+ import { defineConfig } from "vite";
33
+ import marko from "@marko/run/vite"; // Import the Vite plugin
34
+
35
+ export default defineConfig({
36
+ plugins: [marko()], // Register the Vite plugin
37
+ build: {
38
+ sourcemap: true, // Generate sourcemaps for all builds.
39
+ emptyOutDir: false, // Avoid server & client deleting files from each other.
40
+ }
41
+ })
42
+ ```
43
+
44
+ ## Runtime
45
+
46
+ Generally you'll want to use one of the adapters to provide a more convenient experience but this package provides the following runtime interface:
47
+
48
+ ```ts
49
+ import { router, getMatchedRoute } from '@marko/run`;
50
+ ```
51
+
52
+ ### `router`
53
+ ```ts
54
+ (request: Request) => Promise<Response>;
55
+ ```
56
+ This asynchronouse function takes a [WHATWG request](https://fetch.spec.whatwg.org/#request-class) object and returns a [response](https://fetch.spec.whatwg.org/#response-class) object generated by executing the corresponding matched route files. If no match is found, a response with a 404 status code is returned. If an unhandled error occurs, a response with a 500 status code will be returned.
57
+
58
+ ### `getMatchedRoute`
59
+ ```ts
60
+ (method: string, url: URL) => {
61
+ params: Record<string, string>;
62
+ meta: unknown;
63
+ invoke(request: Request): Promise<Response>;
64
+ } | null;
65
+ ```
66
+ This synchronous function takes a HTTP verb method, and URL and returns an object representing the best match or null if no match is found.
67
+ - `params` - a key-value collection of any path parameters for the route
68
+ - `meta` - meta data for the route
69
+ - `invoke` - an asynchronouse function that takes a WHATWG request and returns the response generated by executing the matched route files. Note: unlike the top-level `router` function errors will not be caught.
70
+
71
+ ## File-based Routing
72
+
73
+ ## Nested Routing
74
+
75
+ *TODO: provide a quick overview*
76
+
77
+ ### Routes Directory
78
+
79
+ By default, the plugin will look for files in the configured _routes directory_. By default it will look in `./src/routes` (relative to the Vite config file) which can be configured:
80
+
81
+ ```ts
82
+ // vite.config.ts
83
+ import { defineConfig } from "vite";
84
+ import marko from "@marko/run/vite";
85
+
86
+ export default defineConfig({
87
+ plugins: [marko({
88
+ routesDir: 'src/pages' // Use `./src/pages` (relative to this file) as the routes directory
89
+ })],
90
+ //...
91
+ })
92
+ ```
93
+
94
+ ### Routeable Files
95
+
96
+ In order to allow for co-location of files that should not be served (e.g. tests, stories, assets), the router only recognizes a specific set of file names. The following files will be discovered in any directory within your application's _routes directory_.
97
+
98
+ #### `+page.marko`
99
+ These files establish a route at the current directory path which will be served for GET requests with the HTML content of the page. Only one page may exists for any served path.
100
+
101
+ #### `+layout.marko`
102
+ These files provide a layout component which will wrap all nested layouts and pages.
103
+
104
+ <details>
105
+ <summary>More Info</summary>
106
+
107
+ Layouts are just like any other Marko component with no extra constraints. Each layout receives the request, path params, URL and route meta data as input as well as a renderBody which will be the subsequent layout or page to project.
108
+
109
+ ```marko
110
+ <div>
111
+ <h1>My Products</h1>
112
+ <main>
113
+ ${input.renderBody} // project the page or layout here
114
+ </main>
115
+ </div>
116
+ ```
117
+ </details>
118
+
119
+ #### `+handler.*`
120
+ These files establish a route at the current directory path which can handle requests for GET, POST, PUT and DELETE HTTP verbs. Typically these will be .js or .ts files depending on your project. Just like pages, only one handler may exist for any served path. A handler should export functions
121
+
122
+ <details>
123
+ <summary>More Info</summary>
124
+
125
+ - Valid exports are: `get`, `post`, `put`, `del`.
126
+ - Each method takes a `context` and `next` argument and should return a WHATWG response either synchronously or asynchronously.
127
+ - The `context` argument contains the WHATWG request object, path parameters, URL and route meta data.
128
+ - The `next` argument will call the page for get requests where applicable or return a 204 response.
129
+
130
+ ```ts
131
+ export function post(context, next) {
132
+ const { request, params, url, meta } = context;
133
+ return new Response('updated', { status: 200 });
134
+ }
135
+
136
+ export function put(context, next) {
137
+ return new Response('created', { status: 201 }); // handle the request
138
+ }
139
+
140
+ export function get(context, next) {
141
+ return next(); // Call the next handler
142
+ }
143
+
144
+ export function del(context, next) {
145
+ return new Response('removed', { status: 204 });
146
+ }
147
+ ```
148
+ </details>
149
+
150
+
151
+ #### `+middlware.*`
152
+ These files are analagous to layouts for handlers. Middlware get called before handlers and let you perform arbitrary work before and after. Unlike handlers, middleware run for all HTTP verbs.
153
+
154
+ <details>
155
+ <summary>More Info</summary>
156
+
157
+ - Expects default export that takes a `context` and `next` argument and should return a WHATWG response either synchronously or asynchronously.
158
+ - The `context` argument contains the WHATWG request object, path parameters, URL and route meta data.
159
+ - The `next` argument will call the next middleware, handler or page as applicable for the route.
160
+
161
+ ```ts
162
+ export default async function(context, next) {
163
+ const requestName = `${ctx.request.method} ${ctx.url.href}`;
164
+ let success = true;
165
+ console.log(`${requestName} request started`)
166
+ try {
167
+ return await next(); // wait for subsequent middleware/handler/page
168
+ } catch (err) {
169
+ success = false;
170
+ throw err;
171
+ } finally {
172
+ console.log(`${requestName} completed ${success ? 'successfully' : 'with errors'}`);
173
+ }
174
+ }
175
+ ```
176
+ </details>
177
+
178
+ #### `+meta.*`
179
+ These files represent some meta data to attach to the route. This meta data will be automatically imported by the router and provided on the the route context when invoking a route.
180
+
181
+ ### Special Files
182
+
183
+ In addition to the files above which can be defined in any directory under the _routes directory_, there are some special files which can only be defined within the _routes directory_:
184
+
185
+ #### `+404.marko`
186
+ This is a special page wich will be rendered for any request whose `Accept` header includes `text/html` if no other handler or page handled the request. This page will be subject to the root layout file (ie. +layout.marko file in the _routes directory_). Responses with this page will have a `404` status code.
187
+
188
+ #### `+500.marko`
189
+ This is a special page wich will be rendered for any request whose `Accept` header includes `text/html` if an uncaught error occurs while handling the request. This page will be subject to the root layout file (ie. +layout.marko file in the _routes directory_). Responses with this page will have a `500` status code.
190
+
191
+
192
+ ### Execution Order
193
+
194
+ For a matched route the routable files execute in the following order
195
+ 1. Middlewares from root-most to leaf-most
196
+ 2. Handler
197
+ 3. Layouts from root-most to leaf-most
198
+ 4. Page
199
+
200
+ <details>
201
+ <summary>Diagram</summary>
202
+
203
+ ```mermaid
204
+ sequenceDiagram
205
+ participant Middleware1
206
+ participant Middleware2
207
+ participant Handler
208
+ participant Layout1
209
+ participant Layout2
210
+ participant Page
211
+ Note over Layout1,Page: Combined at build-time as a single component
212
+ Middleware1->>Middleware2: next()
213
+ Middleware2->>Handler: next()
214
+ Handler->>Layout1: next()
215
+ Layout1->Layout2: ${input.renderBody}
216
+ Layout2->Page: ${input.renderBody}
217
+ Layout1-->>Handler: Stream Response
218
+ Handler-->>Middleware2: Response
219
+ Middleware2-->>Middleware1: Response
220
+ ```
221
+ </details>
222
+
223
+ ### Path Structure
224
+
225
+ Within the _routes directory_ the directory structure will determine the path the route will be served. There are four types of directory names:
226
+
227
+ - **Static directories** - The most common type of directory. Each static directory will contribute its name as a segment in the route's served path like a traditional file server. This is the default and unless the directory matches the requirements for one of the below types, it will be a static directory.
228
+
229
+ Examples:
230
+ ```
231
+ /foo
232
+ /users
233
+ /projects
234
+ ```
235
+
236
+ - **Pathless directories** - These directories do not contribute their name to the route's served path. Directory names that start with an underscore ('_') as well as directories named 'index' will be a pathless directory.
237
+
238
+ Examples:
239
+ ```
240
+ /_users
241
+ /_public
242
+ /index
243
+ ```
244
+
245
+ - **Dynamic directories** - These directories introduce a dynamic parameter to the route's served path and will match any value at that segment. Any directory name that starts with a single dollar sign ('\$') will be a dynamic directory and the remaining directory name will be the parameter at runtime. In the case the directory name is '$', the parameter will not exist at runtime but will be matched.
246
+
247
+ Examples:
248
+ ```
249
+ /$id
250
+ /$name
251
+ /$
252
+ ```
253
+
254
+ - **Catcha-all directories** - These directories are similar to dynamic directories and introduce a dynamic parameter but instead of matching a single sement of the path, they match to the end of the path. Any directory that starts with two dollar signs ('\$\$') will be a catch-all directory and the remaining directory name will be the parameter at runtime. In the case of a directory name '$$', the parameter name at runtime will be '*'. Catch-all directories can be used to make not found/404 routes at any level including the root.
255
+
256
+ Because catch-all directories always match and consume all the remaining path, you cannot have nested routes within and no further directories will be traversed.
257
+
258
+ Examples:
259
+ ```
260
+ /$$all
261
+ /$$rest
262
+ /$$
263
+ ```
264
+
265
+ ### Match Ranking
266
+
267
+ *TODO: Write some things*
@@ -0,0 +1,18 @@
1
+ import createStaticServe from "serve-static";
2
+ import { createServer } from "http";
3
+ import { createMiddleware } from "@hattip/adapter-node";
4
+ import { handler } from "@marko/run";
5
+
6
+ const { PORT = 3456 } = process.env;
7
+
8
+ const dir = process.cwd();
9
+ const middleware = createMiddleware(handler);
10
+ const staticServe = createStaticServe(dir, {
11
+ index: false,
12
+ immutable: true,
13
+ maxAge: "365 days",
14
+ });
15
+
16
+ createServer((req, res) =>
17
+ staticServe(req, res, () => middleware(req, res))
18
+ ).listen(PORT);
@@ -0,0 +1,4 @@
1
+ import { ViteDevServer } from "vite";
2
+ import { type NodeMiddleware } from "@hattip/adapter-node";
3
+ export declare function createViteDevMiddleware<T>(devServer: ViteDevServer, load: (prev: T | undefined) => Promise<T>, factory: (value: T) => NodeMiddleware): NodeMiddleware;
4
+ export declare function createDevServer(configFile?: string): Promise<import("vite").Connect.Server>;
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
+
26
+ // src/adapter/index.ts
27
+ var adapter_exports = {};
28
+ __export(adapter_exports, {
29
+ createDevServer: () => createDevServer,
30
+ createViteDevMiddleware: () => createViteDevMiddleware,
31
+ default: () => adapter
32
+ });
33
+ module.exports = __toCommonJS(adapter_exports);
34
+ var import_path = __toESM(require("path"), 1);
35
+ var import_url = require("url");
36
+
37
+ // src/adapter/dev-server.ts
38
+ var import_vite = require("vite");
39
+ var import_adapter_node = require("@hattip/adapter-node");
40
+ function createViteDevMiddleware(devServer, load, factory) {
41
+ let value;
42
+ let middleware;
43
+ return async (req, res, next) => {
44
+ try {
45
+ const nextValue = await load(value);
46
+ if (nextValue !== value) {
47
+ value = nextValue;
48
+ middleware = factory(value);
49
+ }
50
+ await middleware(req, res, next);
51
+ } catch (err) {
52
+ if (err instanceof Error) {
53
+ devServer.ssrFixStacktrace(err);
54
+ }
55
+ return next == null ? void 0 : next();
56
+ }
57
+ };
58
+ }
59
+ async function createDevServer(configFile) {
60
+ const devServer = await (0, import_vite.createServer)({
61
+ configFile,
62
+ appType: "custom",
63
+ server: { middlewareMode: true }
64
+ });
65
+ const middleware = createViteDevMiddleware(
66
+ devServer,
67
+ async () => (await devServer.ssrLoadModule("@marko/run")).handler,
68
+ import_adapter_node.createMiddleware
69
+ );
70
+ return devServer.middlewares.use(middleware);
71
+ }
72
+
73
+ // src/vite/utils/server.ts
74
+ var import_net = __toESM(require("net"), 1);
75
+ var import_child_process = __toESM(require("child_process"), 1);
76
+ async function spawnServer(cmd, port = 0, cwd = process.cwd(), wait = 3e4) {
77
+ if (port <= 0) {
78
+ port = await getAvailablePort();
79
+ }
80
+ const proc = import_child_process.default.spawn(cmd, {
81
+ cwd,
82
+ shell: true,
83
+ stdio: "inherit",
84
+ windowsHide: true,
85
+ env: { NODE_ENV: "development", ...process.env, PORT: `${port}` }
86
+ });
87
+ const close = () => {
88
+ proc.unref();
89
+ proc.kill();
90
+ };
91
+ let remaining = wait > 0 ? wait : Infinity;
92
+ while (!await isPortInUse(port)) {
93
+ if (remaining >= 100) {
94
+ remaining -= 100;
95
+ await sleep(100);
96
+ } else {
97
+ close();
98
+ throw new Error(
99
+ `site-write: timeout while wating for server to start on port "${port}".`
100
+ );
101
+ }
102
+ }
103
+ return {
104
+ port,
105
+ close
106
+ };
107
+ }
108
+ async function isPortInUse(port) {
109
+ return new Promise((resolve) => {
110
+ const connection = import_net.default.connect(port).setNoDelay(true).setKeepAlive(false).on("error", () => done(false)).on("connect", () => done(true));
111
+ function done(connected) {
112
+ connection.end();
113
+ resolve(connected);
114
+ }
115
+ });
116
+ }
117
+ async function getAvailablePort() {
118
+ return new Promise((resolve) => {
119
+ const server = import_net.default.createServer().listen(0, () => {
120
+ const { port } = server.address();
121
+ server.close(() => resolve(port));
122
+ });
123
+ });
124
+ }
125
+ function sleep(ms) {
126
+ return new Promise((resolve) => setTimeout(resolve, ms));
127
+ }
128
+
129
+ // src/adapter/index.ts
130
+ var import_meta = {};
131
+ var __dirname = (0, import_url.fileURLToPath)(new URL(".", import_meta.url));
132
+ function adapter() {
133
+ return {
134
+ name: "base-adapter",
135
+ async getEntryFile() {
136
+ const entry = import_path.default.join(__dirname, "default-entry");
137
+ return entry;
138
+ },
139
+ async startDev(configFile, port) {
140
+ const server = await createDevServer(configFile);
141
+ return new Promise((resolve) => {
142
+ const listener = server.listen(port, () => {
143
+ const address = listener.address();
144
+ console.log(`Dev server started: http://localhost:${address.port}`);
145
+ resolve();
146
+ });
147
+ });
148
+ },
149
+ async startPreview(dir, entry, port) {
150
+ const server = await spawnServer(`node ${entry}`, port, dir);
151
+ console.log(`Preview server started: http://localhost:${server.port}`);
152
+ }
153
+ };
154
+ }
155
+ // Annotate the CommonJS export names for ESM import in node:
156
+ 0 && (module.exports = {
157
+ createDevServer,
158
+ createViteDevMiddleware
159
+ });
@@ -0,0 +1,4 @@
1
+ import type { Adapter } from "../vite";
2
+ export { createDevServer, createViteDevMiddleware } from "./dev-server";
3
+ export type { Adapter };
4
+ export default function adapter(): Adapter;
@@ -0,0 +1,126 @@
1
+ // src/adapter/index.ts
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ // src/adapter/dev-server.ts
6
+ import { createServer } from "vite";
7
+ import { createMiddleware } from "@hattip/adapter-node";
8
+ function createViteDevMiddleware(devServer, load, factory) {
9
+ let value;
10
+ let middleware;
11
+ return async (req, res, next) => {
12
+ try {
13
+ const nextValue = await load(value);
14
+ if (nextValue !== value) {
15
+ value = nextValue;
16
+ middleware = factory(value);
17
+ }
18
+ await middleware(req, res, next);
19
+ } catch (err) {
20
+ if (err instanceof Error) {
21
+ devServer.ssrFixStacktrace(err);
22
+ }
23
+ return next == null ? void 0 : next();
24
+ }
25
+ };
26
+ }
27
+ async function createDevServer(configFile) {
28
+ const devServer = await createServer({
29
+ configFile,
30
+ appType: "custom",
31
+ server: { middlewareMode: true }
32
+ });
33
+ const middleware = createViteDevMiddleware(
34
+ devServer,
35
+ async () => (await devServer.ssrLoadModule("@marko/run")).handler,
36
+ createMiddleware
37
+ );
38
+ return devServer.middlewares.use(middleware);
39
+ }
40
+
41
+ // src/vite/utils/server.ts
42
+ import net from "net";
43
+ import cp from "child_process";
44
+ async function spawnServer(cmd, port = 0, cwd = process.cwd(), wait = 3e4) {
45
+ if (port <= 0) {
46
+ port = await getAvailablePort();
47
+ }
48
+ const proc = cp.spawn(cmd, {
49
+ cwd,
50
+ shell: true,
51
+ stdio: "inherit",
52
+ windowsHide: true,
53
+ env: { NODE_ENV: "development", ...process.env, PORT: `${port}` }
54
+ });
55
+ const close = () => {
56
+ proc.unref();
57
+ proc.kill();
58
+ };
59
+ let remaining = wait > 0 ? wait : Infinity;
60
+ while (!await isPortInUse(port)) {
61
+ if (remaining >= 100) {
62
+ remaining -= 100;
63
+ await sleep(100);
64
+ } else {
65
+ close();
66
+ throw new Error(
67
+ `site-write: timeout while wating for server to start on port "${port}".`
68
+ );
69
+ }
70
+ }
71
+ return {
72
+ port,
73
+ close
74
+ };
75
+ }
76
+ async function isPortInUse(port) {
77
+ return new Promise((resolve) => {
78
+ const connection = net.connect(port).setNoDelay(true).setKeepAlive(false).on("error", () => done(false)).on("connect", () => done(true));
79
+ function done(connected) {
80
+ connection.end();
81
+ resolve(connected);
82
+ }
83
+ });
84
+ }
85
+ async function getAvailablePort() {
86
+ return new Promise((resolve) => {
87
+ const server = net.createServer().listen(0, () => {
88
+ const { port } = server.address();
89
+ server.close(() => resolve(port));
90
+ });
91
+ });
92
+ }
93
+ function sleep(ms) {
94
+ return new Promise((resolve) => setTimeout(resolve, ms));
95
+ }
96
+
97
+ // src/adapter/index.ts
98
+ var __dirname = fileURLToPath(new URL(".", import.meta.url));
99
+ function adapter() {
100
+ return {
101
+ name: "base-adapter",
102
+ async getEntryFile() {
103
+ const entry = path.join(__dirname, "default-entry");
104
+ return entry;
105
+ },
106
+ async startDev(configFile, port) {
107
+ const server = await createDevServer(configFile);
108
+ return new Promise((resolve) => {
109
+ const listener = server.listen(port, () => {
110
+ const address = listener.address();
111
+ console.log(`Dev server started: http://localhost:${address.port}`);
112
+ resolve();
113
+ });
114
+ });
115
+ },
116
+ async startPreview(dir, entry, port) {
117
+ const server = await spawnServer(`node ${entry}`, port, dir);
118
+ console.log(`Preview server started: http://localhost:${server.port}`);
119
+ }
120
+ };
121
+ }
122
+ export {
123
+ createDevServer,
124
+ createViteDevMiddleware,
125
+ adapter as default
126
+ };
@@ -0,0 +1,3 @@
1
+ /// <reference types="node" />
2
+ import type { Server } from "http";
3
+ export default function (dir?: string): Promise<Server>;
@@ -0,0 +1,6 @@
1
+ /// <reference types="node" />
2
+ import { ViteDevServer } from "vite";
3
+ import { type NodeMiddleware } from "@hattip/adapter-node";
4
+ import type { Server } from "http";
5
+ export declare function createViteDevMiddleware<T>(devServer: ViteDevServer, load: (prev: T | undefined) => Promise<T>, factory: (value: T) => NodeMiddleware): NodeMiddleware;
6
+ export default function (entryFile?: string): Promise<Server>;
@@ -0,0 +1,5 @@
1
+ import type { Adapter, Route } from "../../vite";
2
+ export interface Options {
3
+ urls?: string[] | ((routes: Route[]) => string[] | Promise<string[]>);
4
+ }
5
+ export default function staticAdapter(_options?: Options): Adapter;
@@ -0,0 +1,3 @@
1
+ /// <reference types="node" />
2
+ import type { Server } from "http";
3
+ export default function (dir?: string): Promise<Server>;
@@ -0,0 +1,9 @@
1
+ export interface Options {
2
+ out?: string;
3
+ origin?: string;
4
+ notFoundPath?: string;
5
+ }
6
+ export interface Crawler {
7
+ crawl(paths: string[]): Promise<void>;
8
+ }
9
+ export default function createCrawler(makeRequest: (request: Request) => Promise<Response>, opts?: Options): Crawler;
@@ -0,0 +1 @@
1
+ export { router } from '@marko/run';