@autometa/cucumber-expressions 0.4.4 → 1.0.0-rc.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/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # Introduction
2
2
 
3
- There's nothing here yet
3
+ There's nothing here yet
@@ -0,0 +1,9 @@
1
+ import { ParameterType } from "@cucumber/cucumber-expressions";
2
+ export interface ParameterRuntime<World> {
3
+ readonly world: World;
4
+ readonly parameterType: ParameterType<unknown>;
5
+ }
6
+ export type ParameterTransformFn<World> = (values: readonly string[] | null, runtime: ParameterRuntime<World>) => unknown;
7
+ export declare function attachTransform<World>(parameterType: ParameterType<unknown>, transform: ParameterTransformFn<World>): void;
8
+ export declare function applyCucumberExtensions(): void;
9
+ export declare function resetCucumberExtensions(): void;
package/dist/index.cjs ADDED
@@ -0,0 +1,317 @@
1
+ 'use strict';
2
+
3
+ var cucumberExpressions = require('@cucumber/cucumber-expressions');
4
+
5
+ // src/parameter-types.ts
6
+ var transformSymbol = Symbol("autometa:cucumber:transform");
7
+ var extensionsApplied = false;
8
+ var originalTransform;
9
+ var originalGetValue;
10
+ function attachTransform(parameterType, transform) {
11
+ parameterType[transformSymbol] = transform;
12
+ }
13
+ function applyCucumberExtensions() {
14
+ if (extensionsApplied) {
15
+ return;
16
+ }
17
+ originalTransform = originalTransform ?? cucumberExpressions.ParameterType.prototype.transform;
18
+ cucumberExpressions.ParameterType.prototype.transform = function transform(thisObj, groupValues) {
19
+ const transformFn = this[transformSymbol];
20
+ if (transformFn) {
21
+ return transformFn(groupValues ?? null, {
22
+ world: thisObj,
23
+ parameterType: this
24
+ });
25
+ }
26
+ const normalized = groupValues ? [...groupValues] : [];
27
+ if (!originalTransform) {
28
+ throw new Error("Cucumber extensions have not been initialised correctly");
29
+ }
30
+ return originalTransform.call(this, thisObj, normalized);
31
+ };
32
+ originalGetValue = originalGetValue ?? cucumberExpressions.Argument.prototype.getValue;
33
+ cucumberExpressions.Argument.prototype.getValue = function getValue(context) {
34
+ const group = this.group;
35
+ let values = null;
36
+ if (group) {
37
+ const childValues = group.children?.map((child) => child.value).filter((value) => value !== void 0);
38
+ if (childValues && childValues.length > 0) {
39
+ values = childValues;
40
+ } else if (group.value !== void 0 && group.value !== null) {
41
+ values = [group.value];
42
+ } else if (group.values) {
43
+ values = group.values;
44
+ }
45
+ }
46
+ const parameterType = this.parameterType;
47
+ const transformFn = parameterType?.[transformSymbol];
48
+ if (transformFn && parameterType) {
49
+ return transformFn(values, {
50
+ world: context,
51
+ parameterType
52
+ });
53
+ }
54
+ if (!originalGetValue) {
55
+ throw new Error("Cucumber extensions have not been initialised correctly");
56
+ }
57
+ return originalGetValue.call(this, context);
58
+ };
59
+ extensionsApplied = true;
60
+ }
61
+ function resetCucumberExtensions() {
62
+ if (!extensionsApplied) {
63
+ return;
64
+ }
65
+ if (originalTransform) {
66
+ cucumberExpressions.ParameterType.prototype.transform = originalTransform;
67
+ }
68
+ if (originalGetValue) {
69
+ cucumberExpressions.Argument.prototype.getValue = originalGetValue;
70
+ }
71
+ extensionsApplied = false;
72
+ }
73
+
74
+ // src/parameter-types.ts
75
+ function toPatternArray(pattern) {
76
+ return Array.isArray(pattern) ? [...pattern] : [pattern];
77
+ }
78
+ function buildDefaultValue(rawValues) {
79
+ if (rawValues.length === 0) {
80
+ return void 0;
81
+ }
82
+ if (rawValues.length === 1) {
83
+ return rawValues[0];
84
+ }
85
+ return [...rawValues];
86
+ }
87
+ function resolveScopedName(name, namespace) {
88
+ if (!name || !namespace) {
89
+ return name;
90
+ }
91
+ return `${namespace}:${name}`;
92
+ }
93
+ function buildTransform(definition, scopedName, options) {
94
+ return (values, runtime) => {
95
+ const rawValues = values ?? [];
96
+ const resolved = buildDefaultValue(rawValues);
97
+ if (definition.transform) {
98
+ const context = {
99
+ raw: rawValues,
100
+ world: runtime.world,
101
+ name: scopedName,
102
+ originalName: definition.name,
103
+ parameterType: runtime.parameterType,
104
+ definition,
105
+ ...options?.namespace !== void 0 ? { namespace: options.namespace } : {}
106
+ };
107
+ return definition.transform(resolved, context);
108
+ }
109
+ return resolved;
110
+ };
111
+ }
112
+ function firstValue(input) {
113
+ return Array.isArray(input) ? input[0] : input;
114
+ }
115
+ function firstString(input) {
116
+ const value = firstValue(input);
117
+ if (value === void 0 || value === null) {
118
+ return void 0;
119
+ }
120
+ return String(value);
121
+ }
122
+ function parseNumberValue(input, parser) {
123
+ const raw = firstString(input);
124
+ if (raw === void 0) {
125
+ return null;
126
+ }
127
+ const numeric = parser(raw);
128
+ return Number.isNaN(numeric) ? null : numeric;
129
+ }
130
+ function parseBigIntValue(input) {
131
+ const raw = firstString(input);
132
+ if (raw === void 0) {
133
+ return null;
134
+ }
135
+ try {
136
+ return BigInt(raw);
137
+ } catch {
138
+ return null;
139
+ }
140
+ }
141
+ function createParameterTypes(options) {
142
+ applyCucumberExtensions();
143
+ const define = (registry, definition) => {
144
+ const patterns = toPatternArray(definition.pattern);
145
+ const scopedName = resolveScopedName(definition.name, options?.namespace);
146
+ const transform = buildTransform(definition, scopedName, options);
147
+ const parameterType = new cucumberExpressions.ParameterType(
148
+ scopedName,
149
+ patterns,
150
+ null,
151
+ // The original transform is overridden by applyCucumberExtensions.
152
+ (...matches) => matches.length <= 1 ? matches[0] : matches,
153
+ definition.useForSnippets,
154
+ definition.preferForRegexpMatch,
155
+ definition.builtin
156
+ );
157
+ attachTransform(parameterType, transform);
158
+ registry.defineParameterType(parameterType);
159
+ return parameterType;
160
+ };
161
+ define.many = (registry, ...definitions) => {
162
+ const list = definitions.length === 1 && Array.isArray(definitions[0]) ? definitions[0] : definitions;
163
+ list.forEach((definition) => {
164
+ define(registry, definition);
165
+ });
166
+ return registry;
167
+ };
168
+ return define;
169
+ }
170
+ var defineParameterType = createParameterTypes();
171
+ var INTEGER_REGEXPS = [/-?\d+/, /\d+/];
172
+ var FLOAT_REGEXP = /(?=.*\d.*)[-+]?\d*(?:\.(?=\d.*))?\d*(?:\d+[E][+-]?\d+)?/;
173
+ var WORD_REGEXP = /[^\s]+/;
174
+ var STRING_REGEXP = /"([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'/;
175
+ var ANONYMOUS_REGEXP = /.*/;
176
+ function createDefaultParameterTypes(options) {
177
+ const define = createParameterTypes(options);
178
+ return (registry) => {
179
+ const defaults = [
180
+ {
181
+ name: "int",
182
+ pattern: INTEGER_REGEXPS,
183
+ transform: (value) => parseNumberValue(value, (raw) => parseInt(raw, 10)),
184
+ useForSnippets: true,
185
+ preferForRegexpMatch: true,
186
+ builtin: true
187
+ },
188
+ {
189
+ name: "float",
190
+ pattern: FLOAT_REGEXP,
191
+ transform: (value) => parseNumberValue(value, (raw) => parseFloat(raw)),
192
+ useForSnippets: true,
193
+ preferForRegexpMatch: false,
194
+ builtin: true
195
+ },
196
+ {
197
+ name: "number",
198
+ pattern: FLOAT_REGEXP,
199
+ transform: (value) => parseNumberValue(value, (raw) => parseFloat(raw)),
200
+ useForSnippets: true,
201
+ preferForRegexpMatch: false,
202
+ builtin: true
203
+ },
204
+ {
205
+ name: "word",
206
+ pattern: WORD_REGEXP,
207
+ transform: (value) => firstString(value) ?? "",
208
+ useForSnippets: false,
209
+ preferForRegexpMatch: false,
210
+ builtin: true
211
+ },
212
+ {
213
+ name: "string",
214
+ pattern: STRING_REGEXP,
215
+ transform: (_value, context) => {
216
+ const [doubleQuoted, singleQuoted] = context.raw;
217
+ const captured = doubleQuoted ?? singleQuoted ?? "";
218
+ return captured.replace(/\\"/g, '"').replace(/\\'/g, "'");
219
+ },
220
+ useForSnippets: true,
221
+ preferForRegexpMatch: false,
222
+ builtin: true
223
+ },
224
+ {
225
+ name: "",
226
+ pattern: ANONYMOUS_REGEXP,
227
+ transform: (_value, context) => context.raw[0] ?? "",
228
+ useForSnippets: false,
229
+ preferForRegexpMatch: true,
230
+ builtin: true
231
+ },
232
+ {
233
+ name: "double",
234
+ pattern: FLOAT_REGEXP,
235
+ transform: (value) => parseNumberValue(value, (raw) => parseFloat(raw)),
236
+ useForSnippets: false,
237
+ preferForRegexpMatch: false,
238
+ builtin: true
239
+ },
240
+ {
241
+ name: "bigdecimal",
242
+ pattern: FLOAT_REGEXP,
243
+ transform: (value) => {
244
+ const text = firstString(value);
245
+ return text ?? null;
246
+ },
247
+ useForSnippets: false,
248
+ preferForRegexpMatch: false,
249
+ builtin: true
250
+ },
251
+ {
252
+ name: "byte",
253
+ pattern: INTEGER_REGEXPS,
254
+ transform: (value) => parseNumberValue(value, (raw) => parseInt(raw, 10)),
255
+ useForSnippets: false,
256
+ preferForRegexpMatch: false,
257
+ builtin: true
258
+ },
259
+ {
260
+ name: "short",
261
+ pattern: INTEGER_REGEXPS,
262
+ transform: (value) => parseNumberValue(value, (raw) => parseInt(raw, 10)),
263
+ useForSnippets: false,
264
+ preferForRegexpMatch: false,
265
+ builtin: true
266
+ },
267
+ {
268
+ name: "long",
269
+ pattern: INTEGER_REGEXPS,
270
+ transform: (value) => parseNumberValue(value, (raw) => parseInt(raw, 10)),
271
+ useForSnippets: false,
272
+ preferForRegexpMatch: false,
273
+ builtin: true
274
+ },
275
+ {
276
+ name: "biginteger",
277
+ pattern: INTEGER_REGEXPS,
278
+ transform: (value) => parseBigIntValue(value),
279
+ useForSnippets: false,
280
+ preferForRegexpMatch: false,
281
+ builtin: true
282
+ }
283
+ ];
284
+ const prepared = defaults.map(
285
+ (definition) => options?.namespace && definition.preferForRegexpMatch ? { ...definition, preferForRegexpMatch: false } : definition
286
+ );
287
+ const toRegister = [];
288
+ prepared.forEach((definition) => {
289
+ const scopedName = resolveScopedName(
290
+ definition.name,
291
+ options?.namespace
292
+ );
293
+ const existing = registry.lookupByTypeName(scopedName);
294
+ if (existing) {
295
+ const transform = buildTransform(definition, scopedName, options);
296
+ attachTransform(existing, transform);
297
+ return;
298
+ }
299
+ toRegister.push(definition);
300
+ });
301
+ if (toRegister.length > 0) {
302
+ define.many(registry, ...toRegister);
303
+ }
304
+ return registry;
305
+ };
306
+ }
307
+ var defineDefaultParameterTypes = createDefaultParameterTypes();
308
+
309
+ exports.applyCucumberExtensions = applyCucumberExtensions;
310
+ exports.attachTransform = attachTransform;
311
+ exports.createDefaultParameterTypes = createDefaultParameterTypes;
312
+ exports.createParameterTypes = createParameterTypes;
313
+ exports.defineDefaultParameterTypes = defineDefaultParameterTypes;
314
+ exports.defineParameterType = defineParameterType;
315
+ exports.resetCucumberExtensions = resetCucumberExtensions;
316
+ //# sourceMappingURL=out.js.map
317
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parameter-types.ts","../src/extensions.ts"],"names":["ParameterType"],"mappings":";AAAA;AAAA,EACE,iBAAAA;AAAA,OAEK;;;ACHP,SAAS,UAAU,qBAAqB;AAExC,IAAM,kBAAiC,OAAO,6BAA6B;AAkB3E,IAAI,oBAAoB;AACxB,IAAI;AACJ,IAAI;AAEG,SAAS,gBACd,eACA,WACA;AACA,EAAC,cAAwC,eAAe,IACtD;AACJ;AAEO,SAAS,0BAA0B;AACxC,MAAI,mBAAmB;AACrB;AAAA,EACF;AAEA,sBAAoB,qBAAqB,cAAc,UAAU;AAEjE,gBAAc,UAAU,YAAY,SAAS,UAE3C,SACA,aACA;AACA,UAAM,cAAc,KAAK,eAAe;AACxC,QAAI,aAAa;AACf,aAAO,YAAY,eAAe,MAAM;AAAA,QACtC,OAAO;AAAA,QACP,eAAe;AAAA,MACjB,CAAC;AAAA,IACH;AACA,UAAM,aAAa,cAAc,CAAC,GAAG,WAAW,IAAI,CAAC;AACrD,QAAI,CAAC,mBAAmB;AACtB,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC3E;AACA,WAAO,kBAAkB,KAAK,MAAM,SAAS,UAAU;AAAA,EACzD;AAEA,qBAAmB,oBAAqB,SAAS,UAAU;AAE3D,WAAS,UAAU,WAAW,SAAS,SAErC,SACG;AACH,UAAM,QAAQ,KAAK;AACnB,QAAI,SAAmC;AAEvC,QAAI,OAAO;AACT,YAAM,cAAc,MAAM,UACtB,IAAI,CAAC,UAA0C,MAAM,KAAK,EAC3D,OAAO,CAAC,UAA+C,UAAU,MAAS;AAE7E,UAAI,eAAe,YAAY,SAAS,GAAG;AACzC,iBAAS;AAAA,MACX,WAAW,MAAM,UAAU,UAAa,MAAM,UAAU,MAAM;AAC5D,iBAAS,CAAC,MAAM,KAAK;AAAA,MACvB,WAAW,MAAM,QAAQ;AACvB,iBAAS,MAAM;AAAA,MACjB;AAAA,IACF;AAEA,UAAM,gBAAgB,KAAK;AAC3B,UAAM,cAAc,gBAAgB,eAAe;AACnD,QAAI,eAAe,eAAe;AAChC,aAAO,YAAY,QAAQ;AAAA,QACzB,OAAO;AAAA,QACP;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,kBAAkB;AACrB,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC3E;AAEA,WAAO,iBAAiB,KAAK,MAAM,OAAO;AAAA,EAC5C;AAEA,sBAAoB;AACtB;AAEO,SAAS,0BAA0B;AACxC,MAAI,CAAC,mBAAmB;AACtB;AAAA,EACF;AAEA,MAAI,mBAAmB;AACrB,kBAAc,UAAU,YAAY;AAAA,EACtC;AAEA,MAAI,kBAAkB;AACpB,aAAS,UAAU,WAAW;AAAA,EAChC;AAEA,sBAAoB;AACtB;;;AD3EA,SAAS,eAAe,SAAqC;AAC3D,SAAO,MAAM,QAAQ,OAAO,IAAI,CAAC,GAAG,OAAO,IAAI,CAAC,OAAO;AACzD;AAEA,SAAS,kBAAkB,WAAuC;AAChE,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,UAAU,CAAC;AAAA,EACpB;AAEA,SAAO,CAAC,GAAG,SAAS;AACtB;AAEA,SAAS,kBAAkB,MAAc,WAA+B;AACtE,MAAI,CAAC,QAAQ,CAAC,WAAW;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,SAAS,IAAI,IAAI;AAC7B;AAEA,SAAS,eACP,YACA,YACA,SAC6B;AAC7B,SAAO,CAAC,QAAkC,YAAqC;AAC7E,UAAM,YAAY,UAAU,CAAC;AAC7B,UAAM,WAAW,kBAAkB,SAAS;AAE5C,QAAI,WAAW,WAAW;AACxB,YAAM,UAA4C;AAAA,QAChD,KAAK;AAAA,QACL,OAAO,QAAQ;AAAA,QACf,MAAM;AAAA,QACN,cAAc,WAAW;AAAA,QACzB,eAAe,QAAQ;AAAA,QACvB;AAAA,QACA,GAAI,SAAS,cAAc,SACvB,EAAE,WAAW,QAAQ,UAAU,IAC/B,CAAC;AAAA,MACP;AAEA,aAAO,WAAW,UAAU,UAAU,OAAO;AAAA,IAC/C;AAEA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAc,OAA+B;AACpD,SAAO,MAAM,QAAQ,KAAK,IAAK,MAAM,CAAC,IAAuB;AAC/D;AAEA,SAAS,YAAY,OAAoC;AACvD,QAAM,QAAQ,WAAoB,KAAK;AACvC,MAAI,UAAU,UAAa,UAAU,MAAM;AACzC,WAAO;AAAA,EACT;AACA,SAAO,OAAO,KAAK;AACrB;AAEA,SAAS,iBACP,OACA,QACe;AACf,QAAM,MAAM,YAAY,KAAK;AAC7B,MAAI,QAAQ,QAAW;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,OAAO,GAAG;AAC1B,SAAO,OAAO,MAAM,OAAO,IAAI,OAAO;AACxC;AAEA,SAAS,iBAAiB,OAA+B;AACvD,QAAM,MAAM,YAAY,KAAK;AAC7B,MAAI,QAAQ,QAAW;AACrB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,WAAO,OAAO,GAAG;AAAA,EACnB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAeO,SAAS,qBACd,SAC8B;AAC9B,0BAAwB;AAExB,QAAM,SAAU,CACd,UACA,eACG;AACH,UAAM,WAAW,eAAe,WAAW,OAAO;AAClD,UAAM,aAAa,kBAAkB,WAAW,MAAM,SAAS,SAAS;AACxE,UAAM,YAAY,eAAe,YAAY,YAAY,OAAO;AAChE,UAAM,gBAAgB,IAAIA;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA,IAAI,YAAuB,QAAQ,UAAU,IAAI,QAAQ,CAAC,IAAI;AAAA,MAC9D,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AAEA,oBAAgB,eAAe,SAAS;AACxC,aAAS,oBAAoB,aAAa;AAC1C,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,CACZ,aACG,gBAGA;AACH,UAAM,OACJ,YAAY,WAAW,KAAK,MAAM,QAAQ,YAAY,CAAC,CAAC,IACnD,YAAY,CAAC,IACb;AAEP,SAAK,QAAQ,CAAC,eAAe;AAC3B,aAAO,UAAU,UAAU;AAAA,IAC7B,CAAC;AAED,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,IAAM,sBAAsB,qBAA8B;AAEjE,IAAM,kBAAkB,CAAC,SAAS,KAAK;AACvC,IAAM,eAAe;AACrB,IAAM,cAAc;AACpB,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAElB,SAAS,4BACd,SACA;AACA,QAAM,SAAS,qBAA4B,OAAO;AAElD,SAAO,CAAC,aAAoC;AAC1C,UAAM,WAA6C;AAAA,MACjD;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UACV,iBAAiB,OAAO,CAAC,QAAQ,SAAS,KAAK,EAAE,CAAC;AAAA,QACpD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UACV,iBAAiB,OAAO,CAAC,QAAQ,WAAW,GAAG,CAAC;AAAA,QAClD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UACV,iBAAiB,OAAO,CAAC,QAAQ,WAAW,GAAG,CAAC;AAAA,QAClD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UAAmB,YAAY,KAAK,KAAK;AAAA,QACrD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,QAAiB,YAA8C;AACzE,gBAAM,CAAC,cAAc,YAAY,IAAI,QAAQ;AAC7C,gBAAM,WAAW,gBAAgB,gBAAgB;AACjD,iBAAO,SACJ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,QAAQ,GAAG;AAAA,QACxB;AAAA,QACA,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,QAAiB,YAC3B,QAAQ,IAAI,CAAC,KAAK;AAAA,QACpB,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UACV,iBAAiB,OAAO,CAAC,QAAQ,WAAW,GAAG,CAAC;AAAA,QAClD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UAAmB;AAC7B,gBAAM,OAAO,YAAY,KAAK;AAC9B,iBAAO,QAAQ;AAAA,QACjB;AAAA,QACA,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UACV,iBAAiB,OAAO,CAAC,QAAQ,SAAS,KAAK,EAAE,CAAC;AAAA,QACpD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UACV,iBAAiB,OAAO,CAAC,QAAQ,SAAS,KAAK,EAAE,CAAC;AAAA,QACpD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UACV,iBAAiB,OAAO,CAAC,QAAQ,SAAS,KAAK,EAAE,CAAC;AAAA,QACpD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,CAAC,UAAmB,iBAAiB,KAAK;AAAA,QACrD,gBAAgB;AAAA,QAChB,sBAAsB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,WAAW,SAAS;AAAA,MAAI,CAAC,eAC7B,SAAS,aAAa,WAAW,uBAC7B,EAAE,GAAG,YAAY,sBAAsB,MAAM,IAC7C;AAAA,IACN;AAEA,UAAM,aAA+C,CAAC;AAEtD,aAAS,QAAQ,CAAC,eAAe;AAC/B,YAAM,aAAa;AAAA,QACjB,WAAW;AAAA,QACX,SAAS;AAAA,MACX;AACA,YAAM,WAAW,SAAS,iBAAiB,UAAU;AAErD,UAAI,UAAU;AACZ,cAAM,YAAY,eAAe,YAAY,YAAY,OAAO;AAChE,wBAAgB,UAAU,SAAS;AACnC;AAAA,MACF;AAEA,iBAAW,KAAK,UAAU;AAAA,IAC5B,CAAC;AAED,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO,KAAK,UAAU,GAAG,UAAU;AAAA,IACrC;AAEA,WAAO;AAAA,EACT;AACF;AAEO,IAAM,8BACX,4BAAqC","sourcesContent":["import {\n ParameterType,\n ParameterTypeRegistry,\n} from \"@cucumber/cucumber-expressions\";\nimport { attachTransform, applyCucumberExtensions } from \"./extensions\";\nimport type { ParameterRuntime, ParameterTransformFn } from \"./extensions\";\n\nexport interface CreateParameterTypesOptions {\n readonly namespace?: string;\n}\n\nexport interface ParameterTransformContext<World> {\n readonly raw: readonly string[];\n readonly world: World;\n readonly name: string | undefined;\n readonly originalName: string | undefined;\n readonly namespace?: string;\n readonly parameterType: ParameterType<unknown>;\n readonly definition: ParameterTypeDefinition<World>;\n}\n\nexport type ParameterTransformer<TResult, World> = (\n value: unknown,\n context: ParameterTransformContext<World>\n) => TResult | Promise<TResult>;\n\nexport interface ParameterTypeDefinition<World, TResult = unknown> {\n readonly name: string;\n readonly pattern: RegExp | readonly RegExp[];\n readonly transform?: ParameterTransformer<TResult, World>;\n readonly useForSnippets?: boolean;\n readonly preferForRegexpMatch?: boolean;\n readonly builtin?: boolean;\n}\n\nexport type ParameterTypeDefinitions<World> = ReadonlyArray<\n ParameterTypeDefinition<World>\n>;\n\nfunction toPatternArray(pattern: RegExp | readonly RegExp[]) {\n return Array.isArray(pattern) ? [...pattern] : [pattern];\n}\n\nfunction buildDefaultValue(rawValues: readonly string[]): unknown {\n if (rawValues.length === 0) {\n return undefined;\n }\n\n if (rawValues.length === 1) {\n return rawValues[0];\n }\n\n return [...rawValues];\n}\n\nfunction resolveScopedName(name: string, namespace: string | undefined) {\n if (!name || !namespace) {\n return name;\n }\n\n return `${namespace}:${name}`;\n}\n\nfunction buildTransform<World>(\n definition: ParameterTypeDefinition<World>,\n scopedName: string,\n options: CreateParameterTypesOptions | undefined\n): ParameterTransformFn<World> {\n return (values: readonly string[] | null, runtime: ParameterRuntime<World>) => {\n const rawValues = values ?? [];\n const resolved = buildDefaultValue(rawValues);\n\n if (definition.transform) {\n const context: ParameterTransformContext<World> = {\n raw: rawValues,\n world: runtime.world,\n name: scopedName,\n originalName: definition.name,\n parameterType: runtime.parameterType,\n definition,\n ...(options?.namespace !== undefined\n ? { namespace: options.namespace }\n : {}),\n };\n\n return definition.transform(resolved, context);\n }\n\n return resolved;\n };\n}\n\nfunction firstValue<T>(input: unknown): T | undefined {\n return Array.isArray(input) ? (input[0] as T | undefined) : (input as T | undefined);\n}\n\nfunction firstString(input: unknown): string | undefined {\n const value = firstValue<unknown>(input);\n if (value === undefined || value === null) {\n return undefined;\n }\n return String(value);\n}\n\nfunction parseNumberValue(\n input: unknown,\n parser: (raw: string) => number\n): number | null {\n const raw = firstString(input);\n if (raw === undefined) {\n return null;\n }\n\n const numeric = parser(raw);\n return Number.isNaN(numeric) ? null : numeric;\n}\n\nfunction parseBigIntValue(input: unknown): bigint | null {\n const raw = firstString(input);\n if (raw === undefined) {\n return null;\n }\n\n try {\n return BigInt(raw);\n } catch {\n return null;\n }\n}\n\nexport interface DefineParameterTypeFn<World> {\n (\n registry: ParameterTypeRegistry,\n definition: ParameterTypeDefinition<World>\n ): ParameterType<unknown>;\n many(\n registry: ParameterTypeRegistry,\n ...definitions:\n | ParameterTypeDefinitions<World>\n | [ParameterTypeDefinition<World>]\n ): ParameterTypeRegistry;\n}\n\nexport function createParameterTypes<World>(\n options?: CreateParameterTypesOptions\n): DefineParameterTypeFn<World> {\n applyCucumberExtensions();\n\n const define = ((\n registry: ParameterTypeRegistry,\n definition: ParameterTypeDefinition<World>\n ) => {\n const patterns = toPatternArray(definition.pattern);\n const scopedName = resolveScopedName(definition.name, options?.namespace);\n const transform = buildTransform(definition, scopedName, options);\n const parameterType = new ParameterType<unknown>(\n scopedName,\n patterns,\n null,\n // The original transform is overridden by applyCucumberExtensions.\n (...matches: string[]) => (matches.length <= 1 ? matches[0] : matches),\n definition.useForSnippets,\n definition.preferForRegexpMatch,\n definition.builtin\n );\n\n attachTransform(parameterType, transform);\n registry.defineParameterType(parameterType);\n return parameterType;\n }) as DefineParameterTypeFn<World>;\n\n define.many = (\n registry: ParameterTypeRegistry,\n ...definitions:\n | ParameterTypeDefinitions<World>\n | [ParameterTypeDefinition<World>]\n ) => {\n const list =\n definitions.length === 1 && Array.isArray(definitions[0])\n ? (definitions[0] as ParameterTypeDefinitions<World>)\n : (definitions as ParameterTypeDefinition<World>[]);\n\n list.forEach((definition) => {\n define(registry, definition);\n });\n\n return registry;\n };\n\n return define;\n}\n\nexport const defineParameterType = createParameterTypes<unknown>();\n\nconst INTEGER_REGEXPS = [/-?\\d+/, /\\d+/] as const;\nconst FLOAT_REGEXP = /(?=.*\\d.*)[-+]?\\d*(?:\\.(?=\\d.*))?\\d*(?:\\d+[E][+-]?\\d+)?/;\nconst WORD_REGEXP = /[^\\s]+/;\nconst STRING_REGEXP = /\"([^\"\\\\]*(\\\\.[^\"\\\\]*)*)\"|'([^'\\\\]*(\\\\.[^'\\\\]*)*)'/;\nconst ANONYMOUS_REGEXP = /.*/;\n\nexport function createDefaultParameterTypes<World>(\n options?: CreateParameterTypesOptions\n) {\n const define = createParameterTypes<World>(options);\n\n return (registry: ParameterTypeRegistry) => {\n const defaults: ParameterTypeDefinition<World>[] = [\n {\n name: \"int\",\n pattern: INTEGER_REGEXPS,\n transform: (value: unknown) =>\n parseNumberValue(value, (raw) => parseInt(raw, 10)),\n useForSnippets: true,\n preferForRegexpMatch: true,\n builtin: true,\n },\n {\n name: \"float\",\n pattern: FLOAT_REGEXP,\n transform: (value: unknown) =>\n parseNumberValue(value, (raw) => parseFloat(raw)),\n useForSnippets: true,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"number\",\n pattern: FLOAT_REGEXP,\n transform: (value: unknown) =>\n parseNumberValue(value, (raw) => parseFloat(raw)),\n useForSnippets: true,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"word\",\n pattern: WORD_REGEXP,\n transform: (value: unknown) => firstString(value) ?? \"\",\n useForSnippets: false,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"string\",\n pattern: STRING_REGEXP,\n transform: (_value: unknown, context: ParameterTransformContext<World>) => {\n const [doubleQuoted, singleQuoted] = context.raw;\n const captured = doubleQuoted ?? singleQuoted ?? \"\";\n return captured\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\'/g, \"'\");\n },\n useForSnippets: true,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"\",\n pattern: ANONYMOUS_REGEXP,\n transform: (_value: unknown, context: ParameterTransformContext<World>) =>\n context.raw[0] ?? \"\",\n useForSnippets: false,\n preferForRegexpMatch: true,\n builtin: true,\n },\n {\n name: \"double\",\n pattern: FLOAT_REGEXP,\n transform: (value: unknown) =>\n parseNumberValue(value, (raw) => parseFloat(raw)),\n useForSnippets: false,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"bigdecimal\",\n pattern: FLOAT_REGEXP,\n transform: (value: unknown) => {\n const text = firstString(value);\n return text ?? null;\n },\n useForSnippets: false,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"byte\",\n pattern: INTEGER_REGEXPS,\n transform: (value: unknown) =>\n parseNumberValue(value, (raw) => parseInt(raw, 10)),\n useForSnippets: false,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"short\",\n pattern: INTEGER_REGEXPS,\n transform: (value: unknown) =>\n parseNumberValue(value, (raw) => parseInt(raw, 10)),\n useForSnippets: false,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"long\",\n pattern: INTEGER_REGEXPS,\n transform: (value: unknown) =>\n parseNumberValue(value, (raw) => parseInt(raw, 10)),\n useForSnippets: false,\n preferForRegexpMatch: false,\n builtin: true,\n },\n {\n name: \"biginteger\",\n pattern: INTEGER_REGEXPS,\n transform: (value: unknown) => parseBigIntValue(value),\n useForSnippets: false,\n preferForRegexpMatch: false,\n builtin: true,\n },\n ];\n\n const prepared = defaults.map((definition) =>\n options?.namespace && definition.preferForRegexpMatch\n ? { ...definition, preferForRegexpMatch: false }\n : definition\n );\n\n const toRegister: ParameterTypeDefinition<World>[] = [];\n\n prepared.forEach((definition) => {\n const scopedName = resolveScopedName(\n definition.name,\n options?.namespace\n );\n const existing = registry.lookupByTypeName(scopedName);\n\n if (existing) {\n const transform = buildTransform(definition, scopedName, options);\n attachTransform(existing, transform);\n return;\n }\n\n toRegister.push(definition);\n });\n\n if (toRegister.length > 0) {\n define.many(registry, ...toRegister);\n }\n\n return registry;\n };\n}\n\nexport const defineDefaultParameterTypes =\n createDefaultParameterTypes<unknown>();\n","import { Argument, ParameterType } from \"@cucumber/cucumber-expressions\";\n\nconst transformSymbol: unique symbol = Symbol(\"autometa:cucumber:transform\");\n\nexport interface ParameterRuntime<World> {\n readonly world: World;\n readonly parameterType: ParameterType<unknown>;\n}\n\nexport type ParameterTransformFn<World> = (\n values: readonly string[] | null,\n runtime: ParameterRuntime<World>\n) => unknown;\n\ntype StoredParameterTransformFn = ParameterTransformFn<unknown>;\n\ninterface AppAwareParameterType extends ParameterType<unknown> {\n [transformSymbol]?: StoredParameterTransformFn;\n}\n\nlet extensionsApplied = false;\nlet originalTransform: typeof ParameterType.prototype.transform | undefined;\nlet originalGetValue: typeof Argument.prototype.getValue | undefined;\n\nexport function attachTransform<World>(\n parameterType: ParameterType<unknown>,\n transform: ParameterTransformFn<World>\n) {\n (parameterType as AppAwareParameterType)[transformSymbol] =\n transform as StoredParameterTransformFn;\n}\n\nexport function applyCucumberExtensions() {\n if (extensionsApplied) {\n return;\n }\n\n originalTransform = originalTransform ?? ParameterType.prototype.transform;\n\n ParameterType.prototype.transform = function transform(\n this: AppAwareParameterType,\n thisObj: unknown,\n groupValues: readonly string[] | null\n ) {\n const transformFn = this[transformSymbol];\n if (transformFn) {\n return transformFn(groupValues ?? null, {\n world: thisObj,\n parameterType: this,\n });\n }\n const normalized = groupValues ? [...groupValues] : [];\n if (!originalTransform) {\n throw new Error(\"Cucumber extensions have not been initialised correctly\");\n }\n return originalTransform.call(this, thisObj, normalized);\n } as unknown as typeof ParameterType.prototype.transform;\n\n originalGetValue = originalGetValue ?? (Argument.prototype.getValue as typeof Argument.prototype.getValue);\n\n Argument.prototype.getValue = function getValue<T>(\n this: Argument,\n context?: unknown\n ): T {\n const group = this.group;\n let values: readonly string[] | null = null;\n\n if (group) {\n const childValues = group.children\n ?.map((child: { value?: string | undefined }) => child.value)\n .filter((value: string | undefined): value is string => value !== undefined);\n\n if (childValues && childValues.length > 0) {\n values = childValues;\n } else if (group.value !== undefined && group.value !== null) {\n values = [group.value];\n } else if (group.values) {\n values = group.values;\n }\n }\n\n const parameterType = this.parameterType as AppAwareParameterType | undefined;\n const transformFn = parameterType?.[transformSymbol];\n if (transformFn && parameterType) {\n return transformFn(values, {\n world: context as unknown,\n parameterType,\n }) as T;\n }\n\n if (!originalGetValue) {\n throw new Error(\"Cucumber extensions have not been initialised correctly\");\n }\n\n return originalGetValue.call(this, context) as T;\n };\n\n extensionsApplied = true;\n}\n\nexport function resetCucumberExtensions() {\n if (!extensionsApplied) {\n return;\n }\n\n if (originalTransform) {\n ParameterType.prototype.transform = originalTransform;\n }\n\n if (originalGetValue) {\n Argument.prototype.getValue = originalGetValue;\n }\n\n extensionsApplied = false;\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,104 +1,5 @@
1
- import { Change } from 'diff';
2
- import { Expression, ParameterTypeRegistry } from '@cucumber/cucumber-expressions';
3
- import { Class } from '@autometa/types';
4
- import { App } from '@autometa/app';
5
-
6
- type CachedStep = {
7
- keyword: string;
8
- type: string;
9
- expression: Expression;
10
- matches: (text: string) => boolean;
11
- };
12
-
13
- type StepDiff = {
14
- merged: string;
15
- step: CachedStep;
16
- gherkin: string;
17
- distance: number;
18
- };
19
- type StepDiffs = StepDiff[];
20
- type LimitedStepDiffs = {
21
- same: StepDiffs;
22
- other: StepDiffs;
23
- };
24
- declare function checkMatch(text: string, it: CachedStep): boolean;
25
- declare function limitDiffs(sameStepType: StepDiffs, differentStepType: StepDiffs, max: number): LimitedStepDiffs;
26
- declare function getDiffs(text: string, maxResults: number, step: CachedStep[]): {
27
- merged: string;
28
- step: CachedStep;
29
- gherkin: string;
30
- distance: number;
31
- }[];
32
- declare function getDiff(text: string, it: CachedStep): Change[];
33
- declare function refineDiff(diff: Change[]): string;
34
- declare function isExpressionCandidate(change1: Change, change2: Change): boolean;
35
-
36
- declare class SameStepTypeMatch {
37
- readonly keyword: string;
38
- readonly text: string;
39
- readonly source: string;
40
- readonly distance: number;
41
- constructor(diff: StepDiff);
42
- toString(): string;
43
- }
44
- declare class DifferentStepTypeMatch {
45
- readonly keyword: string;
46
- readonly text: string;
47
- readonly source: string;
48
- readonly distance: number;
49
- constructor(diff: StepDiff);
50
- toString(): string;
51
- }
52
- declare class FuzzySearchReport {
53
- #private;
54
- readonly depth: number;
55
- headingText: string;
56
- matches: (SameStepTypeMatch | DifferentStepTypeMatch)[];
57
- children: FuzzySearchReport[];
58
- constructor(depth?: number);
59
- get length(): number;
60
- addHeading(headingText: string): this;
61
- addMatch(match: SameStepTypeMatch | DifferentStepTypeMatch): this;
62
- addChild(child: FuzzySearchReport): this;
63
- toString(): string;
64
- }
65
- declare function buildFuzzySearchReport({ same, other }: LimitedStepDiffs, depth: number): FuzzySearchReport;
66
-
67
- declare module "@cucumber/cucumber-expressions" {
68
- interface ParameterType<T> {
69
- transform(groupValues: string[] | null, app: App): T;
70
- }
71
- }
72
- type ParamTypeDefinition = {
73
- name: string;
74
- regex: RegExp | RegExp[];
75
- /**
76
- * @deprecated use regex instead
77
- */
78
- regexpPattern?: RegExp | RegExp[];
79
- transform?: (value: any, app: App) => unknown;
80
- type?: Class<unknown>;
81
- primitive?: typeof String | typeof Number | typeof Boolean | typeof BigInt | typeof Date;
82
- };
83
- declare function defineParameterType<T extends ParamTypeDefinition[]>(registry: ParameterTypeRegistry, ...params: T): void;
84
-
85
- type AutoParamTypeDefinition = Omit<ParamTypeDefinition, "transform">;
86
- declare const OrdinalParam: ParamTypeDefinition;
87
- declare const NumberParam: AutoParamTypeDefinition;
88
- declare const AnyParam: AutoParamTypeDefinition;
89
- declare const UnknownParam: AutoParamTypeDefinition;
90
- declare const TextParam: ParamTypeDefinition;
91
- declare const BooleanParam: {
92
- name: string;
93
- regex: RegExp;
94
- primitive: BooleanConstructor;
95
- };
96
- declare const BoolParam: {
97
- name: string;
98
- regex: RegExp;
99
- primitive: BooleanConstructor;
100
- };
101
- declare const DateParam: AutoParamTypeDefinition;
102
- declare const PrimitiveParam: ParamTypeDefinition;
103
-
104
- export { AnyParam, BoolParam, BooleanParam, DateParam, DifferentStepTypeMatch, FuzzySearchReport, LimitedStepDiffs, NumberParam, OrdinalParam, ParamTypeDefinition, PrimitiveParam, SameStepTypeMatch, StepDiff, StepDiffs, TextParam, UnknownParam, buildFuzzySearchReport, checkMatch, defineParameterType, getDiff, getDiffs, isExpressionCandidate, limitDiffs, refineDiff };
1
+ export { createParameterTypes, defineParameterType, createDefaultParameterTypes, defineDefaultParameterTypes, } from "./parameter-types";
2
+ export type { ParameterTransformContext, ParameterTransformer, ParameterTypeDefinition, ParameterTypeDefinitions, CreateParameterTypesOptions, } from "./parameter-types";
3
+ export { attachTransform, applyCucumberExtensions, resetCucumberExtensions, } from "./extensions";
4
+ export type { ParameterRuntime, ParameterTransformFn } from "./extensions";
5
+ export type { CachedStep, StepDiff, StepDiffList, LimitedStepDiffs } from "./types";