@octaviaflow/flow-rules 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog/actions/console-log/config.d.ts +4 -0
- package/dist/catalog/actions/http-request/config.d.ts +60 -0
- package/dist/catalog/communication/whatsapp-send/config.d.ts +34 -0
- package/dist/catalog/general/query/config.d.ts +36 -0
- package/dist/catalog/general/transform/config.d.ts +4 -0
- package/dist/catalog/utility/debug/config.d.ts +42 -0
- package/dist/catalog/utility/variables/config.d.ts +6 -0
- package/dist/index.cjs +832 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +832 -2
- package/dist/rules/configContracts.d.ts +92 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1086,6 +1086,149 @@ var BuildQueryConfigDefaults = {
|
|
|
1086
1086
|
parameters: {}
|
|
1087
1087
|
}
|
|
1088
1088
|
};
|
|
1089
|
+
var validateBuildQueryConfig = (config) => {
|
|
1090
|
+
const errors = [];
|
|
1091
|
+
const warnings = [];
|
|
1092
|
+
if (!config.connectorId) {
|
|
1093
|
+
errors.push({
|
|
1094
|
+
field: "connectorId",
|
|
1095
|
+
message: "Please select a connector",
|
|
1096
|
+
severity: "error"
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
if (!config.mode) {
|
|
1100
|
+
errors.push({
|
|
1101
|
+
field: "mode",
|
|
1102
|
+
message: "Query mode is required",
|
|
1103
|
+
severity: "error"
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
if (!config.queryType) {
|
|
1107
|
+
errors.push({
|
|
1108
|
+
field: "queryType",
|
|
1109
|
+
message: "Query type is required",
|
|
1110
|
+
severity: "error"
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
if (config.mode === "visual" /* Visual */) {
|
|
1114
|
+
const visualErrors = validateVisualQueryConfig(config.visualConfig);
|
|
1115
|
+
errors.push(...visualErrors);
|
|
1116
|
+
} else if (config.mode === "sql" /* SQL */) {
|
|
1117
|
+
const sqlErrors = validateSQLQueryConfig(config.sqlConfig);
|
|
1118
|
+
errors.push(...sqlErrors);
|
|
1119
|
+
}
|
|
1120
|
+
if (config.timeout !== undefined) {
|
|
1121
|
+
if (config.timeout < 1000) {
|
|
1122
|
+
errors.push({
|
|
1123
|
+
field: "timeout",
|
|
1124
|
+
message: "Timeout must be at least 1000ms",
|
|
1125
|
+
severity: "error"
|
|
1126
|
+
});
|
|
1127
|
+
} else if (config.timeout > 300000) {
|
|
1128
|
+
warnings.push({
|
|
1129
|
+
field: "timeout",
|
|
1130
|
+
message: "Timeout is very high (>5 minutes)",
|
|
1131
|
+
severity: "warning"
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
if (config.maxRows !== undefined) {
|
|
1136
|
+
if (config.maxRows < 1) {
|
|
1137
|
+
errors.push({
|
|
1138
|
+
field: "maxRows",
|
|
1139
|
+
message: "Max rows must be at least 1",
|
|
1140
|
+
severity: "error"
|
|
1141
|
+
});
|
|
1142
|
+
} else if (config.maxRows > 1e4) {
|
|
1143
|
+
warnings.push({
|
|
1144
|
+
field: "maxRows",
|
|
1145
|
+
message: "Max rows is very high (>10,000). This may impact performance.",
|
|
1146
|
+
severity: "warning"
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
return {
|
|
1151
|
+
valid: errors.length === 0,
|
|
1152
|
+
errors,
|
|
1153
|
+
warnings
|
|
1154
|
+
};
|
|
1155
|
+
};
|
|
1156
|
+
var validateVisualQueryConfig = (config) => {
|
|
1157
|
+
const errors = [];
|
|
1158
|
+
if (!config) {
|
|
1159
|
+
errors.push({
|
|
1160
|
+
field: "visualConfig",
|
|
1161
|
+
message: "Visual query configuration is required",
|
|
1162
|
+
severity: "error"
|
|
1163
|
+
});
|
|
1164
|
+
return errors;
|
|
1165
|
+
}
|
|
1166
|
+
if (!config.tables || config.tables.length === 0) {
|
|
1167
|
+
errors.push({
|
|
1168
|
+
field: "visualConfig.tables",
|
|
1169
|
+
message: "At least one table must be selected",
|
|
1170
|
+
severity: "error"
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
if (!config.fields || config.fields.length === 0) {
|
|
1174
|
+
errors.push({
|
|
1175
|
+
field: "visualConfig.fields",
|
|
1176
|
+
message: "At least one field must be selected",
|
|
1177
|
+
severity: "error"
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
if (config.tables && config.tables.length > 1) {
|
|
1181
|
+
if (!config.joins || config.joins.length === 0) {
|
|
1182
|
+
errors.push({
|
|
1183
|
+
field: "visualConfig.joins",
|
|
1184
|
+
message: "Joins are required when selecting from multiple tables",
|
|
1185
|
+
severity: "error"
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
const hasAggregates = config.fields?.some((field) => field.aggregate);
|
|
1190
|
+
const hasNonAggregates = config.fields?.some((field) => !field.aggregate);
|
|
1191
|
+
if (hasAggregates && hasNonAggregates) {
|
|
1192
|
+
if (!config.groupBy || config.groupBy.length === 0) {
|
|
1193
|
+
errors.push({
|
|
1194
|
+
field: "visualConfig.groupBy",
|
|
1195
|
+
message: "Group by is required when mixing aggregate and non-aggregate fields",
|
|
1196
|
+
severity: "error"
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
return errors;
|
|
1201
|
+
};
|
|
1202
|
+
var validateSQLQueryConfig = (config) => {
|
|
1203
|
+
const errors = [];
|
|
1204
|
+
if (!config) {
|
|
1205
|
+
errors.push({
|
|
1206
|
+
field: "sqlConfig",
|
|
1207
|
+
message: "SQL query configuration is required",
|
|
1208
|
+
severity: "error"
|
|
1209
|
+
});
|
|
1210
|
+
return errors;
|
|
1211
|
+
}
|
|
1212
|
+
if (!config.sql || config.sql.trim().length === 0) {
|
|
1213
|
+
errors.push({
|
|
1214
|
+
field: "sqlConfig.sql",
|
|
1215
|
+
message: "SQL query is required",
|
|
1216
|
+
severity: "error"
|
|
1217
|
+
});
|
|
1218
|
+
} else {
|
|
1219
|
+
const sql = config.sql.trim().toLowerCase();
|
|
1220
|
+
const dangerousKeywords = ["drop", "truncate", "alter", "create", "grant", "revoke"];
|
|
1221
|
+
const hasDangerousKeyword = dangerousKeywords.some((keyword) => sql.includes(keyword + " "));
|
|
1222
|
+
if (hasDangerousKeyword) {
|
|
1223
|
+
errors.push({
|
|
1224
|
+
field: "sqlConfig.sql",
|
|
1225
|
+
message: "SQL query contains potentially dangerous operations (DROP, TRUNCATE, ALTER, etc.)",
|
|
1226
|
+
severity: "error"
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
return errors;
|
|
1231
|
+
};
|
|
1089
1232
|
function isQueryableConnector(connector) {
|
|
1090
1233
|
if (connector.isQueryable !== undefined) {
|
|
1091
1234
|
return connector.isQueryable;
|
|
@@ -1111,6 +1254,15 @@ function isQueryableConnector(connector) {
|
|
|
1111
1254
|
];
|
|
1112
1255
|
return !storageTypes.includes(connector.type.toLowerCase());
|
|
1113
1256
|
}
|
|
1257
|
+
var BuildQueryContractSchema = {
|
|
1258
|
+
connectorId: { type: "connection", required: true },
|
|
1259
|
+
mode: { type: "select", required: true },
|
|
1260
|
+
queryType: { type: "select", required: true },
|
|
1261
|
+
visualConfig: { type: "object", required: false },
|
|
1262
|
+
sqlConfig: { type: "object", required: false },
|
|
1263
|
+
timeout: { type: "number", required: false },
|
|
1264
|
+
maxRows: { type: "number", required: false }
|
|
1265
|
+
};
|
|
1114
1266
|
|
|
1115
1267
|
// src/catalog/general/query/index.ts
|
|
1116
1268
|
var queryDefinition = {
|
|
@@ -2000,7 +2152,7 @@ var slackMessageDefinition = {
|
|
|
2000
2152
|
fields: [
|
|
2001
2153
|
{ key: "connection", label: "Slack Workspace", type: "connection" /* Connection */, validation: { required: true } },
|
|
2002
2154
|
{ key: "channel", label: "Channel/User", type: "string" /* String */, validation: { required: true } },
|
|
2003
|
-
{ key: "
|
|
2155
|
+
{ key: "text", label: "Message", type: "string" /* String */, validation: { required: true } },
|
|
2004
2156
|
{ key: "blocks", label: "Blocks (JSON)", type: "json" /* JSON */, validation: { required: false } }
|
|
2005
2157
|
]
|
|
2006
2158
|
},
|
|
@@ -3224,6 +3376,9 @@ function buildPathOptions(upstreamNodes) {
|
|
|
3224
3376
|
var RESERVED_KEYS = new Set(["_lineage", "_meta", "_redacted", "_error"]);
|
|
3225
3377
|
var KEY_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
3226
3378
|
var VariablesConfig = {
|
|
3379
|
+
schema: {
|
|
3380
|
+
fields: { type: "array", required: true }
|
|
3381
|
+
},
|
|
3227
3382
|
defaults: {
|
|
3228
3383
|
fields: []
|
|
3229
3384
|
},
|
|
@@ -3274,6 +3429,18 @@ function fieldToJsonSchema(f) {
|
|
|
3274
3429
|
}
|
|
3275
3430
|
// src/catalog/utility/debug/config.ts
|
|
3276
3431
|
var DebugConfig = {
|
|
3432
|
+
schema: {
|
|
3433
|
+
mode: { type: "select", required: true },
|
|
3434
|
+
label: { type: "string", required: false },
|
|
3435
|
+
pinned: { type: "boolean", required: false },
|
|
3436
|
+
condition: { type: "expression", required: false },
|
|
3437
|
+
sampling: { type: "object", required: false },
|
|
3438
|
+
log: { type: "object", required: false },
|
|
3439
|
+
snapshot: { type: "object", required: false },
|
|
3440
|
+
watch: { type: "object", required: false },
|
|
3441
|
+
assert: { type: "object", required: false },
|
|
3442
|
+
profile: { type: "object", required: false }
|
|
3443
|
+
},
|
|
3277
3444
|
defaults: {
|
|
3278
3445
|
mode: "log",
|
|
3279
3446
|
label: "",
|
|
@@ -3459,6 +3626,7 @@ var TransformConfig = {
|
|
|
3459
3626
|
sheetColumns: ""
|
|
3460
3627
|
},
|
|
3461
3628
|
schema: {
|
|
3629
|
+
name: { type: "string", required: false },
|
|
3462
3630
|
operation: { type: "select", required: true },
|
|
3463
3631
|
connectorId: { type: "connection", required: true },
|
|
3464
3632
|
database: { type: "text", required: false },
|
|
@@ -3996,6 +4164,661 @@ function validateFlowData(flow) {
|
|
|
3996
4164
|
const f = flow;
|
|
3997
4165
|
return typeof f.id === "string" && typeof f.name === "string" && f.workflow !== undefined && typeof f.workflow === "object" && f.workflow !== null && Array.isArray(f.workflow.steps);
|
|
3998
4166
|
}
|
|
4167
|
+
// src/catalog/actions/console-log/config.ts
|
|
4168
|
+
var ConsoleLogConfig = {
|
|
4169
|
+
defaults: {
|
|
4170
|
+
message: "",
|
|
4171
|
+
level: "info",
|
|
4172
|
+
data: undefined,
|
|
4173
|
+
includeInputData: true
|
|
4174
|
+
},
|
|
4175
|
+
schema: {
|
|
4176
|
+
includeInputData: { type: "boolean", required: false },
|
|
4177
|
+
message: {
|
|
4178
|
+
type: "string",
|
|
4179
|
+
required: true,
|
|
4180
|
+
description: "Message to log"
|
|
4181
|
+
},
|
|
4182
|
+
level: {
|
|
4183
|
+
type: "select",
|
|
4184
|
+
required: false,
|
|
4185
|
+
description: "Log level for the message"
|
|
4186
|
+
},
|
|
4187
|
+
data: {
|
|
4188
|
+
type: "json",
|
|
4189
|
+
required: false,
|
|
4190
|
+
description: "Additional data to log"
|
|
4191
|
+
}
|
|
4192
|
+
},
|
|
4193
|
+
validate: (config) => {
|
|
4194
|
+
const errors = [];
|
|
4195
|
+
if (!config.message) {
|
|
4196
|
+
errors.push("Message is required");
|
|
4197
|
+
} else if (typeof config.message !== "string") {
|
|
4198
|
+
errors.push("Message must be a string");
|
|
4199
|
+
}
|
|
4200
|
+
if (config.level && !["info", "warning", "error", "debug"].includes(config.level)) {
|
|
4201
|
+
errors.push("Invalid log level");
|
|
4202
|
+
}
|
|
4203
|
+
return {
|
|
4204
|
+
valid: errors.length === 0,
|
|
4205
|
+
errors
|
|
4206
|
+
};
|
|
4207
|
+
},
|
|
4208
|
+
merge: (userConfig) => {
|
|
4209
|
+
return {
|
|
4210
|
+
...ConsoleLogConfig.defaults,
|
|
4211
|
+
...userConfig
|
|
4212
|
+
};
|
|
4213
|
+
},
|
|
4214
|
+
getLabel: (config) => {
|
|
4215
|
+
return `Log [${config.level}]: ${config.message}`;
|
|
4216
|
+
}
|
|
4217
|
+
};
|
|
4218
|
+
|
|
4219
|
+
// src/catalog/actions/delay/config.ts
|
|
4220
|
+
var DelayConfig = {
|
|
4221
|
+
defaults: {
|
|
4222
|
+
duration: 1000,
|
|
4223
|
+
unit: "milliseconds"
|
|
4224
|
+
},
|
|
4225
|
+
schema: {
|
|
4226
|
+
duration: {
|
|
4227
|
+
type: "number",
|
|
4228
|
+
required: true,
|
|
4229
|
+
description: "Duration to delay",
|
|
4230
|
+
min: 0
|
|
4231
|
+
},
|
|
4232
|
+
unit: {
|
|
4233
|
+
type: "select",
|
|
4234
|
+
required: false,
|
|
4235
|
+
description: "Time unit for the duration"
|
|
4236
|
+
}
|
|
4237
|
+
},
|
|
4238
|
+
validate: (config) => {
|
|
4239
|
+
const errors = [];
|
|
4240
|
+
if (config.duration === undefined || config.duration === null) {
|
|
4241
|
+
errors.push("Duration is required");
|
|
4242
|
+
} else if (typeof config.duration !== "number") {
|
|
4243
|
+
errors.push("Duration must be a number");
|
|
4244
|
+
} else if (config.duration < 0) {
|
|
4245
|
+
errors.push("Duration must be non-negative");
|
|
4246
|
+
}
|
|
4247
|
+
if (config.unit && !["milliseconds", "seconds", "minutes", "hours"].includes(config.unit)) {
|
|
4248
|
+
errors.push("Invalid time unit");
|
|
4249
|
+
}
|
|
4250
|
+
return {
|
|
4251
|
+
valid: errors.length === 0,
|
|
4252
|
+
errors
|
|
4253
|
+
};
|
|
4254
|
+
},
|
|
4255
|
+
toMilliseconds: (duration, unit = "milliseconds") => {
|
|
4256
|
+
const multipliers = {
|
|
4257
|
+
milliseconds: 1,
|
|
4258
|
+
seconds: 1000,
|
|
4259
|
+
minutes: 60000,
|
|
4260
|
+
hours: 3600000
|
|
4261
|
+
};
|
|
4262
|
+
return duration * (multipliers[unit] || 1);
|
|
4263
|
+
},
|
|
4264
|
+
merge: (userConfig) => {
|
|
4265
|
+
return {
|
|
4266
|
+
...DelayConfig.defaults,
|
|
4267
|
+
...userConfig
|
|
4268
|
+
};
|
|
4269
|
+
},
|
|
4270
|
+
getLabel: (config) => {
|
|
4271
|
+
return `Delay ${config.duration}${config.unit ? " " + config.unit : "ms"}`;
|
|
4272
|
+
}
|
|
4273
|
+
};
|
|
4274
|
+
|
|
4275
|
+
// src/catalog/actions/http-request/config.ts
|
|
4276
|
+
var HTTPRequestConfig = {
|
|
4277
|
+
defaults: {
|
|
4278
|
+
apiType: "rest",
|
|
4279
|
+
method: "GET",
|
|
4280
|
+
url: "",
|
|
4281
|
+
queryParams: [],
|
|
4282
|
+
headers: [],
|
|
4283
|
+
bodyType: "json",
|
|
4284
|
+
body: undefined,
|
|
4285
|
+
formData: [],
|
|
4286
|
+
graphqlQuery: "",
|
|
4287
|
+
graphqlVariables: {},
|
|
4288
|
+
auth: { type: "none" },
|
|
4289
|
+
timeout: 30000,
|
|
4290
|
+
failOnError: true,
|
|
4291
|
+
followRedirects: true,
|
|
4292
|
+
retry: { maxAttempts: 1, retryOn: [429, 500, 502, 503, 504], initialDelayMs: 1000, backoffFactor: 2, maxDelayMs: 30000 },
|
|
4293
|
+
pagination: { type: "none" },
|
|
4294
|
+
extract: {},
|
|
4295
|
+
responseType: "json",
|
|
4296
|
+
expectedContentTypes: []
|
|
4297
|
+
},
|
|
4298
|
+
schema: {
|
|
4299
|
+
apiType: { type: "select", required: false },
|
|
4300
|
+
baseUrl: { type: "string", required: false },
|
|
4301
|
+
queryParams: { type: "array", required: false },
|
|
4302
|
+
bodyType: { type: "select", required: false },
|
|
4303
|
+
formData: { type: "array", required: false },
|
|
4304
|
+
graphqlQuery: { type: "code", required: false },
|
|
4305
|
+
graphqlVariables: { type: "json", required: false },
|
|
4306
|
+
auth: { type: "object", required: false },
|
|
4307
|
+
failOnError: { type: "boolean", required: false },
|
|
4308
|
+
followRedirects: { type: "boolean", required: false },
|
|
4309
|
+
retry: { type: "object", required: false },
|
|
4310
|
+
pagination: { type: "object", required: false },
|
|
4311
|
+
extract: { type: "object", required: false },
|
|
4312
|
+
responseType: { type: "select", required: false },
|
|
4313
|
+
expectedContentTypes: { type: "array", required: false },
|
|
4314
|
+
method: {
|
|
4315
|
+
type: "select",
|
|
4316
|
+
required: true,
|
|
4317
|
+
description: "HTTP method to use"
|
|
4318
|
+
},
|
|
4319
|
+
url: {
|
|
4320
|
+
type: "url",
|
|
4321
|
+
required: true,
|
|
4322
|
+
description: "The URL to send the request to"
|
|
4323
|
+
},
|
|
4324
|
+
headers: {
|
|
4325
|
+
type: "json",
|
|
4326
|
+
required: false,
|
|
4327
|
+
description: "HTTP headers to send with the request"
|
|
4328
|
+
},
|
|
4329
|
+
body: {
|
|
4330
|
+
type: "json",
|
|
4331
|
+
required: false,
|
|
4332
|
+
description: "Request body (for POST, PUT, PATCH)"
|
|
4333
|
+
},
|
|
4334
|
+
timeout: {
|
|
4335
|
+
type: "number",
|
|
4336
|
+
required: false,
|
|
4337
|
+
description: "Request timeout in milliseconds",
|
|
4338
|
+
min: 1000
|
|
4339
|
+
}
|
|
4340
|
+
},
|
|
4341
|
+
validate: (config) => {
|
|
4342
|
+
const errors = [];
|
|
4343
|
+
const apiType = config.apiType ?? "rest";
|
|
4344
|
+
if (apiType === "rest" && !config.method) {
|
|
4345
|
+
errors.push("Method is required");
|
|
4346
|
+
}
|
|
4347
|
+
if (apiType === "graphql" && !config.graphqlQuery?.trim()) {
|
|
4348
|
+
errors.push("GraphQL query is required");
|
|
4349
|
+
}
|
|
4350
|
+
if (!config.url) {
|
|
4351
|
+
errors.push("URL is required");
|
|
4352
|
+
} else if (typeof config.url === "string") {
|
|
4353
|
+
try {
|
|
4354
|
+
new URL(config.url);
|
|
4355
|
+
} catch {
|
|
4356
|
+
errors.push("Invalid URL format");
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4359
|
+
if (config.timeout !== undefined && typeof config.timeout === "number") {
|
|
4360
|
+
if (config.timeout < 1000) {
|
|
4361
|
+
errors.push("Timeout must be at least 1000ms");
|
|
4362
|
+
}
|
|
4363
|
+
}
|
|
4364
|
+
return {
|
|
4365
|
+
valid: errors.length === 0,
|
|
4366
|
+
errors
|
|
4367
|
+
};
|
|
4368
|
+
},
|
|
4369
|
+
merge: (userConfig) => {
|
|
4370
|
+
return {
|
|
4371
|
+
...HTTPRequestConfig.defaults,
|
|
4372
|
+
...userConfig
|
|
4373
|
+
};
|
|
4374
|
+
},
|
|
4375
|
+
getLabel: (config) => {
|
|
4376
|
+
const type = config.apiType === "graphql" ? "GraphQL" : config.method ?? "GET";
|
|
4377
|
+
return `${type} ${config.url}`;
|
|
4378
|
+
}
|
|
4379
|
+
};
|
|
4380
|
+
|
|
4381
|
+
// src/catalog/api/graphql-query/config.ts
|
|
4382
|
+
var GraphQLQueryConfig = {
|
|
4383
|
+
defaults: {
|
|
4384
|
+
endpoint: "",
|
|
4385
|
+
query: "",
|
|
4386
|
+
variables: {},
|
|
4387
|
+
headers: {}
|
|
4388
|
+
},
|
|
4389
|
+
schema: {
|
|
4390
|
+
endpoint: { type: "url", required: true },
|
|
4391
|
+
query: { type: "code", required: true },
|
|
4392
|
+
variables: { type: "json", required: false },
|
|
4393
|
+
headers: { type: "json", required: false }
|
|
4394
|
+
},
|
|
4395
|
+
validate: (config) => {
|
|
4396
|
+
const errors = [];
|
|
4397
|
+
if (!config.endpoint)
|
|
4398
|
+
errors.push("Endpoint is required");
|
|
4399
|
+
if (!config.query)
|
|
4400
|
+
errors.push("Query is required");
|
|
4401
|
+
return { valid: errors.length === 0, errors };
|
|
4402
|
+
},
|
|
4403
|
+
merge: (userConfig) => {
|
|
4404
|
+
return { ...GraphQLQueryConfig.defaults, ...userConfig };
|
|
4405
|
+
},
|
|
4406
|
+
getLabel: (config) => {
|
|
4407
|
+
return `GraphQL: ${config.endpoint}`;
|
|
4408
|
+
}
|
|
4409
|
+
};
|
|
4410
|
+
|
|
4411
|
+
// src/catalog/communication/google-chat/config.ts
|
|
4412
|
+
var GoogleChatConfig = {
|
|
4413
|
+
defaults: { connection: "", space: "", spaceName: "", text: "", threadKey: "" },
|
|
4414
|
+
schema: {
|
|
4415
|
+
connection: { type: "connection", required: true },
|
|
4416
|
+
space: { type: "string", required: true },
|
|
4417
|
+
text: { type: "string", required: false },
|
|
4418
|
+
threadKey: { type: "string", required: false }
|
|
4419
|
+
},
|
|
4420
|
+
validate: (config) => {
|
|
4421
|
+
const errors = [];
|
|
4422
|
+
if (!config.connection)
|
|
4423
|
+
errors.push("Connect a Google Chat account");
|
|
4424
|
+
if (!config.space)
|
|
4425
|
+
errors.push("Pick a space");
|
|
4426
|
+
if (!config.text && !config.message)
|
|
4427
|
+
errors.push("Add a message");
|
|
4428
|
+
return { valid: errors.length === 0, errors };
|
|
4429
|
+
},
|
|
4430
|
+
merge: (userConfig) => ({
|
|
4431
|
+
...GoogleChatConfig.defaults,
|
|
4432
|
+
...userConfig
|
|
4433
|
+
}),
|
|
4434
|
+
getLabel: () => "Google Chat"
|
|
4435
|
+
};
|
|
4436
|
+
|
|
4437
|
+
// src/catalog/communication/slack-message/config.ts
|
|
4438
|
+
var SlackMessageConfig = {
|
|
4439
|
+
defaults: { connection: "", messageType: "channel", channel: "", channelName: "", text: "", blocks: undefined },
|
|
4440
|
+
schema: {
|
|
4441
|
+
connection: { type: "connection", required: true },
|
|
4442
|
+
messageType: { type: "string", required: false },
|
|
4443
|
+
channel: { type: "string", required: true },
|
|
4444
|
+
text: { type: "string", required: false },
|
|
4445
|
+
blocks: { type: "json", required: false }
|
|
4446
|
+
},
|
|
4447
|
+
validate: (config) => {
|
|
4448
|
+
const errors = [];
|
|
4449
|
+
if (!config.connection)
|
|
4450
|
+
errors.push("Slack workspace connection is required");
|
|
4451
|
+
if (!config.channel)
|
|
4452
|
+
errors.push(config.messageType === "user" ? "A user is required" : "A channel is required");
|
|
4453
|
+
const hasText = Boolean(config.text || config.message);
|
|
4454
|
+
const hasBlocks = Array.isArray(config.blocks) && config.blocks.length > 0;
|
|
4455
|
+
if (!hasText && !hasBlocks)
|
|
4456
|
+
errors.push("Add a message or at least one block");
|
|
4457
|
+
return { valid: errors.length === 0, errors };
|
|
4458
|
+
},
|
|
4459
|
+
merge: (userConfig) => {
|
|
4460
|
+
return { ...SlackMessageConfig.defaults, ...userConfig };
|
|
4461
|
+
},
|
|
4462
|
+
getLabel: (config) => {
|
|
4463
|
+
const prefix = config.messageType === "user" ? "@" : "#";
|
|
4464
|
+
return config.channelName ? `Slack: ${prefix}${config.channelName}` : config.channel ? `Slack: ${config.channel}` : "Slack";
|
|
4465
|
+
}
|
|
4466
|
+
};
|
|
4467
|
+
|
|
4468
|
+
// src/catalog/communication/teams-message/config.ts
|
|
4469
|
+
var TeamsMessageConfig = {
|
|
4470
|
+
defaults: { connection: "", teamId: "", teamName: "", channelId: "", channelName: "", title: "", message: "" },
|
|
4471
|
+
schema: {
|
|
4472
|
+
connection: { type: "connection", required: true },
|
|
4473
|
+
teamId: { type: "string", required: true },
|
|
4474
|
+
channelId: { type: "string", required: true },
|
|
4475
|
+
title: { type: "string", required: false },
|
|
4476
|
+
message: { type: "string", required: true }
|
|
4477
|
+
},
|
|
4478
|
+
validate: (config) => {
|
|
4479
|
+
const errors = [];
|
|
4480
|
+
if (!config.connection)
|
|
4481
|
+
errors.push("Connect a Microsoft Teams account");
|
|
4482
|
+
if (!config.teamId)
|
|
4483
|
+
errors.push("Pick a team");
|
|
4484
|
+
if (!config.channelId)
|
|
4485
|
+
errors.push("Pick a channel");
|
|
4486
|
+
if (!config.message)
|
|
4487
|
+
errors.push("Add a message");
|
|
4488
|
+
return { valid: errors.length === 0, errors };
|
|
4489
|
+
},
|
|
4490
|
+
merge: (userConfig) => {
|
|
4491
|
+
return { ...TeamsMessageConfig.defaults, ...userConfig };
|
|
4492
|
+
},
|
|
4493
|
+
getLabel: (config) => config.channelName ? `Teams: #${config.channelName}` : "Teams"
|
|
4494
|
+
};
|
|
4495
|
+
|
|
4496
|
+
// src/catalog/communication/webhook-call/config.ts
|
|
4497
|
+
var WebhookCallConfig = {
|
|
4498
|
+
defaults: {
|
|
4499
|
+
url: "",
|
|
4500
|
+
method: "POST",
|
|
4501
|
+
payload: {},
|
|
4502
|
+
headers: {}
|
|
4503
|
+
},
|
|
4504
|
+
schema: {
|
|
4505
|
+
url: { type: "url", required: true },
|
|
4506
|
+
method: { type: "select", required: true },
|
|
4507
|
+
payload: { type: "json", required: false },
|
|
4508
|
+
headers: { type: "json", required: false }
|
|
4509
|
+
},
|
|
4510
|
+
validate: (config) => {
|
|
4511
|
+
const errors = [];
|
|
4512
|
+
if (!config.url)
|
|
4513
|
+
errors.push("Webhook URL is required");
|
|
4514
|
+
if (!config.method)
|
|
4515
|
+
errors.push("HTTP method is required");
|
|
4516
|
+
return { valid: errors.length === 0, errors };
|
|
4517
|
+
},
|
|
4518
|
+
merge: (userConfig) => {
|
|
4519
|
+
return { ...WebhookCallConfig.defaults, ...userConfig };
|
|
4520
|
+
},
|
|
4521
|
+
getLabel: (config) => {
|
|
4522
|
+
return `${config.method}: ${config.url.substring(0, 40)}...`;
|
|
4523
|
+
}
|
|
4524
|
+
};
|
|
4525
|
+
|
|
4526
|
+
// src/catalog/communication/whatsapp-send/config.ts
|
|
4527
|
+
var WhatsappSendConfig = {
|
|
4528
|
+
schema: {
|
|
4529
|
+
connection: { type: "connection", required: true },
|
|
4530
|
+
to: { type: "string", required: true },
|
|
4531
|
+
mode: { type: "select", required: true },
|
|
4532
|
+
templateName: { type: "string", required: false },
|
|
4533
|
+
templateLanguage: { type: "string", required: false },
|
|
4534
|
+
templateVariables: { type: "array", required: false },
|
|
4535
|
+
text: { type: "string", required: false },
|
|
4536
|
+
previewUrl: { type: "boolean", required: false }
|
|
4537
|
+
},
|
|
4538
|
+
defaults: {
|
|
4539
|
+
connection: "",
|
|
4540
|
+
to: "",
|
|
4541
|
+
mode: "template",
|
|
4542
|
+
templateLanguage: "en_US",
|
|
4543
|
+
templateVariables: []
|
|
4544
|
+
},
|
|
4545
|
+
validate: (config) => {
|
|
4546
|
+
const errors = [];
|
|
4547
|
+
if (!config.connection)
|
|
4548
|
+
errors.push("Select a WhatsApp connection");
|
|
4549
|
+
if (!config.to?.trim())
|
|
4550
|
+
errors.push("Recipient phone number is required");
|
|
4551
|
+
if (config.mode === "text") {
|
|
4552
|
+
if (!config.text?.trim())
|
|
4553
|
+
errors.push("Message text is required");
|
|
4554
|
+
} else {
|
|
4555
|
+
if (!config.templateName?.trim())
|
|
4556
|
+
errors.push("Choose an approved template");
|
|
4557
|
+
}
|
|
4558
|
+
return { valid: errors.length === 0, errors };
|
|
4559
|
+
},
|
|
4560
|
+
merge: (userConfig) => {
|
|
4561
|
+
return { ...WhatsappSendConfig.defaults, ...userConfig };
|
|
4562
|
+
},
|
|
4563
|
+
getLabel: (config) => config.mode === "text" ? `WhatsApp to ${config.to || "—"}` : `WhatsApp template "${config.templateName || "—"}" to ${config.to || "—"}`
|
|
4564
|
+
};
|
|
4565
|
+
|
|
4566
|
+
// src/catalog/storage/file-operation/config.ts
|
|
4567
|
+
var FileOperationConfig = {
|
|
4568
|
+
defaults: {
|
|
4569
|
+
connection: "",
|
|
4570
|
+
operation: "upload",
|
|
4571
|
+
sourcePath: "",
|
|
4572
|
+
destinationPath: "",
|
|
4573
|
+
fileContent: "",
|
|
4574
|
+
options: {}
|
|
4575
|
+
},
|
|
4576
|
+
schema: {
|
|
4577
|
+
connection: { type: "connection", required: true },
|
|
4578
|
+
operation: { type: "select", required: true },
|
|
4579
|
+
sourcePath: { type: "string", required: false },
|
|
4580
|
+
destinationPath: { type: "string", required: true },
|
|
4581
|
+
fileContent: { type: "string", required: false },
|
|
4582
|
+
options: { type: "json", required: false }
|
|
4583
|
+
},
|
|
4584
|
+
validate: (config) => {
|
|
4585
|
+
const errors = [];
|
|
4586
|
+
if (!config.connection)
|
|
4587
|
+
errors.push("Storage connection is required");
|
|
4588
|
+
if (!config.operation)
|
|
4589
|
+
errors.push("Operation is required");
|
|
4590
|
+
if (!config.destinationPath)
|
|
4591
|
+
errors.push("Destination path is required");
|
|
4592
|
+
if (config.operation === "upload" || config.operation === "copy" || config.operation === "move") {
|
|
4593
|
+
if (!config.sourcePath) {
|
|
4594
|
+
errors.push("Source path is required for upload/copy/move operations");
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
return { valid: errors.length === 0, errors };
|
|
4598
|
+
},
|
|
4599
|
+
merge: (userConfig) => {
|
|
4600
|
+
return { ...FileOperationConfig.defaults, ...userConfig };
|
|
4601
|
+
},
|
|
4602
|
+
getLabel: (config) => {
|
|
4603
|
+
return `${config.operation.toUpperCase()}: ${config.destinationPath}`;
|
|
4604
|
+
}
|
|
4605
|
+
};
|
|
4606
|
+
|
|
4607
|
+
// src/catalog/transforms/format/config.ts
|
|
4608
|
+
var FormatConfig = {
|
|
4609
|
+
defaults: { input: "", format: "json" },
|
|
4610
|
+
schema: {
|
|
4611
|
+
input: { type: "expression", required: true },
|
|
4612
|
+
format: { type: "select", required: true }
|
|
4613
|
+
},
|
|
4614
|
+
validate: (config) => {
|
|
4615
|
+
const errors = [];
|
|
4616
|
+
if (!config.input)
|
|
4617
|
+
errors.push("Input required");
|
|
4618
|
+
if (!config.format)
|
|
4619
|
+
errors.push("Format required");
|
|
4620
|
+
return { valid: errors.length === 0, errors };
|
|
4621
|
+
},
|
|
4622
|
+
merge: (userConfig) => {
|
|
4623
|
+
return { ...FormatConfig.defaults, ...userConfig };
|
|
4624
|
+
},
|
|
4625
|
+
getLabel: (config) => `Format as ${config.format.toUpperCase()}`
|
|
4626
|
+
};
|
|
4627
|
+
|
|
4628
|
+
// src/catalog/triggers/schedule-trigger/config.ts
|
|
4629
|
+
var ScheduleTriggerConfig = {
|
|
4630
|
+
defaults: {
|
|
4631
|
+
scheduleType: "interval",
|
|
4632
|
+
interval: 60,
|
|
4633
|
+
intervalUnit: "minutes",
|
|
4634
|
+
timezone: "UTC"
|
|
4635
|
+
},
|
|
4636
|
+
schema: {
|
|
4637
|
+
scheduleType: { type: "select", required: true },
|
|
4638
|
+
interval: { type: "number", required: false, min: 1 },
|
|
4639
|
+
intervalUnit: { type: "select", required: false },
|
|
4640
|
+
cronExpression: { type: "string", required: false },
|
|
4641
|
+
timezone: { type: "string", required: false }
|
|
4642
|
+
},
|
|
4643
|
+
validate: (config) => {
|
|
4644
|
+
const errors = [];
|
|
4645
|
+
if (!config.scheduleType) {
|
|
4646
|
+
errors.push("Schedule type is required");
|
|
4647
|
+
}
|
|
4648
|
+
if (config.scheduleType === "interval") {
|
|
4649
|
+
if (!config.interval || config.interval < 1) {
|
|
4650
|
+
errors.push("Interval must be at least 1");
|
|
4651
|
+
}
|
|
4652
|
+
}
|
|
4653
|
+
if (config.scheduleType === "cron" && !config.cronExpression) {
|
|
4654
|
+
errors.push("Cron expression is required");
|
|
4655
|
+
}
|
|
4656
|
+
return { valid: errors.length === 0, errors };
|
|
4657
|
+
},
|
|
4658
|
+
merge: (userConfig) => {
|
|
4659
|
+
return { ...ScheduleTriggerConfig.defaults, ...userConfig };
|
|
4660
|
+
},
|
|
4661
|
+
getLabel: (config) => {
|
|
4662
|
+
if (config.scheduleType === "interval") {
|
|
4663
|
+
return `Every ${config.interval} ${config.intervalUnit}`;
|
|
4664
|
+
}
|
|
4665
|
+
return `Schedule: ${config.scheduleType}`;
|
|
4666
|
+
}
|
|
4667
|
+
};
|
|
4668
|
+
|
|
4669
|
+
// src/catalog/triggers/webhook-trigger/config.ts
|
|
4670
|
+
var WebhookTriggerConfig = {
|
|
4671
|
+
defaults: {
|
|
4672
|
+
method: "POST",
|
|
4673
|
+
requireAuth: true
|
|
4674
|
+
},
|
|
4675
|
+
schema: {
|
|
4676
|
+
webhookPath: { type: "string", required: false },
|
|
4677
|
+
method: { type: "select", required: true },
|
|
4678
|
+
requireAuth: { type: "boolean", required: false }
|
|
4679
|
+
},
|
|
4680
|
+
validate: (config) => {
|
|
4681
|
+
const errors = [];
|
|
4682
|
+
if (!config.method) {
|
|
4683
|
+
errors.push("HTTP method is required");
|
|
4684
|
+
}
|
|
4685
|
+
return { valid: errors.length === 0, errors };
|
|
4686
|
+
},
|
|
4687
|
+
merge: (userConfig) => {
|
|
4688
|
+
return { ...WebhookTriggerConfig.defaults, ...userConfig };
|
|
4689
|
+
},
|
|
4690
|
+
getLabel: (config) => {
|
|
4691
|
+
return `Webhook ${config.method}${config.webhookPath ? ` ${config.webhookPath}` : ""}`;
|
|
4692
|
+
}
|
|
4693
|
+
};
|
|
4694
|
+
|
|
4695
|
+
// src/catalog/utility/error/config.ts
|
|
4696
|
+
var ErrorConfig = {
|
|
4697
|
+
defaults: {
|
|
4698
|
+
message: "",
|
|
4699
|
+
code: undefined
|
|
4700
|
+
},
|
|
4701
|
+
schema: {
|
|
4702
|
+
message: { type: "string", required: true },
|
|
4703
|
+
code: { type: "string", required: false }
|
|
4704
|
+
},
|
|
4705
|
+
validate: (config) => {
|
|
4706
|
+
const errors = [];
|
|
4707
|
+
if (!config.message)
|
|
4708
|
+
errors.push("Error message is required");
|
|
4709
|
+
return { valid: errors.length === 0, errors };
|
|
4710
|
+
},
|
|
4711
|
+
merge: (userConfig) => {
|
|
4712
|
+
return { ...ErrorConfig.defaults, ...userConfig };
|
|
4713
|
+
},
|
|
4714
|
+
getLabel: (config) => {
|
|
4715
|
+
return `Error: ${config.message}`;
|
|
4716
|
+
}
|
|
4717
|
+
};
|
|
4718
|
+
|
|
4719
|
+
// src/rules/configContracts.ts
|
|
4720
|
+
var asValidator = (fn) => (config) => fn(config);
|
|
4721
|
+
var CONFIG_CONTRACTS = {
|
|
4722
|
+
console_log: { schema: ConsoleLogConfig.schema, validate: asValidator(ConsoleLogConfig.validate) },
|
|
4723
|
+
delay: { schema: DelayConfig.schema, validate: asValidator(DelayConfig.validate) },
|
|
4724
|
+
http_request: { schema: HTTPRequestConfig.schema, validate: asValidator(HTTPRequestConfig.validate) },
|
|
4725
|
+
graphql_query: { schema: GraphQLQueryConfig.schema, validate: asValidator(GraphQLQueryConfig.validate) },
|
|
4726
|
+
email: { schema: EmailConfig.schema, validate: asValidator(EmailConfig.validate) },
|
|
4727
|
+
google_chat: { schema: GoogleChatConfig.schema, validate: asValidator(GoogleChatConfig.validate) },
|
|
4728
|
+
slack_message: { schema: SlackMessageConfig.schema, validate: asValidator(SlackMessageConfig.validate) },
|
|
4729
|
+
teams_message: { schema: TeamsMessageConfig.schema, validate: asValidator(TeamsMessageConfig.validate) },
|
|
4730
|
+
webhook_call: { schema: WebhookCallConfig.schema, validate: asValidator(WebhookCallConfig.validate) },
|
|
4731
|
+
whatsapp_send: { schema: WhatsappSendConfig.schema, validate: asValidator(WhatsappSendConfig.validate) },
|
|
4732
|
+
query: {
|
|
4733
|
+
schema: BuildQueryContractSchema,
|
|
4734
|
+
validate: (config) => {
|
|
4735
|
+
const r = validateBuildQueryConfig(config);
|
|
4736
|
+
const errors = (r.errors ?? []).filter((e) => e.severity !== "warning").map((e) => e.message);
|
|
4737
|
+
return { valid: errors.length === 0, errors };
|
|
4738
|
+
}
|
|
4739
|
+
},
|
|
4740
|
+
transform: { schema: TransformConfig.schema, validate: asValidator(TransformConfig.validate) },
|
|
4741
|
+
condition: { schema: ConditionConfig.schema, validate: asValidator(ConditionConfig.validate) },
|
|
4742
|
+
for_each: { schema: ForEachConfig.schema, validate: asValidator(ForEachConfig.validate) },
|
|
4743
|
+
file_operation: { schema: FileOperationConfig.schema, validate: asValidator(FileOperationConfig.validate) },
|
|
4744
|
+
format: { schema: FormatConfig.schema, validate: asValidator(FormatConfig.validate) },
|
|
4745
|
+
manual_trigger: { schema: ManualTriggerConfig.schema, validate: asValidator(ManualTriggerConfig.validate) },
|
|
4746
|
+
schedule_trigger: { schema: ScheduleTriggerConfig.schema, validate: asValidator(ScheduleTriggerConfig.validate) },
|
|
4747
|
+
webhook_trigger: { schema: WebhookTriggerConfig.schema, validate: asValidator(WebhookTriggerConfig.validate) },
|
|
4748
|
+
debug: { schema: DebugConfig.schema, validate: asValidator(DebugConfig.validate) },
|
|
4749
|
+
error: { schema: ErrorConfig.schema, validate: asValidator(ErrorConfig.validate) },
|
|
4750
|
+
variables: { schema: VariablesConfig.schema, validate: asValidator(VariablesConfig.validate) }
|
|
4751
|
+
};
|
|
4752
|
+
function contractFor(actionId) {
|
|
4753
|
+
return actionId ? CONFIG_CONTRACTS[actionId] : undefined;
|
|
4754
|
+
}
|
|
4755
|
+
function declaredKeys(actionId) {
|
|
4756
|
+
const c = contractFor(actionId);
|
|
4757
|
+
if (!c)
|
|
4758
|
+
return [];
|
|
4759
|
+
return Object.entries(c.schema).filter(([, f]) => f.type !== "none").map(([k]) => k);
|
|
4760
|
+
}
|
|
4761
|
+
function isEditorPrivateKey(key) {
|
|
4762
|
+
return key.startsWith("_");
|
|
4763
|
+
}
|
|
4764
|
+
var CONTRACT_TYPE_TO_FIELD_TYPE = {
|
|
4765
|
+
string: "string" /* String */,
|
|
4766
|
+
text: "string" /* String */,
|
|
4767
|
+
select: "select" /* Select */,
|
|
4768
|
+
json: "json" /* JSON */,
|
|
4769
|
+
connection: "connection" /* Connection */,
|
|
4770
|
+
number: "number" /* Number */,
|
|
4771
|
+
boolean: "boolean" /* Boolean */,
|
|
4772
|
+
array: "array" /* Array */,
|
|
4773
|
+
object: "object" /* Object */,
|
|
4774
|
+
url: "url" /* URL */,
|
|
4775
|
+
expression: "expression" /* Expression */,
|
|
4776
|
+
code: "code" /* Code */
|
|
4777
|
+
};
|
|
4778
|
+
function humanise(key) {
|
|
4779
|
+
return key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/^\w/, (c) => c.toUpperCase());
|
|
4780
|
+
}
|
|
4781
|
+
function contractFieldsFor(definition) {
|
|
4782
|
+
const declared = definition.inputSchema?.fields ?? [];
|
|
4783
|
+
const contract = contractFor(definition.id);
|
|
4784
|
+
if (!contract)
|
|
4785
|
+
return declared;
|
|
4786
|
+
const seen = new Set(declared.map((f) => f.key));
|
|
4787
|
+
const derived = [];
|
|
4788
|
+
for (const [key, field] of Object.entries(contract.schema)) {
|
|
4789
|
+
if (seen.has(key) || field.type === "none")
|
|
4790
|
+
continue;
|
|
4791
|
+
derived.push({
|
|
4792
|
+
key,
|
|
4793
|
+
label: humanise(key),
|
|
4794
|
+
type: CONTRACT_TYPE_TO_FIELD_TYPE[field.type] ?? "string" /* String */,
|
|
4795
|
+
validation: { required: field.required === true },
|
|
4796
|
+
...field.options ? { options: field.options.map((v) => ({ label: String(v), value: v })) } : {}
|
|
4797
|
+
});
|
|
4798
|
+
}
|
|
4799
|
+
return [...declared, ...derived];
|
|
4800
|
+
}
|
|
4801
|
+
function contractDrift(definition) {
|
|
4802
|
+
const contract = contractFor(definition.id);
|
|
4803
|
+
if (!contract)
|
|
4804
|
+
return [];
|
|
4805
|
+
const covers = (key) => {
|
|
4806
|
+
if (key in contract.schema)
|
|
4807
|
+
return true;
|
|
4808
|
+
const root = key.split(".")[0];
|
|
4809
|
+
const rootField = contract.schema[root];
|
|
4810
|
+
return !!rootField && (rootField.type === "object" || rootField.type === "json");
|
|
4811
|
+
};
|
|
4812
|
+
return (definition.inputSchema?.fields ?? []).map((f) => f.key).filter((k) => !covers(k));
|
|
4813
|
+
}
|
|
4814
|
+
function contractVocabularyDrift(actionId) {
|
|
4815
|
+
const c = contractFor(actionId);
|
|
4816
|
+
if (!c)
|
|
4817
|
+
return [];
|
|
4818
|
+
const known = new Set([...Object.keys(CONTRACT_TYPE_TO_FIELD_TYPE), "none"]);
|
|
4819
|
+
return Object.entries(c.schema).filter(([, f]) => !known.has(f.type)).map(([k, f]) => `${k}:${f.type}`);
|
|
4820
|
+
}
|
|
4821
|
+
|
|
3999
4822
|
// src/rules/configSafety.ts
|
|
4000
4823
|
var MAX_STEP_CONFIG_BYTES = 256 * 1024;
|
|
4001
4824
|
var FORBIDDEN_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
@@ -4104,7 +4927,7 @@ function validateStepConfig(step) {
|
|
|
4104
4927
|
const definition = typeof step.actionDefinitionId === "string" ? getActionById(step.actionDefinitionId) : undefined;
|
|
4105
4928
|
if (!definition)
|
|
4106
4929
|
return issues;
|
|
4107
|
-
const declared = new Map(definition.
|
|
4930
|
+
const declared = new Map(contractFieldsFor(definition).map((f) => [f.key, f]));
|
|
4108
4931
|
const entries = Object.entries(config);
|
|
4109
4932
|
for (const [key, value] of entries) {
|
|
4110
4933
|
const field = declared.get(key);
|
|
@@ -4239,6 +5062,7 @@ export {
|
|
|
4239
5062
|
ActionType,
|
|
4240
5063
|
AggregateFunction,
|
|
4241
5064
|
CONDITION_OPERATORS,
|
|
5065
|
+
CONFIG_CONTRACTS,
|
|
4242
5066
|
ConditionConfig,
|
|
4243
5067
|
DATABASE_CONNECTOR_IDS,
|
|
4244
5068
|
DebugConfig,
|
|
@@ -4266,6 +5090,11 @@ export {
|
|
|
4266
5090
|
collectArrayPaths,
|
|
4267
5091
|
collectArrayPathsFromSample,
|
|
4268
5092
|
configErrors,
|
|
5093
|
+
contractDrift,
|
|
5094
|
+
contractFieldsFor,
|
|
5095
|
+
contractFor,
|
|
5096
|
+
contractVocabularyDrift,
|
|
5097
|
+
declaredKeys,
|
|
4269
5098
|
emailDefinition,
|
|
4270
5099
|
flattenNestedWorkflow,
|
|
4271
5100
|
generateConnectionsFromSteps,
|
|
@@ -4281,6 +5110,7 @@ export {
|
|
|
4281
5110
|
getNodeValidationStatus,
|
|
4282
5111
|
getStorageProvider,
|
|
4283
5112
|
inferSchemaFromSample,
|
|
5113
|
+
isEditorPrivateKey,
|
|
4284
5114
|
isMappingFunction,
|
|
4285
5115
|
isQueryableConnector,
|
|
4286
5116
|
mappingTransformFunctionName,
|