@spirobel/mininext 0.6.0 → 0.7.1

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.
@@ -1,5 +1,11 @@
1
1
  /// <reference types="bun-types" />
2
2
  /// <reference types="bun-types" />
3
+ /// <reference types="bun-types" />
4
+ /// <reference types="bun-types" />
5
+ /// <reference types="bun-types" />
6
+ /// <reference types="bun-types" />
7
+ /// <reference types="bun-types" />
8
+ /// <reference types="bun-types" />
3
9
  import { url, Mini, has, type HtmlHandler } from "./url";
4
10
  import { isError, HtmlString, BasedHtml, head, commonHead, cssReset, basedHtml as html } from "./html";
5
11
  import { type Server, type WebSocketHandler } from "bun";
package/dist/mininext.js CHANGED
@@ -66,33 +66,53 @@ const nodeHttpsPlugin = {
66
66
  },
67
67
  };
68
68
  async function buildBackend(backendPath = "backend/backend.ts") {
69
- global.FrontendScriptUrls = [];
70
- global.FrontendScripts = [];
69
+ global.bundledFrontends = {};
71
70
  global.bundledSVGs = {};
72
71
  const i = await import(path.resolve(projectRoot(), backendPath));
73
72
  for (const frontend of url.getFrontends()) {
74
- const firstPlaceToLook = path.resolve(path.dirname(frontend.callerPath), `frontend/${frontend.path}`);
75
- const secondPlaceToLook = path.resolve(projectRoot(), `frontend/${frontend.path}`);
73
+ const firstPlaceToLook = path.resolve(path.dirname(frontend.callerPath), `frontend/${frontend.frontendFilePath}`);
74
+ const secondPlaceToLook = path.resolve(projectRoot(), `frontend/${frontend.frontendFilePath}`);
76
75
  const frontEndPath = (await Bun.file(firstPlaceToLook).exists())
77
76
  ? firstPlaceToLook
78
77
  : secondPlaceToLook;
79
78
  try {
80
- const f = await $ `bun run build.ts frontend ${frontEndPath}`.json();
81
- FrontendScriptUrls.push("/" + f.url);
82
- FrontendScripts.push(f.script);
79
+ const frontendResult = await $ `bun run build.ts frontend ${frontEndPath}`.json();
80
+ bundledFrontends[`/${frontendResult.url}`] = {
81
+ frontendContent: frontendResult.script,
82
+ frontendFilePath: frontend.frontendFilePath,
83
+ position: frontend.position,
84
+ };
83
85
  }
84
86
  catch (error) {
87
+ if (error &&
88
+ typeof error === "object" &&
89
+ "exitCode" in error &&
90
+ "stdout" in error &&
91
+ "stderr" in error &&
92
+ error.stdout instanceof Buffer &&
93
+ error.stderr instanceof Buffer) {
94
+ console.error(`Failed with exit code: ${error.exitCode}`);
95
+ console.error("Standard Output:", error.stdout.toString());
96
+ console.error("Standard Error:", error.stderr.toString());
97
+ }
85
98
  console.log(await $ `bun run build.ts frontend ${frontEndPath}`.text());
86
99
  }
87
100
  }
88
- for (const svgPath of url.getSvgPaths()) {
89
- const parsedSvgPath = path.parse(svgPath);
90
- const svgContent = Bun.file(path.join(projectRoot() + "/backend/", svgPath));
101
+ for (const svg of url.getSvgs()) {
102
+ const firstPlaceToLook = path.resolve(path.dirname(svg.callerPath), `svgs/${svg.svgFilePath}`);
103
+ const secondPlaceToLook = path.resolve(projectRoot(), `${svg.svgFilePath}`);
104
+ const svgResolvedFilePath = (await Bun.file(firstPlaceToLook).exists())
105
+ ? firstPlaceToLook
106
+ : secondPlaceToLook;
107
+ const parsedSvgPath = path.parse(svgResolvedFilePath);
108
+ const svgContent = Bun.file(svgResolvedFilePath);
91
109
  const svgHash = Bun.hash(await svgContent.arrayBuffer());
92
110
  const svgUrl = `/${parsedSvgPath.name}-${svgHash}.svg`;
93
111
  bundledSVGs[svgUrl] = {
94
112
  svgContent: await svgContent.text(),
95
- svgPath,
113
+ svgFilePath: svg.svgFilePath,
114
+ position: svg.position,
115
+ options: svg.options,
96
116
  };
97
117
  }
98
118
  const res = await Bun.build({
@@ -102,8 +122,7 @@ async function buildBackend(backendPath = "backend/backend.ts") {
102
122
  minify: Bun.argv[2] === "dev" ? false : true, //production
103
123
  target: "bun",
104
124
  define: {
105
- FrontendScripts: JSON.stringify(FrontendScripts),
106
- FrontendScriptUrls: JSON.stringify(FrontendScriptUrls),
125
+ bundledFrontends: JSON.stringify(bundledFrontends),
107
126
  bundledSVGs: JSON.stringify(bundledSVGs),
108
127
  },
109
128
  });
package/dist/url.d.ts CHANGED
@@ -1,8 +1,22 @@
1
1
  /// <reference types="bun-types" />
2
2
  /// <reference types="bun-types" />
3
- import type { Server, WebSocketHandler } from "bun";
3
+ /// <reference types="bun-types" />
4
+ /// <reference types="bun-types" />
5
+ /// <reference types="bun-types" />
6
+ /// <reference types="bun-types" />
7
+ /// <reference types="bun-types" />
8
+ /// <reference types="bun-types" />
9
+ import type { Server, WebSocketHandler, RouterTypes, BunRequest } from "bun";
4
10
  import { html, json, dangerjson, HtmlString } from "./html";
5
11
  import { BasedHtml, type DangerJsonInHtml, type JsonString, type JsonStringValues } from "./html";
12
+ export type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
13
+ export type MiniNextRouteHandlerObject<T extends string> = {
14
+ [K in HTTPMethod]?: HtmlHandler<unknown, T>;
15
+ };
16
+ export type MiniNextRouteValue<T extends string> = HtmlHandler<unknown, T> | MiniNextRouteHandlerObject<T>;
17
+ export type BunRoutes<R extends {
18
+ [K in keyof R]: RouterTypes.RouteValue<Extract<K, string>>;
19
+ }> = R;
6
20
  /**
7
21
  * A helper function that helps narrow unknown objects
8
22
  * @param object - the object of type unknown that is to be narrowed
@@ -43,13 +57,13 @@ export type NamedFormHandlerReturnType<X> = HandlerReturnType | Promise<HandlerR
43
57
  * const {html,json, css, data, req, form, link, svg, deliver, route, params, header, head } = mini //pull everything out of the mini handbag
44
58
  * ```
45
59
  */
46
- export declare class Mini<X = unknown> {
60
+ export declare class Mini<X = unknown, ROUTE extends string = ""> {
47
61
  html: typeof html<X>;
48
62
  css: typeof html<X>;
49
63
  json: typeof json<X>;
50
64
  dangerjson: typeof dangerjson<X>;
51
65
  data: X;
52
- req: Request;
66
+ req: BunRequest<ROUTE>;
53
67
  head: (head: HtmlHandler | HtmlString) => undefined;
54
68
  headers: (headers: HeadersInit, overwrite?: boolean) => undefined;
55
69
  options: (options: ResponseInit) => undefined;
@@ -71,14 +85,19 @@ export declare class Mini<X = unknown> {
71
85
  * const {html,json, css, data, req, form, link, svg, deliver, route, params, header, head } = mini //pull everything out of the mini handbag
72
86
  * ```
73
87
  */
74
- export type HtmlHandler<Y = unknown> = ((mini: Mini<Y>) => LazyHandlerReturnType) | (() => LazyHandlerReturnType);
88
+ export type HtmlHandler<Y = unknown, ROUTE extends string = ""> = ((mini: Mini<Y, ROUTE>) => LazyHandlerReturnType) | (() => LazyHandlerReturnType);
75
89
  export type NamedFormHandler<Y = unknown, Z = undefined> = ((mini: Mini<Y>) => NamedFormHandlerReturnType<Z>) | (() => NamedFormHandlerReturnType<Z>);
76
90
  declare global {
77
- var FrontendScripts: Array<string>;
78
- var FrontendScriptUrls: Array<string>;
91
+ var bundledFrontends: Record<string, {
92
+ frontendFilePath: string;
93
+ frontendContent: string;
94
+ position: number;
95
+ }>;
79
96
  var bundledSVGs: Record<string, {
80
97
  svgContent: string;
81
- svgPath: string;
98
+ svgFilePath: string;
99
+ options: ResponseInit;
100
+ position: number;
82
101
  }>;
83
102
  }
84
103
  export type ScriptTag = (...params: any[]) => Promise<HtmlString>;
@@ -88,22 +107,40 @@ interface LinkSettings {
88
107
  export declare class url {
89
108
  static websocket: WebSocketHandler | undefined;
90
109
  static server: Server;
110
+ static routes: BunRoutes<{}>;
91
111
  static direct_handlers_html: Map<string, HtmlHandler>;
92
112
  private static frontends;
93
113
  private static svgs;
94
- static svg(path: string, options?: ResponseInit): string | undefined;
95
- static frontend<X>(path: string, snippet?: BasedHtml): HtmlString;
96
- static frontend<X>(path: string, snippet?: HtmlHandler<X>): (mini: Mini<X>) => HtmlString;
114
+ /**
115
+ * This function takes care of bundling your svg (icons?) into the webapp
116
+ * they will have a hash in the name to break the cache when needed
117
+ * @param svgFilePath first place to look: svgs folder in the same path the calling file, after that path from project root.
118
+ * @param options ResponseInit, default headers for an svg
119
+ * @returns url to the svg
120
+ */
121
+ static svg(svgFilePath: string, options?: ResponseInit): string | undefined;
122
+ /**
123
+ * this function helps you build frontends with any kind of framework (no framework at all) and get the bundle
124
+ * @param path first place to look: frontend folder in the same path the calling file, after that /frontend path from project root.
125
+ * @param snippet this is handy to pass in a piece of html that often goes along with a certain frontend
126
+ * @returns a html script element with the bundled frontend as the src
127
+ */
128
+ static frontend<X>(frontendFilePath: string, snippet?: BasedHtml): HtmlString;
129
+ static frontend<X>(frontendFilePath: string, snippet?: HtmlHandler<X>): (mini: Mini<X>) => HtmlString;
97
130
  /**
98
131
  * This is used by the frontend bundler in order to find all frontends and their corresponding script files.
99
132
  */
100
133
  static getFrontends(): {
101
- path: string;
134
+ frontendFilePath: string;
102
135
  callerPath: string;
136
+ position: number;
137
+ }[];
138
+ static getSvgs(): {
139
+ svgFilePath: string;
140
+ callerPath: string;
141
+ position: number;
142
+ options: ResponseInit;
103
143
  }[];
104
- static getSvgPaths(): string[];
105
- static serveFrontend(req: Request): Response | undefined;
106
- static serveSvg(req: Request): Response | undefined;
107
144
  /**
108
145
  * tool to expose data to a frontend as a global variable.
109
146
  * @param name this will be added as window.name to the window object in the frontend
@@ -136,7 +173,7 @@ export declare class url {
136
173
  * @example const {html,json, css, data, req, form, link, svg, deliver, route, params, header, head } = mini //pull everything out of the mini handbag
137
174
  * @returns
138
175
  */
139
- handler: (dataHandler: HtmlHandler<T>) => (oldmini: Mini) => Promise<string | void | HtmlString>;
176
+ handler: (dataHandler: HtmlHandler<T>) => (oldmini: Mini) => Promise<string | void | JsonString>;
140
177
  dataMaker: DataMaker<T, Z>;
141
178
  /**
142
179
  * use this to **specify the input type for the functions**,
@@ -144,7 +181,7 @@ export declare class url {
144
181
  * that you want to use in the HtmlHandlers that follow this **data blend!**
145
182
  * @example type lol = typeof MaybeLoggedIn.$Mini
146
183
  */
147
- $Mini: Mini<T>;
184
+ $Mini: Mini<T, "">;
148
185
  /**
149
186
  * use this to **specify the input type for the functions**,
150
187
  *
@@ -168,19 +205,12 @@ export declare class url {
168
205
  * ```
169
206
  */
170
207
  static set<K extends string>(entries: [K, HtmlHandler][]): void;
208
+ static set<R extends {
209
+ [X in keyof R]: MiniNextRouteValue<Extract<X, string>>;
210
+ }>({ routes }: {
211
+ routes: R;
212
+ }): void;
171
213
  static set(urlPath: string, handler: HtmlHandler): void;
172
- /**
173
- * use this to remove routes.
174
- * @param urlPath - the route to remove
175
- * @example
176
- * ``` js
177
- * let perma_link_defined_by_editor_or_admin_user_that_changed = "/haha"
178
- * url.remove(perma_link_defined_by_editor_or_admin_user_that_changed);
179
- * // add new url after removing the old one (that might come from a sqlite db)
180
- * url.set("/huhu", (mini)=> mini.html`huhu`)
181
- * ```
182
- */
183
- static remove(urlPath: string): void;
184
214
  /**
185
215
  * wrap your handlers in this if you mutate something to prevent CSRF issues.
186
216
  * @param handler - normal html handler with mini as the argument
@@ -231,9 +261,9 @@ export declare class url {
231
261
  * @throws Will throw an Error if the provided url is not found in the urls array.
232
262
  */
233
263
  static get(Url: string): string | null;
234
- static match(req: Request, reqPath?: string): Promise<Response | undefined>;
264
+ static handleWithMini(req: BunRequest<string>, server: Server, handler: HtmlHandler): Promise<Response>;
235
265
  /**
236
- * user this to set the Websocket object. Check out [the bun docs](https://bun.sh/docs/api/websockets) for more details.
266
+ * use this to set the Websocket object. Check out [the bun docs](https://bun.sh/docs/api/websockets) for more details.
237
267
  * @param wsObject the websocketsocket object {@link WebSocketHandler}
238
268
  */
239
269
  static setWebsocket<T = undefined>(wsObject: WebSocketHandler<T>): void;
@@ -250,8 +280,9 @@ export declare class url {
250
280
  * @return {Promise<Response>} - The Response object.
251
281
  */
252
282
  static install(): {
253
- fetch: (req: Request, server: Server) => Promise<Response>;
283
+ fetch: (req: Request, server: Server) => Response;
254
284
  websocket: WebSocketHandler<undefined> | undefined;
285
+ routes: {};
255
286
  };
256
287
  }
257
288
  export {};
package/dist/url.js CHANGED
@@ -67,29 +67,58 @@ export class Mini {
67
67
  export class url {
68
68
  static websocket = undefined;
69
69
  static server;
70
+ static routes;
70
71
  // direct mapping of "url string" -> function leads to Html Response
71
72
  static direct_handlers_html = new Map();
72
73
  // An array of the uncompiled frontend files, example frontends[0] = "index.tsx" -> frontend/index.tsx (from the project root)
73
74
  static frontends = [];
74
- static svgs = new Map();
75
- static svg(path, options = {
75
+ static svgs = [];
76
+ /**
77
+ * This function takes care of bundling your svg (icons?) into the webapp
78
+ * they will have a hash in the name to break the cache when needed
79
+ * @param svgFilePath first place to look: svgs folder in the same path the calling file, after that path from project root.
80
+ * @param options ResponseInit, default headers for an svg
81
+ * @returns url to the svg
82
+ */
83
+ static svg(svgFilePath, options = {
76
84
  headers: {
77
85
  "Content-Type": "image/svg+xml",
78
86
  "Content-Disposition": "attachment",
79
87
  },
80
88
  }) {
81
- url.svgs.set(path, options);
82
- var foundEntry = Object.entries(bundledSVGs).find(([key, value]) => value.svgPath === path);
83
- return foundEntry && foundEntry[0];
89
+ const stack = new Error().stack?.split("\n");
90
+ let callerPath = "";
91
+ if (stack) {
92
+ callerPath = stack[2].slice(stack[2].lastIndexOf("(") + 1, stack[2].lastIndexOf(".") + 3);
93
+ callerPath = callerPath.slice(callerPath.search("at") + 2).trim();
94
+ }
95
+ const position = url.svgs.length;
96
+ //we register the svg for bundleing.
97
+ url.svgs.push({
98
+ svgFilePath,
99
+ callerPath,
100
+ options,
101
+ position: url.svgs.length,
102
+ });
103
+ //this will be filled in by the bundling step.
104
+ var foundSvg = Object.entries(bundledSVGs).find(([key, value]) => value.position === position);
105
+ return foundSvg && foundSvg[0];
84
106
  }
85
- static frontend(path, snippet) {
107
+ static frontend(frontendFilePath, snippet) {
86
108
  const stack = new Error().stack?.split("\n");
87
109
  let callerPath = "";
88
110
  if (stack) {
89
111
  callerPath = stack[2].slice(stack[2].lastIndexOf("(") + 1, stack[2].lastIndexOf(".") + 3);
112
+ callerPath = callerPath.slice(callerPath.search("at") + 2).trim();
90
113
  }
91
- const frontendIndex = url.frontends.push({ path, callerPath }) - 1;
92
- const scriptUrl = FrontendScriptUrls[frontendIndex];
114
+ const position = url.frontends.length;
115
+ //we register the frontend for bundleing.
116
+ url.frontends.push({ frontendFilePath, callerPath, position });
117
+ //this will be filled in by the bundling step.
118
+ const bundledFrontend = Object.entries(bundledFrontends).find(([key, value]) => value.position === position);
119
+ if (!bundledFrontend)
120
+ return;
121
+ const scriptUrl = bundledFrontend[0];
93
122
  if (snippet instanceof BasedHtml || !snippet) {
94
123
  return html ` ${snippet}
95
124
  <script type="module" src="${scriptUrl}"></script>`; // return an html script tag with the index hash
@@ -105,26 +134,8 @@ export class url {
105
134
  static getFrontends() {
106
135
  return url.frontends;
107
136
  }
108
- static getSvgPaths() {
109
- return [...url.svgs.keys()];
110
- }
111
- static serveFrontend(req) {
112
- const reqPath = new URL(req.url).pathname;
113
- const index = FrontendScriptUrls.indexOf(reqPath);
114
- if (index !== -1) {
115
- return new Response(FrontendScripts[index], {
116
- headers: {
117
- "Content-Type": "application/javascript; charset=utf-8",
118
- },
119
- });
120
- }
121
- }
122
- static serveSvg(req) {
123
- const reqPath = new URL(req.url).pathname;
124
- const resolvedSvg = bundledSVGs[reqPath];
125
- if (resolvedSvg) {
126
- return new Response(resolvedSvg.svgContent, url.svgs.get(resolvedSvg.svgPath));
127
- }
137
+ static getSvgs() {
138
+ return url.svgs;
128
139
  }
129
140
  /**
130
141
  * tool to expose data to a frontend as a global variable.
@@ -210,27 +221,14 @@ export class url {
210
221
  if (typeof entries === "string" && handler) {
211
222
  addUrl(entries, handler);
212
223
  }
213
- if (typeof entries !== "string")
224
+ if (typeof entries !== "string" && "routes" in entries) {
225
+ url.routes = entries.routes;
226
+ }
227
+ if (typeof entries !== "string" && !("routes" in entries))
214
228
  for (const [entryUrl, entryHandler] of entries) {
215
229
  addUrl(entryUrl, entryHandler);
216
230
  }
217
231
  }
218
- /**
219
- * use this to remove routes.
220
- * @param urlPath - the route to remove
221
- * @example
222
- * ``` js
223
- * let perma_link_defined_by_editor_or_admin_user_that_changed = "/haha"
224
- * url.remove(perma_link_defined_by_editor_or_admin_user_that_changed);
225
- * // add new url after removing the old one (that might come from a sqlite db)
226
- * url.set("/huhu", (mini)=> mini.html`huhu`)
227
- * ```
228
- */
229
- static remove(urlPath) {
230
- for (const u of url.generateVariations(urlPath)) {
231
- url.direct_handlers_html.delete(u);
232
- }
233
- }
234
232
  /**
235
233
  * wrap your handlers in this if you mutate something to prevent CSRF issues.
236
234
  * @param handler - normal html handler with mini as the argument
@@ -387,95 +385,92 @@ export class url {
387
385
  }
388
386
  return Url;
389
387
  }
390
- static async match(req, reqPath) {
388
+ static async handleWithMini(req, server, handler) {
389
+ if (!url.server)
390
+ url.server = server;
391
391
  const miniurl = Object.freeze(new URL(req.url));
392
- if (typeof reqPath === "undefined") {
393
- reqPath = miniurl.pathname;
392
+ const reqPath = miniurl.pathname;
393
+ let redirectTarget = null;
394
+ let redirectStatus = undefined;
395
+ let handlerHead = undefined;
396
+ let handlerOptions = {
397
+ headers: {
398
+ "Content-Type": "text/html; charset=utf-8",
399
+ },
400
+ };
401
+ const post = req.method === "POST";
402
+ let formJson;
403
+ let formData;
404
+ const urlencoded = (req.headers.get("Content-Type") + "").includes("application/x-www-form-urlencoded");
405
+ const multipart = (req.headers.get("Content-Type") + "").includes("multipart/form-data");
406
+ if (post && !urlencoded && !multipart) {
407
+ const length = Number(req.headers.get("content-length"));
408
+ const bodyNotEmpty = length > 0;
409
+ if (bodyNotEmpty) {
410
+ formJson = await req.json();
411
+ }
412
+ else {
413
+ formJson = {};
414
+ }
394
415
  }
395
- const handler = url.direct_handlers_html.get(reqPath);
396
- if (handler) {
397
- let redirectTarget = null;
398
- let redirectStatus = undefined;
399
- let handlerHead = undefined;
400
- let handlerOptions = {
401
- headers: {
402
- "Content-Type": "text/html; charset=utf-8",
416
+ if (post && (urlencoded || multipart)) {
417
+ formData = await req.formData();
418
+ }
419
+ //this is the source of mini
420
+ const mini = new Mini({
421
+ requrl: miniurl,
422
+ data: undefined,
423
+ req: req,
424
+ html,
425
+ css: html,
426
+ deliver: url.deliver,
427
+ route: reqPath,
428
+ params: new URL(req.url).searchParams,
429
+ json,
430
+ form: {
431
+ post,
432
+ urlencoded,
433
+ multipart,
434
+ formJson,
435
+ formData,
436
+ onPostSubmit(cb) {
437
+ if (post) {
438
+ return cb();
439
+ }
403
440
  },
404
- };
405
- const post = req.method === "POST";
406
- let formJson;
407
- let formData;
408
- const urlencoded = (req.headers.get("Content-Type") + "").includes("application/x-www-form-urlencoded");
409
- const multipart = (req.headers.get("Content-Type") + "").includes("multipart/form-data");
410
- if (post && !urlencoded && !multipart) {
411
- const length = Number(req.headers.get("content-length"));
412
- const bodyNotEmpty = length > 0;
413
- if (bodyNotEmpty) {
414
- formJson = await req.json();
441
+ actionlink: (qs = "", settings) => url.link(reqPath, qs, settings),
442
+ },
443
+ dangerjson,
444
+ head: (head) => {
445
+ handlerHead = head;
446
+ },
447
+ headers: (headers, overwrite = false) => {
448
+ if (overwrite) {
449
+ handlerOptions.headers = headers;
415
450
  }
416
451
  else {
417
- formJson = {};
452
+ handlerOptions.headers = {
453
+ ...handlerOptions.headers,
454
+ ...headers,
455
+ };
418
456
  }
419
- }
420
- if (post && (urlencoded || multipart)) {
421
- formData = await req.formData();
422
- }
423
- //this is the source of mini
424
- const mini = new Mini({
425
- requrl: miniurl,
426
- data: undefined,
427
- req,
428
- html,
429
- css: html,
430
- deliver: url.deliver,
431
- route: reqPath,
432
- params: new URL(req.url).searchParams,
433
- json,
434
- form: {
435
- post,
436
- urlencoded,
437
- multipart,
438
- formJson,
439
- formData,
440
- onPostSubmit(cb) {
441
- if (post) {
442
- return cb();
443
- }
444
- },
445
- actionlink: (qs = "", settings) => url.link(reqPath, qs, settings),
446
- },
447
- dangerjson,
448
- head: (head) => {
449
- handlerHead = head;
450
- },
451
- headers: (headers, overwrite = false) => {
452
- if (overwrite) {
453
- handlerOptions.headers = headers;
454
- }
455
- else {
456
- handlerOptions.headers = {
457
- ...handlerOptions.headers,
458
- ...headers,
459
- };
460
- }
461
- },
462
- options: (options) => {
463
- handlerOptions = options;
464
- },
465
- redirect: (url, status) => {
466
- redirectTarget = url;
467
- redirectStatus = status;
468
- },
469
- }, undefined);
470
- const unresolved = await handler(mini); //passing mini
471
- if (redirectTarget) {
472
- return Response.redirect(redirectTarget, redirectStatus);
473
- }
474
- return htmlResponder(mini, unresolved, handlerHead, handlerOptions);
457
+ },
458
+ options: (options) => {
459
+ handlerOptions = options;
460
+ },
461
+ redirect: (url, status) => {
462
+ redirectTarget = url;
463
+ redirectStatus = status;
464
+ },
465
+ }, undefined);
466
+ const unresolved = await handler(mini); //passing mini
467
+ if (redirectTarget) {
468
+ return Response.redirect(redirectTarget, redirectStatus);
475
469
  }
470
+ return htmlResponder(mini, unresolved, handlerHead, handlerOptions);
476
471
  }
477
472
  /**
478
- * user this to set the Websocket object. Check out [the bun docs](https://bun.sh/docs/api/websockets) for more details.
473
+ * use this to set the Websocket object. Check out [the bun docs](https://bun.sh/docs/api/websockets) for more details.
479
474
  * @param wsObject the websocketsocket object {@link WebSocketHandler}
480
475
  */
481
476
  static setWebsocket(wsObject) {
@@ -496,24 +491,44 @@ export class url {
496
491
  * @return {Promise<Response>} - The Response object.
497
492
  */
498
493
  static install() {
499
- async function fetchFunction(req, server) {
500
- if (!url.server)
501
- url.server = server;
502
- //go through all the Htmlhandlers and see if there is a match
503
- let res = await url.match(req);
504
- if (res)
505
- return res;
506
- //handle frontend js file serving
507
- res = url.serveFrontend(req);
508
- if (res)
509
- return res;
510
- //handle svg file serving
511
- res = url.serveSvg(req);
512
- if (res)
513
- return res;
494
+ for (const route in url.routes) {
495
+ //handle route object split by methods and pull them through mininext
496
+ const handler = url.routes[route];
497
+ if (typeof handler === "function") {
498
+ url.routes[route] = (req, server) => url.handleWithMini(req, server, handler);
499
+ }
500
+ else {
501
+ const newHandlerObject = {};
502
+ for (const HTTPmethod in handler) {
503
+ newHandlerObject[HTTPmethod] = (req, server) => url.handleWithMini(req, server, handler[HTTPmethod]);
504
+ }
505
+ url.routes[route] = newHandlerObject;
506
+ }
507
+ }
508
+ //TODO add fronted + svg to routes object
509
+ for (const [route, handler] of url.direct_handlers_html) {
510
+ url.routes[route] = (req, server) => url.handleWithMini(req, server, handler);
511
+ }
512
+ for (const svgUrl in bundledSVGs) {
513
+ const resolvedSvg = bundledSVGs[svgUrl];
514
+ url.routes[svgUrl] = (req, server) => new Response(resolvedSvg.svgContent, resolvedSvg.options);
515
+ }
516
+ for (const frontendUrl in bundledFrontends) {
517
+ const resolvedFrontend = bundledFrontends[frontendUrl];
518
+ url.routes[frontendUrl] = (req, server) => new Response(resolvedFrontend.frontendContent, {
519
+ headers: {
520
+ "Content-Type": "application/javascript; charset=utf-8",
521
+ },
522
+ });
523
+ }
524
+ function fetchFunction(req, server) {
514
525
  return new Response("No matching url found", { status: 404 });
515
526
  }
516
- return { fetch: fetchFunction, websocket: url.websocket };
527
+ return {
528
+ fetch: fetchFunction,
529
+ websocket: url.websocket,
530
+ routes: url.routes,
531
+ };
517
532
  }
518
533
  }
519
534
  const no_post_warning = html `<div style="color:red;">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spirobel/mininext",
3
- "license" : "MIT" ,
3
+ "license": "MIT",
4
4
  "module": "dist/mininext/mininext.js",
5
5
  "type": "module",
6
6
  "main": "dist/mininext.js",
@@ -8,12 +8,12 @@
8
8
  "scripts": {
9
9
  "publish": "bun run build && npm publish",
10
10
  "build": "tsc",
11
- "clean":"rm -rf ./dist"
11
+ "clean": "rm -rf ./dist"
12
12
  },
13
13
  "files": ["dist"],
14
- "version": "0.6.0",
14
+ "version": "0.7.1",
15
15
  "devDependencies": {
16
- "@types/bun": "latest"
16
+ "@types/bun": "^1.2.9"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "typescript": "^5.0.0"