@torpor/build 0.4.14 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -2
- package/dist/Jsonify-Dg6gChd3.d.mts +10 -0
- package/dist/Jsonify-Dg6gChd3.d.mts.map +1 -0
- package/dist/ParseRouteParams-DBmqlmLh.d.mts +42 -0
- package/dist/ParseRouteParams-DBmqlmLh.d.mts.map +1 -0
- package/dist/{RouteType-B6BMOyYw.mjs → Router-C4ADUfhv.mjs} +30 -42
- package/dist/Router-C4ADUfhv.mjs.map +1 -0
- package/dist/{Server-CF5wDJp6.d.mts → Server-C_IKav_e.d.mts} +44 -16
- package/dist/Server-C_IKav_e.d.mts.map +1 -0
- package/dist/{ServerEvent-CxPwA4lH.mjs → ServerEvent-Dljn5i7A.mjs} +37 -11
- package/dist/ServerEvent-Dljn5i7A.mjs.map +1 -0
- package/dist/Site-CMa153FA.d.mts +565 -0
- package/dist/Site-CMa153FA.d.mts.map +1 -0
- package/dist/StandardSchema-D28L8_zZ.d.mts +100 -0
- package/dist/StandardSchema-D28L8_zZ.d.mts.map +1 -0
- package/dist/TypedResponse-6lznqN4U.d.mts +22 -0
- package/dist/TypedResponse-6lznqN4U.d.mts.map +1 -0
- package/dist/{_page-BQs4WvCO.mjs → _page-4cQKs_Dn.mjs} +3 -5
- package/dist/_page-4cQKs_Dn.mjs.map +1 -0
- package/dist/bin/index.d.mts +1 -1
- package/dist/bin/index.js +15 -11
- package/dist/bin/index.js.map +1 -1
- package/dist/flattenHeaders-C_YYLdOq.mjs +114 -0
- package/dist/flattenHeaders-C_YYLdOq.mjs.map +1 -0
- package/dist/form.d.mts +35 -0
- package/dist/form.d.mts.map +1 -0
- package/dist/form.mjs +48 -0
- package/dist/form.mjs.map +1 -0
- package/dist/index.d.mts +72 -156
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +158 -26
- package/dist/index.mjs.map +1 -1
- package/dist/nav.d.mts +58 -5
- package/dist/nav.d.mts.map +1 -1
- package/dist/nav.mjs +116 -38
- package/dist/nav.mjs.map +1 -1
- package/dist/openapi.d.mts +144 -0
- package/dist/openapi.d.mts.map +1 -0
- package/dist/openapi.mjs +2 -0
- package/dist/pathTrie-D4Ax2Mu9.mjs +160 -0
- package/dist/pathTrie-D4Ax2Mu9.mjs.map +1 -0
- package/dist/plugin-D8Www11B.mjs +202 -0
- package/dist/plugin-D8Www11B.mjs.map +1 -0
- package/dist/{response-C5TtAsh1.mjs → response-Bg4w2S1q.mjs} +16 -39
- package/dist/response-Bg4w2S1q.mjs.map +1 -0
- package/dist/response.d.mts +309 -289
- package/dist/response.d.mts.map +1 -1
- package/dist/response.mjs +3 -4
- package/dist/run.d.mts +11 -4
- package/dist/run.d.mts.map +1 -1
- package/dist/run.mjs +2 -8
- package/dist/runOpenApi-BUi1RH1l.mjs +1381 -0
- package/dist/runOpenApi-BUi1RH1l.mjs.map +1 -0
- package/dist/schema.d.mts +32 -0
- package/dist/schema.d.mts.map +1 -0
- package/dist/schema.mjs +2 -0
- package/dist/server.d.mts +10 -8
- package/dist/server.d.mts.map +1 -1
- package/dist/server.mjs +132 -4
- package/dist/server.mjs.map +1 -0
- package/dist/state.d.mts.map +1 -1
- package/dist/state.mjs +2 -3
- package/dist/test.d.mts +8 -10
- package/dist/test.d.mts.map +1 -1
- package/dist/test.mjs +283 -79
- package/dist/test.mjs.map +1 -1
- package/dist/{seeOther-B4Yhu9iq.mjs → unprocessable-DAZbrDeR.mjs} +34 -13
- package/dist/unprocessable-DAZbrDeR.mjs.map +1 -0
- package/dist/validate-Ok4krlkX.mjs +40 -0
- package/dist/validate-Ok4krlkX.mjs.map +1 -0
- package/package.json +28 -17
- package/src/bin/index.ts +13 -2
- package/src/dev.ts +10 -0
- package/src/form/formDataToRecord.ts +23 -0
- package/src/form/readForm.ts +71 -0
- package/src/form.ts +4 -0
- package/src/index.ts +53 -1
- package/src/nav/api.test-d.ts +79 -0
- package/src/nav/api.ts +104 -0
- package/src/nav/formSubmit.ts +18 -4
- package/src/nav/navigate.ts +40 -15
- package/src/nav/route.ts +38 -0
- package/src/nav.ts +3 -1
- package/src/openapi/docsHtml.ts +25 -0
- package/src/openapi/document.ts +154 -0
- package/src/openapi/plugin.ts +78 -0
- package/src/openapi/types.ts +82 -0
- package/src/openapi.ts +14 -0
- package/src/response/TypedResponse.ts +17 -0
- package/src/response/badRequest.ts +14 -2
- package/src/response/created.ts +13 -2
- package/src/response/found.ts +2 -2
- package/src/response/movedPermanently.ts +2 -2
- package/src/response/notModified.ts +2 -2
- package/src/response/ok.ts +13 -4
- package/src/response/response.ts +4 -4
- package/src/response/unprocessable.ts +14 -2
- package/src/run/depCache.ts +175 -0
- package/src/run/devPlugin.ts +128 -0
- package/src/run/prepareTemplate.ts +6 -3
- package/src/run/run.ts +63 -39
- package/src/run/runBuild.ts +63 -12
- package/src/run/runDev.ts +146 -58
- package/src/run/runOpenApi.ts +52 -0
- package/src/run/runPreview.ts +17 -26
- package/src/run/staleTorpCopies.ts +100 -0
- package/src/run.ts +2 -1
- package/src/schema.ts +7 -0
- package/src/server/CookieHelper.ts +17 -7
- package/src/server/Server.ts +54 -30
- package/src/server/ServerEvent.ts +24 -1
- package/src/server/connect/connectMiddleware.ts +44 -40
- package/src/server/connect/flattenHeaders.ts +1 -23
- package/src/server/connect/requestToNodeMessage.ts +6 -3
- package/src/server/types/MiddlewareFunction.ts +18 -4
- package/src/site/Router.ts +52 -41
- package/src/site/Site.ts +184 -10
- package/src/site/checkLayoutSlots.ts +114 -0
- package/src/site/checkRoutes.ts +435 -0
- package/src/site/clientEntry.ts +22 -9
- package/src/site/layoutSlots.ts +53 -0
- package/src/site/manifest.ts +125 -6
- package/src/site/serverEntry.ts +341 -132
- package/src/state/$page.ts +2 -1
- package/src/state/$serverPage.ts +22 -0
- package/src/test/runTest.ts +306 -118
- package/src/types/Adapter.ts +12 -0
- package/src/types/Jsonify.ts +20 -0
- package/src/types/PageData.test-d.ts +136 -0
- package/src/types/PageData.ts +35 -0
- package/src/types/PageEndPoint.ts +25 -9
- package/src/types/PageForm.test-d.ts +78 -0
- package/src/types/PageForm.ts +29 -0
- package/src/types/PageLoadEvent.ts +16 -4
- package/src/types/PageLoadReturn.ts +13 -0
- package/src/types/PageProps.ts +14 -0
- package/src/types/PageServerAction.ts +8 -2
- package/src/types/PageServerEndPoint.test-d.ts +105 -0
- package/src/types/PageServerEndPoint.ts +99 -5
- package/src/types/PageServerLoad.ts +11 -3
- package/src/types/ParseRouteParams.test-d.ts +84 -0
- package/src/types/ParseRouteParams.ts +64 -0
- package/src/types/Route.ts +20 -1
- package/src/types/RouteHandler.ts +8 -1
- package/src/types/ServerEndPoint.test-d.ts +77 -0
- package/src/types/ServerEndPoint.ts +148 -16
- package/src/types/ServerHook.ts +10 -3
- package/src/types/ServerLoadEvent.ts +48 -3
- package/src/types/ServerRequest.ts +10 -2
- package/src/types/SitePlugin.ts +24 -0
- package/src/types/StandardSchema.ts +109 -0
- package/src/utils/pathToRegex.ts +4 -2
- package/src/utils/pathTrie.ts +182 -0
- package/src/utils/searchParamsToRecord.ts +18 -0
- package/src/utils/torporPackages.ts +150 -0
- package/src/utils/tsconfigAliases.ts +90 -0
- package/src/validation/ValidationError.ts +18 -0
- package/src/validation/endpoint.ts +83 -0
- package/src/validation/validate.ts +26 -0
- package/dist/RouteType-B6BMOyYw.mjs.map +0 -1
- package/dist/Server-CF5wDJp6.d.mts.map +0 -1
- package/dist/ServerEvent-CxPwA4lH.mjs.map +0 -1
- package/dist/Site-DgC6WWn1.d.mts +0 -78
- package/dist/Site-DgC6WWn1.d.mts.map +0 -1
- package/dist/_page-BQs4WvCO.mjs.map +0 -1
- package/dist/connectMiddleware-D7nehjj3.mjs +0 -252
- package/dist/connectMiddleware-D7nehjj3.mjs.map +0 -1
- package/dist/pathToRegex-TUAMc3zS.mjs +0 -11
- package/dist/pathToRegex-TUAMc3zS.mjs.map +0 -1
- package/dist/response-C5TtAsh1.mjs.map +0 -1
- package/dist/run-BPFtSYA3.mjs +0 -332
- package/dist/run-BPFtSYA3.mjs.map +0 -1
- package/dist/seeOther-B4Yhu9iq.mjs.map +0 -1
- package/src/server/Routerx.ts +0 -72
- package/src/server/connect/bufferToArrayBuffer.ts +0 -8
- package/src/server/connect/readableToBuffer.ts +0 -16
package/src/site/manifest.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { Plugin } from "vite";
|
|
4
|
+
import type { ResolvedOpenApiOptions } from "../openapi/types";
|
|
5
|
+
import { OPEN_API_STATE_KEY } from "../openapi/plugin";
|
|
4
6
|
import Site from "./Site";
|
|
7
|
+
import { SERVER_ROUTE } from "../types/RouteType";
|
|
5
8
|
|
|
6
9
|
const moduleId = "@torpor/build/manifest";
|
|
7
10
|
|
|
11
|
+
const LOAD_EXPORT_RE =
|
|
12
|
+
/[{,]\s*load\s*[:(]|\bexport\s+(?:async\s+)?(?:function|const|let|var)\s+load\b|\bexport\s*\{[^}]*\bload\b/;
|
|
13
|
+
|
|
14
|
+
export function hasLoadExport(source: string): boolean {
|
|
15
|
+
return LOAD_EXPORT_RE.test(source);
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
/**
|
|
9
19
|
* A Vite plugin that provides information about the app to both clientEntry and
|
|
10
20
|
* serverEntry.
|
|
@@ -24,27 +34,95 @@ export default function manifest(site: Site, server = false): Plugin {
|
|
|
24
34
|
load(id, viteOptions) {
|
|
25
35
|
if (id === moduleId) {
|
|
26
36
|
let serverRequest = server && !!viteOptions?.ssr;
|
|
37
|
+
|
|
38
|
+
// If there are inline endpoints, site plugins or an OpenAPI
|
|
39
|
+
// document, and we're building for the server, we need to import
|
|
40
|
+
// the config file to access them. On the client, the config file
|
|
41
|
+
// is never imported, keeping server code out of the client bundle.
|
|
42
|
+
const hasInline = site.routes.some((r) => r.endPoint && !r.file);
|
|
43
|
+
const hasPlugins = site.plugins.length > 0;
|
|
44
|
+
const hasOpenApi = site.pluginState.has(OPEN_API_STATE_KEY);
|
|
45
|
+
const configImport =
|
|
46
|
+
hasInline || hasPlugins || hasOpenApi
|
|
47
|
+
? serverRequest && site.configFile
|
|
48
|
+
? `import __site from ${JSON.stringify(site.configFile)};`
|
|
49
|
+
: ""
|
|
50
|
+
: "";
|
|
51
|
+
|
|
52
|
+
// Site plugins are run when the server starts up (in dev and in
|
|
53
|
+
// production), so that routes they register are available at
|
|
54
|
+
// runtime. Top-level await is fine here: this module is only
|
|
55
|
+
// loaded through Vite's SSR pipeline
|
|
56
|
+
const pluginLoop =
|
|
57
|
+
serverRequest && hasPlugins
|
|
58
|
+
? `for (const __plugin of __site.plugins ?? []) { await __plugin(__site); }`
|
|
59
|
+
: "";
|
|
60
|
+
|
|
61
|
+
// The OpenAPI document endpoint is generated code (rather than an
|
|
62
|
+
// inline endpoint) because it must load each route file -- which
|
|
63
|
+
// only works from module code that Vite processes/bundles. The
|
|
64
|
+
// options live in `site.pluginState` (set by the plugin), so they
|
|
65
|
+
// are available both here and in the generated runtime code
|
|
66
|
+
const openApiOptions = site.pluginState.get(OPEN_API_STATE_KEY) as
|
|
67
|
+
| ResolvedOpenApiOptions
|
|
68
|
+
| undefined;
|
|
69
|
+
const openApiGlue =
|
|
70
|
+
serverRequest && openApiOptions && site.configFile
|
|
71
|
+
? openApiGlueCode(site, openApiOptions)
|
|
72
|
+
: "";
|
|
73
|
+
|
|
74
|
+
const openApiRoute =
|
|
75
|
+
serverRequest && openApiOptions
|
|
76
|
+
? `{ path: ${JSON.stringify(openApiOptions.path)}, type: ${SERVER_ROUTE}, endPoint: () => Promise.resolve({ default: { get: __openApiGet } }), subFolder: undefined },`
|
|
77
|
+
: "";
|
|
78
|
+
|
|
27
79
|
return `
|
|
28
80
|
${!serverRequest ? "const load = { default: { load: true } };" : ""}
|
|
81
|
+
${configImport}
|
|
82
|
+
${pluginLoop}
|
|
83
|
+
${openApiGlue}
|
|
29
84
|
export default {
|
|
30
85
|
routes: [
|
|
31
86
|
${site.routes
|
|
32
87
|
.map((r) => {
|
|
33
88
|
let endPoint: string;
|
|
34
|
-
if (
|
|
35
|
-
|
|
89
|
+
if (!r.file) {
|
|
90
|
+
// Inline endpoint (no file)
|
|
91
|
+
if (serverRequest) {
|
|
92
|
+
const key = `${r.path}:${r.type}`;
|
|
93
|
+
endPoint = `() => Promise.resolve({ default: __site.inlineEndPoints[${JSON.stringify(key)}] })`;
|
|
94
|
+
} else {
|
|
95
|
+
// Client-side stub: check if the inline
|
|
96
|
+
// endpoint has a load function
|
|
97
|
+
const haveLoad =
|
|
98
|
+
typeof (r.endPoint as Record<string, unknown> | undefined)?.load === "function";
|
|
99
|
+
endPoint = haveLoad ? "() => load" : "undefined";
|
|
100
|
+
}
|
|
101
|
+
} else if (serverRequest || !/server\.(ts|js)$/.test(r.file)) {
|
|
102
|
+
const filePath = path.join(site.root, r.file);
|
|
103
|
+
// NOTE: No `@vite-ignore` here, so that Vite processes the import:
|
|
104
|
+
// in dev the module runner transforms the file on the fly, and in
|
|
105
|
+
// a production build Rollup bundles the route into a chunk and
|
|
106
|
+
// rewrites the import -- leaving the raw source path in place
|
|
107
|
+
// would hand Node/wrangler `.ts`/`.torp` files it can't load
|
|
108
|
+
const importExpr = `() => import("${filePath}")`;
|
|
109
|
+
// A .torp file's default export is a component, so wrap it
|
|
110
|
+
// as a PageEndPoint ({ component }) for the entries
|
|
111
|
+
endPoint = r.file.endsWith(".torp")
|
|
112
|
+
? `${importExpr}.then((m) => ({ default: { component: m.default } }))`
|
|
113
|
+
: importExpr;
|
|
36
114
|
} else {
|
|
37
115
|
// On the client, for a server route, we need to check
|
|
38
116
|
// whether there's a load function and set a dummy endPoint
|
|
39
117
|
// if so. The correct endpoint will be hit in clientEntry
|
|
40
|
-
|
|
41
|
-
const haveLoad = readFileSync(path.join(site.root, r.file)).includes("load:");
|
|
118
|
+
const haveLoad = hasLoadExport(readFileSync(path.join(site.root, r.file), "utf8"));
|
|
42
119
|
endPoint = haveLoad ? "() => load" : "undefined";
|
|
43
120
|
}
|
|
44
121
|
const sub = r.subFolder ? `"${r.subFolder}"` : "undefined";
|
|
45
|
-
return `{ path: "${r.path}", type: ${r.type}, endPoint: ${endPoint}, subFolder: ${sub} }
|
|
122
|
+
return `{ path: "${r.path}", type: ${r.type}, endPoint: ${endPoint}, subFolder: ${sub} },`;
|
|
46
123
|
})
|
|
47
|
-
.join("
|
|
124
|
+
.join("\n ")}
|
|
125
|
+
${openApiRoute}
|
|
48
126
|
],
|
|
49
127
|
};
|
|
50
128
|
`;
|
|
@@ -52,3 +130,44 @@ export default {
|
|
|
52
130
|
},
|
|
53
131
|
};
|
|
54
132
|
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Generates the module code for the OpenAPI document endpoint: a map of
|
|
136
|
+
* route path to endpoint loader, and a cached handler that loads every
|
|
137
|
+
* endpoint and builds the document on first use.
|
|
138
|
+
*/
|
|
139
|
+
function openApiGlueCode(site: Site, options: ResolvedOpenApiOptions): string {
|
|
140
|
+
const loaders = site.routes
|
|
141
|
+
.filter((r) => r.type === SERVER_ROUTE)
|
|
142
|
+
// Don't document the docs page itself
|
|
143
|
+
.filter((r) => r.path !== options.docs)
|
|
144
|
+
.map((r) => {
|
|
145
|
+
if (!r.file) {
|
|
146
|
+
const key = `${r.path}:${r.type}`;
|
|
147
|
+
return `${JSON.stringify(r.path)}: () => Promise.resolve({ default: __site.inlineEndPoints[${JSON.stringify(key)}] })`;
|
|
148
|
+
}
|
|
149
|
+
const filePath = path.join(site.root, r.file);
|
|
150
|
+
return `${JSON.stringify(r.path)}: () => import(${JSON.stringify(filePath)})`;
|
|
151
|
+
})
|
|
152
|
+
.join(",\n ");
|
|
153
|
+
|
|
154
|
+
return `
|
|
155
|
+
import { buildOpenApiDocument, OPEN_API_STATE_KEY } from "@torpor/build/openapi";
|
|
156
|
+
let __openApiDoc;
|
|
157
|
+
const __openApiRoutes = {
|
|
158
|
+
${loaders}
|
|
159
|
+
};
|
|
160
|
+
async function __openApiGet() {
|
|
161
|
+
if (!__openApiDoc) {
|
|
162
|
+
const __entries = [];
|
|
163
|
+
for (const [__path, __loader] of Object.entries(__openApiRoutes)) {
|
|
164
|
+
__entries.push({ path: __path, endPoint: (await __loader()).default });
|
|
165
|
+
}
|
|
166
|
+
__openApiDoc = buildOpenApiDocument(__entries, __site.pluginState.get(OPEN_API_STATE_KEY));
|
|
167
|
+
}
|
|
168
|
+
return new Response(JSON.stringify(__openApiDoc), {
|
|
169
|
+
headers: { "Content-Type": "application/json" },
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
}
|