bun-plugin-stx 0.2.277 → 0.2.279

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.
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Run stx page middleware through one public seam.
3
+ *
4
+ * Function handlers remain supported. Class-style middleware additionally
5
+ * contributes a priority, receives colon parameters through
6
+ * `request._middlewareParams`, and may throw a Response or status-carrying
7
+ * error to stop the chain.
8
+ */
9
+ export declare function runPageMiddleware(options: RunPageMiddlewareOptions): Promise<Response | null>;
10
+ /**
11
+ * Request surface shared with class-style middleware such as
12
+ * `@stacksjs/router`'s `Middleware` class.
13
+ */
14
+ export declare interface MiddlewareRequest extends Request {
15
+ params?: Record<string, string>
16
+ _middlewareParams?: Record<string, string>
17
+ }
18
+ /**
19
+ * Structural middleware contract. A `Middleware` instance from
20
+ * `@stacksjs/router` satisfies this without an adapter.
21
+ */
22
+ export declare interface MiddlewareDefinition {
23
+ readonly name: string
24
+ readonly priority?: number
25
+ readonly handle: MiddlewareDefinitionHandler
26
+ }
27
+ export declare interface MiddlewareContext {
28
+ path: string
29
+ url: URL
30
+ params: Record<string, string>
31
+ cookies: Record<string, string>
32
+ redirect: (to: string, status?: number) => Response
33
+ }
34
+ export declare interface RunPageMiddlewareOptions {
35
+ request: MiddlewareRequest
36
+ context: MiddlewareContext
37
+ entries: string[]
38
+ registry: Readonly<Record<string, PageMiddleware>>
39
+ prepareRequest?: PrepareMiddlewareRequest
40
+ }
41
+ /**
42
+ * Middleware handler compatible with the original stx page middleware API.
43
+ */
44
+ export type MiddlewareHandler = (
45
+ req: MiddlewareRequest,
46
+ ctx: MiddlewareContext,
47
+ ...args: string[]
48
+ ) => Response | null | undefined | void | Promise<Response | null | undefined | void>;
49
+ declare type MiddlewareDefinitionHandler = {
50
+ bivarianceHack: (
51
+ req: MiddlewareRequest,
52
+ ctx: MiddlewareContext,
53
+ ...args: string[]
54
+ ) => Response | null | undefined | void | Promise<Response | null | undefined | void>
55
+ }['bivarianceHack'];
56
+ export type PageMiddleware = MiddlewareHandler | MiddlewareDefinition;
57
+ export type PrepareMiddlewareRequest = (
58
+ request: MiddlewareRequest,
59
+ context: MiddlewareContext,
60
+ ) => MiddlewareRequest | Promise<MiddlewareRequest>;
package/dist/serve.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { MiddlewareContext, MiddlewareHandler, MiddlewareRequest, PageMiddleware, PrepareMiddlewareRequest } from './page-middleware';
2
+ export type { MiddlewareContext, MiddlewareDefinition, MiddlewareHandler, MiddlewareRequest, PageMiddleware, PrepareMiddlewareRequest } from './page-middleware';
1
3
  /**
2
4
  * Extract real top-level `<script server>` elements without matching tag-like
3
5
  * text inside HTML comments or another script body. A regex over the whole
@@ -243,7 +245,8 @@ export declare interface ServeOptions {
243
245
  | null
244
246
  | undefined
245
247
  | Promise<Response | null | undefined>
246
- middleware?: Record<string, MiddlewareHandler>
248
+ middleware?: Record<string, PageMiddleware>
249
+ prepareMiddlewareRequest?: PrepareMiddlewareRequest
247
250
  globalMiddleware?: string[]
248
251
  middlewareGroups?: Record<string, string[]>
249
252
  auth?: false | {
@@ -253,13 +256,6 @@ export declare interface ServeOptions {
253
256
  protectedPaths?: string[]
254
257
  }
255
258
  }
256
- export declare interface MiddlewareContext {
257
- path: string
258
- url: URL
259
- params: Record<string, string>
260
- cookies: Record<string, string>
261
- redirect: (to: string, status?: number) => Response
262
- }
263
259
  /**
264
260
  * The slice of Crosswind this server calls, taken from the package's own types
265
261
  * rather than restated here.
@@ -272,18 +268,3 @@ export declare interface MiddlewareContext {
272
268
  * `cwcss-crosswind.d.ts`). `typeof import` cannot drift from the real engine.
273
269
  */
274
270
  declare type CrosswindEngine = Pick<typeof import('@cwcss/crosswind'), 'CSSGenerator' | 'config'>;
275
- /**
276
- * Middleware handler — a Laravel-style gate that either passes through
277
- * (returns `void`/`null`/`undefined`) or terminates the pipeline by
278
- * returning a `Response`.
279
- *
280
- * The third argument is the colon-separated arg list, so a page that
281
- * declares `middleware: ['auth:admin']` invokes the `auth` handler
282
- * with `args = ['admin']` — the same shape as Laravel's
283
- * `handle($request, $next, ...$args)`.
284
- */
285
- export type MiddlewareHandler = (
286
- req: Request,
287
- ctx: MiddlewareContext,
288
- ...args: string[]
289
- ) => Response | null | undefined | void | Promise<Response | null | undefined | void>;
package/dist/serve.js CHANGED
@@ -8722,6 +8722,89 @@ import { BUILD_ID_HEADER, extractPageResponseStatus, findContainerRegion, FRAGME
8722
8722
  import { buildCodeFrame, locateFailureLine } from "@stacksjs/stx/build-message";
8723
8723
  import { clearBundleFailures, getBundleFailures } from "@stacksjs/stx/client-script-bundler";
8724
8724
  import { actionRedirectResponse, compressResponse, runPageAction as sharedRunPageAction } from "@stacksjs/stx";
8725
+
8726
+ // src/page-middleware.ts
8727
+ var DEFAULT_PRIORITY = 10;
8728
+ function middlewarePriority(middleware) {
8729
+ const raw = middleware.priority;
8730
+ return typeof raw === "number" && Number.isFinite(raw) && raw >= 0 ? raw : DEFAULT_PRIORITY;
8731
+ }
8732
+ function parseMiddlewareEntry(entry, registry) {
8733
+ const negated = entry.startsWith("!");
8734
+ const bare = negated ? entry.slice(1) : entry;
8735
+ if (Object.hasOwn(registry, bare))
8736
+ return { args: [], name: bare, negated };
8737
+ const colon = bare.indexOf(":");
8738
+ if (colon === -1)
8739
+ return { args: [], name: bare, negated };
8740
+ const params = bare.slice(colon + 1);
8741
+ return {
8742
+ args: params === "" ? [] : params.split(","),
8743
+ name: bare.slice(0, colon),
8744
+ negated,
8745
+ params
8746
+ };
8747
+ }
8748
+ function statusResponse(thrown) {
8749
+ if (thrown instanceof Response)
8750
+ return thrown;
8751
+ if (typeof thrown !== "object" || thrown === null)
8752
+ return null;
8753
+ const candidate = thrown;
8754
+ const rawStatus = candidate.statusCode ?? candidate.status;
8755
+ if (typeof rawStatus !== "number" || !Number.isInteger(rawStatus) || rawStatus < 100 || rawStatus > 599)
8756
+ return null;
8757
+ const message = typeof candidate.message === "string" ? candidate.message : "Middleware rejected the request";
8758
+ return new Response(message, { status: rawStatus });
8759
+ }
8760
+ async function invokeMiddleware(middleware, request, context, args) {
8761
+ try {
8762
+ const result = typeof middleware === "function" ? await middleware(request, context, ...args) : await middleware.handle(request, context, ...args);
8763
+ return result instanceof Response ? result : null;
8764
+ } catch (thrown) {
8765
+ const response = statusResponse(thrown);
8766
+ if (response)
8767
+ return response;
8768
+ throw thrown;
8769
+ }
8770
+ }
8771
+ async function runPageMiddleware(options) {
8772
+ options.request.params = options.context.params;
8773
+ const request = options.prepareRequest ? await options.prepareRequest(options.request, options.context) : options.request;
8774
+ request.params = options.context.params;
8775
+ request._middlewareParams ||= {};
8776
+ const resolved = [];
8777
+ for (const [index, entry] of options.entries.entries()) {
8778
+ const parsed = parseMiddlewareEntry(entry, options.registry);
8779
+ const middleware = options.registry[parsed.name];
8780
+ if (!middleware) {
8781
+ console.warn(`[stx serve] unknown middleware "${parsed.name}" on ${options.context.path}; failing closed`);
8782
+ return new Response(`Route middleware '${parsed.name}' is not registered`, { status: 500 });
8783
+ }
8784
+ resolved.push({
8785
+ ...parsed,
8786
+ index,
8787
+ middleware,
8788
+ priority: middlewarePriority(middleware)
8789
+ });
8790
+ }
8791
+ resolved.sort((a, b) => a.priority - b.priority || a.index - b.index);
8792
+ for (const entry of resolved) {
8793
+ if (entry.params !== undefined)
8794
+ request._middlewareParams[entry.name] = entry.params;
8795
+ const response = await invokeMiddleware(entry.middleware, request, options.context, entry.args);
8796
+ if (entry.negated) {
8797
+ if (response)
8798
+ continue;
8799
+ return new Response(`Access denied. This route requires "${entry.name}" not to apply.`, { status: 403 });
8800
+ }
8801
+ if (response)
8802
+ return response;
8803
+ }
8804
+ return null;
8805
+ }
8806
+
8807
+ // src/serve.ts
8725
8808
  var defaultStxModule = import("@stacksjs/stx");
8726
8809
  var REACTIVE_TEMPLATE_DIRECTIVE_RE = /@for|:for|@if|:if|@else|:else|x-for|x-if|x-else/;
8727
8810
  function extractServerScriptsFromTemplate(content) {
@@ -10393,19 +10476,15 @@ ${block}`;
10393
10476
  });
10394
10477
  }
10395
10478
  };
10396
- for (const entry of expanded) {
10397
- const colon = entry.indexOf(":");
10398
- const name = colon === -1 ? entry : entry.slice(0, colon);
10399
- const args = colon === -1 ? [] : entry.slice(colon + 1).split(",");
10400
- const handler = middlewareRegistry[name];
10401
- if (!handler) {
10402
- console.warn(`[stx serve] unknown middleware "${name}" on ${path}`);
10403
- continue;
10404
- }
10405
- const result = await handler(req, ctx, ...args);
10406
- if (result instanceof Response)
10407
- return result;
10408
- }
10479
+ const middlewareResponse = await runPageMiddleware({
10480
+ request: req,
10481
+ context: ctx,
10482
+ entries: expanded,
10483
+ registry: middlewareRegistry,
10484
+ prepareRequest: options.prepareMiddlewareRequest
10485
+ });
10486
+ if (middlewareResponse)
10487
+ return middlewareResponse;
10409
10488
  }
10410
10489
  if (options.routes) {
10411
10490
  const routeHandler = options.routes[path];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bun-plugin-stx",
3
3
  "type": "module",
4
- "version": "0.2.277",
4
+ "version": "0.2.279",
5
5
  "description": "A Bun plugin that allows for using Laravel Blade-like syntax.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",