@lynxwall/cucumber-tsflow 7.2.0 → 7.3.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.
Files changed (77) hide show
  1. package/README.md +59 -35
  2. package/lib/api/load-configuration.js +60 -16
  3. package/lib/api/load-configuration.js.map +1 -1
  4. package/lib/bindings/binding-context.d.ts +40 -4
  5. package/lib/bindings/binding-context.js +50 -6
  6. package/lib/bindings/binding-context.js.map +1 -1
  7. package/lib/bindings/binding-decorator.js +32 -9
  8. package/lib/bindings/binding-decorator.js.map +1 -1
  9. package/lib/bindings/binding-registry.js +10 -0
  10. package/lib/bindings/binding-registry.js.map +1 -1
  11. package/lib/bindings/hook-decorators.js +4 -3
  12. package/lib/bindings/hook-decorators.js.map +1 -1
  13. package/lib/bindings/step-decorators.js +12 -9
  14. package/lib/bindings/step-decorators.js.map +1 -1
  15. package/lib/cli/argv-parser.js +1 -2
  16. package/lib/cli/argv-parser.js.map +1 -1
  17. package/lib/runtime/parallel/worker.js +1 -1
  18. package/lib/runtime/parallel/worker.js.map +1 -1
  19. package/lib/runtime/test-case-runner.d.ts +2 -1
  20. package/lib/runtime/test-case-runner.js +8 -5
  21. package/lib/runtime/test-case-runner.js.map +1 -1
  22. package/lib/transpilers/esbuild-transpiler.d.ts +1 -1
  23. package/lib/transpilers/esbuild-transpiler.js.map +1 -1
  24. package/lib/transpilers/esbuild.js.map +1 -1
  25. package/lib/transpilers/esm/esbuild-transpiler-cjs.js +2174 -0
  26. package/lib/transpilers/esm/esbuild-transpiler.mjs +19 -0
  27. package/lib/transpilers/esm/esbuild.mjs +141 -0
  28. package/lib/transpilers/esm/esmbuild-transpiler.d.ts +4 -0
  29. package/lib/transpilers/esm/esmbuild-transpiler.js +19 -0
  30. package/lib/transpilers/esm/esmbuild-transpiler.js.map +1 -0
  31. package/lib/transpilers/esm/esmbuild.d.ts +12 -0
  32. package/lib/transpilers/esm/esmbuild.js +72 -0
  33. package/lib/transpilers/esm/esmbuild.js.map +1 -0
  34. package/lib/transpilers/esm/esmnode.d.ts +1 -0
  35. package/lib/transpilers/esm/esmnode.js +8 -0
  36. package/lib/transpilers/esm/esmnode.js.map +1 -0
  37. package/lib/transpilers/esm/esmvue.d.ts +1 -0
  38. package/lib/transpilers/esm/esmvue.js +29 -0
  39. package/lib/transpilers/esm/esmvue.js.map +1 -0
  40. package/lib/transpilers/esm/esnode-loader.mjs +9 -0
  41. package/lib/transpilers/esm/esvue-loader.mjs +9 -0
  42. package/lib/transpilers/esm/loader-utils.mjs +278 -0
  43. package/lib/transpilers/esm/tsnode-esm.d.ts +1 -0
  44. package/lib/transpilers/esm/tsnode-esm.js +25 -0
  45. package/lib/transpilers/esm/tsnode-esm.js.map +1 -0
  46. package/lib/transpilers/esm/tsnode-exp-esm.d.ts +1 -0
  47. package/lib/transpilers/esm/tsnode-exp-esm.js +19 -0
  48. package/lib/transpilers/esm/tsnode-exp-esm.js.map +1 -0
  49. package/lib/transpilers/esm/tsnode-loader.mjs +107 -0
  50. package/lib/transpilers/esm/tsnode-service.mjs +40 -0
  51. package/lib/transpilers/esm/tsvue-esm.d.ts +1 -0
  52. package/lib/transpilers/esm/tsvue-esm.js +40 -0
  53. package/lib/transpilers/esm/tsvue-esm.js.map +1 -0
  54. package/lib/transpilers/esm/tsvue-exp-esm.d.ts +1 -0
  55. package/lib/transpilers/esm/tsvue-exp-esm.js +40 -0
  56. package/lib/transpilers/esm/tsvue-exp-esm.js.map +1 -0
  57. package/lib/transpilers/esm/vue-jsdom-setup.mjs +19 -0
  58. package/lib/transpilers/esm/vue-loader.mjs +113 -0
  59. package/lib/transpilers/esm/vue-sfc-compiler.mjs +216 -0
  60. package/lib/transpilers/esnode.js +1 -1
  61. package/lib/transpilers/esnode.js.map +1 -1
  62. package/lib/transpilers/esvue.js +1 -1
  63. package/lib/transpilers/esvue.js.map +1 -1
  64. package/lib/transpilers/tsnode-exp.js +1 -1
  65. package/lib/transpilers/tsnode-exp.js.map +1 -1
  66. package/lib/transpilers/tsnode.js +1 -1
  67. package/lib/transpilers/tsnode.js.map +1 -1
  68. package/lib/transpilers/tsvue-exp.js +1 -1
  69. package/lib/transpilers/tsvue-exp.js.map +1 -1
  70. package/lib/transpilers/tsvue.js +2 -2
  71. package/lib/transpilers/tsvue.js.map +1 -1
  72. package/lib/transpilers/vue-sfc/index.js.map +1 -1
  73. package/lib/tsconfig.node.tsbuildinfo +1 -1
  74. package/lib/version.d.ts +1 -1
  75. package/lib/version.js +1 -1
  76. package/lib/version.js.map +1 -1
  77. package/package.json +27 -17
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ require('ts-node/esm').register({
4
+ compilerOptions: {
5
+ module: 'nodeNext',
6
+ target: 'es2022',
7
+ strict: true,
8
+ allowJs: true,
9
+ allowSyntheticDefaultImports: true,
10
+ esModuleInterop: true,
11
+ experimentalDecorators: true,
12
+ resolveJsonModule: true,
13
+ skipLibCheck: true,
14
+ lib: ['es2022']
15
+ },
16
+ transpileOnly: true
17
+ });
18
+ require('tsconfig-paths').register();
19
+ //# sourceMappingURL=tsnode-exp-esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsnode-exp-esm.js","sourceRoot":"","sources":["../../../src/transpilers/esm/tsnode-exp-esm.ts"],"names":[],"mappings":";;AAEA,OAAO,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC;IAC/B,eAAe,EAAE;QAChB,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,IAAI;QACb,4BAA4B,EAAE,IAAI;QAClC,eAAe,EAAE,IAAI;QACrB,sBAAsB,EAAE,IAAI;QAC5B,iBAAiB,EAAE,IAAI;QACvB,YAAY,EAAE,IAAI;QAClB,GAAG,EAAE,CAAC,QAAQ,CAAC;KACf;IACD,aAAa,EAAE,IAAI;CACnB,CAAC,CAAC;AAEH,OAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC","sourcesContent":["import { SourceMap } from 'node:module';\r\n\r\nrequire('ts-node/esm').register({\r\n\tcompilerOptions: {\r\n\t\tmodule: 'nodeNext',\r\n\t\ttarget: 'es2022',\r\n\t\tstrict: true,\r\n\t\tallowJs: true,\r\n\t\tallowSyntheticDefaultImports: true,\r\n\t\tesModuleInterop: true,\r\n\t\texperimentalDecorators: true,\r\n\t\tresolveJsonModule: true,\r\n\t\tskipLibCheck: true,\r\n\t\tlib: ['es2022']\r\n\t},\r\n\ttranspileOnly: true\r\n});\r\n\r\nrequire('tsconfig-paths').register();\r\n"]}
@@ -0,0 +1,107 @@
1
+ import { pathToFileURL } from 'url';
2
+ import { createRequire } from 'node:module';
3
+ import { resolveSpecifier } from './loader-utils.mjs';
4
+ import { loadConfig } from 'tsconfig-paths';
5
+ import path from 'path';
6
+
7
+ const require = createRequire(import.meta.url);
8
+
9
+ // Load tsconfig to get paths
10
+ const configLoaderResult = loadConfig(process.cwd());
11
+ let paths = {};
12
+ let baseUrl = './';
13
+
14
+ if (configLoaderResult.resultType === 'success') {
15
+ paths = configLoaderResult.paths || {};
16
+ baseUrl = configLoaderResult.baseUrl || './';
17
+ }
18
+
19
+ // Create ts-node service with our configuration
20
+ const tsNode = require('ts-node-maintained');
21
+
22
+ const service = tsNode.create({
23
+ esm: true,
24
+ experimentalSpecifierResolution: 'node',
25
+ files: true,
26
+ transpileOnly: true,
27
+ compilerOptions: {
28
+ experimentalDecorators: process.env.CUCUMBER_EXPERIMENTAL_DECORATORS === 'true',
29
+ module: 'ESNext',
30
+ target: 'ES2022',
31
+ // Add path mapping to ts-node's compiler options
32
+ baseUrl: baseUrl,
33
+ paths: paths
34
+ }
35
+ });
36
+
37
+ // Create ESM hooks from the service
38
+ const esmHooks = tsNode.createEsmHooks(service);
39
+
40
+ export async function resolve(specifier, context, nextResolve) {
41
+ // Try common resolution logic (includes path mapping + extension resolution)
42
+ const resolved = await resolveSpecifier(specifier, context, {
43
+ checkExtensions: true,
44
+ handleTsFiles: true,
45
+ tsNodeHooks: esmHooks,
46
+ nextResolve
47
+ });
48
+
49
+ if (resolved) {
50
+ return resolved;
51
+ }
52
+
53
+ // Fall back to ts-node's resolver
54
+ return esmHooks.resolve(specifier, context, nextResolve);
55
+ }
56
+
57
+ export const load = async (url, context, nextLoad) => {
58
+ // Only intercept TypeScript files for path rewriting
59
+ if (url.endsWith('.ts') || url.endsWith('.tsx')) {
60
+ // First, let ts-node load the file
61
+ const result = await esmHooks.load(url, context, nextLoad);
62
+
63
+ // If we have path mappings, check if we need to rewrite the source
64
+ if (configLoaderResult.resultType === 'success' && configLoaderResult.paths) {
65
+ let code = result.source.toString();
66
+ let modified = false;
67
+
68
+ for (const [pattern, replacements] of Object.entries(configLoaderResult.paths)) {
69
+ // Convert TS path pattern to regex: @fixtures/* -> @fixtures/
70
+ const searchPattern = pattern.replace('/*', '/');
71
+ const searchRegex = new RegExp(`(from\\s+['"])${searchPattern}([^'"]+)(['"])`, 'g');
72
+
73
+ if (searchRegex.test(code)) {
74
+ // Get the replacement path (use first one if multiple)
75
+ const replacementPath = replacements[0].replace('/*', '');
76
+
77
+ code = code.replace(searchRegex, (match, prefix, importPath, suffix) => {
78
+ // Create the full path
79
+ const fullPath = path.join(configLoaderResult.absoluteBaseUrl, replacementPath, importPath);
80
+ // Convert to file:// URL for ESM
81
+ const fileUrl = pathToFileURL(fullPath).href;
82
+ return `${prefix}${fileUrl}${suffix}`;
83
+ });
84
+
85
+ modified = true;
86
+ }
87
+ }
88
+
89
+ if (modified) {
90
+ // Return the modified result
91
+ return {
92
+ ...result,
93
+ source: code
94
+ };
95
+ }
96
+ }
97
+
98
+ // Return the unmodified result from ts-node
99
+ return result;
100
+ }
101
+
102
+ // For non-TypeScript files, let ts-node handle it
103
+ return esmHooks.load(url, context, nextLoad);
104
+ };
105
+
106
+ export const getFormat = esmHooks.getFormat;
107
+ export const transformSource = esmHooks.transformSource;
@@ -0,0 +1,40 @@
1
+ import { createRequire } from 'module';
2
+
3
+ const require = createRequire(import.meta.url);
4
+ const tsNode = require('ts-node-maintained');
5
+
6
+ // Cache for different ts-node configurations
7
+ const serviceCache = new Map();
8
+
9
+ export function createTsNodeService(options = {}) {
10
+ const cacheKey = JSON.stringify(options);
11
+
12
+ if (serviceCache.has(cacheKey)) {
13
+ return serviceCache.get(cacheKey);
14
+ }
15
+
16
+ // Ensure ts-node respects tsconfig.json files
17
+ process.env.TS_NODE_FILES = process.env.TS_NODE_FILES || 'true';
18
+
19
+ const defaultOptions = {
20
+ esm: true,
21
+ experimentalSpecifierResolution: 'node',
22
+ files: true,
23
+ transpileOnly: true,
24
+ compilerOptions: {
25
+ experimentalDecorators: process.env.CUCUMBER_EXPERIMENTAL_DECORATORS === 'true',
26
+ module: 'ESNext',
27
+ target: 'ES2022'
28
+ }
29
+ };
30
+
31
+ const service = tsNode.create({ ...defaultOptions, ...options });
32
+ serviceCache.set(cacheKey, service);
33
+
34
+ return service;
35
+ }
36
+
37
+ export function createEsmHooks(transpiler) {
38
+ const service = createTsNodeService({ transpiler });
39
+ return tsNode.createEsmHooks(service);
40
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const hooks = require('require-extension-hooks');
7
+ const vue_sfc_1 = __importDefault(require("../vue-sfc"));
8
+ require('ts-node/esm').register({
9
+ compilerOptions: {
10
+ module: 'esnext',
11
+ target: 'es2022',
12
+ strict: true,
13
+ allowJs: true,
14
+ allowSyntheticDefaultImports: true,
15
+ esModuleInterop: true,
16
+ experimentalDecorators: false,
17
+ resolveJsonModule: true,
18
+ skipLibCheck: true,
19
+ lib: ['es2022', 'esnext.decorators']
20
+ },
21
+ transpileOnly: true
22
+ });
23
+ require('tsconfig-paths').register();
24
+ // Register jsdom globally and set SVGElement on global
25
+ require('jsdom-global')();
26
+ global.SVGElement = global.window.SVGElement;
27
+ hooks('vue').push(function (params) {
28
+ try {
29
+ const transformer = new vue_sfc_1.default({
30
+ exclude: ['(?:^|/)node_modules/', '(?:^|/)cucumber-tsflow/lib/']
31
+ });
32
+ const transformResult = transformer.transformCode(params.content, params.filename);
33
+ return transformResult.code;
34
+ }
35
+ catch (err) {
36
+ console.log(err);
37
+ }
38
+ return params.content;
39
+ });
40
+ //# sourceMappingURL=tsvue-esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsvue-esm.js","sourceRoot":"","sources":["../../../src/transpilers/esm/tsvue-esm.ts"],"names":[],"mappings":";;;;;AAAA,MAAM,KAAK,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;AACjD,yDAAwC;AAExC,OAAO,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC;IAC/B,eAAe,EAAE;QAChB,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,IAAI;QACb,4BAA4B,EAAE,IAAI;QAClC,eAAe,EAAE,IAAI;QACrB,sBAAsB,EAAE,KAAK;QAC7B,iBAAiB,EAAE,IAAI;QACvB,YAAY,EAAE,IAAI;QAClB,GAAG,EAAE,CAAC,QAAQ,EAAE,mBAAmB,CAAC;KACpC;IACD,aAAa,EAAE,IAAI;CACnB,CAAC,CAAC;AAEH,OAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC;AAErC,uDAAuD;AACvD,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;AACzB,MAAc,CAAC,UAAU,GAAI,MAAc,CAAC,MAAM,CAAC,UAAU,CAAC;AAE/D,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,MAAW;IACtC,IAAI,CAAC;QACJ,MAAM,WAAW,GAAG,IAAI,iBAAc,CAAC;YACtC,OAAO,EAAE,CAAC,sBAAsB,EAAE,6BAA6B,CAAC;SAChE,CAAC,CAAC;QACH,MAAM,eAAe,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEnF,OAAO,eAAe,CAAC,IAAI,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["const hooks = require('require-extension-hooks');\r\nimport VueTransformer from '../vue-sfc';\r\n\r\nrequire('ts-node/esm').register({\r\n\tcompilerOptions: {\r\n\t\tmodule: 'esnext',\r\n\t\ttarget: 'es2022',\r\n\t\tstrict: true,\r\n\t\tallowJs: true,\r\n\t\tallowSyntheticDefaultImports: true,\r\n\t\tesModuleInterop: true,\r\n\t\texperimentalDecorators: false,\r\n\t\tresolveJsonModule: true,\r\n\t\tskipLibCheck: true,\r\n\t\tlib: ['es2022', 'esnext.decorators']\r\n\t},\r\n\ttranspileOnly: true\r\n});\r\n\r\nrequire('tsconfig-paths').register();\r\n\r\n// Register jsdom globally and set SVGElement on global\r\nrequire('jsdom-global')();\r\n(global as any).SVGElement = (global as any).window.SVGElement;\r\n\r\nhooks('vue').push(function (params: any) {\r\n\ttry {\r\n\t\tconst transformer = new VueTransformer({\r\n\t\t\texclude: ['(?:^|/)node_modules/', '(?:^|/)cucumber-tsflow/lib/']\r\n\t\t});\r\n\t\tconst transformResult = transformer.transformCode(params.content, params.filename);\r\n\r\n\t\treturn transformResult.code;\r\n\t} catch (err) {\r\n\t\tconsole.log(err);\r\n\t}\r\n\treturn params.content;\r\n});\r\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const hooks = require('require-extension-hooks');
7
+ const vue_sfc_1 = __importDefault(require("../vue-sfc"));
8
+ require('ts-node/esm').register({
9
+ compilerOptions: {
10
+ module: 'nodeNext',
11
+ target: 'es2022',
12
+ strict: true,
13
+ allowJs: true,
14
+ allowSyntheticDefaultImports: true,
15
+ esModuleInterop: true,
16
+ experimentalDecorators: true,
17
+ resolveJsonModule: true,
18
+ skipLibCheck: true,
19
+ lib: ['es2022']
20
+ },
21
+ transpileOnly: true
22
+ });
23
+ require('tsconfig-paths').register();
24
+ // Register jsdom globally and set SVGElement on global
25
+ require('jsdom-global')();
26
+ global.SVGElement = global.window.SVGElement;
27
+ hooks('vue').push(function (params) {
28
+ try {
29
+ const transformer = new vue_sfc_1.default({
30
+ exclude: ['(?:^|/)node_modules/', '(?:^|/)cucumber-tsflow/lib/']
31
+ });
32
+ const transformResult = transformer.transformCode(params.content, params.filename);
33
+ return transformResult.code;
34
+ }
35
+ catch (err) {
36
+ console.log(err);
37
+ }
38
+ return params.content;
39
+ });
40
+ //# sourceMappingURL=tsvue-exp-esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tsvue-exp-esm.js","sourceRoot":"","sources":["../../../src/transpilers/esm/tsvue-exp-esm.ts"],"names":[],"mappings":";;;;;AAAA,MAAM,KAAK,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;AACjD,yDAAwC;AAExC,OAAO,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC;IAC/B,eAAe,EAAE;QAChB,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,IAAI;QACb,4BAA4B,EAAE,IAAI;QAClC,eAAe,EAAE,IAAI;QACrB,sBAAsB,EAAE,IAAI;QAC5B,iBAAiB,EAAE,IAAI;QACvB,YAAY,EAAE,IAAI;QAClB,GAAG,EAAE,CAAC,QAAQ,CAAC;KACf;IACD,aAAa,EAAE,IAAI;CACnB,CAAC,CAAC;AAEH,OAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC;AAErC,uDAAuD;AACvD,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;AACzB,MAAc,CAAC,UAAU,GAAI,MAAc,CAAC,MAAM,CAAC,UAAU,CAAC;AAE/D,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,MAAW;IACtC,IAAI,CAAC;QACJ,MAAM,WAAW,GAAG,IAAI,iBAAc,CAAC;YACtC,OAAO,EAAE,CAAC,sBAAsB,EAAE,6BAA6B,CAAC;SAChE,CAAC,CAAC;QACH,MAAM,eAAe,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEnF,OAAO,eAAe,CAAC,IAAI,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["const hooks = require('require-extension-hooks');\r\nimport VueTransformer from '../vue-sfc';\r\n\r\nrequire('ts-node/esm').register({\r\n\tcompilerOptions: {\r\n\t\tmodule: 'nodeNext',\r\n\t\ttarget: 'es2022',\r\n\t\tstrict: true,\r\n\t\tallowJs: true,\r\n\t\tallowSyntheticDefaultImports: true,\r\n\t\tesModuleInterop: true,\r\n\t\texperimentalDecorators: true,\r\n\t\tresolveJsonModule: true,\r\n\t\tskipLibCheck: true,\r\n\t\tlib: ['es2022']\r\n\t},\r\n\ttranspileOnly: true\r\n});\r\n\r\nrequire('tsconfig-paths').register();\r\n\r\n// Register jsdom globally and set SVGElement on global\r\nrequire('jsdom-global')();\r\n(global as any).SVGElement = (global as any).window.SVGElement;\r\n\r\nhooks('vue').push(function (params: any) {\r\n\ttry {\r\n\t\tconst transformer = new VueTransformer({\r\n\t\t\texclude: ['(?:^|/)node_modules/', '(?:^|/)cucumber-tsflow/lib/']\r\n\t\t});\r\n\t\tconst transformResult = transformer.transformCode(params.content, params.filename);\r\n\r\n\t\treturn transformResult.code;\r\n\t} catch (err) {\r\n\t\tconsole.log(err);\r\n\t}\r\n\treturn params.content;\r\n});\r\n"]}
@@ -0,0 +1,19 @@
1
+ // lib/transpilers/esm/vue-jsdom-setup.mjs
2
+ /* eslint-disable no-undef */
3
+
4
+ import { createRequire } from 'module';
5
+ const require = createRequire(import.meta.url);
6
+
7
+ require('jsdom-global')();
8
+
9
+ // After jsdom-global, window and document should be global
10
+ // Add Vue-specific constructors to global scope
11
+ if (typeof window !== 'undefined') {
12
+ // Use globalThis for cleaner code
13
+ globalThis.SVGElement = window.SVGElement;
14
+ globalThis.Element = window.Element;
15
+ globalThis.HTMLElement = window.HTMLElement;
16
+ globalThis.HTMLDivElement = window.HTMLDivElement;
17
+ }
18
+
19
+ export {}; // Make it a module
@@ -0,0 +1,113 @@
1
+ /**
2
+ * ESM loader for Vue Single File Components (.vue files)
3
+ *
4
+ * This loader enables importing and testing Vue SFC components in Node.js ESM environments.
5
+ * It provides feature parity with the CJS vue-loader but uses Node.js ESM loader hooks.
6
+ *
7
+ * Key features:
8
+ * - Compiles Vue SFC components (template, script, and optionally styles)
9
+ * - Handles TypeScript in Vue components via ts-node delegation
10
+ * - Supports extensionless imports (e.g., import Component from './Component')
11
+ * - Handles asset imports (images, fonts, etc.)
12
+ * - Integrates with tsconfig path mappings
13
+ * - Optional style processing controlled by global.enableVueStyle
14
+ *
15
+ * Differences from CJS version:
16
+ * - Uses ESM loader hooks (resolve/load) instead of require.extensions
17
+ * - Delegates TypeScript handling to ts-node/esm instead of inline transpilation
18
+ * - Sets TS_NODE_FILES=true to ensure ts-node respects tsconfig.json includes
19
+ * (needed for type definition files like Vue shims)
20
+ *
21
+ * Usage:
22
+ * 1. Or configure in cucumber.json:
23
+ * {
24
+ * "default": {
25
+ * "transpiler": ["tsvueesm"]
26
+ * }
27
+ * }
28
+ *
29
+ * 2. Register this loader when running tests:
30
+ * node --loader=@lynxwall/cucumber-tsflow/lib/transpilers/esm/vue-loader.mjs
31
+ *
32
+ * 3. To enable style processing:
33
+ * - Set global.enableVueStyle = true in your test setup
34
+ * - Or set environment variable: CUCUMBER_ENABLE_VUE_STYLE=true
35
+ *
36
+ * Note: Style preprocessing (SCSS, Less, etc.) requires the corresponding
37
+ * preprocessor packages to be installed. Missing preprocessors will be skipped
38
+ * with a warning rather than failing the compilation.
39
+ */
40
+ import path from 'path';
41
+ import { ASSET_EXTENSIONS, resolveSpecifier, loadAsset, loadVue } from './loader-utils.mjs';
42
+
43
+ // Cache for the TypeScript loader
44
+ let tsLoader;
45
+
46
+ async function getTsLoader() {
47
+ if (!tsLoader) {
48
+ try {
49
+ // Ensure ts-node respects tsconfig.json files
50
+ // This is crucial for picking up:
51
+ // - Type definition files (d.ts)
52
+ // - Include/exclude patterns
53
+ // - Custom type roots (e.g., for Vue shims)
54
+ // Without this, ts-node might ignore the tsconfig.json includes process.env.TS_NODE_FILES = process.env.TS_NODE_FILES || 'true';
55
+
56
+ // Import ts-node's ESM loader
57
+ const tsNodeEsm = await import('ts-node-maintained/esm');
58
+ tsLoader = tsNodeEsm;
59
+ } catch (error) {
60
+ console.error('>>> vue-loader: Failed to load ts-node ESM loader:', error);
61
+ throw error;
62
+ }
63
+ }
64
+ return tsLoader;
65
+ }
66
+
67
+ export async function load(url, context, nextLoad) {
68
+ // Handle asset files that Vue compiler turns into imports
69
+ const ext = path.extname(url).toLowerCase();
70
+ if (ASSET_EXTENSIONS.includes(ext)) {
71
+ return loadAsset(url);
72
+ }
73
+
74
+ // Only process .vue files directly
75
+ if (url.endsWith('.vue')) {
76
+ try {
77
+ return loadVue(url, context, nextLoad);
78
+ } catch (error) {
79
+ console.error(`>>> vue-loader: Failed to compile Vue SFC ${url}:`, error);
80
+ throw new Error(`Failed to compile Vue SFC ${url}: ${error.message}`);
81
+ }
82
+ }
83
+
84
+ // For TypeScript files, delegate to ts-node
85
+ if (url.endsWith('.ts') || url.endsWith('.tsx')) {
86
+ try {
87
+ const tsNode = await getTsLoader();
88
+ return tsNode.load(url, context, nextLoad);
89
+ } catch (error) {
90
+ console.error(`>>> vue-loader: ts-node failed for ${url}:`, error);
91
+ throw error;
92
+ }
93
+ }
94
+
95
+ // For everything else, use the default loader
96
+ // This includes: .js, .mjs, .json, node: URLs, etc.
97
+ return nextLoad(url, context);
98
+ }
99
+
100
+ export async function resolve(specifier, context, nextResolve) {
101
+ // Try common resolution logic
102
+ const resolved = await resolveSpecifier(specifier, context, {
103
+ checkExtensions: true,
104
+ handleTsFiles: false, // Vue loader doesn't handle TS files directly
105
+ nextResolve
106
+ });
107
+
108
+ if (resolved) {
109
+ return resolved;
110
+ }
111
+
112
+ return nextResolve(specifier, context);
113
+ }
@@ -0,0 +1,216 @@
1
+ import { parse, compileScript, compileTemplate, compileStyle } from 'vue/compiler-sfc';
2
+ import hash from 'hash-sum';
3
+ import { transformSync } from 'esbuild';
4
+
5
+ /**
6
+ * Vue Single File Component compiler for ESM
7
+ *
8
+ * Compiles .vue files into JavaScript modules that can be imported in Node.js.
9
+ * Uses @vue/compiler-sfc to handle template, script, and style blocks.
10
+ *
11
+ * Features:
12
+ * - TypeScript support in <script> blocks via esbuild
13
+ * - Template compilation with proper component resolution
14
+ * - Optional style compilation (controlled by enableStyle option)
15
+ * - Asset URL transformation (images become imports)
16
+ * - Scoped CSS support
17
+ *
18
+ * Style handling:
19
+ * - When enableStyle is false (default): styles are ignored
20
+ * - When enableStyle is true: styles are compiled and injected into document
21
+ * - Preprocessors (SCSS, Less, etc.) are skipped if not installed
22
+ *
23
+ * @param {string} source - Vue SFC source code
24
+ * @param {string} filename - Path to the Vue file
25
+ * @param {Object} options - Compilation options
26
+ * @param {boolean} options.enableStyle - Whether to process <style> blocks
27
+ * @returns {Object} { code: string } - Compiled JavaScript module
28
+ */
29
+ export function compileVueSFC(source, filename, options = {}) {
30
+ const { enableStyle = false } = options;
31
+
32
+ const { descriptor, errors } = parse(source, {
33
+ filename,
34
+ sourceMap: true
35
+ });
36
+
37
+ if (errors.length) {
38
+ throw new Error(errors.map(e => e.message).join('\n'));
39
+ }
40
+
41
+ const id = hash(filename);
42
+ const hasScoped = descriptor.styles.some(s => s.scoped);
43
+
44
+ // First, we need to check if template uses any components
45
+ let templateAst = null;
46
+ if (descriptor.template) {
47
+ // Parse template to get AST - this helps compileScript understand component usage
48
+ const { ast } = compileTemplate({
49
+ source: descriptor.template.content,
50
+ filename,
51
+ id,
52
+ compilerOptions: {
53
+ mode: 'module',
54
+ parseOnly: true // Just parse, don't compile yet
55
+ }
56
+ });
57
+ templateAst = ast;
58
+ }
59
+
60
+ // Compile script
61
+ let scriptCode = '';
62
+ let compiledScript = undefined;
63
+ if (descriptor.script || descriptor.scriptSetup) {
64
+ compiledScript = compileScript(descriptor, {
65
+ id,
66
+ inlineTemplate: false,
67
+ sourceMap: true,
68
+ genDefaultAs: '_sfc_main',
69
+ templateAst, // Pass template AST so it knows which components are used
70
+ // This tells the compiler to resolve components from setup bindings
71
+ resolveComponents: true
72
+ });
73
+
74
+ // Check if the script is TypeScript
75
+ const isTS = descriptor.script?.lang === 'ts' || descriptor.scriptSetup?.lang === 'ts';
76
+
77
+ if (isTS) {
78
+ // Transpile TypeScript to JavaScript
79
+ const result = transformSync(compiledScript.content, {
80
+ loader: 'ts',
81
+ format: 'esm',
82
+ target: 'es2022',
83
+ sourcemap: 'inline'
84
+ });
85
+ scriptCode = result.code;
86
+ } else {
87
+ scriptCode = compiledScript.content;
88
+ }
89
+ }
90
+
91
+ // Compile template if exists
92
+ let templateCode = '';
93
+ if (descriptor.template) {
94
+ const template = compileTemplate({
95
+ source: descriptor.template.content,
96
+ filename,
97
+ id,
98
+ scoped: hasScoped,
99
+ compilerOptions: {
100
+ mode: 'module',
101
+ // Pass the bindings from script compilation to template
102
+ bindingMetadata: compiledScript ? compiledScript.bindings : undefined
103
+ },
104
+ // Force asset URLs to become imports (matching CJS behavior)
105
+ transformAssetUrls: {
106
+ includeAbsolute: true
107
+ }
108
+ });
109
+
110
+ if (template.errors.length) {
111
+ throw new Error(template.errors.map(e => e.message).join('\n'));
112
+ }
113
+
114
+ templateCode = template.code;
115
+ }
116
+
117
+ // Compile styles if enabled
118
+ let styleCode = '';
119
+ if (enableStyle && descriptor.styles.length > 0) {
120
+ const styles = [];
121
+
122
+ for (const style of descriptor.styles) {
123
+ try {
124
+ const compiled = compileStyle({
125
+ source: style.content,
126
+ filename,
127
+ id,
128
+ scoped: style.scoped,
129
+ preprocessLang: style.lang
130
+ });
131
+
132
+ if (compiled.errors.length) {
133
+ // Check if it's a preprocessor error
134
+ const hasPreprocessorError = compiled.errors.some(
135
+ e =>
136
+ e.message.includes('sass') ||
137
+ e.message.includes('scss') ||
138
+ e.message.includes('less') ||
139
+ e.message.includes('stylus')
140
+ );
141
+
142
+ if (hasPreprocessorError) {
143
+ console.warn(`Skipping ${style.lang || 'css'} style in ${filename} - preprocessor not available`);
144
+ continue;
145
+ }
146
+
147
+ console.warn(`Style compilation errors in ${filename}:`, compiled.errors);
148
+ }
149
+
150
+ styles.push(compiled.code);
151
+ } catch (error) {
152
+ // Handle missing preprocessor errors
153
+ if (error.message.includes('Cannot find module')) {
154
+ console.warn(`Skipping ${style.lang || 'css'} style in ${filename} - ${error.message}`);
155
+ continue;
156
+ }
157
+ throw error;
158
+ }
159
+ }
160
+
161
+ if (styles.length > 0) {
162
+ // Create a style injection function
163
+ styleCode = `
164
+ // Style injection
165
+ if (typeof document !== 'undefined') {
166
+ (function() {
167
+ const styles = ${JSON.stringify(styles)};
168
+ const id = '${id}';
169
+
170
+ // Check if styles already injected
171
+ if (!document.querySelector(\`[data-vite-vue-id="\${id}"]\`)) {
172
+ styles.forEach((css, index) => {
173
+ const style = document.createElement('style');
174
+ style.setAttribute('data-vite-vue-id', id);
175
+ if (${hasScoped}) {
176
+ style.setAttribute('data-v-' + id, '');
177
+ }
178
+ style.textContent = css;
179
+ document.head.appendChild(style);
180
+ });
181
+ }
182
+ })();
183
+ }
184
+ `;
185
+ }
186
+ }
187
+
188
+ // Combine everything
189
+ let finalCode = scriptCode;
190
+
191
+ if (templateCode) {
192
+ // Add the render function to the component
193
+ finalCode += '\n' + templateCode;
194
+ finalCode += '\n_sfc_main.render = render;';
195
+ }
196
+
197
+ // Add scoped id if needed
198
+ if (hasScoped) {
199
+ finalCode += `\n_sfc_main.__scopeId = 'data-v-${id}';`;
200
+ }
201
+
202
+ // Add style injection
203
+ if (styleCode) {
204
+ finalCode = styleCode + '\n' + finalCode;
205
+ }
206
+
207
+ // Ensure there's a default export
208
+ if (!/export\s+default/.test(finalCode)) {
209
+ finalCode += '\nexport default _sfc_main;';
210
+ }
211
+
212
+ // For ESM, we need to export everything properly
213
+ return {
214
+ code: finalCode
215
+ };
216
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- require('ts-node').register({
3
+ require('ts-node-maintained').register({
4
4
  transpileOnly: true,
5
5
  transpiler: '@lynxwall/cucumber-tsflow/lib/transpilers/esbuild-transpiler'
6
6
  });
@@ -1 +1 @@
1
- {"version":3,"file":"esnode.js","sourceRoot":"","sources":["../../src/transpilers/esnode.ts"],"names":[],"mappings":";;AAAA,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC;IAC3B,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,8DAA8D;CAC1E,CAAC,CAAC;AAEH,OAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC","sourcesContent":["require('ts-node').register({\r\n\ttranspileOnly: true,\r\n\ttranspiler: '@lynxwall/cucumber-tsflow/lib/transpilers/esbuild-transpiler'\r\n});\r\n\r\nrequire('tsconfig-paths').register();\r\n"]}
1
+ {"version":3,"file":"esnode.js","sourceRoot":"","sources":["../../src/transpilers/esnode.ts"],"names":[],"mappings":";;AAAA,OAAO,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC;IACtC,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,8DAA8D;CAC1E,CAAC,CAAC;AAEH,OAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC","sourcesContent":["require('ts-node-maintained').register({\r\n\ttranspileOnly: true,\r\n\ttranspiler: '@lynxwall/cucumber-tsflow/lib/transpilers/esbuild-transpiler'\r\n});\r\n\r\nrequire('tsconfig-paths').register();\r\n"]}
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const hooks = require('require-extension-hooks');
7
7
  const vue_sfc_1 = __importDefault(require("./vue-sfc"));
8
- require('ts-node').register({
8
+ require('ts-node-maintained').register({
9
9
  transpileOnly: true,
10
10
  transpiler: '@lynxwall/cucumber-tsflow/lib/transpilers/esbuild-transpiler'
11
11
  });
@@ -1 +1 @@
1
- {"version":3,"file":"esvue.js","sourceRoot":"","sources":["../../src/transpilers/esvue.ts"],"names":[],"mappings":";;;;;AAAA,MAAM,KAAK,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;AACjD,wDAAuC;AAEvC,OAAO,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC;IAC3B,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,8DAA8D;CAC1E,CAAC,CAAC;AAEH,OAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC;AAErC,uDAAuD;AACvD,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;AACzB,MAAc,CAAC,UAAU,GAAI,MAAc,CAAC,MAAM,CAAC,UAAU,CAAC;AAE/D,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,MAAW;IACtC,IAAI,CAAC;QACJ,MAAM,WAAW,GAAG,IAAI,iBAAc,CAAC;YACtC,OAAO,EAAE,CAAC,sBAAsB,EAAE,6BAA6B,CAAC;SAChE,CAAC,CAAC;QACH,MAAM,eAAe,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEnF,OAAO,eAAe,CAAC,IAAI,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["const hooks = require('require-extension-hooks');\r\nimport VueTransformer from './vue-sfc';\r\n\r\nrequire('ts-node').register({\r\n\ttranspileOnly: true,\r\n\ttranspiler: '@lynxwall/cucumber-tsflow/lib/transpilers/esbuild-transpiler'\r\n});\r\n\r\nrequire('tsconfig-paths').register();\r\n\r\n// Register jsdom globally and set SVGElement on global\r\nrequire('jsdom-global')();\r\n(global as any).SVGElement = (global as any).window.SVGElement;\r\n\r\nhooks('vue').push(function (params: any) {\r\n\ttry {\r\n\t\tconst transformer = new VueTransformer({\r\n\t\t\texclude: ['(?:^|/)node_modules/', '(?:^|/)cucumber-tsflow/lib/']\r\n\t\t});\r\n\t\tconst transformResult = transformer.transformCode(params.content, params.filename);\r\n\r\n\t\treturn transformResult.code;\r\n\t} catch (err) {\r\n\t\tconsole.log(err);\r\n\t}\r\n\treturn params.content;\r\n});\r\n"]}
1
+ {"version":3,"file":"esvue.js","sourceRoot":"","sources":["../../src/transpilers/esvue.ts"],"names":[],"mappings":";;;;;AAAA,MAAM,KAAK,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;AACjD,wDAAuC;AAEvC,OAAO,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC;IACtC,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,8DAA8D;CAC1E,CAAC,CAAC;AAEH,OAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC;AAErC,uDAAuD;AACvD,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;AACzB,MAAc,CAAC,UAAU,GAAI,MAAc,CAAC,MAAM,CAAC,UAAU,CAAC;AAE/D,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,MAAW;IACtC,IAAI,CAAC;QACJ,MAAM,WAAW,GAAG,IAAI,iBAAc,CAAC;YACtC,OAAO,EAAE,CAAC,sBAAsB,EAAE,6BAA6B,CAAC;SAChE,CAAC,CAAC;QACH,MAAM,eAAe,GAAG,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEnF,OAAO,eAAe,CAAC,IAAI,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["const hooks = require('require-extension-hooks');\r\nimport VueTransformer from './vue-sfc';\r\n\r\nrequire('ts-node-maintained').register({\r\n\ttranspileOnly: true,\r\n\ttranspiler: '@lynxwall/cucumber-tsflow/lib/transpilers/esbuild-transpiler'\r\n});\r\n\r\nrequire('tsconfig-paths').register();\r\n\r\n// Register jsdom globally and set SVGElement on global\r\nrequire('jsdom-global')();\r\n(global as any).SVGElement = (global as any).window.SVGElement;\r\n\r\nhooks('vue').push(function (params: any) {\r\n\ttry {\r\n\t\tconst transformer = new VueTransformer({\r\n\t\t\texclude: ['(?:^|/)node_modules/', '(?:^|/)cucumber-tsflow/lib/']\r\n\t\t});\r\n\t\tconst transformResult = transformer.transformCode(params.content, params.filename);\r\n\r\n\t\treturn transformResult.code;\r\n\t} catch (err) {\r\n\t\tconsole.log(err);\r\n\t}\r\n\treturn params.content;\r\n});\r\n"]}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- require('ts-node').register({
3
+ require('ts-node-maintained').register({
4
4
  compilerOptions: {
5
5
  module: 'nodeNext',
6
6
  target: 'es2022',