isc-transforms-mcp 1.0.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/JSONS/authoritative-operation-catalog.json +280 -0
- package/JSONS/sailpoint.isc.transforms.accountAttribute.schema.json +164 -0
- package/JSONS/sailpoint.isc.transforms.base64Decode.schema.json +37 -0
- package/JSONS/sailpoint.isc.transforms.base64Encode.schema.json +32 -0
- package/JSONS/sailpoint.isc.transforms.concat.schema.json +109 -0
- package/JSONS/sailpoint.isc.transforms.conditional.schema.json +161 -0
- package/JSONS/sailpoint.isc.transforms.dateCompare.schema.json +159 -0
- package/JSONS/sailpoint.isc.transforms.dateFormat.schema.json +101 -0
- package/JSONS/sailpoint.isc.transforms.dateMath.schema.json +119 -0
- package/JSONS/sailpoint.isc.transforms.decomposeDiacriticalMarks.schema.json +92 -0
- package/JSONS/sailpoint.isc.transforms.displayName.schema.json +42 -0
- package/JSONS/sailpoint.isc.transforms.e164phone.schema.json +107 -0
- package/JSONS/sailpoint.isc.transforms.firstValid.schema.json +129 -0
- package/JSONS/sailpoint.isc.transforms.generateRandomString.schema.json +94 -0
- package/JSONS/sailpoint.isc.transforms.getEndOfString.schema.json +118 -0
- package/JSONS/sailpoint.isc.transforms.getReferenceIdentityAttribute.schema.json +79 -0
- package/JSONS/sailpoint.isc.transforms.identityAttribute.schema.json +104 -0
- package/JSONS/sailpoint.isc.transforms.index.schema.json +48 -0
- package/JSONS/sailpoint.isc.transforms.indexOf.schema.json +90 -0
- package/JSONS/sailpoint.isc.transforms.iso3166.schema.json +103 -0
- package/JSONS/sailpoint.isc.transforms.join.schema.json +113 -0
- package/JSONS/sailpoint.isc.transforms.lastIndexOf.schema.json +90 -0
- package/JSONS/sailpoint.isc.transforms.leftPad.schema.json +96 -0
- package/JSONS/sailpoint.isc.transforms.lookup.schema.json +100 -0
- package/JSONS/sailpoint.isc.transforms.lower.schema.json +80 -0
- package/JSONS/sailpoint.isc.transforms.normalizeNames.schema.json +79 -0
- package/JSONS/sailpoint.isc.transforms.randomAlphaNumeric.schema.json +53 -0
- package/JSONS/sailpoint.isc.transforms.randomNumeric.schema.json +53 -0
- package/JSONS/sailpoint.isc.transforms.reference.schema.json +90 -0
- package/JSONS/sailpoint.isc.transforms.replace.schema.json +96 -0
- package/JSONS/sailpoint.isc.transforms.replaceAll.schema.json +96 -0
- package/JSONS/sailpoint.isc.transforms.rfc5646.schema.json +79 -0
- package/JSONS/sailpoint.isc.transforms.rightPad.schema.json +96 -0
- package/JSONS/sailpoint.isc.transforms.rule.schema.json +106 -0
- package/JSONS/sailpoint.isc.transforms.split.schema.json +103 -0
- package/JSONS/sailpoint.isc.transforms.static.schema.json +131 -0
- package/JSONS/sailpoint.isc.transforms.substring.schema.json +167 -0
- package/JSONS/sailpoint.isc.transforms.trim.schema.json +93 -0
- package/JSONS/sailpoint.isc.transforms.upper.schema.json +80 -0
- package/JSONS/sailpoint.isc.transforms.usernameGenerator.schema.json +106 -0
- package/JSONS/sailpoint.isc.transforms.uuid.schema.json +32 -0
- package/LICENSE +21 -0
- package/README.md +221 -0
- package/bin/isc-transforms-mcp.mjs +3 -0
- package/dist/allowlist.js +37 -0
- package/dist/config.js +67 -0
- package/dist/http/errors.js +19 -0
- package/dist/http/iscAuth.js +45 -0
- package/dist/http/iscClient.js +73 -0
- package/dist/index.js +613 -0
- package/dist/logger.js +9 -0
- package/dist/redact.js +28 -0
- package/dist/transforms/catalog.js +566 -0
- package/dist/transforms/explain.js +266 -0
- package/dist/transforms/generate.js +551 -0
- package/dist/transforms/index.js +9 -0
- package/dist/transforms/lint.js +839 -0
- package/dist/transforms/normalize.js +96 -0
- package/dist/transforms/patterns.js +295 -0
- package/dist/transforms/testcases.js +350 -0
- package/dist/transforms/validate.js +250 -0
- package/dist/util/diff.js +23 -0
- package/package.json +76 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
// src/transforms/catalog.ts
|
|
2
|
+
/**
|
|
3
|
+
* Transform operation catalog for SailPoint Identity Security Cloud (ISC).
|
|
4
|
+
*
|
|
5
|
+
* Source of truth (official SailPoint docs):
|
|
6
|
+
* - Operations index: https://developer.sailpoint.com/docs/extensibility/transforms/operations/
|
|
7
|
+
* - Individual operation pages are linked from the index above.
|
|
8
|
+
*
|
|
9
|
+
* Notes:
|
|
10
|
+
* - Some "operations" (e.g., generateRandomString, getEndOfString, getReferenceIdentityAttribute) are implemented
|
|
11
|
+
* as *rule-backed* transforms via the SailPoint-provided rule named "Cloud Services Deployment Utility".
|
|
12
|
+
* In those cases, the *payload* sent to ISC is `{ type: "rule", attributes: { name: "Cloud Services Deployment Utility", operation: "<op>", ... } }`.
|
|
13
|
+
* The catalog keeps the "operation key" (e.g., "generateRandomString") so the MCP can lint/guide users,
|
|
14
|
+
* while normalization can emit the correct `type: "rule"` payload.
|
|
15
|
+
*/
|
|
16
|
+
const DOCS_BASE = "https://developer.sailpoint.com/docs/extensibility/transforms/operations";
|
|
17
|
+
const doc = (slug) => `${DOCS_BASE}/${slug}/`;
|
|
18
|
+
const CSDU_RULE_NAME = "Cloud Services Deployment Utility"; // Official SailPoint rule name (see rule-backed operation docs)
|
|
19
|
+
function buildRuleBackedSpec(opts) {
|
|
20
|
+
const injected = { name: CSDU_RULE_NAME, operation: opts.op };
|
|
21
|
+
return {
|
|
22
|
+
type: opts.op,
|
|
23
|
+
title: `${opts.title} (rule-backed)`,
|
|
24
|
+
docUrl: doc(opts.docSlug),
|
|
25
|
+
// Final payload must include name + operation + user attrs
|
|
26
|
+
requiredAttributes: ["name", "operation", ...opts.requiredUserAttributes],
|
|
27
|
+
requiredUserAttributes: [...opts.requiredUserAttributes],
|
|
28
|
+
injectedAttributes: injected,
|
|
29
|
+
attributesOptional: false,
|
|
30
|
+
scaffold: (name) => ({
|
|
31
|
+
type: "rule",
|
|
32
|
+
name,
|
|
33
|
+
attributes: {
|
|
34
|
+
...injected,
|
|
35
|
+
...opts.scaffoldAttributes,
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// Rule-backed operations via CSDU
|
|
41
|
+
const ruleBacked = {
|
|
42
|
+
generateRandomString: buildRuleBackedSpec({
|
|
43
|
+
op: "generateRandomString",
|
|
44
|
+
title: "Generate Random String",
|
|
45
|
+
docSlug: "generate-random-string",
|
|
46
|
+
requiredUserAttributes: ["length", "includeNumbers", "includeSpecialChars"],
|
|
47
|
+
scaffoldAttributes: {
|
|
48
|
+
// Docs: max length is 450; includeNumbers/includeSpecialChars are strings "true"/"false"
|
|
49
|
+
length: "16",
|
|
50
|
+
includeNumbers: "true",
|
|
51
|
+
includeSpecialChars: "true",
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
getEndOfString: buildRuleBackedSpec({
|
|
55
|
+
op: "getEndOfString",
|
|
56
|
+
title: "Get End of String",
|
|
57
|
+
docSlug: "get-end-of-string",
|
|
58
|
+
requiredUserAttributes: ["numChars"],
|
|
59
|
+
scaffoldAttributes: {
|
|
60
|
+
numChars: "4",
|
|
61
|
+
// optional: input
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
getReferenceIdentityAttribute: buildRuleBackedSpec({
|
|
65
|
+
op: "getReferenceIdentityAttribute",
|
|
66
|
+
title: "Get Reference Identity Attribute",
|
|
67
|
+
docSlug: "get-reference-identity-attribute",
|
|
68
|
+
requiredUserAttributes: ["uid", "attributeName"],
|
|
69
|
+
scaffoldAttributes: {
|
|
70
|
+
// uid = Identity user name or "manager" keyword; attributeName = identity attribute system name
|
|
71
|
+
uid: "2c9180...EXAMPLE_ID",
|
|
72
|
+
attributeName: "email",
|
|
73
|
+
},
|
|
74
|
+
}),
|
|
75
|
+
};
|
|
76
|
+
export const TRANSFORM_CATALOG = {
|
|
77
|
+
// --- Standard transforms (payload type == catalog key) ---
|
|
78
|
+
accountAttribute: {
|
|
79
|
+
type: "accountAttribute",
|
|
80
|
+
title: "Account Attribute",
|
|
81
|
+
docUrl: doc("account-attribute"),
|
|
82
|
+
// Docs allow one of: sourceName OR applicationId/applicationName (plus attributeName)
|
|
83
|
+
requiredAttributes: ["attributeName", "sourceName|applicationId|applicationName"],
|
|
84
|
+
requiredUserAttributes: ["attributeName", "sourceName|applicationId|applicationName"],
|
|
85
|
+
attributesOptional: false,
|
|
86
|
+
scaffold: (name) => ({
|
|
87
|
+
type: "accountAttribute",
|
|
88
|
+
name,
|
|
89
|
+
attributes: {
|
|
90
|
+
sourceName: "HR Source",
|
|
91
|
+
attributeName: "department",
|
|
92
|
+
// Optional filters (examples in docs):
|
|
93
|
+
// accountPropertyFilter: "(department == \"Engineering\")",
|
|
94
|
+
// accountFilter: "Employee",
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
},
|
|
98
|
+
base64Decode: {
|
|
99
|
+
type: "base64Decode",
|
|
100
|
+
title: "Base64 Decode",
|
|
101
|
+
docUrl: doc("base64-decode"),
|
|
102
|
+
attributesOptional: true,
|
|
103
|
+
scaffold: (name) => ({ type: "base64Decode", name }),
|
|
104
|
+
},
|
|
105
|
+
base64Encode: {
|
|
106
|
+
type: "base64Encode",
|
|
107
|
+
title: "Base64 Encode",
|
|
108
|
+
docUrl: doc("base64-encode"),
|
|
109
|
+
attributesOptional: true,
|
|
110
|
+
scaffold: (name) => ({ type: "base64Encode", name }),
|
|
111
|
+
},
|
|
112
|
+
concat: {
|
|
113
|
+
type: "concat",
|
|
114
|
+
title: "Concatenation",
|
|
115
|
+
docUrl: doc("concatenation"),
|
|
116
|
+
requiredAttributes: ["values"],
|
|
117
|
+
attributesOptional: false,
|
|
118
|
+
scaffold: (name) => ({
|
|
119
|
+
type: "concat",
|
|
120
|
+
name,
|
|
121
|
+
attributes: {
|
|
122
|
+
values: [
|
|
123
|
+
{ type: "identityAttribute", attributes: { name: "givenName" } },
|
|
124
|
+
" ",
|
|
125
|
+
{ type: "identityAttribute", attributes: { name: "sn" } },
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
}),
|
|
129
|
+
},
|
|
130
|
+
conditional: {
|
|
131
|
+
type: "conditional",
|
|
132
|
+
title: "Conditional",
|
|
133
|
+
docUrl: doc("conditional"),
|
|
134
|
+
requiredAttributes: ["expression", "positiveCondition", "negativeCondition"],
|
|
135
|
+
attributesOptional: false,
|
|
136
|
+
scaffold: (name) => ({
|
|
137
|
+
type: "conditional",
|
|
138
|
+
name,
|
|
139
|
+
attributes: {
|
|
140
|
+
// Optional variables can be defined and referenced via $variableName syntax.
|
|
141
|
+
department: {
|
|
142
|
+
type: "accountAttribute",
|
|
143
|
+
attributes: { sourceName: "HR Source", attributeName: "department" },
|
|
144
|
+
},
|
|
145
|
+
// Docs: expression follows "ValueA eq ValueB" and `eq` is the only valid operator.
|
|
146
|
+
// Example: "$department eq Engineering"
|
|
147
|
+
expression: "$department eq Engineering",
|
|
148
|
+
positiveCondition: "ENG",
|
|
149
|
+
negativeCondition: "NONENG",
|
|
150
|
+
},
|
|
151
|
+
}),
|
|
152
|
+
},
|
|
153
|
+
dateCompare: {
|
|
154
|
+
type: "dateCompare",
|
|
155
|
+
title: "Date Compare",
|
|
156
|
+
docUrl: doc("date-compare"),
|
|
157
|
+
// SailPoint docs show dateCompare returns positiveCondition/negativeCondition values.
|
|
158
|
+
// Source: https://developer.sailpoint.com/docs/extensibility/transforms/operations/date-compare/
|
|
159
|
+
requiredAttributes: ["firstDate", "secondDate", "operator", "positiveCondition", "negativeCondition"],
|
|
160
|
+
attributesOptional: false,
|
|
161
|
+
scaffold: (name) => ({
|
|
162
|
+
type: "dateCompare",
|
|
163
|
+
name,
|
|
164
|
+
attributes: {
|
|
165
|
+
firstDate: "2025-01-01T00:00:00Z",
|
|
166
|
+
secondDate: "2025-01-31T00:00:00Z",
|
|
167
|
+
operator: "LT",
|
|
168
|
+
positiveCondition: "true",
|
|
169
|
+
negativeCondition: "false",
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
},
|
|
173
|
+
dateFormat: {
|
|
174
|
+
type: "dateFormat",
|
|
175
|
+
title: "Date Format",
|
|
176
|
+
docUrl: doc("date-format"),
|
|
177
|
+
// Docs: inputFormat and outputFormat are both optional (default: ISO8601)
|
|
178
|
+
requiredAttributes: [],
|
|
179
|
+
attributesOptional: true,
|
|
180
|
+
scaffold: (name) => ({
|
|
181
|
+
type: "dateFormat",
|
|
182
|
+
name,
|
|
183
|
+
attributes: {
|
|
184
|
+
inputFormat: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
|
|
185
|
+
outputFormat: "yyyy-MM-dd",
|
|
186
|
+
// Optional: input
|
|
187
|
+
},
|
|
188
|
+
}),
|
|
189
|
+
},
|
|
190
|
+
dateMath: {
|
|
191
|
+
type: "dateMath",
|
|
192
|
+
title: "Date Math",
|
|
193
|
+
docUrl: doc("date-math"),
|
|
194
|
+
requiredAttributes: ["expression"],
|
|
195
|
+
attributesOptional: false,
|
|
196
|
+
scaffold: (name) => ({
|
|
197
|
+
type: "dateMath",
|
|
198
|
+
name,
|
|
199
|
+
attributes: {
|
|
200
|
+
expression: "now+1w",
|
|
201
|
+
},
|
|
202
|
+
}),
|
|
203
|
+
},
|
|
204
|
+
decomposeDiacriticalMarks: {
|
|
205
|
+
type: "decomposeDiacriticalMarks",
|
|
206
|
+
title: "Decompose Diacritical Marks",
|
|
207
|
+
docUrl: doc("decompose-diacritical-marks"),
|
|
208
|
+
attributesOptional: true,
|
|
209
|
+
scaffold: (name) => ({ type: "decomposeDiacriticalMarks", name }),
|
|
210
|
+
},
|
|
211
|
+
displayName: {
|
|
212
|
+
type: "displayName",
|
|
213
|
+
title: "Display Name",
|
|
214
|
+
docUrl: doc("display-name"),
|
|
215
|
+
requiredAttributes: ["input"], // docs require attributes object; include input placeholder
|
|
216
|
+
attributesOptional: false,
|
|
217
|
+
scaffold: (name) => ({
|
|
218
|
+
type: "displayName",
|
|
219
|
+
name,
|
|
220
|
+
attributes: { input: "input" },
|
|
221
|
+
}),
|
|
222
|
+
},
|
|
223
|
+
e164phone: {
|
|
224
|
+
type: "e164phone",
|
|
225
|
+
title: "E.164 Phone",
|
|
226
|
+
docUrl: doc("e-164-phone"),
|
|
227
|
+
// Docs: defaultRegion is optional (default: "US")
|
|
228
|
+
requiredAttributes: [],
|
|
229
|
+
attributesOptional: true,
|
|
230
|
+
scaffold: (name) => ({
|
|
231
|
+
type: "e164phone",
|
|
232
|
+
name,
|
|
233
|
+
attributes: { defaultRegion: "US" },
|
|
234
|
+
}),
|
|
235
|
+
},
|
|
236
|
+
firstValid: {
|
|
237
|
+
type: "firstValid",
|
|
238
|
+
title: "First Valid",
|
|
239
|
+
docUrl: doc("first-valid"),
|
|
240
|
+
requiredAttributes: ["values"],
|
|
241
|
+
attributesOptional: false,
|
|
242
|
+
scaffold: (name) => ({
|
|
243
|
+
type: "firstValid",
|
|
244
|
+
name,
|
|
245
|
+
attributes: {
|
|
246
|
+
values: [
|
|
247
|
+
{ type: "identityAttribute", attributes: { name: "preferredName" } },
|
|
248
|
+
{ type: "identityAttribute", attributes: { name: "givenName" } },
|
|
249
|
+
"UNKNOWN",
|
|
250
|
+
],
|
|
251
|
+
},
|
|
252
|
+
}),
|
|
253
|
+
},
|
|
254
|
+
identityAttribute: {
|
|
255
|
+
type: "identityAttribute",
|
|
256
|
+
title: "Identity Attribute",
|
|
257
|
+
docUrl: doc("identity-attribute"),
|
|
258
|
+
requiredAttributes: ["name"],
|
|
259
|
+
attributesOptional: false,
|
|
260
|
+
scaffold: (name) => ({
|
|
261
|
+
type: "identityAttribute",
|
|
262
|
+
name,
|
|
263
|
+
attributes: { name: "email" },
|
|
264
|
+
}),
|
|
265
|
+
},
|
|
266
|
+
indexOf: {
|
|
267
|
+
type: "indexOf",
|
|
268
|
+
title: "Index Of",
|
|
269
|
+
docUrl: doc("index-of"),
|
|
270
|
+
requiredAttributes: ["substring"],
|
|
271
|
+
attributesOptional: false,
|
|
272
|
+
scaffold: (name) => ({
|
|
273
|
+
type: "indexOf",
|
|
274
|
+
name,
|
|
275
|
+
attributes: { substring: "@" },
|
|
276
|
+
}),
|
|
277
|
+
},
|
|
278
|
+
iso3166: {
|
|
279
|
+
type: "iso3166",
|
|
280
|
+
title: "ISO3166",
|
|
281
|
+
docUrl: doc("iso3166"),
|
|
282
|
+
// Docs: format is optional (default: "alpha2"). No "defaultRegion" attribute exists for iso3166.
|
|
283
|
+
requiredAttributes: [],
|
|
284
|
+
attributesOptional: true,
|
|
285
|
+
scaffold: (name) => ({
|
|
286
|
+
type: "iso3166",
|
|
287
|
+
name,
|
|
288
|
+
attributes: { format: "alpha2" },
|
|
289
|
+
}),
|
|
290
|
+
},
|
|
291
|
+
join: {
|
|
292
|
+
type: "join",
|
|
293
|
+
title: "Join",
|
|
294
|
+
docUrl: doc("join"),
|
|
295
|
+
// Docs: "values" is required. "separator" is optional (default: ","). Docs use "separator", NOT "delimiter".
|
|
296
|
+
requiredAttributes: ["values"],
|
|
297
|
+
attributesOptional: false,
|
|
298
|
+
scaffold: (name) => ({
|
|
299
|
+
type: "join",
|
|
300
|
+
name,
|
|
301
|
+
attributes: { values: ["a", "b", "c"], separator: "," },
|
|
302
|
+
}),
|
|
303
|
+
},
|
|
304
|
+
lastIndexOf: {
|
|
305
|
+
type: "lastIndexOf",
|
|
306
|
+
title: "Last Index Of",
|
|
307
|
+
docUrl: doc("last-index-of"),
|
|
308
|
+
requiredAttributes: ["substring"],
|
|
309
|
+
attributesOptional: false,
|
|
310
|
+
scaffold: (name) => ({
|
|
311
|
+
type: "lastIndexOf",
|
|
312
|
+
name,
|
|
313
|
+
attributes: { substring: "/" },
|
|
314
|
+
}),
|
|
315
|
+
},
|
|
316
|
+
leftPad: {
|
|
317
|
+
type: "leftPad",
|
|
318
|
+
title: "Left Pad",
|
|
319
|
+
docUrl: doc("left-pad"),
|
|
320
|
+
// Docs: "length" is required. "padding" is optional (default: single space " ").
|
|
321
|
+
requiredAttributes: ["length"],
|
|
322
|
+
attributesOptional: false,
|
|
323
|
+
scaffold: (name) => ({
|
|
324
|
+
type: "leftPad",
|
|
325
|
+
name,
|
|
326
|
+
attributes: { length: "8", padding: "0" },
|
|
327
|
+
}),
|
|
328
|
+
},
|
|
329
|
+
lookup: {
|
|
330
|
+
type: "lookup",
|
|
331
|
+
title: "Lookup",
|
|
332
|
+
docUrl: doc("lookup"),
|
|
333
|
+
requiredAttributes: ["table"],
|
|
334
|
+
attributesOptional: false,
|
|
335
|
+
scaffold: (name) => ({
|
|
336
|
+
type: "lookup",
|
|
337
|
+
name,
|
|
338
|
+
attributes: {
|
|
339
|
+
table: { A: "Alpha", B: "Beta", default: "Unknown" },
|
|
340
|
+
},
|
|
341
|
+
}),
|
|
342
|
+
},
|
|
343
|
+
lower: {
|
|
344
|
+
type: "lower",
|
|
345
|
+
title: "Lower",
|
|
346
|
+
docUrl: doc("lower"),
|
|
347
|
+
attributesOptional: true,
|
|
348
|
+
scaffold: (name) => ({ type: "lower", name }),
|
|
349
|
+
},
|
|
350
|
+
normalizeNames: {
|
|
351
|
+
type: "normalizeNames",
|
|
352
|
+
title: "Name Normalizer",
|
|
353
|
+
docUrl: doc("name-normalizer"),
|
|
354
|
+
// Docs: type is "normalizeNames". No configurable attributes (regex/replacement are NOT part of this transform).
|
|
355
|
+
// The transform uses built-in normalization rules (capitalization, patronymic Mc/Mac, toponymic von/de, Roman numerals).
|
|
356
|
+
requiredAttributes: [],
|
|
357
|
+
attributesOptional: true,
|
|
358
|
+
scaffold: (name) => ({ type: "normalizeNames", name }),
|
|
359
|
+
},
|
|
360
|
+
randomAlphaNumeric: {
|
|
361
|
+
type: "randomAlphaNumeric",
|
|
362
|
+
title: "Random Alphanumeric",
|
|
363
|
+
docUrl: doc("random-alphanumeric"),
|
|
364
|
+
attributesOptional: true,
|
|
365
|
+
scaffold: (name) => ({ type: "randomAlphaNumeric", name, attributes: { length: "32" } }),
|
|
366
|
+
},
|
|
367
|
+
randomNumeric: {
|
|
368
|
+
type: "randomNumeric",
|
|
369
|
+
title: "Random Numeric",
|
|
370
|
+
docUrl: doc("random-numeric"),
|
|
371
|
+
attributesOptional: true,
|
|
372
|
+
scaffold: (name) => ({ type: "randomNumeric", name, attributes: { length: "10" } }),
|
|
373
|
+
},
|
|
374
|
+
reference: {
|
|
375
|
+
type: "reference",
|
|
376
|
+
title: "Reference",
|
|
377
|
+
docUrl: doc("reference"),
|
|
378
|
+
requiredAttributes: ["id"],
|
|
379
|
+
attributesOptional: false,
|
|
380
|
+
scaffold: (name) => ({
|
|
381
|
+
type: "reference",
|
|
382
|
+
name,
|
|
383
|
+
attributes: { id: "Existing Transform Name" },
|
|
384
|
+
}),
|
|
385
|
+
},
|
|
386
|
+
replaceAll: {
|
|
387
|
+
type: "replaceAll",
|
|
388
|
+
title: "Replace All",
|
|
389
|
+
docUrl: doc("replace-all"),
|
|
390
|
+
requiredAttributes: ["table"],
|
|
391
|
+
attributesOptional: false,
|
|
392
|
+
scaffold: (name) => ({
|
|
393
|
+
type: "replaceAll",
|
|
394
|
+
name,
|
|
395
|
+
attributes: {
|
|
396
|
+
table: { "-": "", " ": "" },
|
|
397
|
+
},
|
|
398
|
+
}),
|
|
399
|
+
},
|
|
400
|
+
replace: {
|
|
401
|
+
type: "replace",
|
|
402
|
+
title: "Replace",
|
|
403
|
+
docUrl: doc("replace"),
|
|
404
|
+
requiredAttributes: ["regex", "replacement"],
|
|
405
|
+
attributesOptional: false,
|
|
406
|
+
scaffold: (name) => ({
|
|
407
|
+
type: "replace",
|
|
408
|
+
name,
|
|
409
|
+
attributes: { regex: "[^a-zA-Z]", replacement: "" },
|
|
410
|
+
}),
|
|
411
|
+
},
|
|
412
|
+
rfc5646: {
|
|
413
|
+
type: "rfc5646",
|
|
414
|
+
title: "RFC5646",
|
|
415
|
+
docUrl: doc("rfc5646"),
|
|
416
|
+
requiredAttributes: ["format"],
|
|
417
|
+
attributesOptional: false,
|
|
418
|
+
scaffold: (name) => ({
|
|
419
|
+
type: "rfc5646",
|
|
420
|
+
name,
|
|
421
|
+
attributes: { format: "alpha2" },
|
|
422
|
+
}),
|
|
423
|
+
},
|
|
424
|
+
rightPad: {
|
|
425
|
+
type: "rightPad",
|
|
426
|
+
title: "Right Pad",
|
|
427
|
+
docUrl: doc("right-pad"),
|
|
428
|
+
// Docs: "length" is required. "padding" is optional (default: single space " ").
|
|
429
|
+
requiredAttributes: ["length"],
|
|
430
|
+
attributesOptional: false,
|
|
431
|
+
scaffold: (name) => ({
|
|
432
|
+
type: "rightPad",
|
|
433
|
+
name,
|
|
434
|
+
attributes: { length: "8", padding: "0" },
|
|
435
|
+
}),
|
|
436
|
+
},
|
|
437
|
+
rule: {
|
|
438
|
+
type: "rule",
|
|
439
|
+
title: "Rule",
|
|
440
|
+
docUrl: doc("rule"),
|
|
441
|
+
// Generic rule transform: docs require attributes.name (rule name). Operation is rule-specific.
|
|
442
|
+
requiredAttributes: ["name"],
|
|
443
|
+
attributesOptional: false,
|
|
444
|
+
scaffold: (name) => ({
|
|
445
|
+
type: "rule",
|
|
446
|
+
name,
|
|
447
|
+
attributes: { name: "My Custom Rule Name", operation: "optionalOperation" },
|
|
448
|
+
}),
|
|
449
|
+
},
|
|
450
|
+
split: {
|
|
451
|
+
type: "split",
|
|
452
|
+
title: "Split",
|
|
453
|
+
docUrl: doc("split"),
|
|
454
|
+
requiredAttributes: ["delimiter", "index"],
|
|
455
|
+
attributesOptional: false,
|
|
456
|
+
scaffold: (name) => ({
|
|
457
|
+
type: "split",
|
|
458
|
+
name,
|
|
459
|
+
attributes: { delimiter: ",", index: 0 },
|
|
460
|
+
}),
|
|
461
|
+
},
|
|
462
|
+
static: {
|
|
463
|
+
type: "static",
|
|
464
|
+
title: "Static",
|
|
465
|
+
docUrl: doc("static"),
|
|
466
|
+
requiredAttributes: ["value"],
|
|
467
|
+
attributesOptional: false,
|
|
468
|
+
scaffold: (name) => ({
|
|
469
|
+
type: "static",
|
|
470
|
+
name,
|
|
471
|
+
attributes: { value: "HelloWorld" },
|
|
472
|
+
}),
|
|
473
|
+
},
|
|
474
|
+
substring: {
|
|
475
|
+
type: "substring",
|
|
476
|
+
title: "Substring",
|
|
477
|
+
docUrl: doc("substring"),
|
|
478
|
+
// Docs: "begin" is required. "end" is optional (defaults to end of string / -1).
|
|
479
|
+
requiredAttributes: ["begin"],
|
|
480
|
+
attributesOptional: false,
|
|
481
|
+
scaffold: (name) => ({
|
|
482
|
+
type: "substring",
|
|
483
|
+
name,
|
|
484
|
+
attributes: { begin: 0, end: 5 },
|
|
485
|
+
}),
|
|
486
|
+
},
|
|
487
|
+
trim: {
|
|
488
|
+
type: "trim",
|
|
489
|
+
title: "Trim",
|
|
490
|
+
docUrl: doc("trim"),
|
|
491
|
+
attributesOptional: true,
|
|
492
|
+
scaffold: (name) => ({ type: "trim", name }),
|
|
493
|
+
},
|
|
494
|
+
upper: {
|
|
495
|
+
type: "upper",
|
|
496
|
+
title: "Upper",
|
|
497
|
+
docUrl: doc("upper"),
|
|
498
|
+
attributesOptional: true,
|
|
499
|
+
scaffold: (name) => ({ type: "upper", name }),
|
|
500
|
+
},
|
|
501
|
+
usernameGenerator: {
|
|
502
|
+
type: "usernameGenerator",
|
|
503
|
+
title: "Username Generator",
|
|
504
|
+
docUrl: doc("username-generator"),
|
|
505
|
+
requiredAttributes: ["patterns"],
|
|
506
|
+
attributesOptional: false,
|
|
507
|
+
scaffold: (name) => ({
|
|
508
|
+
type: "usernameGenerator",
|
|
509
|
+
name,
|
|
510
|
+
attributes: {
|
|
511
|
+
// Minimal example; patterns and uniqueness settings vary by use-case.
|
|
512
|
+
patterns: ["${firstName}.${lastName}"],
|
|
513
|
+
},
|
|
514
|
+
}),
|
|
515
|
+
},
|
|
516
|
+
uuid: {
|
|
517
|
+
type: "uuid",
|
|
518
|
+
title: "UUID Generator",
|
|
519
|
+
docUrl: doc("uuid-generator"),
|
|
520
|
+
attributesOptional: true,
|
|
521
|
+
scaffold: (name) => ({ type: "uuid", name }),
|
|
522
|
+
},
|
|
523
|
+
// --- Rule-backed operation keys ---
|
|
524
|
+
...ruleBacked,
|
|
525
|
+
};
|
|
526
|
+
export function getTransformSpec(type) {
|
|
527
|
+
const t = toCanonicalType(type);
|
|
528
|
+
return t ? TRANSFORM_CATALOG[t] : undefined;
|
|
529
|
+
}
|
|
530
|
+
export function listTransformTypes() {
|
|
531
|
+
return Object.keys(TRANSFORM_CATALOG);
|
|
532
|
+
}
|
|
533
|
+
export function toCanonicalType(type) {
|
|
534
|
+
if (!type)
|
|
535
|
+
return undefined;
|
|
536
|
+
const t = String(type).trim();
|
|
537
|
+
// Accept some friendly aliases for people typing from docs/UI
|
|
538
|
+
const map = {
|
|
539
|
+
concatenation: "concat",
|
|
540
|
+
namenormalizer: "normalizeNames",
|
|
541
|
+
"name normalizer": "normalizeNames",
|
|
542
|
+
normalizenames: "normalizeNames",
|
|
543
|
+
join: "join",
|
|
544
|
+
"e.164phone": "e164phone",
|
|
545
|
+
"e164 phone": "e164phone",
|
|
546
|
+
iso3166: "iso3166",
|
|
547
|
+
"iso-3166": "iso3166",
|
|
548
|
+
"replace all": "replaceAll",
|
|
549
|
+
"replaceall": "replaceAll",
|
|
550
|
+
"random alphanumeric": "randomAlphaNumeric",
|
|
551
|
+
"random alphanum": "randomAlphaNumeric",
|
|
552
|
+
"random numeric": "randomNumeric",
|
|
553
|
+
"uuid generator": "uuid",
|
|
554
|
+
"username generator": "usernameGenerator",
|
|
555
|
+
"generate random string": "generateRandomString",
|
|
556
|
+
"get end of string": "getEndOfString",
|
|
557
|
+
"get reference identity attribute": "getReferenceIdentityAttribute",
|
|
558
|
+
};
|
|
559
|
+
const key = t.toLowerCase();
|
|
560
|
+
if (map[key])
|
|
561
|
+
return map[key];
|
|
562
|
+
// Exact match (case-sensitive API types)
|
|
563
|
+
if (TRANSFORM_CATALOG[t])
|
|
564
|
+
return t;
|
|
565
|
+
return undefined;
|
|
566
|
+
}
|