@spirobel/mininext 0.2.27 → 0.3.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.
package/dist/html.d.ts CHANGED
@@ -54,5 +54,20 @@ export declare function isError(submissionResult: any | {
54
54
  error: HtmlString;
55
55
  };
56
56
  declare global {
57
- var Reloader: HtmlString | undefined;
57
+ var Reloader: BasedHtml | HtmlString | undefined;
58
58
  }
59
+ /**
60
+ * The difference between this and HtmlString is that it is fully resolved and only accepts primitive types.
61
+ * In plain english this means:
62
+ * It does not accept functions (that will be resolved at request time with (mini)=>mini.html) like mini.html does.
63
+ */
64
+ export declare class BasedHtml extends String {
65
+ }
66
+ export type BasedHtmlValues = number | string | undefined | null | boolean | BasedHtml | BasedHtml[];
67
+ /**
68
+ * The difference between this and HtmlString is that it is fully resolved and only accepts primitive types.
69
+ * @param strings - html literals
70
+ * @param values - values will get escaped to prevent xss
71
+ * @returns
72
+ */
73
+ export declare const basedHtml: (strings: TemplateStringsArray, ...values: BasedHtmlValues[]) => BasedHtml;
package/dist/html.js CHANGED
@@ -245,3 +245,35 @@ export async function htmlResponder(mini, maybeUnresolved, head = default_head,
245
245
  export function isError(submissionResult) {
246
246
  return ("error" in submissionResult && submissionResult.error instanceof HtmlString);
247
247
  }
248
+ /**
249
+ * The difference between this and HtmlString is that it is fully resolved and only accepts primitive types.
250
+ * In plain english this means:
251
+ * It does not accept functions (that will be resolved at request time with (mini)=>mini.html) like mini.html does.
252
+ */
253
+ export class BasedHtml extends String {
254
+ }
255
+ //TODO make it so we can embed BasedHtml into mini.html partially resolved html strings
256
+ /**
257
+ * The difference between this and HtmlString is that it is fully resolved and only accepts primitive types.
258
+ * @param strings - html literals
259
+ * @param values - values will get escaped to prevent xss
260
+ * @returns
261
+ */
262
+ export const basedHtml = (strings, ...values) => {
263
+ // Apply escapeHtml to each value before using them in the template string
264
+ // In case it didn't already get escaped
265
+ for (const [index, value] of values.entries()) {
266
+ // we can pass arrays of BasedHtml and they will get flattened automatically
267
+ if (Array.isArray(value) &&
268
+ value.every((val) => val instanceof BasedHtml)) {
269
+ // If the value is an array of BasedHtml objects, flatten it and add to ...values
270
+ values[index] = value.join("");
271
+ }
272
+ else if (!(value instanceof BasedHtml)) {
273
+ const notEmpty = value || "";
274
+ // values will be escaped by default
275
+ values[index] = Bun.escapeHTML(notEmpty + "");
276
+ }
277
+ }
278
+ return new BasedHtml(String.raw({ raw: strings }, ...values));
279
+ };
@@ -1,9 +1,15 @@
1
+ /// <reference types="bun-types" />
2
+ /// <reference types="bun-types" />
1
3
  import { url, Mini, type HtmlHandler } from "./url";
2
- import { isError, HtmlString, head, commonHead, cssReset } from "./html";
4
+ import { isError, HtmlString, BasedHtml, head, commonHead, cssReset, basedHtml as html } from "./html";
5
+ import type { Server, WebSocketHandler } from "bun";
3
6
  declare global {
4
7
  var PROJECT_ROOT: string | undefined;
5
8
  }
6
9
  declare function build(backendPath?: string): Promise<void>;
7
- declare const standardDevReloader: HtmlString;
8
- declare function makeEntrypoint(): Promise<(w: any) => Promise<Response>>;
9
- export { url, head, build, makeEntrypoint, isError, HtmlString, type HtmlHandler, Mini, standardDevReloader, commonHead, cssReset, };
10
+ declare const standardDevReloader: BasedHtml;
11
+ declare function makeEntrypoint(): Promise<{
12
+ fetch: (req: Request, server: Server) => Promise<Response>;
13
+ websocket: WebSocketHandler;
14
+ }>;
15
+ export { html, url, head, build, makeEntrypoint, isError, BasedHtml, HtmlString, type HtmlHandler, Mini, standardDevReloader, commonHead, cssReset, };
package/dist/mininext.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { url, Mini } from "./url";
2
- import { html, isError, HtmlString, head, commonHead, cssReset } from "./html";
2
+ import { isError, HtmlString, BasedHtml, head, commonHead, cssReset, basedHtml as html, } from "./html";
3
3
  import { watch } from "fs/promises";
4
4
  import * as path from "path";
5
5
  function projectRoot() {
@@ -156,6 +156,6 @@ async function makeEntrypoint() {
156
156
  // @ts-ignore
157
157
  module = await import(backendImportPath);
158
158
  }
159
- return module.default;
159
+ return module.default();
160
160
  }
161
- export { url, head, build, makeEntrypoint, isError, HtmlString, Mini, standardDevReloader, commonHead, cssReset, };
161
+ export { html, url, head, build, makeEntrypoint, isError, BasedHtml, HtmlString, Mini, standardDevReloader, commonHead, cssReset, };
package/dist/url.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ /// <reference types="bun-types" />
2
+ /// <reference types="bun-types" />
3
+ import type { Server, WebSocketHandler } from "bun";
1
4
  import { html, json, dangerjson, HtmlString } from "./html";
2
5
  import type { DangerJsonInHtml, JsonString, JsonStringValues } from "./html";
3
6
  export type Form = {
@@ -68,6 +71,8 @@ interface LinkSettings {
68
71
  [key: string]: string | null | undefined;
69
72
  }
70
73
  export declare class url {
74
+ static websocket: WebSocketHandler | undefined;
75
+ static server: Server;
71
76
  static direct_handlers_html: ReadonlyMap<string, HtmlHandler>;
72
77
  private static frontends;
73
78
  private static svgs;
@@ -146,7 +151,7 @@ export declare class url {
146
151
  * @param handler - normal html handler with mini as the argument
147
152
  * @returns a wrapped html handler that will only be called when the request is post
148
153
  */
149
- static post<Y = unknown>(handler: HtmlHandler<Y>): (mini: Mini<Y>) => LazyHandlerReturnType;
154
+ static post(handler: HtmlHandler): (mini: Mini) => LazyHandlerReturnType;
150
155
  /**
151
156
  * wrap your handlers in this if you mutate something to prevent CSRF issues.
152
157
  * @param handler - normal html handler with mini as the argument
@@ -183,11 +188,19 @@ export declare class url {
183
188
  */
184
189
  static get(Url: string): string;
185
190
  static match(req: Request, reqPath?: string): Promise<Response | undefined>;
191
+ /**
192
+ * user this to set the Websocket object. Check out [the bun docs](https://bun.sh/docs/api/websockets) for more details.
193
+ * @param wsObject the websocketsocket object {@link WebSocketHandler}
194
+ */
195
+ static setWebsocket<T = undefined>(wsObject: WebSocketHandler<T>): void;
186
196
  /**
187
197
  * Fetch handler that is called by the server when a request is made to any of the urls.
188
198
  * @param {Request} req - The Request object.
189
199
  * @return {Promise<Response>} - The Response object.
190
200
  */
191
- static install(req: Request): Promise<Response>;
201
+ static install(): {
202
+ fetch: (req: Request, server: Server) => Promise<Response>;
203
+ websocket: WebSocketHandler<undefined> | undefined;
204
+ };
192
205
  }
193
206
  export {};
package/dist/url.js CHANGED
@@ -47,6 +47,8 @@ export class Mini {
47
47
  }
48
48
  }
49
49
  export class url {
50
+ static websocket = undefined;
51
+ static server;
50
52
  // direct mapping of "url string" -> function leads to Html Response
51
53
  static direct_handlers_html;
52
54
  // An array of the uncompiled frontend files, example frontends[0] = "index.tsx" -> frontend/index.tsx (from the project root)
@@ -386,29 +388,41 @@ export class url {
386
388
  return htmlResponder(mini, unresolved, handlerHead, handlerOptions);
387
389
  }
388
390
  }
391
+ /**
392
+ * user this to set the Websocket object. Check out [the bun docs](https://bun.sh/docs/api/websockets) for more details.
393
+ * @param wsObject the websocketsocket object {@link WebSocketHandler}
394
+ */
395
+ static setWebsocket(wsObject) {
396
+ url.websocket = wsObject;
397
+ }
389
398
  /**
390
399
  * Fetch handler that is called by the server when a request is made to any of the urls.
391
400
  * @param {Request} req - The Request object.
392
401
  * @return {Promise<Response>} - The Response object.
393
402
  */
394
- static async install(req) {
395
- //go through all the Htmlhandlers and see if there is a match
396
- let res = await url.match(req);
397
- if (res)
398
- return res;
399
- //handle frontend js file serving
400
- res = url.serveFrontend(req);
401
- if (res)
402
- return res;
403
- //handle svg file serving
404
- res = url.serveSvg(req);
405
- if (res)
406
- return res;
407
- // go through all the Htmlhandlers again with added slash at the end.
408
- res = await url.match(req, new URL(req.url).pathname + "/");
409
- if (res)
410
- return res;
411
- return new Response("No matching url found", { status: 404 });
403
+ static install() {
404
+ async function fetchFunction(req, server) {
405
+ if (!url.server)
406
+ url.server = server;
407
+ //go through all the Htmlhandlers and see if there is a match
408
+ let res = await url.match(req);
409
+ if (res)
410
+ return res;
411
+ //handle frontend js file serving
412
+ res = url.serveFrontend(req);
413
+ if (res)
414
+ return res;
415
+ //handle svg file serving
416
+ res = url.serveSvg(req);
417
+ if (res)
418
+ return res;
419
+ // go through all the Htmlhandlers again with added slash at the end.
420
+ res = await url.match(req, new URL(req.url).pathname + "/");
421
+ if (res)
422
+ return res;
423
+ return new Response("No matching url found", { status: 404 });
424
+ }
425
+ return { fetch: fetchFunction, websocket: url.websocket };
412
426
  }
413
427
  }
414
428
  const no_post_warning = html `<div style="color:red;">
package/mininext/html.ts CHANGED
@@ -295,5 +295,48 @@ export function isError(
295
295
  }
296
296
 
297
297
  declare global {
298
- var Reloader: HtmlString | undefined;
298
+ var Reloader: BasedHtml | HtmlString | undefined;
299
299
  }
300
+ /**
301
+ * The difference between this and HtmlString is that it is fully resolved and only accepts primitive types.
302
+ * In plain english this means:
303
+ * It does not accept functions (that will be resolved at request time with (mini)=>mini.html) like mini.html does.
304
+ */
305
+ export class BasedHtml extends String {}
306
+ export type BasedHtmlValues =
307
+ | number
308
+ | string
309
+ | undefined
310
+ | null
311
+ | boolean
312
+ | BasedHtml
313
+ | BasedHtml[];
314
+ //TODO make it so we can embed BasedHtml into mini.html partially resolved html strings
315
+ /**
316
+ * The difference between this and HtmlString is that it is fully resolved and only accepts primitive types.
317
+ * @param strings - html literals
318
+ * @param values - values will get escaped to prevent xss
319
+ * @returns
320
+ */
321
+ export const basedHtml = (
322
+ strings: TemplateStringsArray,
323
+ ...values: BasedHtmlValues[]
324
+ ) => {
325
+ // Apply escapeHtml to each value before using them in the template string
326
+ // In case it didn't already get escaped
327
+ for (const [index, value] of values.entries()) {
328
+ // we can pass arrays of BasedHtml and they will get flattened automatically
329
+ if (
330
+ Array.isArray(value) &&
331
+ value.every((val) => val instanceof BasedHtml)
332
+ ) {
333
+ // If the value is an array of BasedHtml objects, flatten it and add to ...values
334
+ values[index] = value.join("");
335
+ } else if (!(value instanceof BasedHtml)) {
336
+ const notEmpty = value || "";
337
+ // values will be escaped by default
338
+ values[index] = Bun.escapeHTML(notEmpty + "");
339
+ }
340
+ }
341
+ return new BasedHtml(String.raw({ raw: strings }, ...values));
342
+ };
@@ -1,5 +1,14 @@
1
1
  import { url, Mini, type HtmlHandler } from "./url";
2
- import { html, isError, HtmlString, head, commonHead, cssReset } from "./html";
2
+ import {
3
+ isError,
4
+ HtmlString,
5
+ BasedHtml,
6
+ head,
7
+ commonHead,
8
+ cssReset,
9
+ basedHtml as html,
10
+ } from "./html";
11
+ import type { BunPlugin, Server, WebSocketHandler } from "bun";
3
12
  import { watch } from "fs/promises";
4
13
  import * as path from "path";
5
14
  function projectRoot() {
@@ -14,7 +23,6 @@ async function build(backendPath: string = "backend/backend.ts") {
14
23
  await devServer();
15
24
  }
16
25
  }
17
- import type { BunPlugin } from "bun";
18
26
 
19
27
  const myPlugin: BunPlugin = {
20
28
  name: "node buffer in the frontend",
@@ -168,14 +176,19 @@ async function makeEntrypoint() {
168
176
  // @ts-ignore
169
177
  module = await import(backendImportPath);
170
178
  }
171
- return module.default as (w: any) => Promise<Response>;
179
+ return module.default() as {
180
+ fetch: (req: Request, server: Server) => Promise<Response>;
181
+ websocket: WebSocketHandler;
182
+ };
172
183
  }
173
184
  export {
185
+ html,
174
186
  url,
175
187
  head,
176
188
  build,
177
189
  makeEntrypoint,
178
190
  isError,
191
+ BasedHtml,
179
192
  HtmlString,
180
193
  type HtmlHandler,
181
194
  Mini,
package/mininext/url.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { Server, WebSocketHandler } from "bun";
1
2
  import { htmlResponder, html, json, dangerjson, HtmlString } from "./html";
2
3
  import type { DangerJsonInHtml, JsonString, JsonStringValues } from "./html";
3
4
  export type Form = {
@@ -116,6 +117,9 @@ interface LinkSettings {
116
117
  [key: string]: string | null | undefined;
117
118
  }
118
119
  export class url {
120
+ static websocket: WebSocketHandler | undefined = undefined;
121
+ static server: Server;
122
+
119
123
  // direct mapping of "url string" -> function leads to Html Response
120
124
  static direct_handlers_html: ReadonlyMap<string, HtmlHandler>;
121
125
 
@@ -272,8 +276,8 @@ export class url {
272
276
  * @param handler - normal html handler with mini as the argument
273
277
  * @returns a wrapped html handler that will only be called when the request is post
274
278
  */
275
- static post<Y = unknown>(handler: HtmlHandler<Y>) {
276
- return (mini: Mini<Y>) => {
279
+ static post(handler: HtmlHandler) {
280
+ return (mini: Mini) => {
277
281
  if (mini.form.post) {
278
282
  return handler(mini);
279
283
  } else {
@@ -486,28 +490,39 @@ export class url {
486
490
  return htmlResponder(mini, unresolved, handlerHead, handlerOptions);
487
491
  }
488
492
  }
493
+ /**
494
+ * user this to set the Websocket object. Check out [the bun docs](https://bun.sh/docs/api/websockets) for more details.
495
+ * @param wsObject the websocketsocket object {@link WebSocketHandler}
496
+ */
497
+ static setWebsocket<T = undefined>(wsObject: WebSocketHandler<T>) {
498
+ url.websocket = wsObject as WebSocketHandler;
499
+ }
489
500
 
490
501
  /**
491
502
  * Fetch handler that is called by the server when a request is made to any of the urls.
492
503
  * @param {Request} req - The Request object.
493
504
  * @return {Promise<Response>} - The Response object.
494
505
  */
495
- static async install(req: Request) {
496
- //go through all the Htmlhandlers and see if there is a match
497
- let res = await url.match(req);
498
- if (res) return res;
506
+ static install() {
507
+ async function fetchFunction(req: Request, server: Server) {
508
+ if (!url.server) url.server = server;
509
+ //go through all the Htmlhandlers and see if there is a match
510
+ let res = await url.match(req);
511
+ if (res) return res;
499
512
 
500
- //handle frontend js file serving
501
- res = url.serveFrontend(req);
502
- if (res) return res;
503
- //handle svg file serving
504
- res = url.serveSvg(req);
505
- if (res) return res;
506
- // go through all the Htmlhandlers again with added slash at the end.
507
- res = await url.match(req, new URL(req.url).pathname + "/");
508
- if (res) return res;
513
+ //handle frontend js file serving
514
+ res = url.serveFrontend(req);
515
+ if (res) return res;
516
+ //handle svg file serving
517
+ res = url.serveSvg(req);
518
+ if (res) return res;
519
+ // go through all the Htmlhandlers again with added slash at the end.
520
+ res = await url.match(req, new URL(req.url).pathname + "/");
521
+ if (res) return res;
509
522
 
510
- return new Response("No matching url found", { status: 404 });
523
+ return new Response("No matching url found", { status: 404 });
524
+ }
525
+ return { fetch: fetchFunction, websocket: url.websocket };
511
526
  }
512
527
  }
513
528
 
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  },
14
14
  "files": ["dist", "mininext"],
15
- "version": "0.2.27",
15
+ "version": "0.3.1",
16
16
  "devDependencies": {
17
17
  "@types/bun": "latest"
18
18
  },