@cosmicdrift/kumiko-server-runtime 0.377.0 → 0.378.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/dist/disk-file-route.d.ts +10 -0
- package/dist/disk-file-route.js +28 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +7 -7
- package/src/changes.json +6 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AnonymousExtraRoute } from "@cosmicdrift/kumiko-framework/api";
|
|
2
|
+
export type DiskFileRouteOptions = {
|
|
3
|
+
/** Route path containing the `:file` parameter, e.g. `/fonts/:file`. */
|
|
4
|
+
readonly path: string;
|
|
5
|
+
/** Maps a plain file name to an absolute disk path, or null to answer 404. Only one
|
|
6
|
+
* segment without a leading dot or separator gets here; anything else is 404 already.
|
|
7
|
+
* Must return fixed, allowlisted paths, never `join(dir, name)`: symlinks are not checked. */
|
|
8
|
+
readonly resolveFile: (requestedFile: string) => string | null;
|
|
9
|
+
};
|
|
10
|
+
export declare function diskFileRoute(options: DiskFileRouteOptions): AnonymousExtraRoute;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { readStaticFile, serveDiskFile } from "./run-prod-app-static-files.js";
|
|
2
|
+
// Hono percent-decodes the param, so `..%2F` arrives as `../`; a leading dot also
|
|
3
|
+
// covers `.`, `..` and dotfiles such as `.env` next to the served files.
|
|
4
|
+
function isPlainFileName(name) {
|
|
5
|
+
return name.length > 0 && !name.startsWith(".") && !/[/\\\0]/.test(name);
|
|
6
|
+
}
|
|
7
|
+
export function diskFileRoute(options) {
|
|
8
|
+
if (!options.path.includes(":file")) {
|
|
9
|
+
throw new Error(`diskFileRoute: path "${options.path}" must contain the ":file" parameter`);
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
method: "GET",
|
|
13
|
+
path: options.path,
|
|
14
|
+
entry: "anonymous",
|
|
15
|
+
handler: async (c) => {
|
|
16
|
+
const requestedFile = c.req.param("file") ?? "";
|
|
17
|
+
if (!isPlainFileName(requestedFile))
|
|
18
|
+
return c.notFound();
|
|
19
|
+
const filePath = options.resolveFile(requestedFile);
|
|
20
|
+
if (filePath === null)
|
|
21
|
+
return c.notFound();
|
|
22
|
+
const file = await readStaticFile(filePath);
|
|
23
|
+
if (!file)
|
|
24
|
+
return c.notFound();
|
|
25
|
+
return serveDiskFile(c.req.raw, c.req.path, file);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type { ProdSeedsConfig, ProdSeedTenant } from "./boot-options/seed-shortc
|
|
|
11
11
|
export { assertStackBootRequirements } from "./boot-options/stack-boot-requirements.ts";
|
|
12
12
|
export { type BundledAssetDeclaration, type BundledAssetOptions, readBundledAsset, resolveBundledAsset, } from "./bundled-assets.ts";
|
|
13
13
|
export { type ComposeFeaturesOptions, composeFeatures } from "./compose-features.ts";
|
|
14
|
+
export { type DiskFileRouteOptions, diskFileRoute } from "./disk-file-route.ts";
|
|
14
15
|
export type { RateLimitOption } from "./rate-limit-defaults.ts";
|
|
15
16
|
export type { RunBootstrapOptions } from "./run-bootstrap.ts";
|
|
16
17
|
export { runBootstrap } from "./run-bootstrap.ts";
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { isSeedFnList, rejectRemovedEffectiveFeatures, resolveBootOptionWiring,
|
|
|
9
9
|
export { assertStackBootRequirements } from "./boot-options/stack-boot-requirements.js";
|
|
10
10
|
export { readBundledAsset, resolveBundledAsset, } from "./bundled-assets.js";
|
|
11
11
|
export { composeFeatures } from "./compose-features.js";
|
|
12
|
+
export { diskFileRoute } from "./disk-file-route.js";
|
|
12
13
|
export { runBootstrap } from "./run-bootstrap.js";
|
|
13
14
|
export { parseRunMode, requireEnv, runProdApp } from "./run-prod-app.js";
|
|
14
15
|
export { runWorkerApp } from "./run-worker-app.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-server-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.378.0",
|
|
4
4
|
"description": "Production server-boot runtime for Kumiko apps: connections, schema-drift-gate, seeds, lifecycle, graceful shutdown. Symmetric to kumiko-dev-server's runDevApp, without dev/scaffold tooling.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -88,18 +88,18 @@
|
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
92
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
93
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
94
|
-
"@cosmicdrift/kumiko-renderer-mail-html": "0.
|
|
95
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
91
|
+
"@cosmicdrift/kumiko-bundled-features": "0.378.0",
|
|
92
|
+
"@cosmicdrift/kumiko-framework": "0.378.0",
|
|
93
|
+
"@cosmicdrift/kumiko-renderer": "0.378.0",
|
|
94
|
+
"@cosmicdrift/kumiko-renderer-mail-html": "0.378.0",
|
|
95
|
+
"@cosmicdrift/kumiko-types": "0.378.0",
|
|
96
96
|
"bun-types": "^1.3.13",
|
|
97
97
|
"ioredis": "^5.10.1",
|
|
98
98
|
"temporal-polyfill": "^0.3.2",
|
|
99
99
|
"zod": "^4.4.3"
|
|
100
100
|
},
|
|
101
101
|
"devDependencies": {
|
|
102
|
-
"@cosmicdrift/kumiko-testing": "0.
|
|
102
|
+
"@cosmicdrift/kumiko-testing": "0.378.0"
|
|
103
103
|
},
|
|
104
104
|
"publishConfig": {
|
|
105
105
|
"registry": "https://registry.npmjs.org",
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.378.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "diskFileRoute for allowlisted disk files",
|
|
6
|
+
"detail": "diskFileRoute({ path, resolveFile }) returns an anonymous GET extra route with a :file parameter. resolveFile maps the raw name to a disk path or null for 404; the file is served with mime type, ETag and 304 handling."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.376.0",
|
|
4
10
|
"type": "breaking",
|