@gambrel/bun 0.0.0-stage → 0.2.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/LICENSE ADDED
@@ -0,0 +1,106 @@
1
+ Required Notice: Copyright (c) 2026 Nolly (https://github.com/thenolle)
2
+
3
+ # PolyForm Strict License 1.0.0
4
+
5
+ <https://polyformproject.org/licenses/strict/1.0.0>
6
+
7
+ ## Acceptance
8
+
9
+ In order to get any license under these terms, you must agree
10
+ to them as both strict obligations and conditions to all
11
+ your licenses.
12
+
13
+ ## Copyright License
14
+
15
+ The licensor grants you a copyright license for the software
16
+ to do everything you might do with the software that would
17
+ otherwise infringe the licensor's copyright in it for any
18
+ permitted purpose, other than distributing the software or
19
+ making changes or new works based on the software.
20
+
21
+ ## Patent License
22
+
23
+ The licensor grants you a patent license for the software that
24
+ covers patent claims the licensor can license, or becomes able
25
+ to license, that you would infringe by using the software.
26
+
27
+ ## Noncommercial Purposes
28
+
29
+ Any noncommercial purpose is a permitted purpose.
30
+
31
+ ## Personal Uses
32
+
33
+ Personal use for research, experiment, and testing for
34
+ the benefit of public knowledge, personal study, private
35
+ entertainment, hobby projects, amateur pursuits, or religious
36
+ observance, without any anticipated commercial application,
37
+ is use for a permitted purpose.
38
+
39
+ ## Noncommercial Organizations
40
+
41
+ Use by any charitable organization, educational institution,
42
+ public research organization, public safety or health
43
+ organization, environmental protection organization,
44
+ or government institution is use for a permitted purpose
45
+ regardless of the source of funding or obligations resulting
46
+ from the funding.
47
+
48
+ ## Fair Use
49
+
50
+ You may have "fair use" rights for the software under the
51
+ law. These terms do not limit them.
52
+
53
+ ## No Other Rights
54
+
55
+ These terms do not allow you to sublicense or transfer any of
56
+ your licenses to anyone else, or prevent the licensor from
57
+ granting licenses to anyone else. These terms do not imply
58
+ any other licenses.
59
+
60
+ ## Patent Defense
61
+
62
+ If you make any written claim that the software infringes or
63
+ contributes to infringement of any patent, your patent license
64
+ for the software granted under these terms ends immediately. If
65
+ your company makes such a claim, your patent license ends
66
+ immediately for work on behalf of your company.
67
+
68
+ ## Violations
69
+
70
+ The first time you are notified in writing that you have
71
+ violated any of these terms, or done anything with the software
72
+ not covered by your licenses, your licenses can nonetheless
73
+ continue if you come into full compliance with these terms,
74
+ and take practical steps to correct past violations, within
75
+ 32 days of receiving notice. Otherwise, all your licenses
76
+ end immediately.
77
+
78
+ ## No Liability
79
+
80
+ ***As far as the law allows, the software comes as is, without
81
+ any warranty or condition, and the licensor will not be liable
82
+ to you for any damages arising out of these terms or the use
83
+ or nature of the software, under any kind of legal claim.***
84
+
85
+ ## Definitions
86
+
87
+ The **licensor** is the individual or entity offering these
88
+ terms, and the **software** is the software the licensor makes
89
+ available under these terms.
90
+
91
+ **You** refers to the individual or entity agreeing to these
92
+ terms.
93
+
94
+ **Your company** is any legal entity, sole proprietorship,
95
+ or other kind of organization that you work for, plus all
96
+ organizations that have control over, are under the control of,
97
+ or are under common control with that organization. **Control**
98
+ means ownership of substantially all the assets of an entity,
99
+ or the power to direct its management and policies by vote,
100
+ contract, or otherwise. Control can be direct or indirect.
101
+
102
+ **Your licenses** are all the licenses granted to you for the
103
+ software under these terms.
104
+
105
+ **Use** means anything you do with the software requiring one
106
+ of your licenses.
package/README.md CHANGED
@@ -1,3 +1,19 @@
1
- # Temporary Holding Version
1
+ # @gambrel/bun
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `Bun.serve` adapter
4
+
5
+ Part of [Gambrel](https://github.com/thenolle/gambrel), a small TypeScript-first, JSX-based full-stack framework for Bun.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ bun add @gambrel/bun
11
+ ```
12
+
13
+ ## Documentation
14
+
15
+ See the [Gambrel documentation](https://github.com/thenolle/gambrel/tree/master/docs).
16
+
17
+ ## License
18
+
19
+ Licensed under the PolyForm-Strict-1.0.0: noncommercial use only, no distribution, no modification. See the LICENSE file.
@@ -0,0 +1,4 @@
1
+ export { serve } from './serve.js';
2
+ export { staticFiles } from './static.js';
3
+ export type { ServeOptions, ServerHandle } from './serve.js';
4
+ export type { StaticFilesOptions } from './static.js';
package/dist/index.js ADDED
@@ -0,0 +1,54 @@
1
+ // @bun
2
+ // packages/bun/src/serve.ts
3
+ function serve(app, options = {}) {
4
+ const server = Bun.serve({
5
+ port: options.port ?? 3000,
6
+ development: options.development ?? false,
7
+ ...options.hostname === undefined ? {} : { hostname: options.hostname },
8
+ fetch: (request) => app.fetch(request)
9
+ });
10
+ return {
11
+ url: server.url,
12
+ stop: (closeActiveConnections = false) => server.stop(closeActiveConnections)
13
+ };
14
+ }
15
+ // packages/bun/src/static.ts
16
+ import { stat } from "fs/promises";
17
+ import { resolve, sep } from "path";
18
+ import { text } from "@gambrel/core";
19
+ function isMissing(error) {
20
+ return typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
21
+ }
22
+ function staticFiles(options) {
23
+ const directory = resolve(options.directory);
24
+ const prefix = options.prefix.endsWith("/") ? options.prefix : `${options.prefix}/`;
25
+ return async (ctx, next) => {
26
+ if (ctx.method !== "GET" && ctx.method !== "HEAD" || !ctx.url.pathname.startsWith(prefix))
27
+ return next();
28
+ let relativePath;
29
+ try {
30
+ relativePath = decodeURIComponent(ctx.url.pathname.slice(prefix.length));
31
+ } catch {
32
+ return text("Bad Request", { status: 400 });
33
+ }
34
+ const path = resolve(directory, relativePath);
35
+ if (relativePath.includes("\x00") || !path.startsWith(directory + sep))
36
+ return text("Not Found", { status: 404 });
37
+ try {
38
+ if (!(await stat(path)).isFile())
39
+ return text("Not Found", { status: 404 });
40
+ } catch (error) {
41
+ if (isMissing(error))
42
+ return text("Not Found", { status: 404 });
43
+ throw error;
44
+ }
45
+ const file = Bun.file(path);
46
+ return new Response(ctx.method === "HEAD" ? null : file, {
47
+ headers: { "content-type": file.type, "cache-control": "no-cache" }
48
+ });
49
+ };
50
+ }
51
+ export {
52
+ serve,
53
+ staticFiles
54
+ };
@@ -0,0 +1,24 @@
1
+ import type { App } from '@gambrel/core';
2
+ export interface ServeOptions {
3
+ /**
4
+ * TCP port. Use 0 to let the OS pick a free port. Defaults to 3000.
5
+ */
6
+ readonly port?: number;
7
+ /**
8
+ * Interface to bind. Defaults to Bun's default.
9
+ */
10
+ readonly hostname?: string;
11
+ /**
12
+ * Enables Bun's development mode (more detailed error pages). Independent of the
13
+ * application's own `development` option. Defaults to false.
14
+ */
15
+ readonly development?: boolean;
16
+ }
17
+ export interface ServerHandle {
18
+ readonly url: URL;
19
+ stop(closeActiveConnections?: boolean): Promise<void>;
20
+ }
21
+ /**
22
+ * Serves an application through `Bun.serve`. Every request is passed to `app.fetch`.
23
+ */
24
+ export declare function serve(app: Pick<App, 'fetch'>, options?: ServeOptions): ServerHandle;
@@ -0,0 +1,18 @@
1
+ import { type Middleware } from '@gambrel/core';
2
+ export interface StaticFilesOptions {
3
+ /**
4
+ * Directory to serve files from.
5
+ */
6
+ readonly directory: string;
7
+ /**
8
+ * URL prefix, for example `/assets`.
9
+ */
10
+ readonly prefix: string;
11
+ }
12
+ /**
13
+ * Serves files under `prefix` from `directory` for GET and HEAD requests. Requests under
14
+ * the prefix never fall through: a missing file, a directory or a path that escapes the
15
+ * directory is a plain-text 404, so a missing asset can never be answered with an HTML page.
16
+ * Other methods and other paths go to the next handler. Responses use `cache-control: no-cache`.
17
+ */
18
+ export declare function staticFiles(options: StaticFilesOptions): Middleware;
package/package.json CHANGED
@@ -1,6 +1,44 @@
1
1
  {
2
2
  "name": "@gambrel/bun",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "`Bun.serve` adapter",
5
+ "license": "PolyForm-Strict-1.0.0",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "dependencies": {
18
+ "@gambrel/core": "^0.2.0"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md",
23
+ "LICENSE"
24
+ ],
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/thenolle/gambrel.git",
28
+ "directory": "packages/bun"
29
+ },
30
+ "homepage": "https://github.com/thenolle/gambrel#readme",
31
+ "bugs": {
32
+ "url": "https://github.com/thenolle/gambrel/issues"
33
+ },
34
+ "keywords": [
35
+ "gambrel",
36
+ "bun",
37
+ "typescript",
38
+ "ssr",
39
+ "jsx"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public"
43
+ }
44
+ }