@jskit-ai/kernel 0.1.54 → 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,22 +1,38 @@
|
|
|
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 { ModuleConfigError, defineModuleConfig } from "./moduleConfig.js";
|
|
6
6
|
|
|
7
7
|
test("defineModuleConfig resolves valid config and freezes nested objects", () => {
|
|
8
8
|
const moduleConfig = defineModuleConfig({
|
|
9
9
|
moduleId: "contacts",
|
|
10
|
-
schema:
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
inviteExpiryHours: Type.Integer({ minimum: 1, maximum: 168 })
|
|
16
|
-
})
|
|
10
|
+
schema: createSchema({
|
|
11
|
+
mode: {
|
|
12
|
+
type: "string",
|
|
13
|
+
required: true,
|
|
14
|
+
enum: ["standard", "strict"]
|
|
17
15
|
},
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
maxContacts: {
|
|
17
|
+
type: "integer",
|
|
18
|
+
required: true,
|
|
19
|
+
min: 1
|
|
20
|
+
},
|
|
21
|
+
limits: {
|
|
22
|
+
type: "object",
|
|
23
|
+
required: true,
|
|
24
|
+
validator(value) {
|
|
25
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
26
|
+
return "limits must be an object";
|
|
27
|
+
}
|
|
28
|
+
const inviteExpiryHours = Number(value.inviteExpiryHours);
|
|
29
|
+
if (!Number.isInteger(inviteExpiryHours) || inviteExpiryHours < 1 || inviteExpiryHours > 168) {
|
|
30
|
+
return "inviteExpiryHours must be an integer between 1 and 168";
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}),
|
|
20
36
|
load({ env }) {
|
|
21
37
|
return {
|
|
22
38
|
mode: String(env.CONTACTS_MODE || "standard"),
|
|
@@ -46,12 +62,13 @@ test("defineModuleConfig resolves valid config and freezes nested objects", () =
|
|
|
46
62
|
test("defineModuleConfig reports schema validation issues with module-scoped details", () => {
|
|
47
63
|
const moduleConfig = defineModuleConfig({
|
|
48
64
|
moduleId: "contacts",
|
|
49
|
-
schema:
|
|
50
|
-
{
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
schema: createSchema({
|
|
66
|
+
maxContacts: {
|
|
67
|
+
type: "integer",
|
|
68
|
+
required: true,
|
|
69
|
+
min: 1
|
|
70
|
+
}
|
|
71
|
+
})
|
|
55
72
|
});
|
|
56
73
|
|
|
57
74
|
assert.throws(
|
|
@@ -66,13 +83,13 @@ test("defineModuleConfig reports schema validation issues with module-scoped det
|
|
|
66
83
|
);
|
|
67
84
|
});
|
|
68
85
|
|
|
69
|
-
test("defineModuleConfig supports coercion via
|
|
86
|
+
test("defineModuleConfig supports coercion via json-rest-schema casts", () => {
|
|
70
87
|
const moduleConfig = defineModuleConfig({
|
|
71
88
|
moduleId: "contacts",
|
|
72
89
|
coerce: true,
|
|
73
|
-
schema:
|
|
74
|
-
maxContacts:
|
|
75
|
-
enabled:
|
|
90
|
+
schema: createSchema({
|
|
91
|
+
maxContacts: { type: "integer", required: true, min: 1 },
|
|
92
|
+
enabled: { type: "boolean", required: true }
|
|
76
93
|
})
|
|
77
94
|
});
|
|
78
95
|
|
|
@@ -90,9 +107,16 @@ test("defineModuleConfig supports coercion via TypeBox Parse", () => {
|
|
|
90
107
|
test("defineModuleConfig supports custom cross-field validate hook", () => {
|
|
91
108
|
const moduleConfig = defineModuleConfig({
|
|
92
109
|
moduleId: "contacts",
|
|
93
|
-
schema:
|
|
94
|
-
mode:
|
|
95
|
-
|
|
110
|
+
schema: createSchema({
|
|
111
|
+
mode: {
|
|
112
|
+
type: "string",
|
|
113
|
+
required: true,
|
|
114
|
+
enum: ["standard", "strict"]
|
|
115
|
+
},
|
|
116
|
+
requireAuditTrail: {
|
|
117
|
+
type: "boolean",
|
|
118
|
+
required: true
|
|
119
|
+
}
|
|
96
120
|
}),
|
|
97
121
|
validate(value) {
|
|
98
122
|
if (value.mode === "strict" && value.requireAuditTrail !== true) {
|
|
@@ -133,7 +157,7 @@ test("defineModuleConfig rejects invalid module config definitions", () => {
|
|
|
133
157
|
() =>
|
|
134
158
|
defineModuleConfig({
|
|
135
159
|
moduleId: "contacts",
|
|
136
|
-
schema:
|
|
160
|
+
schema: createSchema({}),
|
|
137
161
|
load: "not-a-function"
|
|
138
162
|
}),
|
|
139
163
|
/load/
|
|
@@ -580,12 +580,16 @@ function resolveInferredPageLinkTo({
|
|
|
580
580
|
explicitLinkTo = "",
|
|
581
581
|
pageTarget = {},
|
|
582
582
|
parentHost = null,
|
|
583
|
-
placementTarget = null
|
|
583
|
+
placementTarget = null,
|
|
584
|
+
suppressImplicitRelativeLinks = false
|
|
584
585
|
} = {}) {
|
|
585
586
|
const normalizedExplicitLinkTo = normalizeText(explicitLinkTo);
|
|
586
587
|
if (normalizedExplicitLinkTo) {
|
|
587
588
|
return normalizedExplicitLinkTo;
|
|
588
589
|
}
|
|
590
|
+
if (suppressImplicitRelativeLinks === true) {
|
|
591
|
+
return "";
|
|
592
|
+
}
|
|
589
593
|
|
|
590
594
|
const parentTargetId = normalizePlacementTargetId(parentHost);
|
|
591
595
|
const placementTargetId = normalizePlacementTargetId(placementTarget);
|
|
@@ -670,24 +674,26 @@ async function resolvePageLinkTargetDetails({
|
|
|
670
674
|
context,
|
|
671
675
|
placement: normalizeText(placement) || parentHost?.id || ""
|
|
672
676
|
});
|
|
677
|
+
const resolvedComponentToken = resolveInferredPageLinkComponentToken({
|
|
678
|
+
explicitComponentToken: componentToken,
|
|
679
|
+
parentHost,
|
|
680
|
+
placementTarget,
|
|
681
|
+
defaultComponentToken,
|
|
682
|
+
subpageComponentToken
|
|
683
|
+
});
|
|
673
684
|
|
|
674
685
|
return Object.freeze({
|
|
675
686
|
pageTarget: resolvedPageTarget,
|
|
676
687
|
parentHost,
|
|
677
688
|
placementTarget,
|
|
678
|
-
componentToken:
|
|
679
|
-
explicitComponentToken: componentToken,
|
|
680
|
-
parentHost,
|
|
681
|
-
placementTarget,
|
|
682
|
-
defaultComponentToken,
|
|
683
|
-
subpageComponentToken
|
|
684
|
-
}),
|
|
689
|
+
componentToken: resolvedComponentToken,
|
|
685
690
|
whenLine: renderPageLinkWhenLine(resolvedPageTarget),
|
|
686
691
|
linkTo: resolveInferredPageLinkTo({
|
|
687
692
|
explicitLinkTo: linkTo,
|
|
688
693
|
pageTarget: resolvedPageTarget,
|
|
689
694
|
parentHost,
|
|
690
|
-
placementTarget
|
|
695
|
+
placementTarget,
|
|
696
|
+
suppressImplicitRelativeLinks: resolvedComponentToken === (normalizeText(defaultComponentToken) || DEFAULT_PAGE_LINK_COMPONENT_TOKEN)
|
|
691
697
|
})
|
|
692
698
|
});
|
|
693
699
|
}
|
|
@@ -316,7 +316,7 @@ test("resolvePageLinkTargetDetails prefers an outlet-declared default link token
|
|
|
316
316
|
assert.equal(details.parentHost?.id, "home-settings:primary-menu");
|
|
317
317
|
assert.equal(details.placementTarget.id, "home-settings:primary-menu");
|
|
318
318
|
assert.equal(details.componentToken, "local.main.ui.surface-aware-menu-link-item");
|
|
319
|
-
assert.equal(details.linkTo, "
|
|
319
|
+
assert.equal(details.linkTo, "");
|
|
320
320
|
});
|
|
321
321
|
});
|
|
322
322
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createSchema } from "json-rest-schema";
|
|
2
2
|
import { normalizeObject, normalizePositiveInteger as toPositiveInteger } from "../support/normalize.js";
|
|
3
3
|
import { hasPermission } from "../support/permissions.js";
|
|
4
4
|
|
|
@@ -13,14 +13,9 @@ function resolveRequest(context) {
|
|
|
13
13
|
return context?.requestMeta?.request || null;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const EMPTY_INPUT_VALIDATOR = Object.freeze({
|
|
23
|
-
schema: Type.Object({}, { additionalProperties: false })
|
|
16
|
+
const emptyInputValidator = Object.freeze({
|
|
17
|
+
schema: createSchema({}),
|
|
18
|
+
mode: "replace"
|
|
24
19
|
});
|
|
25
20
|
|
|
26
21
|
export {
|
|
@@ -29,6 +24,5 @@ export {
|
|
|
29
24
|
requireServiceMethod,
|
|
30
25
|
resolveRequest,
|
|
31
26
|
hasPermission,
|
|
32
|
-
|
|
33
|
-
OBJECT_INPUT_VALIDATOR
|
|
27
|
+
emptyInputValidator
|
|
34
28
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
normalizeSingleSchemaDefinition
|
|
3
|
+
} from "../validators/index.js";
|
|
4
4
|
import { isRecord as isPlainObject, normalizePositiveInteger } from "../support/normalize.js";
|
|
5
5
|
import { normalizePermissionList } from "../support/permissions.js";
|
|
6
6
|
import { normalizeText } from "./textNormalization.js";
|
|
@@ -76,7 +76,7 @@ function normalizeStringArray(value, { fieldName, allowedSet, allowEmpty = false
|
|
|
76
76
|
return normalized;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
function
|
|
79
|
+
function normalizeSingleActionSchema(value, fieldName, { required = false, defaultMode = "" } = {}) {
|
|
80
80
|
if (value == null) {
|
|
81
81
|
if (!required) {
|
|
82
82
|
return null;
|
|
@@ -88,118 +88,47 @@ function normalizeSingleActionValidator(value, fieldName, { required = false } =
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
if (!isPlainObject(value)) {
|
|
91
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName} must be
|
|
91
|
+
throw createActionRuntimeError(500, `Action definition ${fieldName} must be a json-rest-schema schema definition.`, {
|
|
92
92
|
code: "ACTION_DEFINITION_INVALID"
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
try {
|
|
97
|
+
return normalizeSingleSchemaDefinition(value, {
|
|
98
|
+
context: `Action definition ${fieldName}`,
|
|
99
|
+
defaultMode
|
|
99
100
|
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
value.schema == null ||
|
|
104
|
-
(typeof value.schema !== "function" && (typeof value.schema !== "object" || Array.isArray(value.schema)))
|
|
105
|
-
) {
|
|
106
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName}.schema must be a function or object.`, {
|
|
101
|
+
} catch (error) {
|
|
102
|
+
throw createActionRuntimeError(500, error?.message || `Action definition ${fieldName} is invalid.`, {
|
|
107
103
|
code: "ACTION_DEFINITION_INVALID"
|
|
108
104
|
});
|
|
109
105
|
}
|
|
110
|
-
|
|
111
|
-
if (Object.prototype.hasOwnProperty.call(value, "normalize")) {
|
|
112
|
-
if (value.normalize != null && typeof value.normalize !== "function") {
|
|
113
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName}.normalize must be a function.`, {
|
|
114
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return Object.freeze({
|
|
120
|
-
schema: value.schema,
|
|
121
|
-
...(typeof value.normalize === "function" ? { normalize: value.normalize } : {})
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function isActionValidatorShape(value) {
|
|
126
|
-
return (
|
|
127
|
-
isPlainObject(value) &&
|
|
128
|
-
(Object.prototype.hasOwnProperty.call(value, "schema") || Object.prototype.hasOwnProperty.call(value, "normalize"))
|
|
129
|
-
);
|
|
130
106
|
}
|
|
131
107
|
|
|
132
|
-
function
|
|
133
|
-
if (
|
|
134
|
-
|
|
135
|
-
|
|
108
|
+
function normalizeActionInputDefinition(value, fieldName, { required = false } = {}) {
|
|
109
|
+
if (value == null) {
|
|
110
|
+
if (!required) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
136
113
|
|
|
137
|
-
|
|
138
|
-
if (entries.length < 1) {
|
|
139
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName} must define at least one section validator.`, {
|
|
114
|
+
throw createActionRuntimeError(500, `Action definition ${fieldName} is required.`, {
|
|
140
115
|
code: "ACTION_DEFINITION_INVALID"
|
|
141
116
|
});
|
|
142
117
|
}
|
|
143
118
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
for (const [rawKey, rawValidator] of entries) {
|
|
148
|
-
const sectionKey = normalizeText(rawKey);
|
|
149
|
-
if (!sectionKey) {
|
|
150
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName} section keys must be non-empty strings.`, {
|
|
151
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const sectionValidator = normalizeSingleActionValidator(rawValidator, `${fieldName}.${sectionKey}`, {
|
|
156
|
-
required: true
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
schemaProperties[sectionKey] = sectionValidator.schema;
|
|
160
|
-
sectionNormalizers.push({
|
|
161
|
-
key: sectionKey,
|
|
162
|
-
normalize: typeof sectionValidator.normalize === "function" ? sectionValidator.normalize : null
|
|
119
|
+
if (Array.isArray(value)) {
|
|
120
|
+
throw createActionRuntimeError(500, `Action definition ${fieldName} must be a single schema definition.`, {
|
|
121
|
+
code: "ACTION_DEFINITION_INVALID"
|
|
163
122
|
});
|
|
164
123
|
}
|
|
165
124
|
|
|
166
|
-
return
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}),
|
|
170
|
-
async normalize(payload, meta) {
|
|
171
|
-
const source = normalizeObjectInput(payload);
|
|
172
|
-
const normalized = {};
|
|
173
|
-
|
|
174
|
-
for (const section of sectionNormalizers) {
|
|
175
|
-
if (!Object.hasOwn(source, section.key)) {
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const sectionPayload = source[section.key];
|
|
180
|
-
normalized[section.key] = section.normalize ? await section.normalize(sectionPayload, meta) : sectionPayload;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return normalized;
|
|
184
|
-
}
|
|
125
|
+
return normalizeSingleActionSchema(value, fieldName, {
|
|
126
|
+
required,
|
|
127
|
+
defaultMode: "patch"
|
|
185
128
|
});
|
|
186
129
|
}
|
|
187
130
|
|
|
188
|
-
function
|
|
189
|
-
return mergeValidators(validators, {
|
|
190
|
-
context: `Action definition ${fieldName}`,
|
|
191
|
-
requireSchema: true,
|
|
192
|
-
requiredSchemaMessage: `Action definition ${fieldName}.schema is required.`,
|
|
193
|
-
normalizeResultMessage: `Action definition ${fieldName}.normalize must return an object.`,
|
|
194
|
-
createError(message) {
|
|
195
|
-
return createActionRuntimeError(500, message, {
|
|
196
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function normalizeActionValidators(value, fieldName, { required = false } = {}) {
|
|
131
|
+
function normalizeActionOutputDefinition(value, fieldName, { required = false } = {}) {
|
|
203
132
|
if (value == null) {
|
|
204
133
|
if (!required) {
|
|
205
134
|
return null;
|
|
@@ -210,40 +139,15 @@ function normalizeActionValidators(value, fieldName, { required = false } = {})
|
|
|
210
139
|
});
|
|
211
140
|
}
|
|
212
141
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (validatorsSource.length < 1) {
|
|
216
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName} is required.`, {
|
|
142
|
+
if (Array.isArray(value)) {
|
|
143
|
+
throw createActionRuntimeError(500, `Action definition ${fieldName} must be a single schema definition.`, {
|
|
217
144
|
code: "ACTION_DEFINITION_INVALID"
|
|
218
145
|
});
|
|
219
146
|
}
|
|
220
147
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (sectionMapValidator) {
|
|
225
|
-
return sectionMapValidator;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const validator = normalizeSingleActionValidator(entry, contextFieldName, {
|
|
229
|
-
required: true
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
if (!validator) {
|
|
233
|
-
throw createActionRuntimeError(500, `Action definition ${contextFieldName} is required.`, {
|
|
234
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return validator;
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
return mergeNormalizedActionValidators(validators, fieldName);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function normalizeActionOutputValidator(value, fieldName, { required = false } = {}) {
|
|
245
|
-
return normalizeActionValidators(value, fieldName, {
|
|
246
|
-
required
|
|
148
|
+
return normalizeSingleActionSchema(value, fieldName, {
|
|
149
|
+
required,
|
|
150
|
+
defaultMode: "replace"
|
|
247
151
|
});
|
|
248
152
|
}
|
|
249
153
|
|
|
@@ -333,7 +237,9 @@ function normalizeActionExtensions(value) {
|
|
|
333
237
|
});
|
|
334
238
|
}
|
|
335
239
|
|
|
336
|
-
return Object.freeze(
|
|
240
|
+
return Object.freeze({
|
|
241
|
+
...value
|
|
242
|
+
});
|
|
337
243
|
}
|
|
338
244
|
|
|
339
245
|
function normalizeActionDefinition(definition, { contributorId = "", contributorDomain = "" } = {}) {
|
|
@@ -369,12 +275,6 @@ function normalizeActionDefinition(definition, { contributorId = "", contributor
|
|
|
369
275
|
fieldName: "surfaces"
|
|
370
276
|
});
|
|
371
277
|
|
|
372
|
-
if (Object.prototype.hasOwnProperty.call(source, "visibility")) {
|
|
373
|
-
throw createActionRuntimeError(500, `Action definition \"${id}\" visibility is not supported.`, {
|
|
374
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
|
|
378
278
|
const idempotency = normalizeText(source.idempotency || "none").toLowerCase();
|
|
379
279
|
if (!ACTION_IDEMPOTENCY_SET.has(idempotency)) {
|
|
380
280
|
throw createActionRuntimeError(
|
|
@@ -392,18 +292,6 @@ function normalizeActionDefinition(definition, { contributorId = "", contributor
|
|
|
392
292
|
});
|
|
393
293
|
}
|
|
394
294
|
|
|
395
|
-
if (Object.prototype.hasOwnProperty.call(source, "input")) {
|
|
396
|
-
throw createActionRuntimeError(500, `Action definition \"${id}\" must use inputValidator instead of input.`, {
|
|
397
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
if (Object.prototype.hasOwnProperty.call(source, "output")) {
|
|
402
|
-
throw createActionRuntimeError(500, `Action definition \"${id}\" must use outputValidator instead of output.`, {
|
|
403
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
|
|
407
295
|
return Object.freeze({
|
|
408
296
|
id,
|
|
409
297
|
version,
|
|
@@ -411,10 +299,10 @@ function normalizeActionDefinition(definition, { contributorId = "", contributor
|
|
|
411
299
|
kind,
|
|
412
300
|
channels,
|
|
413
301
|
surfaces,
|
|
414
|
-
|
|
302
|
+
input: normalizeActionInputDefinition(source.input, "input", {
|
|
415
303
|
required: true
|
|
416
304
|
}),
|
|
417
|
-
|
|
305
|
+
output: normalizeActionOutputDefinition(source.output, "output", {
|
|
418
306
|
required: false
|
|
419
307
|
}),
|
|
420
308
|
idempotency,
|
|
@@ -466,10 +354,9 @@ const __testables = {
|
|
|
466
354
|
normalizeText,
|
|
467
355
|
isPlainObject,
|
|
468
356
|
normalizeStringArray,
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
normalizeActionOutputValidator,
|
|
357
|
+
normalizeSingleActionSchema,
|
|
358
|
+
normalizeActionInputDefinition,
|
|
359
|
+
normalizeActionOutputDefinition,
|
|
473
360
|
normalizeActionPermission,
|
|
474
361
|
normalizeAuditConfig,
|
|
475
362
|
normalizeObservabilityConfig,
|