@pikku/bun-server 0.12.3 → 0.12.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @pikku/bun-server
2
2
 
3
+ ## 0.12.4
4
+
5
+ ### Patch Changes
6
+
7
+ - d4a2503: Serve the console same-origin at /console (#861). Both dev servers gain
8
+ `staticMounts` (prefix → directory static serving with SPA fallback and path
9
+ traversal protection); `pikku serve` / `pikku dev` mount the bundled console
10
+ app at `/console` on the API port whenever it is bundled, so auth cookies are
11
+ first-party and no `?server=` param is needed. The console is built with
12
+ `base: '/console/'` (its router already derives the basename from BASE_URL).
13
+ The separate `--console <port>` static server is removed; `pikku console`
14
+ serves the bundle under /console and redirects the root there.
15
+ - Updated dependencies [61c9ce9]
16
+ - Updated dependencies [f1f39f8]
17
+ - Updated dependencies [c45e98d]
18
+ - Updated dependencies [472a349]
19
+ - @pikku/core@0.12.52
20
+
3
21
  ## 0.12.3
4
22
 
5
23
  ### Patch Changes
@@ -2,9 +2,15 @@ import type { CoreConfig } from '@pikku/core';
2
2
  import type { Logger } from '@pikku/core/services';
3
3
  import { type RunHTTPWiringOptions } from '@pikku/core/http';
4
4
  import { BunEventHubService } from './bun-event-hub-service.js';
5
+ export type StaticMount = {
6
+ urlPrefix: string;
7
+ directory: string;
8
+ spaFallback?: boolean;
9
+ };
5
10
  export type BunServerConfig = CoreConfig & {
6
11
  port: number;
7
12
  hostname?: string;
13
+ staticMounts?: StaticMount[];
8
14
  healthCheckPath?: string;
9
15
  };
10
16
  export type PikkuBunServerOptions = RunHTTPWiringOptions & {
@@ -29,6 +35,9 @@ export declare class PikkuBunServer {
29
35
  init(): Promise<void>;
30
36
  private initMCP;
31
37
  start(): Promise<void>;
38
+ get port(): number;
39
+ private serveStaticMounts;
40
+ private resolveStaticFile;
32
41
  stop(): Promise<void>;
33
42
  enableExitOnSignals(): void;
34
43
  }
@@ -3,6 +3,7 @@ import { fetchData, PikkuFetchHTTPRequest, PikkuFetchHTTPResponse, logRoutes as
3
3
  import { logChannels } from '@pikku/core/channel';
4
4
  import { runLocalChannel } from '@pikku/core/channel/local';
5
5
  import { compileAllSchemas } from '@pikku/core/schema';
6
+ import { resolve } from 'node:path';
6
7
  import { BunEventHubService } from './bun-event-hub-service.js';
7
8
  const isSerializable = (data) => !(typeof data === 'string' ||
8
9
  data instanceof ArrayBuffer ||
@@ -101,6 +102,10 @@ export class PikkuBunServer {
101
102
  return await mcpHandler(req);
102
103
  }
103
104
  }
105
+ const staticResponse = await this.serveStaticMounts(req);
106
+ if (staticResponse) {
107
+ return staticResponse;
108
+ }
104
109
  const pikkuReq = new PikkuFetchHTTPRequest(req);
105
110
  const pikkuRes = new PikkuFetchHTTPResponse();
106
111
  await fetchData(pikkuReq, pikkuRes, {
@@ -150,6 +155,54 @@ export class PikkuBunServer {
150
155
  eventHub.setServer(this.server);
151
156
  logger.info(`pikku-bun-server: listening on http://${config.hostname ?? 'localhost'}:${config.port}`);
152
157
  }
158
+ get port() {
159
+ return this.server?.port ?? this.config.port;
160
+ }
161
+ async serveStaticMounts(req) {
162
+ const mounts = this.config.staticMounts;
163
+ if (!mounts?.length || (req.method !== 'GET' && req.method !== 'HEAD')) {
164
+ return null;
165
+ }
166
+ const pathname = decodeURIComponent(new URL(req.url).pathname);
167
+ for (const mount of mounts) {
168
+ if (pathname !== mount.urlPrefix &&
169
+ !pathname.startsWith(`${mount.urlPrefix}/`)) {
170
+ continue;
171
+ }
172
+ const key = pathname.slice(mount.urlPrefix.length).replace(/^\/+/, '');
173
+ const file = await this.resolveStaticFile(mount, key);
174
+ if (file) {
175
+ return new Response(req.method === 'HEAD' ? null : file);
176
+ }
177
+ if (mount.spaFallback) {
178
+ const index = await this.resolveStaticFile(mount, 'index.html');
179
+ if (index) {
180
+ return new Response(req.method === 'HEAD' ? null : index);
181
+ }
182
+ }
183
+ return new Response('Not Found', { status: 404 });
184
+ }
185
+ return null;
186
+ }
187
+ async resolveStaticFile(mount, key) {
188
+ const directory = resolve(mount.directory);
189
+ const targetPath = key === '' ? resolve(directory, 'index.html') : resolve(directory, key);
190
+ if (targetPath !== directory && !targetPath.startsWith(`${directory}/`)) {
191
+ return null;
192
+ }
193
+ let file = Bun.file(targetPath);
194
+ if (!(await file.exists())) {
195
+ const indexPath = resolve(targetPath, 'index.html');
196
+ if (!indexPath.startsWith(`${directory}/`)) {
197
+ return null;
198
+ }
199
+ file = Bun.file(indexPath);
200
+ if (!(await file.exists())) {
201
+ return null;
202
+ }
203
+ }
204
+ return file;
205
+ }
153
206
  async stop() {
154
207
  await this.server?.stop();
155
208
  this.server = null;
@@ -1 +1 @@
1
- {"version":3,"file":"pikku-bun-server.js","sourceRoot":"","sources":["../src/pikku-bun-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pikku-bun-server.js","sourceRoot":"","sources":["../src/pikku-bun-server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/bun-server",
3
- "version": "0.12.3",
3
+ "version": "0.12.4",
4
4
  "description": "Pikku server adapter for Bun (Bun.serve)",
5
5
  "license": "MIT",
6
6
  "author": "yasser.fadl@gmail.com",
@@ -16,7 +16,7 @@
16
16
  "prepublishOnly": "bun run build"
17
17
  },
18
18
  "peerDependencies": {
19
- "@pikku/core": "^0.12.44",
19
+ "@pikku/core": "^0.12.52",
20
20
  "@pikku/modelcontextprotocol": "^0.12.6"
21
21
  },
22
22
  "peerDependenciesMeta": {
@@ -15,11 +15,20 @@ import type { PikkuLocalChannelHandler } from '@pikku/core/channel/local'
15
15
  import { runLocalChannel } from '@pikku/core/channel/local'
16
16
  import { compileAllSchemas } from '@pikku/core/schema'
17
17
 
18
+ import { resolve } from 'node:path'
19
+
18
20
  import { BunEventHubService } from './bun-event-hub-service.js'
19
21
 
22
+ export type StaticMount = {
23
+ urlPrefix: string
24
+ directory: string
25
+ spaFallback?: boolean
26
+ }
27
+
20
28
  export type BunServerConfig = CoreConfig & {
21
29
  port: number
22
30
  hostname?: string
31
+ staticMounts?: StaticMount[]
23
32
  healthCheckPath?: string
24
33
  }
25
34
 
@@ -167,6 +176,11 @@ export class PikkuBunServer {
167
176
  }
168
177
  }
169
178
 
179
+ const staticResponse = await this.serveStaticMounts(req)
180
+ if (staticResponse) {
181
+ return staticResponse
182
+ }
183
+
170
184
  const pikkuReq = new PikkuFetchHTTPRequest(req)
171
185
  const pikkuRes = new PikkuFetchHTTPResponse()
172
186
  await fetchData(pikkuReq, pikkuRes, {
@@ -225,6 +239,65 @@ export class PikkuBunServer {
225
239
  )
226
240
  }
227
241
 
242
+ public get port(): number {
243
+ return this.server?.port ?? this.config.port
244
+ }
245
+
246
+ private async serveStaticMounts(req: Request): Promise<Response | null> {
247
+ const mounts = this.config.staticMounts
248
+ if (!mounts?.length || (req.method !== 'GET' && req.method !== 'HEAD')) {
249
+ return null
250
+ }
251
+ const pathname = decodeURIComponent(new URL(req.url).pathname)
252
+
253
+ for (const mount of mounts) {
254
+ if (
255
+ pathname !== mount.urlPrefix &&
256
+ !pathname.startsWith(`${mount.urlPrefix}/`)
257
+ ) {
258
+ continue
259
+ }
260
+ const key = pathname.slice(mount.urlPrefix.length).replace(/^\/+/, '')
261
+ const file = await this.resolveStaticFile(mount, key)
262
+ if (file) {
263
+ return new Response(req.method === 'HEAD' ? null : file)
264
+ }
265
+ if (mount.spaFallback) {
266
+ const index = await this.resolveStaticFile(mount, 'index.html')
267
+ if (index) {
268
+ return new Response(req.method === 'HEAD' ? null : index)
269
+ }
270
+ }
271
+ return new Response('Not Found', { status: 404 })
272
+ }
273
+
274
+ return null
275
+ }
276
+
277
+ private async resolveStaticFile(
278
+ mount: StaticMount,
279
+ key: string
280
+ ): Promise<ReturnType<typeof Bun.file> | null> {
281
+ const directory = resolve(mount.directory)
282
+ const targetPath =
283
+ key === '' ? resolve(directory, 'index.html') : resolve(directory, key)
284
+ if (targetPath !== directory && !targetPath.startsWith(`${directory}/`)) {
285
+ return null
286
+ }
287
+ let file = Bun.file(targetPath)
288
+ if (!(await file.exists())) {
289
+ const indexPath = resolve(targetPath, 'index.html')
290
+ if (!indexPath.startsWith(`${directory}/`)) {
291
+ return null
292
+ }
293
+ file = Bun.file(indexPath)
294
+ if (!(await file.exists())) {
295
+ return null
296
+ }
297
+ }
298
+ return file
299
+ }
300
+
228
301
  public async stop(): Promise<void> {
229
302
  await this.server?.stop()
230
303
  this.server = null
@@ -0,0 +1,108 @@
1
+ import { describe, test, before, after } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs'
4
+ import { tmpdir } from 'node:os'
5
+ import { join } from 'node:path'
6
+ import { setSingletonServices } from '@pikku/core'
7
+ import { resetPikkuState } from '@pikku/core/internal'
8
+ import type { Logger } from '@pikku/core/services'
9
+ import { PikkuBunServer } from './pikku-bun-server.js'
10
+
11
+ const noopLogger = {
12
+ info: () => {},
13
+ error: () => {},
14
+ warn: () => {},
15
+ debug: () => {},
16
+ trace: () => {},
17
+ setLevel: () => {},
18
+ } as unknown as Logger
19
+
20
+ describe('PikkuBunServer static mounts', () => {
21
+ let server: PikkuBunServer
22
+ let tmpDir: string
23
+ let origin: string
24
+
25
+ before(async () => {
26
+ resetPikkuState()
27
+ setSingletonServices({
28
+ logger: noopLogger,
29
+ schema: {
30
+ compileSchema: () => {},
31
+ getSchemaNames: () => new Set<string>(),
32
+ },
33
+ } as any)
34
+ tmpDir = mkdtempSync(join(tmpdir(), 'pikku-bun-static-'))
35
+ writeFileSync(
36
+ join(tmpDir, 'index.html'),
37
+ '<!doctype html><title>console</title>'
38
+ )
39
+ mkdirSync(join(tmpDir, 'assets'))
40
+ writeFileSync(join(tmpDir, 'assets', 'app.js'), 'console.log("app")')
41
+
42
+ server = new PikkuBunServer(
43
+ {
44
+ port: 0,
45
+ hostname: '127.0.0.1',
46
+ staticMounts: [
47
+ { urlPrefix: '/console', directory: tmpDir, spaFallback: true },
48
+ ],
49
+ } as any,
50
+ noopLogger
51
+ )
52
+ await server.init()
53
+ await server.start()
54
+ origin = `http://127.0.0.1:${server.port}`
55
+ })
56
+
57
+ after(async () => {
58
+ await server.stop()
59
+ rmSync(tmpDir, { recursive: true, force: true })
60
+ })
61
+
62
+ test('serves files under the prefix with a content type', async () => {
63
+ const response = await fetch(`${origin}/console/assets/app.js`)
64
+ assert.equal(response.status, 200)
65
+ assert.match(response.headers.get('content-type') ?? '', /javascript/)
66
+ assert.equal(await response.text(), 'console.log("app")')
67
+ })
68
+
69
+ test('serves index.html at the mount root, with and without trailing slash', async () => {
70
+ for (const path of ['/console', '/console/']) {
71
+ const response = await fetch(`${origin}${path}`)
72
+ assert.equal(response.status, 200)
73
+ assert.match(await response.text(), /<title>console<\/title>/)
74
+ }
75
+ })
76
+
77
+ test('SPA fallback serves index.html for unknown paths under the prefix', async () => {
78
+ const response = await fetch(`${origin}/console/tests/userflows?id=x`)
79
+ assert.equal(response.status, 200)
80
+ assert.match(await response.text(), /<title>console<\/title>/)
81
+ })
82
+
83
+ test('does not intercept paths outside the prefix', async () => {
84
+ const response = await fetch(`${origin}/consolerelated`)
85
+ assert.equal(response.status, 404)
86
+ })
87
+
88
+ test('does not intercept non-GET methods', async () => {
89
+ const response = await fetch(`${origin}/console/assets/app.js`, {
90
+ method: 'POST',
91
+ })
92
+ assert.equal(response.status, 404)
93
+ })
94
+
95
+ test('blocks path traversal out of the mount directory', async () => {
96
+ writeFileSync(join(tmpDir, '..', 'pikku-bun-static-secret.txt'), 'secret')
97
+ try {
98
+ const response = await fetch(
99
+ `${origin}/console/%2e%2e/pikku-bun-static-secret.txt`
100
+ )
101
+ assert.notEqual(response.status, 200)
102
+ } finally {
103
+ rmSync(join(tmpDir, '..', 'pikku-bun-static-secret.txt'), {
104
+ force: true,
105
+ })
106
+ }
107
+ })
108
+ })