@mojojs/core 0.25.0 → 0.26.0
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/README.md +2 -2
- package/lib/app.js +2 -6
- package/lib/app.js.map +1 -1
- package/lib/plugins/default-conditions.d.ts +5 -0
- package/lib/plugins/default-conditions.js +22 -0
- package/lib/plugins/default-conditions.js.map +1 -0
- package/lib/plugins/default-helpers.js +122 -0
- package/lib/plugins/default-helpers.js.map +1 -1
- package/lib/plugins/view-helpers.js +1 -6
- package/lib/plugins/view-helpers.js.map +1 -1
- package/package.json +1 -1
- package/vendor/views/mojo/debug.html.mt +2 -1
package/README.md
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
The [Mojolicious](https://mojolicious.org) real-time web framework for [Node.js](https://nodejs.org/). Written in
|
|
14
14
|
TypeScript. Meticulously designed for high performance backend web services using bleeding edge JavaScript features.
|
|
15
15
|
|
|
16
|
-
If you want to stay up to date on the latest developments join us on [
|
|
17
|
-
(
|
|
16
|
+
If you want to stay up to date on the latest developments join us on [Matrix](https://matrix.to/#/#mojo:matrix.org) or
|
|
17
|
+
[IRC](https://web.libera.chat/#mojo).
|
|
18
18
|
|
|
19
19
|
## Features
|
|
20
20
|
|
package/lib/app.js
CHANGED
|
@@ -5,11 +5,9 @@ import { Logger } from './logger.js';
|
|
|
5
5
|
import { Mime } from './mime.js';
|
|
6
6
|
import { MockRequest } from './mock/request.js';
|
|
7
7
|
import { MockResponse } from './mock/response.js';
|
|
8
|
+
import defaultConditionsPlugin from './plugins/default-conditions.js';
|
|
8
9
|
import defaultHelpersPlugin from './plugins/default-helpers.js';
|
|
9
|
-
import exceptionHelpersPlugin from './plugins/exception-helpers.js';
|
|
10
|
-
import headerConditionsPlugin from './plugins/header-conditions.js';
|
|
11
10
|
import mtEnginePlugin from './plugins/mt-engine.js';
|
|
12
|
-
import viewHelpersPlugin from './plugins/view-helpers.js';
|
|
13
11
|
import { Renderer } from './renderer.js';
|
|
14
12
|
import { Router } from './router.js';
|
|
15
13
|
import { Session } from './session.js';
|
|
@@ -84,10 +82,8 @@ export class App {
|
|
|
84
82
|
const isDev = this._mode === 'development';
|
|
85
83
|
this.log = new Logger({ historySize: isDev ? 10 : 0, level: isDev ? 'trace' : 'info' });
|
|
86
84
|
this.plugin(defaultHelpersPlugin);
|
|
87
|
-
this.plugin(
|
|
88
|
-
this.plugin(headerConditionsPlugin);
|
|
85
|
+
this.plugin(defaultConditionsPlugin);
|
|
89
86
|
this.plugin(mtEnginePlugin);
|
|
90
|
-
this.plugin(viewHelpersPlugin);
|
|
91
87
|
}
|
|
92
88
|
/**
|
|
93
89
|
* Add an application hook.
|
package/lib/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,GAAG,EAAC,MAAM,UAAU,CAAC;AAC7B,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,OAAO,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACnC,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAC/B,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default condition plugin.
|
|
3
|
+
*/
|
|
4
|
+
export default function defaultConditionsPlugin(app) {
|
|
5
|
+
const router = app.router;
|
|
6
|
+
router.addCondition('headers', headerCondition);
|
|
7
|
+
router.addCondition('host', hostCondition);
|
|
8
|
+
}
|
|
9
|
+
function headerCondition(ctx, requirement) {
|
|
10
|
+
for (const [name, regex] of Object.entries(requirement)) {
|
|
11
|
+
const value = ctx.req.get(name);
|
|
12
|
+
if (typeof value !== 'string')
|
|
13
|
+
return false;
|
|
14
|
+
if (regex.test(value) === false)
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
function hostCondition(ctx, requirement) {
|
|
20
|
+
return headerCondition(ctx, { Host: requirement });
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=default-conditions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-conditions.js","sourceRoot":"","sources":["../../src/plugins/default-conditions.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,uBAAuB,CAAC,GAAQ;IACtD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAC1B,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAChD,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,eAAe,CAAC,GAAgB,EAAE,WAAmC;IAC5E,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE;QACvD,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;KAC/C;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,GAAgB,EAAE,WAAmB;IAC1D,OAAO,eAAe,CAAC,GAAG,EAAE,EAAC,IAAI,EAAE,WAAW,EAAC,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
import { inspect } from 'util';
|
|
2
|
+
import { Logger } from '../logger.js';
|
|
3
|
+
import { SafeString } from '../util.js';
|
|
4
|
+
import { exceptionContext } from '../util.js';
|
|
5
|
+
import DOM from '@mojojs/dom';
|
|
2
6
|
/**
|
|
3
7
|
* Default helper plugin.
|
|
4
8
|
*/
|
|
5
9
|
export default function defaultHelpersPlugin(app) {
|
|
10
|
+
app.addHelper('exception', exception);
|
|
11
|
+
app.addHelper('htmlException', htmlException);
|
|
12
|
+
app.addHelper('htmlNotFound', htmlNotFound);
|
|
13
|
+
app.addHelper('httpException', httpException);
|
|
14
|
+
app.addHelper('jsonException', jsonException);
|
|
15
|
+
app.addHelper('jsonNotFound', jsonNotFound);
|
|
16
|
+
app.addHelper('txtException', txtException);
|
|
17
|
+
app.addHelper('txtNotFound', txtNotFound);
|
|
18
|
+
app.addHelper('notFound', notFound);
|
|
19
|
+
app.addHelper('websocketException', websocketException);
|
|
6
20
|
app.addHelper('currentRoute', currentRoute);
|
|
21
|
+
app.addHelper('include', include);
|
|
22
|
+
app.addHelper('linkTo', linkTo);
|
|
23
|
+
app.addHelper('mojoFaviconTag', mojoFaviconTag);
|
|
24
|
+
app.addHelper('scriptTag', scriptTag);
|
|
25
|
+
app.addHelper('styleTag', styleTag);
|
|
26
|
+
app.addHelper('tag', tag);
|
|
7
27
|
app.decorateContext('inspect', (object, options) => inspect(object, options));
|
|
8
28
|
}
|
|
9
29
|
function currentRoute(ctx) {
|
|
@@ -15,4 +35,106 @@ function currentRoute(ctx) {
|
|
|
15
35
|
return null;
|
|
16
36
|
return endpoint.customName ?? endpoint.defaultName ?? null;
|
|
17
37
|
}
|
|
38
|
+
async function exception(ctx, error) {
|
|
39
|
+
if (ctx.isWebSocket)
|
|
40
|
+
return ctx.websocketException(error);
|
|
41
|
+
return ctx.httpException(error);
|
|
42
|
+
}
|
|
43
|
+
async function htmlException(ctx, error) {
|
|
44
|
+
ctx.stash.exception = error;
|
|
45
|
+
const mode = ctx.app.mode;
|
|
46
|
+
if (await ctx.render({ view: `exception.${mode}`, maybe: true, status: 500 }))
|
|
47
|
+
return true;
|
|
48
|
+
if (await ctx.render({ view: 'exception', maybe: true, status: 500 }))
|
|
49
|
+
return true;
|
|
50
|
+
const view = mode === 'development' ? 'mojo/debug' : 'mojo/exception';
|
|
51
|
+
return await ctx.render({ view, status: 500, stringFormatter: Logger.stringFormatter, exceptionContext });
|
|
52
|
+
}
|
|
53
|
+
async function htmlNotFound(ctx) {
|
|
54
|
+
ctx.stash.exception = null;
|
|
55
|
+
const mode = ctx.app.mode;
|
|
56
|
+
if (await ctx.render({ view: `not-found.${mode}`, maybe: true, status: 404 }))
|
|
57
|
+
return true;
|
|
58
|
+
if (await ctx.render({ view: 'not-found', maybe: true, status: 404 }))
|
|
59
|
+
return true;
|
|
60
|
+
const view = mode === 'development' ? 'mojo/debug' : 'mojo/not-found';
|
|
61
|
+
return await ctx.render({ view, status: 404, stringFormatter: Logger.stringFormatter });
|
|
62
|
+
}
|
|
63
|
+
async function httpException(ctx, error) {
|
|
64
|
+
error = ensureError(error);
|
|
65
|
+
ctx.log.error(error.stack);
|
|
66
|
+
const exceptionFormat = ctx.exceptionFormat;
|
|
67
|
+
if (exceptionFormat === 'txt')
|
|
68
|
+
return ctx.txtException(error);
|
|
69
|
+
if (exceptionFormat === 'json')
|
|
70
|
+
return ctx.jsonException(error);
|
|
71
|
+
return ctx.htmlException(error);
|
|
72
|
+
}
|
|
73
|
+
async function include(ctx, options, stash) {
|
|
74
|
+
return await ctx.renderToString(options, stash);
|
|
75
|
+
}
|
|
76
|
+
async function jsonException(ctx, error) {
|
|
77
|
+
if (ctx.app.mode === 'development') {
|
|
78
|
+
return await ctx.render({
|
|
79
|
+
json: {
|
|
80
|
+
error: {
|
|
81
|
+
message: error.message,
|
|
82
|
+
name: error.name,
|
|
83
|
+
stack: error.stack ?? ''
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
pretty: true,
|
|
87
|
+
status: 500
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return await ctx.render({ json: { error: { message: 'Internal Server Error' } }, pretty: true, status: 500 });
|
|
91
|
+
}
|
|
92
|
+
async function jsonNotFound(ctx) {
|
|
93
|
+
return await ctx.render({ json: { error: { message: 'Not Found' } }, pretty: true, status: 404 });
|
|
94
|
+
}
|
|
95
|
+
function linkTo(ctx, target, attrs, content) {
|
|
96
|
+
const href = ctx.urlFor(target);
|
|
97
|
+
return ctx.tag('a', { href, ...attrs }, content);
|
|
98
|
+
}
|
|
99
|
+
function mojoFaviconTag(ctx) {
|
|
100
|
+
return ctx.tag('link', { rel: 'icon', href: ctx.urlForFile('/mojo/favicon.ico') });
|
|
101
|
+
}
|
|
102
|
+
async function notFound(ctx) {
|
|
103
|
+
const exceptionFormat = ctx.exceptionFormat;
|
|
104
|
+
if (exceptionFormat === 'txt')
|
|
105
|
+
return ctx.txtNotFound();
|
|
106
|
+
if (exceptionFormat === 'json')
|
|
107
|
+
return ctx.jsonNotFound();
|
|
108
|
+
return ctx.htmlNotFound();
|
|
109
|
+
}
|
|
110
|
+
function scriptTag(ctx, target) {
|
|
111
|
+
return ctx.tag('script', { src: ctx.urlForFile(target) });
|
|
112
|
+
}
|
|
113
|
+
function styleTag(ctx, target) {
|
|
114
|
+
return ctx.tag('link', { rel: 'stylesheet', href: ctx.urlForFile(target) });
|
|
115
|
+
}
|
|
116
|
+
function tag(ctx, name, attrs = {}, content = '') {
|
|
117
|
+
return new SafeString(DOM.newTag(name, attrs, content).toString());
|
|
118
|
+
}
|
|
119
|
+
async function txtException(ctx, error) {
|
|
120
|
+
if (ctx.app.mode === 'development') {
|
|
121
|
+
return await ctx.render({ text: error.stack, status: 500 });
|
|
122
|
+
}
|
|
123
|
+
return await ctx.render({ text: 'Internal Server Error', status: 500 });
|
|
124
|
+
}
|
|
125
|
+
async function txtNotFound(ctx) {
|
|
126
|
+
return await ctx.render({ text: 'Not Found', status: 404 });
|
|
127
|
+
}
|
|
128
|
+
async function websocketException(ctx, error) {
|
|
129
|
+
error = ensureError(error);
|
|
130
|
+
ctx.log.error(error.stack);
|
|
131
|
+
const ws = ctx.ws;
|
|
132
|
+
if (ws !== null && ctx.isEstablished)
|
|
133
|
+
ws.close(1011);
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
// If you see this then your code has thrown something that was not an Error object
|
|
137
|
+
function ensureError(error) {
|
|
138
|
+
return error instanceof Error ? error : new Error(error);
|
|
139
|
+
}
|
|
18
140
|
//# sourceMappingURL=default-helpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-helpers.js","sourceRoot":"","sources":["../../src/plugins/default-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"default-helpers.js","sourceRoot":"","sources":["../../src/plugins/default-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { SafeString } from '../util.js';
|
|
2
1
|
import DOM from '@mojojs/dom';
|
|
2
|
+
import { SafeString } from '@mojojs/template';
|
|
3
3
|
/**
|
|
4
4
|
* View helper plugin.
|
|
5
5
|
*/
|
|
6
6
|
export default function viewHelpersPlugin(app) {
|
|
7
7
|
app.addHelper('include', include);
|
|
8
|
-
app.addHelper('linkTo', linkTo);
|
|
9
8
|
app.addHelper('mojoFaviconTag', mojoFaviconTag);
|
|
10
9
|
app.addHelper('scriptTag', scriptTag);
|
|
11
10
|
app.addHelper('styleTag', styleTag);
|
|
@@ -14,10 +13,6 @@ export default function viewHelpersPlugin(app) {
|
|
|
14
13
|
async function include(ctx, options, stash) {
|
|
15
14
|
return await ctx.renderToString(options, stash);
|
|
16
15
|
}
|
|
17
|
-
function linkTo(ctx, target, attrs, content) {
|
|
18
|
-
const href = ctx.urlFor(target);
|
|
19
|
-
return ctx.tag('a', { href, ...attrs }, content);
|
|
20
|
-
}
|
|
21
16
|
function mojoFaviconTag(ctx) {
|
|
22
17
|
return ctx.tag('link', { rel: 'icon', href: ctx.urlForFile('/mojo/favicon.ico') });
|
|
23
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-helpers.js","sourceRoot":"","sources":["../../src/plugins/view-helpers.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"view-helpers.js","sourceRoot":"","sources":["../../src/plugins/view-helpers.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,aAAa,CAAC;AAC9B,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAE5C;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,GAAY;IACpD,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAElC,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IAChD,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACtC,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACpC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,GAAgB,EAAE,OAAsB,EAAE,KAA0B;IACzF,OAAO,MAAM,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,cAAc,CAAC,GAAgB;IACtC,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,EAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAC,CAAC,CAAC;AACnF,CAAC;AAED,SAAS,SAAS,CAAC,GAAgB,EAAE,MAAc;IACjD,OAAO,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAC,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,QAAQ,CAAC,GAAgB,EAAE,MAAc;IAChD,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,EAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,GAAG,CACV,GAAgB,EAChB,IAAY,EACZ,QAAgC,EAAE,EAClC,UAA+B,EAAE;IAEjC,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;AACrE,CAAC"}
|
package/package.json
CHANGED
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
Community
|
|
43
43
|
</a>
|
|
44
44
|
<div class="dropdown-menu" aria-labelledby="communityDropdown">
|
|
45
|
-
<a class="dropdown-item" href="https://
|
|
45
|
+
<a class="dropdown-item" href="https://matrix.to/#/#mojo:matrix.org">Matrix</a>
|
|
46
|
+
<a class="dropdown-item" href="https://web.libera.chat/#mojo">IRC</a>
|
|
46
47
|
<a class="dropdown-item" href="https://github.com/mojolicious/mojo.js/discussions">Forum</a>
|
|
47
48
|
<a class="dropdown-item" href="https://twitter.com/mojolicious_org">Twitter</a>
|
|
48
49
|
<a class="dropdown-item" href="https://blogs.mojolicious.org">Blogs</a>
|