@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
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const colorize_js_1 = __importDefault(require("./colorize.js"));
|
|
7
|
+
class PsychicLogos {
|
|
8
|
+
static babyAster() {
|
|
9
|
+
const g = (str) => (0, colorize_js_1.default)(str, { color: 'green' });
|
|
10
|
+
return `
|
|
11
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
12
|
+
░░░░░░█▀█░█▀▀░█░█░█▀▀░█░█░▀█▀░█▀▀░░░░░░░░░
|
|
13
|
+
░░░░░░█▀▀░▀▀█░░█░░█░░░█▀█░░█░░█░░░░░░░░░░░
|
|
14
|
+
░░░░░░▀░░░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░░░░░░░░
|
|
15
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
16
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣿⣿⣿⣿⣿⣿⠟⢉⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
17
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⣀⡀⠈⠻⠿⡿⠿⠛⠉⠁⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
18
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠹⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
19
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
20
|
+
⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
21
|
+
⣿⠿⠛⠋⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢴⣲⠀⠀⠀⠋⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
22
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
23
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⡀⠀⢀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
24
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
25
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
26
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
27
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
|
|
28
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
|
|
29
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿
|
|
30
|
+
⠀⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⠀⠀⢸▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓
|
|
31
|
+
⠀⠀⠀⠀⢠▓⣿⠀⠀⠀⣿ ⠀ ⣸⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿
|
|
32
|
+
⠀⠀⠀⢠▓⣿▓⣦⠀⠀⣿▓⠀⠀⠋▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓
|
|
33
|
+
⠀⠀⠀⢸⣿▓⣿▓⡄⠀⠈⠙⣄⣀⣠⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿
|
|
34
|
+
⠀⠀⠀⠺▓⣿▓⣿▓⣄⣀⣤⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓⣿▓\
|
|
35
|
+
`.replace(/▓/g, g('▓'));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.default = PsychicLogos;
|
|
@@ -72,7 +72,7 @@ class PsychicCLI {
|
|
|
72
72
|
.argument('<modelName>', 'the name of the model to create, e.g. Post or Settings/CommunicationPreferences')
|
|
73
73
|
.argument('[columnsWithTypes...]', columnsWithTypesDescription)
|
|
74
74
|
.action(async (route, modelName, columnsWithTypes, options) => {
|
|
75
|
-
await initializePsychicApp();
|
|
75
|
+
await initializePsychicApp({ bypassDreamIntegrityChecks: true });
|
|
76
76
|
await index_js_1.default.generateResource(route, modelName, columnsWithTypes, options);
|
|
77
77
|
process.exit();
|
|
78
78
|
});
|
|
@@ -83,7 +83,7 @@ class PsychicCLI {
|
|
|
83
83
|
.argument('<controllerName>', 'the name of the controller to create, including namespaces, e.g. Posts or Api/V1/Posts')
|
|
84
84
|
.argument('[actions...]', 'the names of controller actions to create')
|
|
85
85
|
.action(async (controllerName, actions) => {
|
|
86
|
-
await initializePsychicApp();
|
|
86
|
+
await initializePsychicApp({ bypassDreamIntegrityChecks: true });
|
|
87
87
|
await index_js_1.default.generateController(controllerName, actions);
|
|
88
88
|
process.exit();
|
|
89
89
|
});
|
|
@@ -140,7 +140,7 @@ class PsychicCLI {
|
|
|
140
140
|
.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')
|
|
141
141
|
.option('--schema-only')
|
|
142
142
|
.action(async (options = {}) => {
|
|
143
|
-
await initializePsychicApp();
|
|
143
|
+
await initializePsychicApp({ bypassDreamIntegrityChecks: !!options.schemaOnly });
|
|
144
144
|
await index_js_1.default.sync(options);
|
|
145
145
|
process.exit();
|
|
146
146
|
});
|
|
@@ -149,7 +149,7 @@ class PsychicCLI {
|
|
|
149
149
|
.description('watches your app for changes, and re-syncs any time they happen')
|
|
150
150
|
.argument('[dir]', 'the folder you want to watch, defaults to ./src')
|
|
151
151
|
.action(async (dir) => {
|
|
152
|
-
await initializePsychicApp();
|
|
152
|
+
await initializePsychicApp({ bypassDreamIntegrityChecks: true });
|
|
153
153
|
Watcher_js_1.default.watch(dir);
|
|
154
154
|
});
|
|
155
155
|
program
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = httpMethodColor;
|
|
4
|
+
exports.httpMethodBgColor = httpMethodBgColor;
|
|
5
|
+
function httpMethodColor(httpMethod) {
|
|
6
|
+
switch (httpMethod) {
|
|
7
|
+
case 'delete':
|
|
8
|
+
return 'red';
|
|
9
|
+
case 'options':
|
|
10
|
+
return 'gray';
|
|
11
|
+
case 'patch':
|
|
12
|
+
case 'put':
|
|
13
|
+
return 'magentaBright';
|
|
14
|
+
case 'post':
|
|
15
|
+
return 'greenBright';
|
|
16
|
+
default:
|
|
17
|
+
return 'blue';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function httpMethodBgColor(httpMethod) {
|
|
21
|
+
switch (httpMethod) {
|
|
22
|
+
case 'delete':
|
|
23
|
+
return 'bgRed';
|
|
24
|
+
case 'options':
|
|
25
|
+
return 'bgWhite';
|
|
26
|
+
case 'patch':
|
|
27
|
+
case 'put':
|
|
28
|
+
return 'bgMagentaBright';
|
|
29
|
+
case 'post':
|
|
30
|
+
return 'bgGreen';
|
|
31
|
+
default:
|
|
32
|
+
return 'bgBlue';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = logIfDevelopment;
|
|
7
|
+
const dream_1 = require("@rvoh/dream");
|
|
8
|
+
const colorize_js_1 = __importDefault(require("../../cli/helpers/colorize.js"));
|
|
9
|
+
const EnvInternal_js_1 = __importDefault(require("../../helpers/EnvInternal.js"));
|
|
10
|
+
const httpMethodColor_js_1 = require("./httpMethodColor.js");
|
|
11
|
+
const statusCodeColor_js_1 = require("./statusCodeColor.js");
|
|
12
|
+
function logIfDevelopment({ req, res, startTime, fallbackStatusCode = 200, }) {
|
|
13
|
+
if (!EnvInternal_js_1.default.isDevelopment)
|
|
14
|
+
return;
|
|
15
|
+
const method = (0, colorize_js_1.default)(` ${req.method.toUpperCase()} `, {
|
|
16
|
+
color: 'black',
|
|
17
|
+
bgColor: (0, httpMethodColor_js_1.httpMethodBgColor)(req.method.toLowerCase()),
|
|
18
|
+
});
|
|
19
|
+
const computedStatus = res.statusCode || fallbackStatusCode;
|
|
20
|
+
const statusBgColor = (0, statusCodeColor_js_1.statusCodeBgColor)(computedStatus);
|
|
21
|
+
const status = (0, colorize_js_1.default)(` ${computedStatus} `, {
|
|
22
|
+
color: 'black',
|
|
23
|
+
bgColor: statusBgColor,
|
|
24
|
+
});
|
|
25
|
+
const url = (0, colorize_js_1.default)(req.url, { color: 'green' });
|
|
26
|
+
const benchmark = (0, colorize_js_1.default)(`${Date.now() - startTime}ms`, { color: 'gray' });
|
|
27
|
+
dream_1.DreamCLI.logger.log(`${method} ${url} ${status} ${benchmark}`, { logPrefix: '' });
|
|
28
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = statusCodeColor;
|
|
4
|
+
exports.statusCodeBgColor = statusCodeBgColor;
|
|
5
|
+
function statusCodeColor(statusCode) {
|
|
6
|
+
if (statusCode >= 200 && statusCode < 300)
|
|
7
|
+
return 'green';
|
|
8
|
+
if (statusCode >= 300 && statusCode < 400)
|
|
9
|
+
return 'yellow';
|
|
10
|
+
if (statusCode >= 400 && statusCode < 500)
|
|
11
|
+
return 'red';
|
|
12
|
+
return 'redBright';
|
|
13
|
+
}
|
|
14
|
+
function statusCodeBgColor(statusCode) {
|
|
15
|
+
if (statusCode >= 200 && statusCode < 300)
|
|
16
|
+
return 'bgGreen';
|
|
17
|
+
if (statusCode >= 300 && statusCode < 400)
|
|
18
|
+
return 'bgYellow';
|
|
19
|
+
if (statusCode >= 400 && statusCode < 500)
|
|
20
|
+
return 'bgRed';
|
|
21
|
+
return 'bgRedBright';
|
|
22
|
+
}
|
|
@@ -43,7 +43,9 @@ const index_js_1 = __importDefault(require("../psychic-app/index.js"));
|
|
|
43
43
|
const params_js_1 = __importDefault(require("../server/params.js"));
|
|
44
44
|
const index_js_2 = __importDefault(require("../session/index.js"));
|
|
45
45
|
const isPaginatedResult_js_1 = __importDefault(require("./helpers/isPaginatedResult.js"));
|
|
46
|
+
const logIfDevelopment_js_1 = __importDefault(require("./helpers/logIfDevelopment.js"));
|
|
46
47
|
const renderDreamOrViewModel_js_1 = __importDefault(require("./helpers/renderDreamOrViewModel.js"));
|
|
48
|
+
const EnvInternal_js_1 = __importDefault(require("../helpers/EnvInternal.js"));
|
|
47
49
|
exports.PsychicParamsPrimitiveLiterals = [
|
|
48
50
|
'bigint',
|
|
49
51
|
'bigint[]',
|
|
@@ -177,7 +179,9 @@ class PsychicController {
|
|
|
177
179
|
session;
|
|
178
180
|
action;
|
|
179
181
|
renderOpts;
|
|
182
|
+
startTime;
|
|
180
183
|
constructor(req, res, { action, }) {
|
|
184
|
+
this.startTime = Date.now();
|
|
181
185
|
this.req = req;
|
|
182
186
|
this.res = res;
|
|
183
187
|
this.session = new index_js_2.default(req, res);
|
|
@@ -428,7 +432,26 @@ class PsychicController {
|
|
|
428
432
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
429
433
|
data) {
|
|
430
434
|
this.validateOpenapiResponseBody(data);
|
|
431
|
-
this.
|
|
435
|
+
this.expressSendJson(data);
|
|
436
|
+
}
|
|
437
|
+
expressSendJson(
|
|
438
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
439
|
+
data, statusCode = this.res.statusCode) {
|
|
440
|
+
this.res.type('json').status(statusCode).send((0, toJson_js_1.default)(data, index_js_1.default.getOrFail().sanitizeResponseJson));
|
|
441
|
+
this.logIfDevelopment();
|
|
442
|
+
}
|
|
443
|
+
expressSendStatus(statusCode) {
|
|
444
|
+
this.res.sendStatus(statusCode);
|
|
445
|
+
this.logIfDevelopment();
|
|
446
|
+
}
|
|
447
|
+
expressRedirect(statusCode, newLocation) {
|
|
448
|
+
this.res.redirect(statusCode, newLocation);
|
|
449
|
+
this.logIfDevelopment();
|
|
450
|
+
}
|
|
451
|
+
logIfDevelopment() {
|
|
452
|
+
if (!EnvInternal_js_1.default.isDevelopment)
|
|
453
|
+
return;
|
|
454
|
+
(0, logIfDevelopment_js_1.default)({ req: this.req, res: this.res, startTime: this.startTime });
|
|
432
455
|
}
|
|
433
456
|
defaultSerializerPassthrough = {};
|
|
434
457
|
serializerPassthrough(passthrough) {
|
|
@@ -475,15 +498,15 @@ class PsychicController {
|
|
|
475
498
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
476
499
|
nonAuthoritativeInformation(message = undefined) {
|
|
477
500
|
if (message) {
|
|
478
|
-
this.
|
|
501
|
+
this.expressSendJson(message, 203);
|
|
479
502
|
}
|
|
480
503
|
else {
|
|
481
|
-
this.
|
|
504
|
+
this.expressSendStatus(203);
|
|
482
505
|
}
|
|
483
506
|
}
|
|
484
507
|
// 204
|
|
485
508
|
noContent() {
|
|
486
|
-
this.
|
|
509
|
+
this.expressSendStatus(204);
|
|
487
510
|
}
|
|
488
511
|
// 205
|
|
489
512
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -499,27 +522,23 @@ class PsychicController {
|
|
|
499
522
|
}
|
|
500
523
|
// 301
|
|
501
524
|
movedPermanently(newLocation) {
|
|
502
|
-
this.
|
|
525
|
+
this.expressRedirect(301, newLocation);
|
|
503
526
|
}
|
|
504
527
|
// 302
|
|
505
528
|
found(newLocation) {
|
|
506
|
-
this.
|
|
529
|
+
this.expressRedirect(302, newLocation);
|
|
507
530
|
}
|
|
508
531
|
// 303
|
|
509
532
|
seeOther(newLocation) {
|
|
510
|
-
this.
|
|
511
|
-
}
|
|
512
|
-
// 304
|
|
513
|
-
notModified(newLocation) {
|
|
514
|
-
this.res.redirect(304, newLocation);
|
|
533
|
+
this.expressRedirect(303, newLocation);
|
|
515
534
|
}
|
|
516
535
|
// 307
|
|
517
536
|
temporaryRedirect(newLocation) {
|
|
518
|
-
this.
|
|
537
|
+
this.expressRedirect(307, newLocation);
|
|
519
538
|
}
|
|
520
539
|
// 308
|
|
521
540
|
permanentRedirect(newLocation) {
|
|
522
|
-
this.
|
|
541
|
+
this.expressRedirect(308, newLocation);
|
|
523
542
|
}
|
|
524
543
|
// 400
|
|
525
544
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -5,10 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.default = generateResourceControllerSpecContent;
|
|
7
7
|
const dream_1 = require("@rvoh/dream");
|
|
8
|
+
const addImportSuffix_js_1 = __importDefault(require("../../helpers/path/addImportSuffix.js"));
|
|
8
9
|
const relativePsychicPath_js_1 = __importDefault(require("../../helpers/path/relativePsychicPath.js"));
|
|
9
10
|
const updirsFromPath_js_1 = __importDefault(require("../../helpers/path/updirsFromPath.js"));
|
|
10
11
|
const index_js_1 = require("../../index.js");
|
|
11
|
-
const addImportSuffix_js_1 = __importDefault(require("../../helpers/path/addImportSuffix.js"));
|
|
12
12
|
function generateResourceControllerSpecContent({ fullyQualifiedControllerName, route, fullyQualifiedModelName, columnsWithTypes, owningModel, forAdmin, singular, actions, }) {
|
|
13
13
|
fullyQualifiedModelName = (0, dream_1.standardizeFullyQualifiedModelName)(fullyQualifiedModelName);
|
|
14
14
|
const modelClassName = (0, dream_1.globalClassNameFromFullyQualifiedModelName)(fullyQualifiedModelName);
|
|
@@ -21,7 +21,7 @@ function generateResourceControllerSpecContent({ fullyQualifiedControllerName, r
|
|
|
21
21
|
? (0, dream_1.globalClassNameFromFullyQualifiedModelName)(owningModel)
|
|
22
22
|
: userModelName;
|
|
23
23
|
const owningModelVariableName = owningModelName ? (0, dream_1.camelize)(owningModelName) : userVariableName;
|
|
24
|
-
const dreamImports = [
|
|
24
|
+
const dreamImports = [];
|
|
25
25
|
const importStatements = (0, dream_1.compact)([
|
|
26
26
|
importStatementForModel(fullyQualifiedControllerName, fullyQualifiedModelName),
|
|
27
27
|
importStatementForModel(fullyQualifiedControllerName, userModelName),
|
|
@@ -34,7 +34,6 @@ function generateResourceControllerSpecContent({ fullyQualifiedControllerName, r
|
|
|
34
34
|
const attributeCreationKeyValues = [];
|
|
35
35
|
const attributeUpdateKeyValues = [];
|
|
36
36
|
const comparableOriginalAttributeKeyValues = [];
|
|
37
|
-
const comparableUpdatedAttributeKeyValues = [];
|
|
38
37
|
const expectEqualOriginalValue = [];
|
|
39
38
|
const expectEqualUpdatedValue = [];
|
|
40
39
|
const expectEqualOriginalNamedVariable = [];
|
|
@@ -43,89 +42,88 @@ function generateResourceControllerSpecContent({ fullyQualifiedControllerName, r
|
|
|
43
42
|
let dateAttributeIncluded = false;
|
|
44
43
|
let datetimeAttributeIncluded = false;
|
|
45
44
|
for (const attribute of columnsWithTypes) {
|
|
46
|
-
const [rawAttributeName,
|
|
45
|
+
const [rawAttributeName, rawAttributeType, , enumValues] = attribute.split(':');
|
|
47
46
|
if (/(_type|_id)$/.test(rawAttributeName ?? ''))
|
|
48
47
|
continue;
|
|
49
48
|
const attributeName = (0, dream_1.camelize)(rawAttributeName ?? '');
|
|
50
49
|
const dotNotationVariable = `${modelVariableName}.${attributeName}`;
|
|
50
|
+
if (!rawAttributeType)
|
|
51
|
+
continue;
|
|
52
|
+
const arrayBracketRegexp = /\[\]$/;
|
|
53
|
+
const isArray = arrayBracketRegexp.test(rawAttributeType);
|
|
54
|
+
const attributeType = rawAttributeType.replace(arrayBracketRegexp, '');
|
|
51
55
|
if (attributeName === 'deletedAt')
|
|
52
56
|
continue;
|
|
53
57
|
switch (attributeType) {
|
|
54
58
|
case 'enum': {
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
const rawOriginalEnumValue = (enumValues ?? '').split(',').at(0);
|
|
60
|
+
const rawUpdatedEnumValue = (enumValues ?? '').split(',').at(-1);
|
|
61
|
+
const originalEnumValue = isArray ? [rawOriginalEnumValue] : rawOriginalEnumValue;
|
|
62
|
+
const updatedEnumValue = isArray ? [rawUpdatedEnumValue] : rawUpdatedEnumValue;
|
|
63
|
+
attributeCreationKeyValues.push(`${attributeName}: ${jsonify(originalEnumValue)},`);
|
|
64
|
+
attributeUpdateKeyValues.push(`${attributeName}: ${jsonify(updatedEnumValue)},`);
|
|
59
65
|
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable},`);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual('${updatedEnumValue}')`);
|
|
66
|
+
expectEqualOriginalValue.push(`expect(${dotNotationVariable}).toEqual(${jsonify(originalEnumValue)})`);
|
|
67
|
+
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual(${jsonify(updatedEnumValue)})`);
|
|
63
68
|
break;
|
|
64
69
|
}
|
|
65
70
|
case 'string':
|
|
66
71
|
case 'text':
|
|
67
72
|
case 'citext': {
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
const rawOriginalStringValue = `The ${fullyQualifiedModelName} ${attributeName}`;
|
|
74
|
+
const rawUpdatedStringValue = `Updated ${fullyQualifiedModelName} ${attributeName}`;
|
|
75
|
+
const originalStringValue = isArray ? [rawOriginalStringValue] : rawOriginalStringValue;
|
|
76
|
+
const updatedStringValue = isArray ? [rawUpdatedStringValue] : rawUpdatedStringValue;
|
|
77
|
+
attributeCreationKeyValues.push(`${attributeName}: ${jsonify(originalStringValue)},`);
|
|
78
|
+
attributeUpdateKeyValues.push(`${attributeName}: ${jsonify(updatedStringValue)},`);
|
|
72
79
|
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable},`);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual('${updatedStringValue}')`);
|
|
80
|
+
expectEqualOriginalValue.push(`expect(${dotNotationVariable}).toEqual(${jsonify(originalStringValue)})`);
|
|
81
|
+
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual(${jsonify(updatedStringValue)})`);
|
|
76
82
|
break;
|
|
77
83
|
}
|
|
78
84
|
case 'integer':
|
|
79
|
-
attributeCreationKeyValues.push(`${attributeName}: 1,`);
|
|
80
|
-
attributeUpdateKeyValues.push(`${attributeName}: 2,`);
|
|
81
|
-
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable},`);
|
|
82
|
-
comparableUpdatedAttributeKeyValues.push(`${attributeName}: 2,`);
|
|
83
|
-
expectEqualOriginalValue.push(`expect(${dotNotationVariable}).toEqual(1)`);
|
|
84
|
-
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual(2)`);
|
|
85
|
-
break;
|
|
86
|
-
case 'bigint':
|
|
87
|
-
attributeCreationKeyValues.push(`${attributeName}: '11111111111111111',`);
|
|
88
|
-
attributeUpdateKeyValues.push(`${attributeName}: '22222222222222222',`);
|
|
89
|
-
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable},`);
|
|
90
|
-
comparableUpdatedAttributeKeyValues.push(`${attributeName}: '22222222222222222',`);
|
|
91
|
-
expectEqualOriginalValue.push(`expect(${dotNotationVariable}).toEqual('11111111111111111')`);
|
|
92
|
-
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual('22222222222222222')`);
|
|
93
|
-
break;
|
|
94
85
|
case 'decimal':
|
|
95
|
-
|
|
96
|
-
|
|
86
|
+
case 'bigint': {
|
|
87
|
+
const rawOriginalValue = attributeType === 'integer' ? 1 : attributeType === 'decimal' ? 1.1 : '11111111111111111';
|
|
88
|
+
const rawUpdatedValue = attributeType === 'integer' ? 2 : attributeType === 'decimal' ? 2.2 : '22222222222222222';
|
|
89
|
+
const originalValue = isArray ? [rawOriginalValue] : rawOriginalValue;
|
|
90
|
+
const updatedValue = isArray ? [rawUpdatedValue] : rawUpdatedValue;
|
|
91
|
+
attributeCreationKeyValues.push(`${attributeName}: ${jsonify(originalValue)},`);
|
|
92
|
+
attributeUpdateKeyValues.push(`${attributeName}: ${jsonify(updatedValue)},`);
|
|
97
93
|
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable},`);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual(2.2)`);
|
|
94
|
+
expectEqualOriginalValue.push(`expect(${dotNotationVariable}).toEqual(${jsonify(originalValue)})`);
|
|
95
|
+
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqual(${jsonify(updatedValue)})`);
|
|
101
96
|
break;
|
|
102
|
-
|
|
97
|
+
}
|
|
98
|
+
case 'date': {
|
|
103
99
|
dreamImports.push('CalendarDate');
|
|
104
100
|
dateAttributeIncluded = true;
|
|
105
|
-
attributeCreationKeyValues.push(`${attributeName}: today,`);
|
|
106
|
-
attributeUpdateKeyValues.push(`${attributeName}: yesterday,`);
|
|
107
|
-
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable}.toISO(),`);
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqualCalendarDate(yesterday)`);
|
|
101
|
+
attributeCreationKeyValues.push(`${attributeName}: ${isArray ? '[today.toISO()]' : 'today.toISO()'},`);
|
|
102
|
+
attributeUpdateKeyValues.push(`${attributeName}: ${isArray ? '[yesterday.toISO()]' : 'yesterday.toISO()'},`);
|
|
103
|
+
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable}${isArray ? '.map(date => date.toISO())' : '.toISO()'},`);
|
|
104
|
+
expectEqualOriginalValue.push(`expect(${dotNotationVariable}${isArray ? '[0]' : ''}).toEqualCalendarDate(today)`);
|
|
105
|
+
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}${isArray ? '[0]' : ''}).toEqualCalendarDate(yesterday)`);
|
|
111
106
|
break;
|
|
112
|
-
|
|
107
|
+
}
|
|
108
|
+
case 'datetime': {
|
|
113
109
|
dreamImports.push('DateTime');
|
|
114
110
|
datetimeAttributeIncluded = true;
|
|
115
|
-
attributeCreationKeyValues.push(`${attributeName}: now,`);
|
|
116
|
-
attributeUpdateKeyValues.push(`${attributeName}: lastHour,`);
|
|
117
|
-
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable}.toISO(),`);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}).toEqualDateTime(lastHour)`);
|
|
111
|
+
attributeCreationKeyValues.push(`${attributeName}: ${isArray ? '[now.toISO()]' : 'now.toISO()'},`);
|
|
112
|
+
attributeUpdateKeyValues.push(`${attributeName}: ${isArray ? '[lastHour.toISO()]' : 'lastHour.toISO()'},`);
|
|
113
|
+
comparableOriginalAttributeKeyValues.push(`${attributeName}: ${dotNotationVariable}${isArray ? '.map(datetime => datetime.toISO())' : '.toISO()'},`);
|
|
114
|
+
expectEqualOriginalValue.push(`expect(${dotNotationVariable}${isArray ? '[0]' : ''}).toEqualDateTime(now)`);
|
|
115
|
+
expectEqualUpdatedValue.push(`expect(${dotNotationVariable}${isArray ? '[0]' : ''}).toEqualDateTime(lastHour)`);
|
|
121
116
|
break;
|
|
117
|
+
}
|
|
122
118
|
default:
|
|
123
119
|
continue;
|
|
124
120
|
}
|
|
125
121
|
keyWithDotValue.push(`${attributeName}: ${dotNotationVariable},`);
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
122
|
+
if (!((attributeType === 'date' || attributeType === 'datetime') && isArray)) {
|
|
123
|
+
const originalAttributeVariableName = 'original' + (0, dream_1.capitalize)(attributeName);
|
|
124
|
+
originalValueVariableAssignments.push(`const ${originalAttributeVariableName} = ${dotNotationVariable}`);
|
|
125
|
+
expectEqualOriginalNamedVariable.push(`expect(${dotNotationVariable}).toEqual(${originalAttributeVariableName})`);
|
|
126
|
+
}
|
|
129
127
|
}
|
|
130
128
|
const simpleCreationCommand = `const ${modelVariableName} = await create${modelClassName}(${forAdmin ? '' : `{ ${owningModelVariableName} }`})`;
|
|
131
129
|
const omitIndex = singular || !actions.includes('index');
|
|
@@ -134,7 +132,10 @@ function generateResourceControllerSpecContent({ fullyQualifiedControllerName, r
|
|
|
134
132
|
const omitUpdate = !actions.includes('update');
|
|
135
133
|
const omitDestroy = !actions.includes('destroy');
|
|
136
134
|
return `\
|
|
137
|
-
import {
|
|
135
|
+
import { DreamRequestAttributes } from '@rvoh/psychic-spec-helpers'${dreamImports.length
|
|
136
|
+
? `
|
|
137
|
+
import { ${(0, dream_1.uniq)(dreamImports).join(', ')} } from '@rvoh/dream'`
|
|
138
|
+
: ''}${(0, dream_1.uniq)(importStatements).join('')}
|
|
138
139
|
import { session, SpecRequestType } from '${specUnitUpdirs}helpers/${(0, addImportSuffix_js_1.default)('authentication.js')}'
|
|
139
140
|
|
|
140
141
|
describe('${fullyQualifiedControllerName}', () => {
|
|
@@ -219,7 +220,7 @@ describe('${fullyQualifiedControllerName}', () => {
|
|
|
219
220
|
|
|
220
221
|
describe('POST create', () => {
|
|
221
222
|
const subject = async <StatusCode extends 201 | 400>(
|
|
222
|
-
data:
|
|
223
|
+
data: DreamRequestAttributes<${modelClassName}>,
|
|
223
224
|
expectedStatus: StatusCode
|
|
224
225
|
) => {
|
|
225
226
|
return request.post('/${route}', expectedStatus, { data })
|
|
@@ -253,7 +254,7 @@ describe('${fullyQualifiedControllerName}', () => {
|
|
|
253
254
|
describe('PATCH update', () => {${singular
|
|
254
255
|
? `
|
|
255
256
|
const subject = async <StatusCode extends 204 | 400 | 404>(
|
|
256
|
-
data:
|
|
257
|
+
data: DreamRequestAttributes<${modelClassName}>,
|
|
257
258
|
expectedStatus: StatusCode
|
|
258
259
|
) => {
|
|
259
260
|
return request.patch('/${route}', expectedStatus, {
|
|
@@ -263,7 +264,7 @@ describe('${fullyQualifiedControllerName}', () => {
|
|
|
263
264
|
: `
|
|
264
265
|
const subject = async <StatusCode extends 204 | 400 | 404>(
|
|
265
266
|
${modelVariableName}: ${modelClassName},
|
|
266
|
-
data:
|
|
267
|
+
data: DreamRequestAttributes<${modelClassName}>,
|
|
267
268
|
expectedStatus: StatusCode
|
|
268
269
|
) => {
|
|
269
270
|
return request.patch('/${route}/{id}', expectedStatus, {
|
|
@@ -292,7 +293,13 @@ describe('${fullyQualifiedControllerName}', () => {
|
|
|
292
293
|
: `
|
|
293
294
|
|
|
294
295
|
context('a ${fullyQualifiedModelName} created by another ${owningModelName}', () => {
|
|
295
|
-
it('is not updated', async () => {
|
|
296
|
+
it('is not updated', async () => {${dateAttributeIncluded
|
|
297
|
+
? `
|
|
298
|
+
const yesterday = CalendarDate.yesterday()`
|
|
299
|
+
: ''}${datetimeAttributeIncluded
|
|
300
|
+
? `
|
|
301
|
+
const lastHour = DateTime.now().minus({ hour: 1 })`
|
|
302
|
+
: ''}${dateAttributeIncluded || datetimeAttributeIncluded ? '\n' : ''}
|
|
296
303
|
const ${modelVariableName} = await create${modelClassName}()
|
|
297
304
|
${originalValueVariableAssignments.length ? originalValueVariableAssignments.join('\n ') : ''}
|
|
298
305
|
|
|
@@ -349,3 +356,7 @@ function importStatementForModel(originModelName, destinationModelName = originM
|
|
|
349
356
|
function importStatementForModelFactory(originModelName, destinationModelName = originModelName) {
|
|
350
357
|
return `\nimport create${(0, dream_1.globalClassNameFromFullyQualifiedModelName)(destinationModelName)} from '${(0, relativePsychicPath_js_1.default)('controllerSpecs', 'factories', originModelName, destinationModelName)}'`;
|
|
351
358
|
}
|
|
359
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
360
|
+
function jsonify(val) {
|
|
361
|
+
return JSON.stringify(val).replace(/"/g, "'");
|
|
362
|
+
}
|
|
@@ -17,6 +17,8 @@ async function generateResource({ route, fullyQualifiedModelName, options, colum
|
|
|
17
17
|
// which will exhibit bad behavior when provided with
|
|
18
18
|
// a prefixing slash.
|
|
19
19
|
route = route.replace(/^\/+/, '');
|
|
20
|
+
if (!options.singular)
|
|
21
|
+
route = (0, pluralize_esm_1.default)(route);
|
|
20
22
|
const fullyQualifiedControllerName = (0, dream_1.standardizeFullyQualifiedModelName)(route);
|
|
21
23
|
const resourcefulActions = options.singular ? [...exports.SINGULAR_RESOURCE_ACTIONS] : [...exports.RESOURCE_ACTIONS];
|
|
22
24
|
const onlyActions = options.only?.split(',');
|
|
@@ -31,7 +33,6 @@ async function generateResource({ route, fullyQualifiedModelName, options, colum
|
|
|
31
33
|
connectionName: options.connectionName,
|
|
32
34
|
},
|
|
33
35
|
});
|
|
34
|
-
route = (0, pluralize_esm_1.default)(route);
|
|
35
36
|
await (0, controller_js_1.default)({
|
|
36
37
|
fullyQualifiedControllerName,
|
|
37
38
|
fullyQualifiedModelName,
|
|
@@ -72,11 +72,7 @@ class SerializerOpenapiRenderer {
|
|
|
72
72
|
const requiredProperties = (0, dream_1.compact)(this.serializerBuilder['attributes'].map(attribute => {
|
|
73
73
|
const attributeType = attribute.type;
|
|
74
74
|
switch (attributeType) {
|
|
75
|
-
case 'attribute':
|
|
76
|
-
if (attribute.options?.required === false)
|
|
77
|
-
return null;
|
|
78
|
-
return attribute.options?.as ?? attribute.name;
|
|
79
|
-
}
|
|
75
|
+
case 'attribute':
|
|
80
76
|
case 'delegatedAttribute': {
|
|
81
77
|
if (attribute.options?.required === false)
|
|
82
78
|
return null;
|
|
@@ -119,23 +115,6 @@ class SerializerOpenapiRenderer {
|
|
|
119
115
|
let newlyReferencedSerializers = [];
|
|
120
116
|
accumulator = (() => {
|
|
121
117
|
switch (attributeType) {
|
|
122
|
-
////////////////
|
|
123
|
-
// attributes //
|
|
124
|
-
////////////////
|
|
125
|
-
case 'attribute': {
|
|
126
|
-
const outputAttributeName = this.setCase(attribute.options?.as ?? attribute.name);
|
|
127
|
-
const openapi = attribute.options.openapi;
|
|
128
|
-
newlyReferencedSerializers = (0, allSerializersFromHandWrittenOpenapi_js_1.default)(openapi);
|
|
129
|
-
accumulator[outputAttributeName] = DataTypeForOpenapi?.isDream
|
|
130
|
-
? (0, dreamAttributeOpenapiShape_js_1.dreamColumnOpenapiShape)(DataTypeForOpenapi, attribute.name, openapi, {
|
|
131
|
-
suppressResponseEnums: this.suppressResponseEnums,
|
|
132
|
-
})
|
|
133
|
-
: (0, allSerializersToRefsInOpenapi_js_1.default)((0, openapiShorthandToOpenapi_js_1.default)(openapi));
|
|
134
|
-
return accumulator;
|
|
135
|
-
}
|
|
136
|
-
/////////////////////
|
|
137
|
-
// end: attributes //
|
|
138
|
-
/////////////////////
|
|
139
118
|
///////////////////////
|
|
140
119
|
// custom attributes //
|
|
141
120
|
///////////////////////
|
|
@@ -154,19 +133,39 @@ class SerializerOpenapiRenderer {
|
|
|
154
133
|
////////////////////////////
|
|
155
134
|
// end: custom attributes //
|
|
156
135
|
////////////////////////////
|
|
157
|
-
|
|
158
|
-
// delegated attributes //
|
|
159
|
-
|
|
136
|
+
//////////////////////////////////////////
|
|
137
|
+
// attributes and delegated attributes //
|
|
138
|
+
//////////////////////////////////////////
|
|
139
|
+
case 'attribute':
|
|
160
140
|
case 'delegatedAttribute': {
|
|
161
141
|
const outputAttributeName = this.setCase(attribute.options?.as ?? attribute.name);
|
|
162
142
|
const openapi = attribute.options.openapi;
|
|
163
143
|
newlyReferencedSerializers = (0, allSerializersFromHandWrittenOpenapi_js_1.default)(openapi);
|
|
164
|
-
|
|
144
|
+
let target;
|
|
145
|
+
if (attributeType === 'delegatedAttribute' && DataTypeForOpenapi?.isDream) {
|
|
146
|
+
const source = DataTypeForOpenapi;
|
|
147
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
148
|
+
const associatedModelOrModels = source['getAssociationMetadata'](attribute.targetName)?.modelCB();
|
|
149
|
+
target = Array.isArray(associatedModelOrModels)
|
|
150
|
+
? associatedModelOrModels[0]
|
|
151
|
+
: associatedModelOrModels;
|
|
152
|
+
}
|
|
153
|
+
else if (attributeType === 'delegatedAttribute') {
|
|
154
|
+
target = undefined;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
target = DataTypeForOpenapi;
|
|
158
|
+
}
|
|
159
|
+
accumulator[outputAttributeName] = (0, allSerializersToRefsInOpenapi_js_1.default)(target?.isDream
|
|
160
|
+
? (0, dreamAttributeOpenapiShape_js_1.dreamColumnOpenapiShape)(target, attribute.name, openapi, {
|
|
161
|
+
suppressResponseEnums: this.suppressResponseEnums,
|
|
162
|
+
})
|
|
163
|
+
: (0, openapiShorthandToOpenapi_js_1.default)(openapi));
|
|
165
164
|
return accumulator;
|
|
166
165
|
}
|
|
167
|
-
|
|
168
|
-
// end: delegated attributes //
|
|
169
|
-
|
|
166
|
+
/////////////////////////////////////////////
|
|
167
|
+
// end:attributes and delegated attributes //
|
|
168
|
+
/////////////////////////////////////////////
|
|
170
169
|
//////////////////
|
|
171
170
|
// rendersOnes //
|
|
172
171
|
//////////////////
|
|
@@ -474,6 +474,8 @@ class OpenapiEndpointRenderer {
|
|
|
474
474
|
return true;
|
|
475
475
|
if (body.including)
|
|
476
476
|
return true;
|
|
477
|
+
if (body.combining)
|
|
478
|
+
return true;
|
|
477
479
|
if (body.for)
|
|
478
480
|
return true;
|
|
479
481
|
if (body.required && body.type !== 'object')
|
|
@@ -494,12 +496,16 @@ class OpenapiEndpointRenderer {
|
|
|
494
496
|
const dreamClass = forDreamClass || this.getSingleDreamModelClass();
|
|
495
497
|
if (!dreamClass)
|
|
496
498
|
return this.defaultRequestBody();
|
|
497
|
-
const { only, including } = (this.requestBody || {});
|
|
499
|
+
const { only, including, combining } = (this.requestBody || {});
|
|
498
500
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
499
501
|
const paramSafeColumns = (0, paramNamesForDreamClass_js_1.default)(dreamClass, { only, including });
|
|
500
502
|
const paramsShape = {
|
|
501
503
|
type: 'object',
|
|
502
|
-
|
|
504
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
505
|
+
properties: {
|
|
506
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
507
|
+
...(combining || {}),
|
|
508
|
+
},
|
|
503
509
|
};
|
|
504
510
|
const required = this.requestBody?.required;
|
|
505
511
|
if (required) {
|