@rvoh/psychic 1.10.4 → 1.11.0-beta.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/cjs/src/bin/helpers/enumsFileStr.js +1 -0
- package/dist/cjs/src/cli/helpers/PsychicLogos.js +38 -0
- package/dist/cjs/src/cli/index.js +4 -4
- package/dist/cjs/src/controller/helpers/httpMethodColor.js +34 -0
- package/dist/cjs/src/controller/helpers/logIfDevelopment.js +28 -0
- package/dist/cjs/src/controller/helpers/statusCodeColor.js +22 -0
- package/dist/cjs/src/controller/index.js +32 -13
- package/dist/cjs/src/generate/helpers/generateResourceControllerSpecContent.js +71 -60
- package/dist/cjs/src/generate/resource.js +2 -1
- package/dist/cjs/src/openapi-renderer/SerializerOpenapiRenderer.js +28 -29
- package/dist/cjs/src/openapi-renderer/endpoint.js +8 -2
- package/dist/cjs/src/psychic-app/index.js +2 -2
- package/dist/cjs/src/router/index.js +10 -19
- package/dist/cjs/src/server/helpers/startPsychicServer.js +17 -4
- package/dist/cjs/src/server/index.js +20 -3
- package/dist/esm/src/bin/helpers/enumsFileStr.js +1 -0
- package/dist/esm/src/cli/helpers/PsychicLogos.js +32 -0
- package/dist/esm/src/cli/index.js +4 -4
- package/dist/esm/src/controller/helpers/httpMethodColor.js +30 -0
- package/dist/esm/src/controller/helpers/logIfDevelopment.js +22 -0
- package/dist/esm/src/controller/helpers/statusCodeColor.js +18 -0
- package/dist/esm/src/controller/index.js +32 -13
- package/dist/esm/src/generate/helpers/generateResourceControllerSpecContent.js +71 -60
- package/dist/esm/src/generate/resource.js +2 -1
- package/dist/esm/src/openapi-renderer/SerializerOpenapiRenderer.js +28 -29
- package/dist/esm/src/openapi-renderer/endpoint.js +8 -2
- package/dist/esm/src/psychic-app/index.js +2 -2
- package/dist/esm/src/router/index.js +10 -19
- package/dist/esm/src/server/helpers/startPsychicServer.js +17 -4
- package/dist/esm/src/server/index.js +21 -4
- package/dist/types/src/cli/helpers/PsychicLogos.d.ts +3 -0
- package/dist/types/src/controller/helpers/httpMethodColor.d.ts +4 -0
- package/dist/types/src/controller/helpers/logIfDevelopment.d.ts +7 -0
- package/dist/types/src/controller/helpers/statusCodeColor.d.ts +3 -0
- package/dist/types/src/controller/index.d.ts +5 -1
- package/dist/types/src/helpers/EnvInternal.d.ts +2 -2
- package/dist/types/src/openapi-renderer/endpoint.d.ts +39 -1
- package/dist/types/src/server/index.d.ts +1 -1
- package/dist/types/src/server/params.d.ts +2 -1
- package/package.json +8 -7
- package/CHANGELOG.md +0 -314
|
@@ -62,7 +62,7 @@ class PsychicApp {
|
|
|
62
62
|
*/
|
|
63
63
|
static async init(cb, dreamCb, opts = {}) {
|
|
64
64
|
let psychicApp;
|
|
65
|
-
await dream_1.DreamApp.init(dreamCb,
|
|
65
|
+
await dream_1.DreamApp.init(dreamCb, opts, async (dreamApp) => {
|
|
66
66
|
psychicApp = new PsychicApp();
|
|
67
67
|
await cb(psychicApp);
|
|
68
68
|
if (!psychicApp.loadedControllers)
|
|
@@ -97,7 +97,7 @@ class PsychicApp {
|
|
|
97
97
|
dreamApp.set('logger', psychicApp.logger);
|
|
98
98
|
dreamApp.set('packageManager', psychicApp.packageManager);
|
|
99
99
|
(0, cache_js_1.cachePsychicApp)(psychicApp);
|
|
100
|
-
if (!opts.
|
|
100
|
+
if (!opts.bypassDreamIntegrityChecks) {
|
|
101
101
|
// routes _must_ be built before openapi
|
|
102
102
|
// cache can be processed
|
|
103
103
|
await psychicApp.buildRoutesCache();
|
|
@@ -266,7 +266,7 @@ suggested fix: "${(0, helpers_js_1.convertRouteParams)(path)}"
|
|
|
266
266
|
async handle(controller, action, { req, res, }) {
|
|
267
267
|
const controllerInstance = this._initializeController(controller, req, res, action);
|
|
268
268
|
if (typeof controllerInstance[action] !== 'function') {
|
|
269
|
-
|
|
269
|
+
controllerInstance['expressSendStatus'](404);
|
|
270
270
|
return;
|
|
271
271
|
}
|
|
272
272
|
try {
|
|
@@ -274,25 +274,23 @@ suggested fix: "${(0, helpers_js_1.convertRouteParams)(path)}"
|
|
|
274
274
|
}
|
|
275
275
|
catch (error) {
|
|
276
276
|
const err = error;
|
|
277
|
-
if (!EnvInternal_js_1.default.isTest)
|
|
278
|
-
index_js_1.default.logWithLevel('error', err.message);
|
|
279
277
|
if ((0, errorIsRescuableHttpError_js_1.default)(err)) {
|
|
280
278
|
const httpErr = err;
|
|
281
279
|
if (httpErr.data) {
|
|
282
|
-
|
|
280
|
+
controllerInstance['expressSendJson'](httpErr.data, httpErr.status);
|
|
283
281
|
}
|
|
284
282
|
else {
|
|
285
|
-
|
|
283
|
+
controllerInstance['expressSendStatus'](httpErr.status);
|
|
286
284
|
}
|
|
287
285
|
}
|
|
288
286
|
else if (err instanceof dream_1.RecordNotFound) {
|
|
289
|
-
|
|
287
|
+
controllerInstance['expressSendStatus'](404);
|
|
290
288
|
}
|
|
291
289
|
else if (err instanceof dream_1.DataIncompatibleWithDatabaseField) {
|
|
292
290
|
/**
|
|
293
291
|
* See comment at top of this method for philosophy of 400
|
|
294
292
|
*/
|
|
295
|
-
|
|
293
|
+
controllerInstance['expressSendStatus'](400);
|
|
296
294
|
}
|
|
297
295
|
else if (err instanceof dream_1.ValidationError) {
|
|
298
296
|
if (this.validationErrorLoggingEnabled) {
|
|
@@ -304,7 +302,7 @@ suggested fix: "${(0, helpers_js_1.convertRouteParams)(path)}"
|
|
|
304
302
|
/**
|
|
305
303
|
* See comment at top of this method for philosophy of 400
|
|
306
304
|
*/
|
|
307
|
-
|
|
305
|
+
controllerInstance['expressSendStatus'](400);
|
|
308
306
|
}
|
|
309
307
|
else if (err instanceof OpenapiRequestValidationFailure_js_1.default) {
|
|
310
308
|
if (this.validationErrorLoggingEnabled) {
|
|
@@ -317,7 +315,7 @@ suggested fix: "${(0, helpers_js_1.convertRouteParams)(path)}"
|
|
|
317
315
|
/**
|
|
318
316
|
* See comment at top of this method for philosophy of 400
|
|
319
317
|
*/
|
|
320
|
-
|
|
318
|
+
controllerInstance['expressSendStatus'](400);
|
|
321
319
|
}
|
|
322
320
|
else if (err instanceof ParamValidationError_js_1.default) {
|
|
323
321
|
if (this.validationErrorLoggingEnabled) {
|
|
@@ -331,7 +329,7 @@ suggested fix: "${(0, helpers_js_1.convertRouteParams)(path)}"
|
|
|
331
329
|
/**
|
|
332
330
|
* See comment at top of this method for philosophy of 400
|
|
333
331
|
*/
|
|
334
|
-
|
|
332
|
+
controllerInstance['expressSendStatus'](400);
|
|
335
333
|
}
|
|
336
334
|
else if (err instanceof ParamValidationErrors_js_1.default) {
|
|
337
335
|
if (this.validationErrorLoggingEnabled) {
|
|
@@ -343,17 +341,10 @@ suggested fix: "${(0, helpers_js_1.convertRouteParams)(path)}"
|
|
|
343
341
|
/**
|
|
344
342
|
* See comment at top of this method for philosophy of 400
|
|
345
343
|
*/
|
|
346
|
-
|
|
344
|
+
controllerInstance['expressSendStatus'](400);
|
|
347
345
|
}
|
|
348
346
|
else {
|
|
349
|
-
|
|
350
|
-
// to have to apply an ugly and annoying try-catch pattern to our controllers
|
|
351
|
-
// and manually console log the error to determine what the actual error was.
|
|
352
|
-
// this block enables us to not have to do that anymore.
|
|
353
|
-
if (EnvInternal_js_1.default.isTest && !EnvInternal_js_1.default.boolean('PSYCHIC_EXPECTING_INTERNAL_SERVER_ERROR')) {
|
|
354
|
-
index_js_1.default.log('ATTENTION: a server error was detected:');
|
|
355
|
-
index_js_1.default.logWithLevel('error', err);
|
|
356
|
-
}
|
|
347
|
+
index_js_1.default.logWithLevel('error', err);
|
|
357
348
|
if (index_js_1.default.getOrFail().specialHooks.serverError.length) {
|
|
358
349
|
try {
|
|
359
350
|
for (const hook of index_js_1.default.getOrFail().specialHooks.serverError) {
|
|
@@ -32,8 +32,10 @@ const dream_1 = require("@rvoh/dream");
|
|
|
32
32
|
const fs = __importStar(require("node:fs"));
|
|
33
33
|
const http = __importStar(require("node:http"));
|
|
34
34
|
const https = __importStar(require("node:https"));
|
|
35
|
+
const colorize_js_1 = __importDefault(require("../../cli/helpers/colorize.js"));
|
|
35
36
|
const EnvInternal_js_1 = __importDefault(require("../../helpers/EnvInternal.js"));
|
|
36
|
-
const index_js_1 = __importDefault(require("../../
|
|
37
|
+
const index_js_1 = __importDefault(require("../../psychic-app/index.js"));
|
|
38
|
+
const PsychicLogos_js_1 = __importDefault(require("../../cli/helpers/PsychicLogos.js"));
|
|
37
39
|
async function startPsychicServer({ app, port, sslCredentials, }) {
|
|
38
40
|
return await new Promise(accept => {
|
|
39
41
|
const httpOrHttps = createPsychicHttpInstance(app, sslCredentials);
|
|
@@ -55,9 +57,20 @@ function createPsychicHttpInstance(app, sslCredentials) {
|
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
function welcomeMessage({ port }) {
|
|
58
|
-
if (
|
|
59
|
-
dream_1.DreamCLI.logger.log(
|
|
60
|
-
|
|
60
|
+
if (EnvInternal_js_1.default.isDevelopment) {
|
|
61
|
+
dream_1.DreamCLI.logger.log((0, colorize_js_1.default)(PsychicLogos_js_1.default.babyAster(), { color: 'greenBright' }), {
|
|
62
|
+
logPrefix: '',
|
|
63
|
+
});
|
|
64
|
+
dream_1.DreamCLI.logger.log('', { logPrefix: '' });
|
|
65
|
+
dream_1.DreamCLI.logger.log((0, colorize_js_1.default)('✺ ' + index_js_1.default.getOrFail().appName, { color: 'greenBright' }), {
|
|
66
|
+
logPrefix: '',
|
|
67
|
+
});
|
|
68
|
+
dream_1.DreamCLI.logger.log((0, colorize_js_1.default)(`└─ http://localhost:${port.toString()}`, { color: 'greenBright' }), {
|
|
69
|
+
logPrefix: '',
|
|
70
|
+
});
|
|
71
|
+
dream_1.DreamCLI.logger.log('', { logPrefix: '' });
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
61
74
|
dream_1.DreamCLI.logger.log(`psychic dev server started at port ${port}`);
|
|
62
75
|
}
|
|
63
76
|
}
|
|
@@ -34,6 +34,7 @@ const EnvInternal_js_1 = __importDefault(require("../helpers/EnvInternal.js"));
|
|
|
34
34
|
const index_js_1 = __importDefault(require("../psychic-app/index.js"));
|
|
35
35
|
const index_js_2 = __importDefault(require("../router/index.js"));
|
|
36
36
|
const startPsychicServer_js_1 = __importStar(require("./helpers/startPsychicServer.js"));
|
|
37
|
+
const logIfDevelopment_js_1 = __importDefault(require("../controller/helpers/logIfDevelopment.js"));
|
|
37
38
|
// const debugEnabled = debuglog('psychic').enabled
|
|
38
39
|
class PsychicServer {
|
|
39
40
|
static async startPsychicServer(opts) {
|
|
@@ -42,9 +43,6 @@ class PsychicServer {
|
|
|
42
43
|
static createPsychicHttpInstance(app, sslCredentials) {
|
|
43
44
|
return (0, startPsychicServer_js_1.createPsychicHttpInstance)(app, sslCredentials);
|
|
44
45
|
}
|
|
45
|
-
static asciiLogo() {
|
|
46
|
-
return dream_1.DreamLogos.colorful();
|
|
47
|
-
}
|
|
48
46
|
expressApp;
|
|
49
47
|
httpServer;
|
|
50
48
|
booted = false;
|
|
@@ -92,9 +90,28 @@ class PsychicServer {
|
|
|
92
90
|
for (const afterRoutesHook of index_js_1.default.getOrFail().specialHooks.serverInitAfterRoutes) {
|
|
93
91
|
await afterRoutesHook(this);
|
|
94
92
|
}
|
|
93
|
+
this.applyNotFoundMiddleware();
|
|
95
94
|
this.booted = true;
|
|
96
95
|
return true;
|
|
97
96
|
}
|
|
97
|
+
applyNotFoundMiddleware() {
|
|
98
|
+
if (!EnvInternal_js_1.default.isDevelopment)
|
|
99
|
+
return;
|
|
100
|
+
this.expressApp.use((req, res, next) => {
|
|
101
|
+
// express by default will set the 200 status code. If a user explicitly
|
|
102
|
+
// provides anything other than 200, we should assume that a prior middleware
|
|
103
|
+
// would have have sent headers, which would prevent any of this from happening.
|
|
104
|
+
// this means that if we are here, we should not be sending a 200. Future middleware
|
|
105
|
+
// by express will automatically pick this up and turn it into a 404, so we are
|
|
106
|
+
// going to automatically set the status to 404 now, so that our logger can
|
|
107
|
+
// pick up the correct status code.
|
|
108
|
+
if (res.statusCode === 200)
|
|
109
|
+
res.status(404);
|
|
110
|
+
(0, logIfDevelopment_js_1.default)({ req, res, startTime: Date.now(), fallbackStatusCode: 404 });
|
|
111
|
+
// call next to let express handle sending the 404
|
|
112
|
+
next();
|
|
113
|
+
});
|
|
114
|
+
}
|
|
98
115
|
setSecureDefaultHeaders() {
|
|
99
116
|
this.expressApp.disable('x-powered-by');
|
|
100
117
|
this.expressApp.use((_, res, next) => {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import colorize from './colorize.js';
|
|
2
|
+
export default class PsychicLogos {
|
|
3
|
+
static babyAster() {
|
|
4
|
+
const g = (str) => colorize(str, { color: 'green' });
|
|
5
|
+
return `
|
|
6
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
7
|
+
░░░░░░█▀█░█▀▀░█░█░█▀▀░█░█░▀█▀░█▀▀░░░░░░░░░
|
|
8
|
+
░░░░░░█▀▀░▀▀█░░█░░█░░░█▀█░░█░░█░░░░░░░░░░░
|
|
9
|
+
░░░░░░▀░░░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░░░░░░░░
|
|
10
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
11
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣿⣿⣿⣿⣿⣿⠟⢉⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
12
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⣀⡀⠈⠻⠿⡿⠿⠛⠉⠁⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
13
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠹⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
14
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
15
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
16
|
+
⣿⠿⠛⠋⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢴⣲⠀⠀⠀⠋⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
17
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
18
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⡀⠀⢀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
19
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
20
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
21
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
22
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
23
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
|
|
24
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿
|
|
25
|
+
⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⠀⠀⢸▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓
|
|
26
|
+
⠀⠀⠀⠀⢠▓⣿⠀⠀⠀⣿ ⠀ ⣸⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿
|
|
27
|
+
⠀⠀⠀⢠▓⣿▓⣦⠀⠀⣿▓⠀⠀⠋▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓
|
|
28
|
+
⠀⠀⠀⢸⣿▓⣿▓⡄⠀⠈⠙⣄⣀⣠⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿
|
|
29
|
+
⠀⠀⠀⠺▓⣿▓⣿▓⣄⣀⣤⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓\
|
|
30
|
+
`.replace(/▓/g, g('▓'));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -67,7 +67,7 @@ export default class PsychicCLI {
|
|
|
67
67
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
68
68
|
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
69
69
|
.action(async (route, modelName, columnsWithTypes, options) => {
|
|
70
|
-
await initializePsychicApp();
|
|
70
|
+
await initializePsychicApp({ bypassDreamIntegrityChecks: true });
|
|
71
71
|
await PsychicBin.generateResource(route, modelName, columnsWithTypes, options);
|
|
72
72
|
process.exit();
|
|
73
73
|
});
|
|
@@ -78,7 +78,7 @@ export default class PsychicCLI {
|
|
|
78
78
|
.argument('<controllerName>', 'the name of the controller to create, including namespaces, e.g. Posts or Api/V1/Posts')
|
|
79
79
|
.argument('[actions...]', 'the names of controller actions to create')
|
|
80
80
|
.action(async (controllerName, actions) => {
|
|
81
|
-
await initializePsychicApp();
|
|
81
|
+
await initializePsychicApp({ bypassDreamIntegrityChecks: true });
|
|
82
82
|
await PsychicBin.generateController(controllerName, actions);
|
|
83
83
|
process.exit();
|
|
84
84
|
});
|
|
@@ -135,7 +135,7 @@ export default class PsychicCLI {
|
|
|
135
135
|
.description('sync introspects your database, updating your schema to reflect, and then syncs the new schema with the installed dream node module, allowing it provide your schema to the underlying kysely integration')
|
|
136
136
|
.option('--schema-only')
|
|
137
137
|
.action(async (options = {}) => {
|
|
138
|
-
await initializePsychicApp();
|
|
138
|
+
await initializePsychicApp({ bypassDreamIntegrityChecks: !!options.schemaOnly });
|
|
139
139
|
await PsychicBin.sync(options);
|
|
140
140
|
process.exit();
|
|
141
141
|
});
|
|
@@ -144,7 +144,7 @@ export default class PsychicCLI {
|
|
|
144
144
|
.description('watches your app for changes, and re-syncs any time they happen')
|
|
145
145
|
.argument('[dir]', 'the folder you want to watch, defaults to ./src')
|
|
146
146
|
.action(async (dir) => {
|
|
147
|
-
await initializePsychicApp();
|
|
147
|
+
await initializePsychicApp({ bypassDreamIntegrityChecks: true });
|
|
148
148
|
Watcher.watch(dir);
|
|
149
149
|
});
|
|
150
150
|
program
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export default function httpMethodColor(httpMethod) {
|
|
2
|
+
switch (httpMethod) {
|
|
3
|
+
case 'delete':
|
|
4
|
+
return 'red';
|
|
5
|
+
case 'options':
|
|
6
|
+
return 'gray';
|
|
7
|
+
case 'patch':
|
|
8
|
+
case 'put':
|
|
9
|
+
return 'magentaBright';
|
|
10
|
+
case 'post':
|
|
11
|
+
return 'greenBright';
|
|
12
|
+
default:
|
|
13
|
+
return 'blue';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function httpMethodBgColor(httpMethod) {
|
|
17
|
+
switch (httpMethod) {
|
|
18
|
+
case 'delete':
|
|
19
|
+
return 'bgRed';
|
|
20
|
+
case 'options':
|
|
21
|
+
return 'bgWhite';
|
|
22
|
+
case 'patch':
|
|
23
|
+
case 'put':
|
|
24
|
+
return 'bgMagentaBright';
|
|
25
|
+
case 'post':
|
|
26
|
+
return 'bgGreen';
|
|
27
|
+
default:
|
|
28
|
+
return 'bgBlue';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DreamCLI } from '@rvoh/dream';
|
|
2
|
+
import colorize from '../../cli/helpers/colorize.js';
|
|
3
|
+
import EnvInternal from '../../helpers/EnvInternal.js';
|
|
4
|
+
import { httpMethodBgColor } from './httpMethodColor.js';
|
|
5
|
+
import { statusCodeBgColor } from './statusCodeColor.js';
|
|
6
|
+
export default function logIfDevelopment({ req, res, startTime, fallbackStatusCode = 200, }) {
|
|
7
|
+
if (!EnvInternal.isDevelopment)
|
|
8
|
+
return;
|
|
9
|
+
const method = colorize(` ${req.method.toUpperCase()} `, {
|
|
10
|
+
color: 'black',
|
|
11
|
+
bgColor: httpMethodBgColor(req.method.toLowerCase()),
|
|
12
|
+
});
|
|
13
|
+
const computedStatus = res.statusCode || fallbackStatusCode;
|
|
14
|
+
const statusBgColor = statusCodeBgColor(computedStatus);
|
|
15
|
+
const status = colorize(` ${computedStatus} `, {
|
|
16
|
+
color: 'black',
|
|
17
|
+
bgColor: statusBgColor,
|
|
18
|
+
});
|
|
19
|
+
const url = colorize(req.url, { color: 'green' });
|
|
20
|
+
const benchmark = colorize(`${Date.now() - startTime}ms`, { color: 'gray' });
|
|
21
|
+
DreamCLI.logger.log(`${method} ${url} ${status} ${benchmark}`, { logPrefix: '' });
|
|
22
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default function statusCodeColor(statusCode) {
|
|
2
|
+
if (statusCode >= 200 && statusCode < 300)
|
|
3
|
+
return 'green';
|
|
4
|
+
if (statusCode >= 300 && statusCode < 400)
|
|
5
|
+
return 'yellow';
|
|
6
|
+
if (statusCode >= 400 && statusCode < 500)
|
|
7
|
+
return 'red';
|
|
8
|
+
return 'redBright';
|
|
9
|
+
}
|
|
10
|
+
export function statusCodeBgColor(statusCode) {
|
|
11
|
+
if (statusCode >= 200 && statusCode < 300)
|
|
12
|
+
return 'bgGreen';
|
|
13
|
+
if (statusCode >= 300 && statusCode < 400)
|
|
14
|
+
return 'bgYellow';
|
|
15
|
+
if (statusCode >= 400 && statusCode < 500)
|
|
16
|
+
return 'bgRed';
|
|
17
|
+
return 'bgRedBright';
|
|
18
|
+
}
|
|
@@ -37,7 +37,9 @@ import PsychicApp from '../psychic-app/index.js';
|
|
|
37
37
|
import Params from '../server/params.js';
|
|
38
38
|
import Session from '../session/index.js';
|
|
39
39
|
import isPaginatedResult from './helpers/isPaginatedResult.js';
|
|
40
|
+
import logIfDevelopment from './helpers/logIfDevelopment.js';
|
|
40
41
|
import renderDreamOrVewModel from './helpers/renderDreamOrViewModel.js';
|
|
42
|
+
import EnvInternal from '../helpers/EnvInternal.js';
|
|
41
43
|
export const PsychicParamsPrimitiveLiterals = [
|
|
42
44
|
'bigint',
|
|
43
45
|
'bigint[]',
|
|
@@ -171,7 +173,9 @@ export default class PsychicController {
|
|
|
171
173
|
session;
|
|
172
174
|
action;
|
|
173
175
|
renderOpts;
|
|
176
|
+
startTime;
|
|
174
177
|
constructor(req, res, { action, }) {
|
|
178
|
+
this.startTime = Date.now();
|
|
175
179
|
this.req = req;
|
|
176
180
|
this.res = res;
|
|
177
181
|
this.session = new Session(req, res);
|
|
@@ -422,7 +426,26 @@ export default class PsychicController {
|
|
|
422
426
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
423
427
|
data) {
|
|
424
428
|
this.validateOpenapiResponseBody(data);
|
|
425
|
-
this.
|
|
429
|
+
this.expressSendJson(data);
|
|
430
|
+
}
|
|
431
|
+
expressSendJson(
|
|
432
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
433
|
+
data, statusCode = this.res.statusCode) {
|
|
434
|
+
this.res.type('json').status(statusCode).send(toJson(data, PsychicApp.getOrFail().sanitizeResponseJson));
|
|
435
|
+
this.logIfDevelopment();
|
|
436
|
+
}
|
|
437
|
+
expressSendStatus(statusCode) {
|
|
438
|
+
this.res.sendStatus(statusCode);
|
|
439
|
+
this.logIfDevelopment();
|
|
440
|
+
}
|
|
441
|
+
expressRedirect(statusCode, newLocation) {
|
|
442
|
+
this.res.redirect(statusCode, newLocation);
|
|
443
|
+
this.logIfDevelopment();
|
|
444
|
+
}
|
|
445
|
+
logIfDevelopment() {
|
|
446
|
+
if (!EnvInternal.isDevelopment)
|
|
447
|
+
return;
|
|
448
|
+
logIfDevelopment({ req: this.req, res: this.res, startTime: this.startTime });
|
|
426
449
|
}
|
|
427
450
|
defaultSerializerPassthrough = {};
|
|
428
451
|
serializerPassthrough(passthrough) {
|
|
@@ -469,15 +492,15 @@ export default class PsychicController {
|
|
|
469
492
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
470
493
|
nonAuthoritativeInformation(message = undefined) {
|
|
471
494
|
if (message) {
|
|
472
|
-
this.
|
|
495
|
+
this.expressSendJson(message, 203);
|
|
473
496
|
}
|
|
474
497
|
else {
|
|
475
|
-
this.
|
|
498
|
+
this.expressSendStatus(203);
|
|
476
499
|
}
|
|
477
500
|
}
|
|
478
501
|
// 204
|
|
479
502
|
noContent() {
|
|
480
|
-
this.
|
|
503
|
+
this.expressSendStatus(204);
|
|
481
504
|
}
|
|
482
505
|
// 205
|
|
483
506
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -493,27 +516,23 @@ export default class PsychicController {
|
|
|
493
516
|
}
|
|
494
517
|
// 301
|
|
495
518
|
movedPermanently(newLocation) {
|
|
496
|
-
this.
|
|
519
|
+
this.expressRedirect(301, newLocation);
|
|
497
520
|
}
|
|
498
521
|
// 302
|
|
499
522
|
found(newLocation) {
|
|
500
|
-
this.
|
|
523
|
+
this.expressRedirect(302, newLocation);
|
|
501
524
|
}
|
|
502
525
|
// 303
|
|
503
526
|
seeOther(newLocation) {
|
|
504
|
-
this.
|
|
505
|
-
}
|
|
506
|
-
// 304
|
|
507
|
-
notModified(newLocation) {
|
|
508
|
-
this.res.redirect(304, newLocation);
|
|
527
|
+
this.expressRedirect(303, newLocation);
|
|
509
528
|
}
|
|
510
529
|
// 307
|
|
511
530
|
temporaryRedirect(newLocation) {
|
|
512
|
-
this.
|
|
531
|
+
this.expressRedirect(307, newLocation);
|
|
513
532
|
}
|
|
514
533
|
// 308
|
|
515
534
|
permanentRedirect(newLocation) {
|
|
516
|
-
this.
|
|
535
|
+
this.expressRedirect(308, newLocation);
|
|
517
536
|
}
|
|
518
537
|
// 400
|
|
519
538
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|