revojs 0.1.7 → 0.1.9

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/index.d.ts CHANGED
@@ -57,6 +57,7 @@ type StatusCode = 100 | 101 | 102 | 103 | 200 | 201 | 202 | 203 | 204 | 205 | 20
57
57
  type MimeType = "text/plain" | "text/css" | "text/html" | "text/csv" | "text/javascript" | "application/json" | "application/xml" | "image/jpeg" | "image/png" | "image/gif" | "image/webp" | "image/svg+xml" | "image/bmp" | "image/x-icon" | "font/ttf" | "font/otf" | "font/woff" | "font/woff2" | "audio/mpeg" | "audio/wav" | "audio/ogg" | "audio/mp4" | "video/mp4" | "video/webm" | "video/ogg" | "video/quicktime" | "video/x-msvideo" | "application/zip" | "application/vnd.rar" | "application/x-tar" | "application/gzip" | "application/x-7z-compressed" | "application/pdf" | "application/msword" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | "application/vnd.ms-excel" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | "application/vnd.ms-powerpoint" | "application/vnd.openxmlformats-officedocument.presentationml.presentation" | "application/vnd.microsoft.portable-executable" | "application/vnd.android.package-archive";
58
58
  type Result = void | Response | Promise<void | Response>;
59
59
  type Node<T> = WildcardNode<T> | ParameterNode<T> | PathNode<T>;
60
+ type States = Record<string, unknown>;
60
61
  interface CookieOptions {
61
62
  domain?: string;
62
63
  expires?: Date;
@@ -78,6 +79,7 @@ interface RouterContext {
78
79
  parameters: Record<string, string>;
79
80
  }
80
81
  interface ServerContext<T extends Context = Context> {
82
+ states: States;
81
83
  request: Request;
82
84
  response: ResponseConfig;
83
85
  variables: T;
@@ -88,9 +90,12 @@ interface Route {
88
90
  interface Middleware {
89
91
  fetch: (scope: Scope, next?: () => Result) => Result;
90
92
  }
93
+ interface Exception {
94
+ fetch: (scope: Scope, exception: unknown) => Result;
95
+ }
91
96
  interface Server {
92
97
  router: Router;
93
- pipeline: Array<Middleware>;
98
+ middlewares: Array<Middleware>;
94
99
  fetch: (scope: Scope) => Promise<Response>;
95
100
  }
96
101
  interface WildcardNode<T> {
@@ -120,6 +125,7 @@ declare class Router extends Radix<Route> implements Middleware {
120
125
  }
121
126
  declare function defineRoute<T extends Route>(route: T): T;
122
127
  declare function defineMiddleware<T extends Middleware>(middleware: T): T;
128
+ declare function useRouter(scope: Scope): RouterContext;
123
129
  declare function useServer<T extends Context>(scope: Scope): ServerContext<T>;
124
130
  declare function useUrl(scope: Scope, base?: string): URL;
125
131
  declare function useQuery(scope: Scope): Record<string, string>;
@@ -129,6 +135,8 @@ declare function useCookies<T extends Schema>(scope: Scope, schema: T): InferOut
129
135
  declare function useSetCookies(scope: Scope): Record<string, string>;
130
136
  declare function useSetCookies<T extends Schema>(scope: Scope, schema: T): InferOutput<T>;
131
137
  declare function setCookie(scope: Scope, name: string, value: string, options?: CookieOptions): void;
138
+ declare function getState<T>(scope: Scope, name: string): T;
139
+ declare function setState<T>(scope: Scope, name: string, value: T): void;
132
140
  declare function sendText(scope: Scope, text: string, config?: Mergeable<ResponseConfig>): Response;
133
141
  declare function sendHtml(scope: Scope, text: string, config?: Mergeable<ResponseConfig>): Response;
134
142
  declare function sendJson<T>(scope: Scope, value: T, config?: Mergeable<ResponseConfig>): Response;
@@ -143,6 +151,7 @@ declare const ROUTER_CONTEXT: Descriptor<RouterContext>;
143
151
  declare const SERVER_CONTEXT: Descriptor<ServerContext<Context>>;
144
152
  declare const WILDCARD = "$";
145
153
  declare const PARAMETER = ":";
154
+ declare let STATES: States;
146
155
  declare const mimeTypes: Record<string, MimeType>;
147
156
  //#endregion
148
157
  //#region src/app/index.d.ts
@@ -151,13 +160,16 @@ type Virtual = (environment: Environment) => undefined | string | Promise<string
151
160
  interface DevelopmentConfig {
152
161
  middlewares: Array<Middleware>;
153
162
  }
163
+ interface BuildConfig {
164
+ externals: Array<string>;
165
+ }
154
166
  interface Config {
155
167
  modules: Array<Module>;
156
168
  client?: string;
157
169
  server?: string;
158
- externals: Array<string>;
159
170
  sources: Record<string, Source>;
160
171
  development: DevelopmentConfig;
172
+ build: BuildConfig;
161
173
  }
162
174
  interface Module {
163
175
  config?: Mergeable<Config>;
@@ -166,7 +178,7 @@ interface Module {
166
178
  interface Source {
167
179
  match: string;
168
180
  entries: Array<string>;
169
- suffix?: string;
181
+ resolve?: (path: string) => string;
170
182
  }
171
183
  interface App {
172
184
  config: Config;
@@ -180,4 +192,4 @@ declare const CLIENT = "client";
180
192
  //#region src/client/index.d.ts
181
193
  declare function $fetch<T>(scope: Scope, input: string | URL, options?: RequestInit): Promise<T>;
182
194
  //#endregion
183
- export { $fetch, App, CLIENT, Config, Context, CookieOptions, CookiePriority, CookieSameSite, Descriptor, DevelopmentConfig, Encoding, Environment, Failure, HttpMethod, InferInput, InferOutput, Issue, Mergeable, Middleware, MimeType, Module, Node, Output, PARAMETER, ParameterNode, PathNode, ROUTER_CONTEXT, Radix, ResponseConfig, Result, Route, Router, RouterContext, SERVER, SERVER_CONTEXT, Schema, Scope, Server, ServerContext, Source, StatusCode, StopEvent, Success, Virtual, WILDCARD, WildcardNode, createApp, createServer, defineContext, defineMiddleware, defineRoute, invoke, isFailure, mergeObjects, mimeType, mimeTypes, parseSchema, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, toRoutePath, useCookies, useQuery, useServer, useSetCookies, useUrl };
195
+ export { $fetch, App, BuildConfig, CLIENT, Config, Context, CookieOptions, CookiePriority, CookieSameSite, Descriptor, DevelopmentConfig, Encoding, Environment, Exception, Failure, HttpMethod, InferInput, InferOutput, Issue, Mergeable, Middleware, MimeType, Module, Node, Output, PARAMETER, ParameterNode, PathNode, ROUTER_CONTEXT, Radix, ResponseConfig, Result, Route, Router, RouterContext, SERVER, SERVER_CONTEXT, STATES, Schema, Scope, Server, ServerContext, Source, States, StatusCode, StopEvent, Success, Virtual, WILDCARD, WildcardNode, createApp, createServer, defineContext, defineMiddleware, defineRoute, getState, invoke, isFailure, mergeObjects, mimeType, mimeTypes, parseSchema, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, setState, toRoutePath, useCookies, useQuery, useRouter, useServer, useSetCookies, useUrl };
package/dist/index.js CHANGED
@@ -88,6 +88,9 @@ function defineRoute(route) {
88
88
  function defineMiddleware(middleware) {
89
89
  return middleware;
90
90
  }
91
+ function useRouter(scope) {
92
+ return scope.getContext(ROUTER_CONTEXT);
93
+ }
91
94
  function useServer(scope) {
92
95
  return scope.getContext(SERVER_CONTEXT);
93
96
  }
@@ -132,6 +135,30 @@ function setCookie(scope, name, value, options) {
132
135
  if (import.meta.client) document.cookie = cookie;
133
136
  else response.headers.append("Set-Cookie", cookie);
134
137
  }
138
+ function getState(scope, name) {
139
+ if (import.meta.server) {
140
+ const { states } = useServer(scope);
141
+ return states[name];
142
+ } else {
143
+ if (STATES === void 0) {
144
+ const element = document.getElementById("STATES");
145
+ STATES = element?.textContent ? JSON.parse(element.textContent) : {};
146
+ }
147
+ return STATES[name];
148
+ }
149
+ }
150
+ function setState(scope, name, value) {
151
+ if (import.meta.server) {
152
+ const { states } = useServer(scope);
153
+ states[name] = value;
154
+ } else {
155
+ if (STATES === void 0) {
156
+ const element = document.getElementById("STATES");
157
+ STATES = element?.textContent ? JSON.parse(element.textContent) : {};
158
+ }
159
+ STATES[name] = value;
160
+ }
161
+ }
135
162
  function sendText(scope, text, config) {
136
163
  const { response } = useServer(scope);
137
164
  response.headers.set("Content-Type", "text/plain");
@@ -176,9 +203,7 @@ function invoke(scope, pipeline, index = 0) {
176
203
  }
177
204
  async function createServer() {
178
205
  const router = new Router();
179
- const pipeline = new Array();
180
- const middlewares = await import("#virtual/middlewares").then((module) => Object.entries(module.default));
181
- for (const [_, middleware] of middlewares) pipeline.push(middleware);
206
+ const middlewares = new Array();
182
207
  const assets = await import("#virtual/assets").then((module) => Object.entries(module.default));
183
208
  for (const [path, asset] of assets) router.use(`GET/${path}`, defineRoute({ async fetch(scope) {
184
209
  const { response } = useServer(scope);
@@ -190,12 +215,24 @@ async function createServer() {
190
215
  const [name, method] = toRoutePath(path);
191
216
  router.use(method?.toUpperCase() + name, route);
192
217
  }
193
- pipeline.push(router);
218
+ const exceptions = await import("#virtual/exceptions").then((module) => Object.values(module.default));
219
+ middlewares.push(defineMiddleware({ async fetch(scope, next) {
220
+ try {
221
+ return await next?.();
222
+ } catch (value) {
223
+ for (const exception of exceptions) {
224
+ const result = exception.fetch(scope, value);
225
+ if (result) return result;
226
+ }
227
+ if (value instanceof Response) return value;
228
+ }
229
+ } }));
230
+ middlewares.push(router);
194
231
  return {
195
232
  router,
196
- pipeline,
233
+ middlewares,
197
234
  async fetch(scope) {
198
- return await invoke(scope, pipeline) ?? sendText(scope, "NOT_FOUND", { status: 404 });
235
+ return await invoke(scope, middlewares) ?? sendText(scope, "NOT_FOUND", { status: 404 });
199
236
  }
200
237
  };
201
238
  }
@@ -203,6 +240,7 @@ const ROUTER_CONTEXT = defineContext("ROUTER_CONTEXT");
203
240
  const SERVER_CONTEXT = defineContext("SERVER_CONTEXT");
204
241
  const WILDCARD = "$";
205
242
  const PARAMETER = ":";
243
+ let STATES;
206
244
  const mimeTypes = {
207
245
  txt: "text/plain",
208
246
  css: "text/css",
@@ -296,7 +334,7 @@ function parseSchema(scope, schema, value) {
296
334
  }
297
335
  function mergeObjects(base, input) {
298
336
  if (input === null || input === void 0) return mergeObjects(base, {});
299
- const object = structuredClone(input);
337
+ const object = Object.assign({}, input);
300
338
  for (const key in base) {
301
339
  if (key === "__proto__" || key === "constructor") continue;
302
340
  const value = base[key];
@@ -313,23 +351,23 @@ function mergeObjects(base, input) {
313
351
  function createApp(inputConfig) {
314
352
  let config = mergeObjects(inputConfig, {
315
353
  modules: [],
316
- externals: [],
317
354
  sources: {
318
355
  assets: {
319
356
  match: "**/*",
320
357
  entries: ["./public"],
321
- suffix: "?raw"
358
+ resolve: (path) => path + "?raw"
322
359
  },
323
360
  routes: {
324
361
  match: "**/*.{js,ts}",
325
362
  entries: ["./routes"]
326
363
  },
327
- middlewares: {
364
+ exceptions: {
328
365
  match: "**/*.{js,ts}",
329
- entries: ["./middlewares"]
366
+ entries: ["./exceptions"]
330
367
  }
331
368
  },
332
- development: { middlewares: [] }
369
+ development: { middlewares: [] },
370
+ build: { externals: [] }
333
371
  });
334
372
  for (const module of config.modules) config = mergeObjects(config, module.config);
335
373
  return {
@@ -346,9 +384,10 @@ const CLIENT = "client";
346
384
  async function $fetch(scope, input, options) {
347
385
  let response;
348
386
  if (import.meta.server) {
349
- const { request, variables } = useServer(scope);
387
+ const { states, request, variables } = useServer(scope);
350
388
  const next = new Scope();
351
389
  next.setContext(SERVER_CONTEXT, {
390
+ states,
352
391
  request: new Request(new URL(input.toString(), request.url), options),
353
392
  response: { headers: new Headers() },
354
393
  variables
@@ -364,4 +403,4 @@ async function $fetch(scope, input, options) {
364
403
  }
365
404
 
366
405
  //#endregion
367
- export { $fetch, CLIENT, PARAMETER, ROUTER_CONTEXT, Radix, Router, SERVER, SERVER_CONTEXT, Scope, StopEvent, WILDCARD, createApp, createServer, defineContext, defineMiddleware, defineRoute, invoke, isFailure, mergeObjects, mimeType, mimeTypes, parseSchema, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, toRoutePath, useCookies, useQuery, useServer, useSetCookies, useUrl };
406
+ export { $fetch, CLIENT, PARAMETER, ROUTER_CONTEXT, Radix, Router, SERVER, SERVER_CONTEXT, STATES, Scope, StopEvent, WILDCARD, createApp, createServer, defineContext, defineMiddleware, defineRoute, getState, invoke, isFailure, mergeObjects, mimeType, mimeTypes, parseSchema, sendBadRequest, sendHtml, sendJson, sendRedirect, sendText, sendUnauthorized, setCookie, setState, toRoutePath, useCookies, useQuery, useRouter, useServer, useSetCookies, useUrl };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "revojs",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "repository": "coverbase/revojs",
6
6
  "license": "MIT",
@@ -26,12 +26,12 @@ declare module "#virtual/routes" {
26
26
  export default routes;
27
27
  }
28
28
 
29
- declare module "#virtual/middlewares" {
30
- import type { Middleware } from "revojs";
29
+ declare module "#virtual/exceptions" {
30
+ import type { Exception } from "revojs";
31
31
 
32
- const middlewares: Record<string, Middleware>;
32
+ const exceptions: Record<string, Exception>;
33
33
 
34
- export default middlewares;
34
+ export default exceptions;
35
35
  }
36
36
 
37
37
  interface ImportMeta {