@server/next 0.21.3 → 0.21.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@server/next",
3
- "version": "0.21.3",
3
+ "version": "0.21.5",
4
4
  "description": "A fully-fledged web server with routing, file uploads, sessions, static files, schema validation, websockets, testing, etc.",
5
5
  "homepage": "https://server-js.com/",
6
6
  "repository": "https://github.com/franciscop/server-next.git",
@@ -17,6 +17,17 @@ export default async (request, options = {}, app) => {
17
17
  ctx.res = { status: null, headers: {}, cookies: {} };
18
18
  ctx.method = request.method.toLowerCase();
19
19
 
20
+ // Private
21
+ const events = {};
22
+ ctx.unstableOn = (name, callback) => {
23
+ events[name] = events[name] || [];
24
+ events[name].push(callback);
25
+ };
26
+ ctx.unstableFire = (name, data) => {
27
+ if (!events[name]) return;
28
+ events[name].forEach((cb) => cb(data));
29
+ };
30
+
20
31
  ctx.headers = parseHeaders(new Headers(chunkArray(request.rawHeaders, 2)));
21
32
  ctx.cookies = parseCookies(ctx.headers.cookie);
22
33
  await auth.load(ctx);
@@ -26,7 +37,7 @@ export default async (request, options = {}, app) => {
26
37
  const path = request.url.replace(/\/$/, "") || "/";
27
38
  ctx.url = new URL(path, `${https}://${host}`);
28
39
  define(ctx.url, "query", (url) =>
29
- Object.fromEntries(url.searchParams.entries())
40
+ Object.fromEntries(url.searchParams.entries()),
30
41
  );
31
42
 
32
43
  await new Promise((resolve, reject) => {
@@ -40,7 +51,7 @@ export default async (request, options = {}, app) => {
40
51
  ctx.body = await parseBody(
41
52
  Buffer.concat(body).toString(),
42
53
  type,
43
- options.uploads
54
+ options.uploads,
44
55
  );
45
56
  resolve();
46
57
  })
@@ -5,18 +5,30 @@ import parseCookies from "./parseCookies.js";
5
5
 
6
6
  export default async (request, options = {}, app) => {
7
7
  const ctx = {};
8
+ ctx.init = performance.now();
8
9
  ctx.options = options;
9
10
  ctx.req = request;
10
11
  ctx.res = { status: null, headers: {}, cookies: {} };
11
12
  ctx.method = request.method.toLowerCase();
12
13
 
14
+ // Private
15
+ const events = {};
16
+ ctx.unstableOn = (name, callback) => {
17
+ events[name] = events[name] || [];
18
+ events[name].push(callback);
19
+ };
20
+ ctx.unstableFire = (name, data) => {
21
+ if (!events[name]) return;
22
+ events[name].forEach((cb) => cb(data));
23
+ };
24
+
13
25
  ctx.headers = parseHeaders(request.headers);
14
26
  ctx.cookies = parseCookies(ctx.headers.cookie);
15
27
  await auth.load(ctx);
16
28
 
17
29
  ctx.url = new URL(request.url.replace(/\/$/, ""));
18
30
  define(ctx.url, "query", (url) =>
19
- Object.fromEntries(url.searchParams.entries())
31
+ Object.fromEntries(url.searchParams.entries()),
20
32
  );
21
33
 
22
34
  if (request.body) {
@@ -3,7 +3,7 @@ import createId from "./createId.js";
3
3
 
4
4
  // Big mess; parse all of the options for server, which can be at launch time
5
5
  // or dynamically per-request for the functions (so have to read ENV inside)
6
- export default function config(options) {
6
+ export default function config(options = {}) {
7
7
  const env = globalThis.env;
8
8
 
9
9
  // Basic options
@@ -13,9 +13,35 @@ const altAttrs = {
13
13
  classname: "class",
14
14
  };
15
15
 
16
+ const minifyCss = (str) =>
17
+ str
18
+ .replace(/\s+/g, " ")
19
+ .replace(/(?!<\")\/\*[^\*]+\*\/(?!\")/g, "")
20
+ .replace(/(\w|\*) (\{)/g, "$1$2")
21
+ .replace(/(\}) (\w|\*)/g, "$1$2")
22
+ .replace(/(\{) (\w)/g, "$1$2")
23
+ .replace(/(\w)(\:) /g, "$1$2")
24
+ .replace(/(\;) (\})/g, "$1$2")
25
+ .replace(/(\;) (\w)/g, "$1$2")
26
+ .replace(/\;(\})/g, "$1")
27
+ .replace(/(\w), (\w)/g, "$1,$2")
28
+ .replace(/(\w), (\w)/g, "$1,$2")
29
+ .replace(/(\{) (\w)/g, "$1$2")
30
+ .trim();
31
+
16
32
  export const jsx = (tag, { children, ...props }) => {
17
33
  if (typeof tag === "function") return tag({ children, ...props });
18
34
 
35
+ // If they include an explicit <script>, let them be, just render it
36
+ // without escaping
37
+ if (tag === "script" && children) {
38
+ const src = children;
39
+ children = () => src;
40
+ }
41
+ if (tag === "style" && children) {
42
+ const src = minifyCss(children);
43
+ children = () => src;
44
+ }
19
45
  if (props.dangerouslySetInnerHTML)
20
46
  children = () => props.dangerouslySetInnerHTML.__html;
21
47
  if (!children) children = [];
package/src/index.js CHANGED
@@ -116,7 +116,7 @@ server.prototype.node = async function () {
116
116
  response.end();
117
117
  }
118
118
  })
119
- .listen(options.port);
119
+ .listen(this.opts.port);
120
120
  };
121
121
 
122
122
  // Netlify
@@ -139,12 +139,16 @@ server.prototype.fetch = async function (request, env) {
139
139
  if (env?.upgrade(request)) return;
140
140
  Object.assign(globalThis.env, env); // Extend env with the passed vars
141
141
 
142
+ let ctx, res, error;
142
143
  try {
143
- const ctx = await createWinterContext(request, this.opts, this);
144
- return await handleRequest(this.handlers, ctx);
145
- } catch (error) {
146
- return new Response(error.message, { status: error.status || 500 });
144
+ ctx = await createWinterContext(request, this.opts, this);
145
+ res = await handleRequest(this.handlers, ctx);
146
+ } catch (err) {
147
+ error = err;
148
+ res = new Response(error.message, { status: error.status || 500 });
147
149
  }
150
+ ctx?.unstableFire("finish", { ...ctx, error, res, end: performance.now() });
151
+ return res;
148
152
  };
149
153
 
150
154
  // #region HTTP methods