diff --git a/README.md b/README.md index a5ddd4f1..a920196e 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ You might want to configure your development tool for debugging. The wizard auto Now, you have to press F5 or press Run -> Start Debugging, and you can set breakpoints, step through lines of code, inspect variables... For more information on how to [debug in VSCode, please refer to this link](https://code.visualstudio.com/docs/editor/debugging). -For other tools, please send documentation to include here. WebStorm instructions are especially needed. +The wizard also creates a configuration for JetBrains IDEs, such as WebStorm. ## Removing diff --git a/package-lock.json b/package-lock.json index 50dadc42..cc9c5f0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,6 +57,7 @@ "chokidar": "^3.6.0", "commander": "^13.1.0", "esbuild": "^0.25.0", + "fast-xml-parser": "^5.0.8", "inquirer": "^12.4.2", "jsonc-parser": "^3.3.1", "node-machine-id": "^1.1.12", @@ -1679,6 +1680,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-cloudformation/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-cloudformation/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/client-cognito-identity": { "version": "3.758.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.758.0.tgz", @@ -2773,6 +2810,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-cognito-identity/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-cognito-identity/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/client-eventbridge": { "version": "3.637.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-eventbridge/-/client-eventbridge-3.637.0.tgz", @@ -3869,6 +3942,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-iam/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-iam/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/client-iot": { "version": "3.758.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-iot/-/client-iot-3.758.0.tgz", @@ -4965,6 +5074,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-iot-data-plane/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-iot-data-plane/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/client-iot/node_modules/@aws-sdk/client-sso": { "version": "3.758.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.758.0.tgz", @@ -5956,6 +6101,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-iot/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-iot/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/client-lambda": { "version": "3.758.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.758.0.tgz", @@ -7003,6 +7184,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-lambda/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/client-s3": { "version": "3.758.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.758.0.tgz", @@ -8119,6 +8336,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/client-s3/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/client-sso": { "version": "3.637.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.637.0.tgz", @@ -8293,6 +8546,42 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/core/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/core/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { "version": "3.758.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.758.0.tgz", @@ -9506,6 +9795,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/credential-providers/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/credential-providers/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { "version": "3.734.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.734.0.tgz", @@ -10154,6 +10479,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/middleware-host-header": { "version": "3.620.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", @@ -11167,6 +11528,42 @@ "node": ">=18.0.0" } }, + "node_modules/@aws-sdk/nested-clients/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/nested-clients/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "inBundle": true, + "license": "MIT" + }, "node_modules/@aws-sdk/region-config-resolver": { "version": "3.614.0", "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", @@ -19531,22 +19928,18 @@ "dev": true }, "node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.0.8.tgz", + "integrity": "sha512-qY8NiI5L8ff00F2giyICiJxSSKHO52tC36LJqx2JtvGyAd5ZfehC/l4iUVVHpmpIa6sM9N5mneSLHQG2INGoHA==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], - "inBundle": true, + "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "strnum": "^2.0.5" }, "bin": { "fxparser": "src/cli/cli.js" @@ -27697,10 +28090,16 @@ } }, "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", - "inBundle": true + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.0.5.tgz", + "integrity": "sha512-YAT3K/sgpCUxhxNMrrdhtod3jckkpYwH6JAuwmUdXZsmzH1wUyzTMrrK2wYCEEqlKwrWDd35NeuUkbBy/1iK+Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" }, "node_modules/strtok3": { "version": "6.3.0", @@ -30667,6 +31066,40 @@ "node": ">=18.0.0" } }, + "test/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "test/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "test/opentofu-basic": { "name": "openotofu-basic", "version": "1.0.0", diff --git a/package.json b/package.json index cfa46fcb..7df4198b 100755 --- a/package.json +++ b/package.json @@ -115,6 +115,7 @@ "chokidar": "^3.6.0", "commander": "^13.1.0", "esbuild": "^0.25.0", + "fast-xml-parser": "^5.0.8", "inquirer": "^12.4.2", "jsonc-parser": "^3.3.1", "node-machine-id": "^1.1.12", @@ -133,6 +134,7 @@ "aws-iot-device-sdk", "chokidar", "commander", + "fast-xml-parser", "node-machine-id", "toml", "yaml", diff --git a/src/configuration/getConfigFromWizard.ts b/src/configuration/getConfigFromWizard.ts index d6820482..ac0fe01e 100644 --- a/src/configuration/getConfigFromWizard.ts +++ b/src/configuration/getConfigFromWizard.ts @@ -17,6 +17,7 @@ import { GitIgnore } from '../gitignore.js'; import { VsCode } from '../vsCode.js'; import { Logger } from '../logger.js'; import { Configuration } from '../configuration.js'; +import { JetBrains } from '../jetBrains.js'; const configFileName = path.resolve(configFileDefaultName); @@ -335,6 +336,19 @@ export async function getConfigFromWizard({ answers.vscode = answersVsCode.vscode; } + if (!(await JetBrains.isConfigured())) { + const answersJetBrains = await inquirer.prompt([ + { + type: 'confirm', + name: 'jetbrains', + message: `Would you like to add configuration for JetBrains IDE, like WebStorm?`, + default: false, + }, + ]); + + answers.jetbrains = answersJetBrains.jetbrains; + } + const answersVerbose = await inquirer.prompt([ { type: 'confirm', @@ -464,6 +478,7 @@ function getConfigFromAnswers(answers: any): LldConfigCliArgs { interactive: answers.interactive, gitignore: answers.gitignore, vscode: answers.vscode, + jetbrains: answers.jetbrains, }; //remove undefined and empty strings diff --git a/src/jetBrains.ts b/src/jetBrains.ts new file mode 100644 index 00000000..163e2f19 --- /dev/null +++ b/src/jetBrains.ts @@ -0,0 +1,150 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { XMLParser, XMLBuilder } from 'fast-xml-parser'; +import { getProjectDirname } from './getDirname.js'; +import { Logger } from './logger.js'; +import { getRuntimeExecutableForIde } from './utils/getRuntimeExecutableForIde.js'; + +const workspaceXmlPath = path.join( + getProjectDirname(), + '.idea', + 'workspace.xml', +); + +async function getJetBrainsLaunchConfig() { + let runtimeExecutable = await getRuntimeExecutableForIde(false); + + if (!runtimeExecutable) { + return undefined; + } + + runtimeExecutable = runtimeExecutable.replace( + '${workspaceFolder}', + '$PROJECT_DIR$', + ); + return { + configuration: { + '@_name': 'Lambda Live Debugger', + '@_type': 'NodeJSConfigurationType', + '@_path-to-js-file': runtimeExecutable, + '@_working-dir': '$PROJECT_DIR$', + method: { '@_v': '2' }, + }, + }; +} + +async function readWorkspaceXml( + filePath: string, +): Promise<{ json: any; xmlString: string }> { + try { + const xmlString = await fs.readFile(filePath, 'utf-8'); + const parser = new XMLParser({ + ignoreAttributes: false, + allowBooleanAttributes: true, + }); + const json = parser.parse(xmlString); + return { json, xmlString }; + } catch (err: any) { + if (err.code === 'ENOENT') { + return { json: null, xmlString: '' }; + } + throw new Error(`Error reading ${filePath}`, { cause: err }); + } +} + +async function writeWorkspaceXml(filePath: string, json: any) { + try { + const builder = new XMLBuilder({ + ignoreAttributes: false, + format: true, + suppressEmptyNode: true, + suppressBooleanAttributes: false, + }); + const xmlString = builder.build(json); + await fs.writeFile(filePath, xmlString, 'utf-8'); + Logger.verbose(`Updated JetBrains IDE configuration at ${filePath}`); + } catch (err) { + throw new Error(`Error writing ${filePath}`, { cause: err }); + } +} + +async function isConfigured() { + const { json } = await readWorkspaceXml(workspaceXmlPath); + if (!json) return false; + + const components = Array.isArray(json.project?.component) + ? json.project.component + : [json.project?.component]; + const runManager = components.find((c: any) => c['@_name'] === 'RunManager'); + if (!runManager) return false; + + const configurations = runManager.configuration || []; + return configurations.some( + (c: any) => c['@_name'] === 'Lambda Live Debugger', + ); +} + +async function addConfiguration() { + Logger.verbose('Adding JetBrains IDE run/debug configuration'); + const { json } = await readWorkspaceXml(workspaceXmlPath); + const config = await getJetBrainsLaunchConfig(); + + if (!config) { + Logger.error( + 'Failed to configure JetBrains IDE. Cannot find a locally installed Lambda Live Debugger. The JetBrains IDE debugger cannot use a globally installed version.', + ); + return; + } + + if (!json) { + // Create new workspace.xml if it does not exist + const newJson = { + '?xml': { '@_version': '1.0', '@_encoding': 'UTF-8' }, + project: { + '@_version': '4', + component: { + '@_name': 'RunManager', + configuration: [config.configuration], + }, + }, + }; + await fs.mkdir(path.dirname(workspaceXmlPath), { recursive: true }); + await writeWorkspaceXml(workspaceXmlPath, newJson); + return; + } + + let runManager = json.project.component.find( + (c: any) => c['@_name'] === 'RunManager', + ); + + if (!runManager) { + Logger.verbose('RunManager not found, creating new RunManager component'); + runManager = { '@_name': 'RunManager', configuration: [] }; + json.project.component.push(runManager); + } + + let configurations; + if (!runManager.configuration) { + configurations = []; + } else if (!Array.isArray(runManager.configuration)) { + configurations = [runManager.configuration]; + } else { + configurations = runManager.configuration; + } + + const exists = configurations.some( + (c: any) => c['@_name'] === config.configuration['@_name'], + ); + if (!exists) { + Logger.verbose('Adding new configuration to workspace.xml'); + runManager.configuration = [...configurations, config.configuration]; + await writeWorkspaceXml(workspaceXmlPath, json); + } else { + Logger.verbose('Configuration already exists in workspace.xml'); + } +} + +export const JetBrains = { + isConfigured, + addConfiguration, +}; diff --git a/src/lldebugger.ts b/src/lldebugger.ts index 517b676b..30467222 100755 --- a/src/lldebugger.ts +++ b/src/lldebugger.ts @@ -17,6 +17,7 @@ import { Logger } from './logger.js'; import { getModuleDirname, getProjectDirname } from './getDirname.js'; import { LambdaConnection } from './lambdaConnection.js'; import inquirer from 'inquirer'; +import { JetBrains } from './jetBrains.js'; /** * Start the Lambda Live Debugger @@ -46,6 +47,10 @@ async function run() { await VsCode.addConfiguration(); } + if (Configuration.config.jetbrains) { + await JetBrains.addConfiguration(); + } + if (!Configuration.config.start && !Configuration.config.remove) { return; } diff --git a/src/types/lldConfig.ts b/src/types/lldConfig.ts index b80f86d4..0c121e60 100644 --- a/src/types/lldConfig.ts +++ b/src/types/lldConfig.ts @@ -78,6 +78,7 @@ export type LldConfigBase = { export type LldConfigCliArgs = { remove?: 'keep-layer' | 'all'; vscode?: boolean; + jetbrains?: boolean; gitignore?: boolean; config?: string; wizard?: boolean; diff --git a/src/utils/getRuntimeExecutableForIde.ts b/src/utils/getRuntimeExecutableForIde.ts new file mode 100644 index 00000000..fa6eef8c --- /dev/null +++ b/src/utils/getRuntimeExecutableForIde.ts @@ -0,0 +1,93 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { getModuleDirname, getProjectDirname } from '../getDirname.js'; +import { Logger } from '../logger.js'; + +/** + * Get the runtime executable for the IDE, like WebStorm or VSCode + * @returns + */ +export async function getRuntimeExecutableForIde(allowGlobal = true) { + let runtimeExecutable: string | undefined; + const localRuntimeExecutable = '${workspaceFolder}/node_modules/.bin/lld'; + + const moduleDirname = getModuleDirname(); + const projectDirname = getProjectDirname(); + + const localFolder = path.resolve( + path.join(projectDirname, 'node_modules/.bin/lld'), + ); + + //if installed locally + Logger.verbose('Lambda Live Debugger is installed locally'); + try { + Logger.verbose( + 'Checking local folder for runtimeExecutable setting for VsCode configuration', + localFolder, + ); + await fs.access(localFolder, fs.constants.F_OK); + runtimeExecutable = localRuntimeExecutable; + } catch { + // Not found + } + + if (!runtimeExecutable) { + Logger.verbose('Lambda Live Debugger is installed globally'); + + if (allowGlobal) { + Logger.verbose( + `Setting absolute path for runtimeExecutable setting for VsCode configuration`, + ); + const localFolderSubfolder = path.resolve('node_modules/.bin/lld'); + const globalModule1 = path.join(moduleDirname, '..', '..', '.bin/lld'); + const globalModule2 = path.join(moduleDirname, '..', '..', 'bin/lld'); + const globalModule3 = path.join( + moduleDirname, + '..', + '..', + '..', + '..', + 'bin/lld', + ); + const possibleFolders = { + [localFolder]: '${workspaceFolder}/node_modules/.bin/lld', + [localFolderSubfolder]: localFolderSubfolder, + [globalModule1]: globalModule1, + [globalModule2]: globalModule2, + [globalModule3]: globalModule3, + }; + + Logger.verbose( + `Checking the following possible folders for lld executable:`, + JSON.stringify(possibleFolders, null, 2), + ); + + // check each possible folder and set the runtimeExecutable + for (const folder in possibleFolders) { + try { + //Logger.log("Checking folder", folder); + await fs.access(folder, fs.constants.F_OK); + runtimeExecutable = possibleFolders[folder]; + Logger.verbose(`Found folder with lld executable: ${folder}`); + break; + } catch { + // Not found + } + } + + if (!runtimeExecutable) { + Logger.error( + `Could not find lld executable. Please check your IDE debugger settings.`, + ); + } + } else { + return null; + } + } + + if (!runtimeExecutable) { + return localRuntimeExecutable; + } + + return runtimeExecutable; +} diff --git a/src/vsCode.ts b/src/vsCode.ts index affd80af..ca7d917d 100644 --- a/src/vsCode.ts +++ b/src/vsCode.ts @@ -9,11 +9,12 @@ import { FormattingOptions, } from 'jsonc-parser'; import { VsCodeLaunch } from './types/vsCodeConfig.js'; -import { getModuleDirname, getProjectDirname } from './getDirname.js'; +import { getProjectDirname } from './getDirname.js'; import { Logger } from './logger.js'; +import { getRuntimeExecutableForIde } from './utils/getRuntimeExecutableForIde.js'; async function getVsCodeLaunchConfig() { - const localRuntimeExecutable = '${workspaceFolder}/node_modules/.bin/lld'; + const runtimeExecutable = await getRuntimeExecutableForIde(); const config: VsCodeLaunch = { version: '0.2.0', @@ -22,7 +23,7 @@ async function getVsCodeLaunchConfig() { name: 'Lambda Live Debugger', type: 'node', request: 'launch', - runtimeExecutable: localRuntimeExecutable, + runtimeExecutable: runtimeExecutable!, runtimeArgs: [], console: 'integratedTerminal', skipFiles: ['/**'], @@ -31,86 +32,6 @@ async function getVsCodeLaunchConfig() { ], }; - const moduleDirname = getModuleDirname(); - //Logger.log("Module folder", moduleDirname); - const projectDirname = getProjectDirname(); - - //Logger.log("Current folder", currentFolder); - const localFolder = path.resolve( - path.join(projectDirname, 'node_modules/.bin/lld'), - ); - - let runtimeExecutableSet = false; - - //if installed locally - if (moduleDirname.startsWith('/home/')) { - Logger.verbose('Lambda Live Debugger is installed locally'); - // check if file exists - try { - Logger.verbose( - 'Checking local folder for runtimeExecutable setting for VsCode configuration', - localFolder, - ); - await fs.access(localFolder, fs.constants.F_OK); - config.configurations![0].runtimeExecutable = localRuntimeExecutable; - runtimeExecutableSet = true; - //Logger.log("Found local folder", localFolder); - } catch { - //Logger.log("Not found", localFolder); - } - } else { - Logger.verbose('Lambda Live Debugger is installed globally'); - } - - if (!runtimeExecutableSet) { - Logger.verbose( - `Setting absolute path for runtimeExecutable setting for VsCode configuration`, - ); - const localFolderSubfolder = path.resolve('node_modules/.bin/lld'); - const globalModule1 = path.join(moduleDirname, '..', '..', '.bin/lld'); - const globalModule2 = path.join(moduleDirname, '..', '..', 'bin/lld'); - const globalModule3 = path.join( - moduleDirname, - '..', - '..', - '..', - '..', - 'bin/lld', - ); - const possibleFolders = { - [localFolder]: '${workspaceFolder}/node_modules/.bin/lld', - [localFolderSubfolder]: localFolderSubfolder, - [globalModule1]: globalModule1, - [globalModule2]: globalModule2, - [globalModule3]: globalModule3, - }; - - Logger.verbose( - `Checking the following possible folders for lld executable:`, - JSON.stringify(possibleFolders, null, 2), - ); - - // check each possible folder and set the runtimeExecutable - for (const folder in possibleFolders) { - try { - //Logger.log("Checking folder", folder); - await fs.access(folder, fs.constants.F_OK); - config.configurations![0].runtimeExecutable = possibleFolders[folder]; - runtimeExecutableSet = true; - Logger.verbose(`Found folder with lld executable: ${folder}`); - break; - } catch { - // Not found - } - } - - if (!runtimeExecutableSet) { - Logger.error( - `Could not find lld executable. Please check the setting runtimeExecutable in '.vscode/launch.json'.`, - ); - } - } - return config; }