@jskit-ai/kernel 0.1.55 → 0.1.56
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 +3 -2
- package/server/actions/ActionRuntimeServiceProvider.test.js +23 -15
- package/server/http/lib/kernel.test.js +447 -0
- package/server/http/lib/routeRegistration.js +236 -15
- package/server/http/lib/routeTransport.js +126 -0
- package/server/http/lib/routeValidator.js +133 -198
- package/server/http/lib/routeValidator.test.js +385 -278
- package/server/http/lib/router.js +17 -2
- package/server/platform/providerRuntime.test.js +7 -7
- package/server/runtime/bootBootstrapRoutes.js +2 -18
- package/server/runtime/bootBootstrapRoutes.test.js +5 -14
- package/server/runtime/fastifyBootstrap.js +119 -0
- package/server/runtime/fastifyBootstrap.test.js +119 -1
- package/server/runtime/moduleConfig.js +32 -62
- package/server/runtime/moduleConfig.test.js +48 -24
- package/server/support/pageTargets.js +15 -9
- package/server/support/pageTargets.test.js +1 -1
- package/shared/actions/actionContributorHelpers.js +5 -11
- package/shared/actions/actionDefinitions.js +37 -150
- package/shared/actions/actionDefinitions.test.js +117 -136
- package/shared/actions/policies.js +25 -169
- package/shared/actions/policies.test.js +76 -87
- package/shared/actions/registry.test.js +24 -50
- package/shared/support/crudFieldContract.js +322 -0
- package/shared/support/crudFieldContract.test.js +67 -0
- package/shared/support/crudListFilters.js +582 -38
- package/shared/support/crudListFilters.test.js +178 -8
- package/shared/support/crudLookup.js +14 -7
- package/shared/support/crudLookup.test.js +91 -66
- package/shared/support/shellLayoutTargets.test.js +1 -1
- package/shared/validators/composeSchemaDefinitions.js +53 -0
- package/shared/validators/composeSchemaDefinitions.test.js +156 -0
- package/shared/validators/createCursorListValidator.js +22 -35
- package/shared/validators/createCursorListValidator.test.js +22 -23
- package/shared/validators/cursorPaginationQueryValidator.js +14 -24
- package/shared/validators/cursorPaginationQueryValidator.test.js +18 -8
- package/shared/validators/htmlTimeSchemas.js +6 -4
- package/shared/validators/index.js +15 -7
- package/shared/validators/jsonRestSchemaSupport.js +139 -0
- package/shared/validators/mergeObjectSchemas.js +44 -6
- package/shared/validators/mergeObjectSchemas.test.js +60 -35
- package/shared/validators/recordIdParamsValidator.js +19 -52
- package/shared/validators/recordIdParamsValidator.test.js +13 -8
- package/shared/validators/resourceRequiredMetadata.js +3 -3
- package/shared/validators/resourceRequiredMetadata.test.js +29 -16
- package/shared/validators/schemaDefinitions.js +126 -0
- package/shared/validators/schemaDefinitions.test.js +51 -0
- package/shared/validators/schemaPayloadValidation.js +65 -0
- package/test/barrelExposure.test.js +30 -0
- package/test/routeInputContractGuard.test.js +10 -6
- package/shared/validators/mergeValidators.js +0 -89
- package/shared/validators/mergeValidators.test.js +0 -116
- package/shared/validators/nestValidator.js +0 -53
- package/shared/validators/nestValidator.test.js +0 -60
- package/shared/validators/settingsFieldNormalization.js +0 -40
|
@@ -1,122 +1,114 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
|
-
import {
|
|
3
|
+
import { createSchema } from "json-rest-schema";
|
|
4
4
|
|
|
5
5
|
import { __testables, normalizeActionDefinition } from "./actionDefinitions.js";
|
|
6
6
|
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
{ additionalProperties: false }
|
|
14
|
-
),
|
|
15
|
-
normalize(input = {}) {
|
|
16
|
-
const source = input && typeof input === "object" ? input : {};
|
|
17
|
-
if (!Object.hasOwn(source, "workspaceSlug")) {
|
|
18
|
-
return {};
|
|
19
|
-
}
|
|
7
|
+
function assertJsonRestSchemaDefinition(definition) {
|
|
8
|
+
assert.equal(typeof definition?.schema?.patch, "function");
|
|
9
|
+
assert.equal(typeof definition?.schema?.replace, "function");
|
|
10
|
+
assert.equal(typeof definition?.schema?.toJsonSchema, "function");
|
|
11
|
+
}
|
|
20
12
|
|
|
13
|
+
function createMockJsonRestSchema() {
|
|
14
|
+
return {
|
|
15
|
+
create(payload = {}) {
|
|
16
|
+
return {
|
|
17
|
+
validatedObject: payload,
|
|
18
|
+
errors: {}
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
replace(payload = {}) {
|
|
22
|
+
return this.create(payload);
|
|
23
|
+
},
|
|
24
|
+
patch(payload = {}) {
|
|
25
|
+
return this.create(payload);
|
|
26
|
+
},
|
|
27
|
+
toJsonSchema() {
|
|
21
28
|
return {
|
|
22
|
-
|
|
29
|
+
type: "object"
|
|
23
30
|
};
|
|
24
31
|
}
|
|
25
32
|
};
|
|
26
33
|
}
|
|
27
34
|
|
|
28
|
-
function
|
|
35
|
+
function createWorkspaceSlugSchema() {
|
|
29
36
|
return {
|
|
30
|
-
schema:
|
|
31
|
-
{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
{ additionalProperties: false }
|
|
35
|
-
),
|
|
36
|
-
normalize(input = {}) {
|
|
37
|
-
const source = input && typeof input === "object" ? input : {};
|
|
38
|
-
if (!Object.hasOwn(source, "name")) {
|
|
39
|
-
return {};
|
|
37
|
+
schema: createSchema({
|
|
38
|
+
workspaceSlug: {
|
|
39
|
+
type: "string",
|
|
40
|
+
minLength: 1
|
|
40
41
|
}
|
|
42
|
+
}),
|
|
43
|
+
mode: "patch"
|
|
44
|
+
};
|
|
45
|
+
}
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
function createPatchSchema() {
|
|
48
|
+
return {
|
|
49
|
+
schema: createSchema({
|
|
50
|
+
name: {
|
|
51
|
+
type: "string",
|
|
52
|
+
minLength: 1
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
mode: "patch"
|
|
46
56
|
};
|
|
47
57
|
}
|
|
48
58
|
|
|
49
|
-
test("
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
},
|
|
54
|
-
"inputValidator",
|
|
59
|
+
test("normalizeActionInputDefinition accepts a single schema definition", () => {
|
|
60
|
+
const definition = __testables.normalizeActionInputDefinition(
|
|
61
|
+
createPatchSchema(),
|
|
62
|
+
"input",
|
|
55
63
|
{ required: true }
|
|
56
64
|
);
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
assert.equal(validator?.schema?.type, "object");
|
|
60
|
-
assert.ok(Object.hasOwn(validator.schema?.properties || {}, "payload"));
|
|
61
|
-
|
|
62
|
-
const normalized = await validator.normalize({
|
|
63
|
-
payload: {
|
|
64
|
-
name: " Acme "
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
assert.deepEqual(normalized, {
|
|
69
|
-
payload: {
|
|
70
|
-
name: "acme"
|
|
71
|
-
}
|
|
72
|
-
});
|
|
66
|
+
assertJsonRestSchemaDefinition(definition);
|
|
73
67
|
});
|
|
74
68
|
|
|
75
|
-
test("
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
69
|
+
test("normalizeActionInputDefinition rejects section-map syntax", () => {
|
|
70
|
+
assert.throws(
|
|
71
|
+
() =>
|
|
72
|
+
__testables.normalizeActionInputDefinition(
|
|
73
|
+
{
|
|
74
|
+
payload: createPatchSchema()
|
|
75
|
+
},
|
|
76
|
+
"input",
|
|
77
|
+
{ required: true }
|
|
78
|
+
),
|
|
79
|
+
/Action definition input must be a schema definition object/
|
|
85
80
|
);
|
|
86
|
-
|
|
87
|
-
const properties = Object.keys(validator.schema?.properties || {}).sort();
|
|
88
|
-
assert.deepEqual(properties, ["patch", "workspaceSlug"]);
|
|
89
|
-
|
|
90
|
-
const normalized = await validator.normalize({
|
|
91
|
-
workspaceSlug: " TEAM-ALPHA ",
|
|
92
|
-
patch: {
|
|
93
|
-
name: " Project X "
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
assert.deepEqual(normalized, {
|
|
98
|
-
workspaceSlug: "team-alpha",
|
|
99
|
-
patch: {
|
|
100
|
-
name: "project x"
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
81
|
});
|
|
104
82
|
|
|
105
|
-
test("
|
|
83
|
+
test("normalizeActionInputDefinition rejects bare schema instances", () => {
|
|
106
84
|
assert.throws(
|
|
107
85
|
() =>
|
|
108
|
-
__testables.
|
|
109
|
-
{
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
86
|
+
__testables.normalizeActionInputDefinition(
|
|
87
|
+
createSchema({
|
|
88
|
+
name: {
|
|
89
|
+
type: "string",
|
|
90
|
+
minLength: 1
|
|
114
91
|
}
|
|
115
|
-
},
|
|
116
|
-
"
|
|
92
|
+
}),
|
|
93
|
+
"input",
|
|
94
|
+
{ required: true }
|
|
95
|
+
),
|
|
96
|
+
/Action definition input must be a schema definition object/
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("normalizeActionInputDefinition rejects validator arrays", () => {
|
|
101
|
+
assert.throws(
|
|
102
|
+
() =>
|
|
103
|
+
__testables.normalizeActionInputDefinition(
|
|
104
|
+
[
|
|
105
|
+
createWorkspaceSlugSchema(),
|
|
106
|
+
createPatchSchema()
|
|
107
|
+
],
|
|
108
|
+
"input",
|
|
117
109
|
{ required: true }
|
|
118
110
|
),
|
|
119
|
-
/
|
|
111
|
+
/input must be a single schema definition/
|
|
120
112
|
);
|
|
121
113
|
});
|
|
122
114
|
|
|
@@ -131,7 +123,7 @@ test("normalizeActionExtensions keeps plain objects", () => {
|
|
|
131
123
|
assert.equal(extensions.assistant?.description, "Update workspace settings.");
|
|
132
124
|
});
|
|
133
125
|
|
|
134
|
-
test("normalizeActionDefinition stays channel-agnostic and ignores unknown
|
|
126
|
+
test("normalizeActionDefinition stays channel-agnostic and ignores unknown extra fields", () => {
|
|
135
127
|
const definition = normalizeActionDefinition({
|
|
136
128
|
id: "demo.workspace.settings.update",
|
|
137
129
|
domain: "demo",
|
|
@@ -139,11 +131,11 @@ test("normalizeActionDefinition stays channel-agnostic and ignores unknown legac
|
|
|
139
131
|
kind: "command",
|
|
140
132
|
channels: ["automation"],
|
|
141
133
|
surfaces: ["admin"],
|
|
142
|
-
|
|
143
|
-
schema:
|
|
134
|
+
input: {
|
|
135
|
+
schema: createSchema({})
|
|
144
136
|
},
|
|
145
|
-
|
|
146
|
-
schema:
|
|
137
|
+
output: {
|
|
138
|
+
schema: createSchema({})
|
|
147
139
|
},
|
|
148
140
|
idempotency: "none",
|
|
149
141
|
assistantTool: {
|
|
@@ -156,57 +148,46 @@ test("normalizeActionDefinition stays channel-agnostic and ignores unknown legac
|
|
|
156
148
|
assert.equal(Object.prototype.hasOwnProperty.call(definition, "assistantTool"), false);
|
|
157
149
|
});
|
|
158
150
|
|
|
159
|
-
test("
|
|
160
|
-
const
|
|
151
|
+
test("normalizeActionOutputDefinition accepts single schema definitions", () => {
|
|
152
|
+
const output = __testables.normalizeActionOutputDefinition(
|
|
161
153
|
{
|
|
162
|
-
|
|
154
|
+
schema: createSchema({
|
|
155
|
+
ok: {
|
|
156
|
+
type: "boolean",
|
|
157
|
+
required: true
|
|
158
|
+
}
|
|
159
|
+
})
|
|
163
160
|
},
|
|
164
|
-
"
|
|
161
|
+
"output",
|
|
165
162
|
{ required: false }
|
|
166
163
|
);
|
|
167
164
|
|
|
168
|
-
|
|
169
|
-
assert.ok(Object.hasOwn(outputValidator?.schema?.properties || {}, "payload"));
|
|
170
|
-
|
|
171
|
-
const normalized = await outputValidator.normalize({
|
|
172
|
-
payload: {
|
|
173
|
-
name: " Acme "
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
assert.deepEqual(normalized, {
|
|
178
|
-
payload: {
|
|
179
|
-
name: "acme"
|
|
180
|
-
}
|
|
181
|
-
});
|
|
165
|
+
assertJsonRestSchemaDefinition(output);
|
|
182
166
|
});
|
|
183
167
|
|
|
184
|
-
test("
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
168
|
+
test("normalizeActionOutputDefinition rejects section-map syntax", () => {
|
|
169
|
+
assert.throws(
|
|
170
|
+
() =>
|
|
171
|
+
__testables.normalizeActionOutputDefinition(
|
|
172
|
+
{
|
|
173
|
+
payload: createPatchSchema()
|
|
174
|
+
},
|
|
175
|
+
"output",
|
|
176
|
+
{ required: false }
|
|
177
|
+
),
|
|
178
|
+
/Action definition output must be a schema definition object/
|
|
194
179
|
);
|
|
180
|
+
});
|
|
195
181
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
182
|
+
test("normalizeActionInputDefinition preserves mode for json-rest-schema definitions", () => {
|
|
183
|
+
const definition = __testables.normalizeActionInputDefinition(
|
|
184
|
+
{
|
|
185
|
+
schema: createMockJsonRestSchema(),
|
|
186
|
+
mode: "patch"
|
|
187
|
+
},
|
|
188
|
+
"input",
|
|
189
|
+
{ required: true }
|
|
190
|
+
);
|
|
205
191
|
|
|
206
|
-
assert.
|
|
207
|
-
workspaceSlug: "team-alpha",
|
|
208
|
-
payload: {
|
|
209
|
-
name: "project x"
|
|
210
|
-
}
|
|
211
|
-
});
|
|
192
|
+
assert.equal(definition.mode, "patch");
|
|
212
193
|
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { Check, Errors } from "typebox/value";
|
|
2
1
|
import { createActionRuntimeError } from "./actionDefinitions.js";
|
|
3
2
|
import { normalizeLowerText, normalizeText } from "./textNormalization.js";
|
|
4
3
|
import { hasPermission, normalizePermissionList } from "../support/permissions.js";
|
|
5
4
|
import { isRecord, normalizeOpaqueId } from "../support/normalize.js";
|
|
5
|
+
import {
|
|
6
|
+
validateSchemaPayload
|
|
7
|
+
} from "../validators/schemaPayloadValidation.js";
|
|
6
8
|
|
|
7
9
|
function createActionValidationError({
|
|
8
10
|
status = 400,
|
|
@@ -106,170 +108,22 @@ function ensureActionPermissionAllowed(definition, context) {
|
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
function normalizeSchemaValidationErrors(schema) {
|
|
110
|
-
const errors = Array.isArray(schema?.errors) ? schema.errors : [];
|
|
111
|
-
if (errors.length < 1) {
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const fieldErrors = {};
|
|
116
|
-
for (const entry of errors) {
|
|
117
|
-
const rawFieldPath = normalizeText(entry?.path || entry?.instancePath || entry?.field || "");
|
|
118
|
-
const fieldPath = rawFieldPath
|
|
119
|
-
? rawFieldPath.replace(/^\//, "").replace(/\//g, ".")
|
|
120
|
-
: "input";
|
|
121
|
-
const message = normalizeText(entry?.message || "Invalid value.") || "Invalid value.";
|
|
122
|
-
fieldErrors[fieldPath] = message;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return Object.keys(fieldErrors).length > 0 ? fieldErrors : null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function buildSchemaValidatorError({ phase, definition } = {}) {
|
|
129
|
-
return createActionValidationError({
|
|
130
|
-
details: {
|
|
131
|
-
error: "Schema validator must return { ok, value, errors } or throw.",
|
|
132
|
-
phase,
|
|
133
|
-
actionId: definition?.id,
|
|
134
|
-
version: definition?.version
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function normalizeTypeBoxValidationErrors(schema, payload) {
|
|
140
|
-
const issues = Check(schema, payload) ? [] : [...Errors(schema, payload)];
|
|
141
|
-
if (issues.length < 1) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return normalizeSchemaValidationErrors({
|
|
146
|
-
errors: issues
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function normalizeFunctionSchemaResult(result, payload, { phase, definition } = {}) {
|
|
151
|
-
if (!isRecord(result) || typeof result.ok !== "boolean") {
|
|
152
|
-
throw buildSchemaValidatorError({ phase, definition });
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (result.ok) {
|
|
156
|
-
if (Object.hasOwn(result, "value")) {
|
|
157
|
-
return result.value;
|
|
158
|
-
}
|
|
159
|
-
return payload;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const details = {};
|
|
163
|
-
if (Object.hasOwn(result, "errors")) {
|
|
164
|
-
if (Array.isArray(result.errors)) {
|
|
165
|
-
const fieldErrors = normalizeSchemaValidationErrors({ errors: result.errors });
|
|
166
|
-
if (fieldErrors) {
|
|
167
|
-
details.fieldErrors = fieldErrors;
|
|
168
|
-
} else {
|
|
169
|
-
details.errors = result.errors;
|
|
170
|
-
}
|
|
171
|
-
} else if (result.errors && typeof result.errors === "object") {
|
|
172
|
-
details.fieldErrors = result.errors;
|
|
173
|
-
} else if (result.errors != null) {
|
|
174
|
-
details.error = String(result.errors);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
throw createActionValidationError({
|
|
179
|
-
details: Object.keys(details).length > 0 ? details : undefined
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async function normalizeValidatorPayload(validator, payload, { phase, definition, context }) {
|
|
184
|
-
if (!validator || typeof validator !== "object") {
|
|
185
|
-
return payload;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (typeof validator.normalize !== "function") {
|
|
189
|
-
return payload;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return await validator.normalize(payload, {
|
|
193
|
-
phase,
|
|
194
|
-
actionId: definition?.id,
|
|
195
|
-
version: definition?.version,
|
|
196
|
-
context
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
async function validateSchemaPayload(schema, payload, { phase, definition }) {
|
|
201
|
-
if (schema == null) {
|
|
202
|
-
return payload;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (typeof schema === "function") {
|
|
206
|
-
const result = await schema(payload, {
|
|
207
|
-
phase,
|
|
208
|
-
actionId: definition?.id,
|
|
209
|
-
version: definition?.version
|
|
210
|
-
});
|
|
211
|
-
return normalizeFunctionSchemaResult(result, payload, { phase, definition });
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (!isRecord(schema)) {
|
|
215
|
-
throw buildSchemaValidatorError({ phase, definition });
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (typeof schema.parse === "function") {
|
|
219
|
-
return schema.parse(payload);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (typeof schema.assert === "function") {
|
|
223
|
-
const assertionResult = await schema.assert(payload);
|
|
224
|
-
return assertionResult == null ? payload : assertionResult;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (typeof schema.check === "function") {
|
|
228
|
-
const valid = await schema.check(payload);
|
|
229
|
-
if (!valid) {
|
|
230
|
-
throw createActionValidationError();
|
|
231
|
-
}
|
|
232
|
-
return payload;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (typeof schema.validate === "function") {
|
|
236
|
-
const valid = await schema.validate(payload);
|
|
237
|
-
if (!valid) {
|
|
238
|
-
throw createActionValidationError({
|
|
239
|
-
details: {
|
|
240
|
-
fieldErrors: normalizeSchemaValidationErrors(schema)
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
return payload;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const fieldErrors = normalizeTypeBoxValidationErrors(schema, payload);
|
|
248
|
-
if (!fieldErrors) {
|
|
249
|
-
return payload;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
throw createActionValidationError({
|
|
253
|
-
details: {
|
|
254
|
-
fieldErrors
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
|
|
259
111
|
async function normalizeActionInput(definition, input, context) {
|
|
260
112
|
try {
|
|
261
|
-
|
|
262
|
-
phase: "input",
|
|
263
|
-
definition,
|
|
264
|
-
context
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
return await validateSchemaPayload(definition?.inputValidator?.schema, normalizedInput, {
|
|
113
|
+
return validateSchemaPayload(definition?.input, input, {
|
|
268
114
|
phase: "input",
|
|
269
115
|
definition,
|
|
270
116
|
context
|
|
271
117
|
});
|
|
272
118
|
} catch (error) {
|
|
119
|
+
if (isRecord(error?.fieldErrors) || isRecord(error?.details?.fieldErrors)) {
|
|
120
|
+
throw createActionValidationError({
|
|
121
|
+
details: {
|
|
122
|
+
fieldErrors: error.fieldErrors || error.details?.fieldErrors
|
|
123
|
+
},
|
|
124
|
+
cause: error
|
|
125
|
+
});
|
|
126
|
+
}
|
|
273
127
|
if (error?.code === "ACTION_VALIDATION_FAILED") {
|
|
274
128
|
throw error;
|
|
275
129
|
}
|
|
@@ -284,23 +138,28 @@ async function normalizeActionInput(definition, input, context) {
|
|
|
284
138
|
}
|
|
285
139
|
|
|
286
140
|
async function normalizeActionOutput(definition, output, context) {
|
|
287
|
-
if (!definition?.
|
|
141
|
+
if (!definition?.output) {
|
|
288
142
|
return output;
|
|
289
143
|
}
|
|
290
144
|
|
|
291
145
|
try {
|
|
292
|
-
|
|
293
|
-
phase: "output",
|
|
294
|
-
definition,
|
|
295
|
-
context
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
return await validateSchemaPayload(definition.outputValidator.schema, normalizedOutput, {
|
|
146
|
+
return validateSchemaPayload(definition.output, output, {
|
|
299
147
|
phase: "output",
|
|
300
148
|
definition,
|
|
301
149
|
context
|
|
302
150
|
});
|
|
303
151
|
} catch (error) {
|
|
152
|
+
if (isRecord(error?.fieldErrors) || isRecord(error?.details?.fieldErrors)) {
|
|
153
|
+
throw createActionValidationError({
|
|
154
|
+
status: 500,
|
|
155
|
+
message: "Action output validation failed.",
|
|
156
|
+
code: "ACTION_OUTPUT_VALIDATION_FAILED",
|
|
157
|
+
details: {
|
|
158
|
+
fieldErrors: error.fieldErrors || error.details?.fieldErrors
|
|
159
|
+
},
|
|
160
|
+
cause: error
|
|
161
|
+
});
|
|
162
|
+
}
|
|
304
163
|
if (error?.code === "ACTION_VALIDATION_FAILED") {
|
|
305
164
|
throw createActionValidationError({
|
|
306
165
|
status: 500,
|
|
@@ -326,9 +185,6 @@ async function normalizeActionOutput(definition, output, context) {
|
|
|
326
185
|
const __testables = {
|
|
327
186
|
normalizeText,
|
|
328
187
|
normalizeLowerText,
|
|
329
|
-
normalizeSchemaValidationErrors,
|
|
330
|
-
normalizeTypeBoxValidationErrors,
|
|
331
|
-
normalizeValidatorPayload,
|
|
332
188
|
validateSchemaPayload
|
|
333
189
|
};
|
|
334
190
|
|