diff --git a/README.md b/README.md index 0792665..1640aa9 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ Fluent (ServiceNow SDK) MCP bridges development tools with AI-assisted developme Key capabilities include: -- All ServiceNow SDK CLI commands: `version`, `help`, `auth`, `init`, `build`, `install`, `upgrade`, `dependencies`, `transform` +- **Complete ServiceNow SDK CLI coverage**: All native SDK commands are now available including `auth`, `init`, `build`, `install`, `dependencies`, `transform`, `download`, `clean`, and `pack` +- **Enhanced SDK information access**: Get SDK version, help, and debug information with improved `sdk_info` command - ServiceNow instance `basic` or `oauth` authentication (optional, only needed for CLI commands, not for resources) - Resource capability of API specifications for metadata types like `acl`, `business-rule`, `client-script`, `table`, `ui-action` and more - Code snippets and examples for different metadata types @@ -24,23 +25,34 @@ Create a new Fluent app under ~/Downloads/fluent-app to track employee time off ### ServiceNow SDK Commands -Note: Use `init` command to switch to a working directory for existing Fluent projects or to create a new one. +Note: Use `init_fluent_app` command to switch to a working directory for existing Fluent projects or to create a new one. -| Tool Name | Description | Parameters | -| -------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `version` | Get ServiceNow SDK version information | None | -| `help` | Get help information about ServiceNow SDK commands | `command`: (Optional) The specific command to get help for | -| `upgrade` | Upgrade ServiceNow SDK to the latest version | `check`: (Optional) Only check for updates without upgrading, `debug`: (Optional) Enable debug - **disabled for now** | -| `auth` | Authenticate to a ServiceNow instance | `add`: (Optional) Instance URL to add, `type`: (Optional) Authentication method, `alias`: (Optional) Alias for the instance | -| `init` | Initialize a new ServiceNow application | `from`: (Optional) sys_id or path, `appName`: App name, `packageName`: Package name, `scopeName`: Scope name, `auth`: (Optional) Authentication alias, `template`: (Optional) Project template (base, javascript.react, typescript.basic, typescript.react, javascript.basic) [new in now-sdk@v4] Select a template that defines the default application structure: `Basic now-sdk boilerplate`: An application with only the basic structure necessary for development in source code. `JavaScript now-sdk + basic`: An application configured for development in ServiceNow Fluent and JavaScript. `JavaScript now-sdk + fullstack React`: An application configured for development in ServiceNow Fluent, JavaScript, and React. `TypeScript now-sdk + basic`: An application configured for development in ServiceNow Fluent and TypeScript. TypeScript source files in the src/server directory are transpiled into JavaScript modules. `TypeScript now-sdk + fullstack React`: An application configured for development in ServiceNow Fluent, TypeScript, and React. TypeScript source files in the src/server directory are transpiled into JavaScript modules.| -| `build` | Build a ServiceNow application package | `source`: Path to source files, `frozenKeys`: (Optional) Whether to use frozen keys | -| `install` | Install a ServiceNow application to an instance | `source`: (Optional) Package path, `reinstall`: (Optional) Whether to reinstall, `auth`: (Optional) Authentication alias, `open-browser`: (Optional) Open browser after install, `info`: (Optional) Show info after install | -| `transform` | Transform ServiceNow metadata to Fluent source code | `from`: (Optional) Path to metadata, `directory`: (Optional) Package path, `preview`: (Optional) Preview only, `auth`: (Optional) Authentication alias | -| `dependencies` | Download application dependencies | `directory`: (Optional) Package path, `auth`: (Optional) Authentication alias | +| Tool Name | Description | Parameters | +| ------------------------------ | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `sdk_info` | Get Fluent (ServiceNow SDK) information using native SDK flags | `flag`: SDK flag to execute (-v/--version, -h/--help, -d/--debug), `command`: (Optional) Specific command to get help for (only used with -h/--help flag) | +| `manage_fluent_auth` | Manage Fluent (ServiceNow SDK) authentication to instance | `add`: (Optional) Instance URL to add, `type`: (Optional) Authentication method, `alias`: (Optional) Alias for the instance, `list`: (Optional) List auth profiles, `delete`: (Optional) Delete auth profile, `use`: (Optional) Switch default auth | +| `init_fluent_app` | Initialize a new ServiceNow custom application or convert a legacy application | `from`: (Optional) sys_id or path, `appName`: App name, `packageName`: Package name, `scopeName`: Scope name, `workingDirectory`: Directory for the project, `template`: Project template (base, javascript.react, typescript.basic, typescript.react, javascript.basic), `intent`: (Optional) Creation or conversion intent | +| `build_fluent_app` | Build the Fluent (ServiceNow SDK) application | `debug`: (Optional) Print debug output | +| `deploy_fluent_app` | Deploy the Fluent (ServiceNow SDK) application to a ServiceNow instance | `auth`: (Optional) Authentication alias to use, `debug`: (Optional) Print debug output | +| `fluent_transform` | Download and convert XML records from instance or local path into Fluent source code | `from`: (Optional) Path to metadata, `directory`: (Optional) Package path, `preview`: (Optional) Preview only, `auth`: (Optional) Authentication alias, `debug`: (Optional) Print debug output | +| `download_fluent_dependencies` | Download configured dependencies in now.config.json and TypeScript type definitions | `auth`: (Optional) Authentication alias to use, `debug`: (Optional) Print debug output | +| `download_fluent_app` **NEW** | Download application metadata from instance | `directory`: Path to expand application, `source`: (Optional) Path to directory containing package.json configuration, `incremental`: (Optional) Download in incremental mode, `debug`: (Optional) Print debug output | +| `clean_fluent_app` **NEW** | Clean output directory | `source`: (Optional) Path to directory containing package.json configuration, `debug`: (Optional) Print debug output | +| `pack_fluent_app` **NEW** | Zip built app into installable artifact | `source`: (Optional) Path to directory containing package.json configuration, `debug`: (Optional) Print debug output | -### auth, init and dependencies commands +### Recent Updates -All these three commands are interactive CLI commands that require user input. The easier way to use them is to have Fluent MCP generate the shell command then run them in a terminal. Preferably, whenever you start a session with Fluent MCP, specify the working directory please. +**Complete ServiceNow SDK Command Coverage** - fluent-mcp now provides 100% coverage of all native ServiceNow SDK commands: + +- **✅ Enhanced `sdk_info` command**: Get SDK version, help, and debug information with improved working directory resolution and error handling +- **✅ New `download_fluent_app` command**: Download application metadata from instance with support for incremental downloads and custom source directories +- **✅ New `clean_fluent_app` command**: Clean output directories with proper package.json configuration detection +- **✅ New `pack_fluent_app` command**: Create installable application artifacts from built applications +- **✅ All commands aligned**: Parameter descriptions and functionality match the native SDK specification exactly + +### Interactive Commands + +All `manage_fluent_auth`, `init_fluent_app` and `download_fluent_dependencies` commands are interactive CLI commands that require user input. The easier way to use them is to have Fluent MCP generate the shell command then run them in a terminal. Preferably, whenever you start a session with Fluent MCP, specify the working directory please. ## Resources @@ -153,7 +165,7 @@ Add MCP server configuration in Cursor settings: #### Windsurf 1. `CMD + ,` to open settings, navigate to Cascade => MCP Servers => Manage MCPs => View raw config -2. Add configuration. +1. Add configuration. ```json { @@ -170,7 +182,7 @@ Add MCP server configuration in Cursor settings: } ``` -3. Refresh when back to Manage MCPs page. +1. Refresh when back to Manage MCPs page. #### Gemini CLI @@ -197,16 +209,16 @@ Configure in `~/.gemini/settings.json` or `./.gemini/settings.json`: ## Getting Started 1. **Authentication** - a. Create a new auth alias: `create Fluent auth to , add the credential alias as myFluentMcpAuth` - b. List existing aliases: `show all Fluent auth profiles` - c. Switch default alias: `use the alias as the default Fluent auth` + a. Create a new auth alias: `Use manage_fluent_auth to create a new auth profile for with alias myFluentMcpAuth` + b. List existing aliases: `Use manage_fluent_auth to show all auth profiles` + c. Switch default alias: `Use manage_fluent_auth to set myFluentMcpAuth as the default auth` -2. **Project Setup** - a. Create a new project: `Create a Fluent project to under directory ` +1. **Project Setup** + a. Create a new project: `Use init_fluent_app to create a new Fluent project for in directory ` b. Convert an existing app: - • By sys_id: `Create a Fluent project by converting the existing scoped app whose sys_id is under directory ` - • By local path: `Create a Fluent project by converting the existing scoped app from , new Fluent project should be stored in directory ` - c. Continue an existing project: `Initialize Fluent project in ` or `Set Fluent working directory to ` + • By sys_id: `Use init_fluent_app to convert the existing scoped app with sys_id to a Fluent project in directory ` + • By local path: `Use init_fluent_app to convert the existing scoped app from to a Fluent project in directory ` + c. Continue an existing project: `Use init_fluent_app to initialize the Fluent project in ` or `Set working directory to for the Fluent project` ### Example Prompts @@ -297,7 +309,7 @@ Prompt: #### Multi-Environment Auth Setup Prompt: -"Configure auth profiles for dev/test/prod environments, then create a build script that deploys to each sequentially. Handle auth failures with rollback. Show the exact manage_fluent_auth and fluent_install commands." +"Configure auth profiles for dev/test/prod environments, then create a build script that deploys to each sequentially. Handle auth failures with rollback. Show the exact manage_fluent_auth and deploy_fluent_app commands." #### Form Field Validation Chain diff --git a/package-lock.json b/package-lock.json index bcafc5b..7bc6261 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +1,24 @@ { "name": "@modesty/fluent-mcp", - "version": "0.0.15", + "version": "0.0.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@modesty/fluent-mcp", - "version": "0.0.15", + "version": "0.0.16", "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "1.17.5", - "@servicenow/sdk": "4.0.0", - "zod": "^3.25.76" + "@modelcontextprotocol/sdk": "1.18.1", + "@servicenow/sdk": "4.0.1", + "zod": "^3.25.76", + "zod-to-json-schema": "^3.24.6" }, "bin": { "fluent-mcp": "dist/index.js" }, "devDependencies": { - "@eslint/js": "^9.35.0", + "@eslint/js": "^9.36.0", "@rollup/plugin-commonjs": "^28.0.6", "@rollup/plugin-eslint": "^9.0.5", "@rollup/plugin-json": "^6.0.1", @@ -25,15 +26,15 @@ "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.4", "@types/jest": "^30.0.0", - "@types/node": "^24.3.1", - "@typescript-eslint/eslint-plugin": "^8.43.0", - "@typescript-eslint/parser": "^8.43.0", - "eslint": "^9.35.0", + "@types/node": "^24.5.2", + "@typescript-eslint/eslint-plugin": "^8.44.0", + "@typescript-eslint/parser": "^8.44.0", + "eslint": "^9.36.0", "jest": "^30.1.3", - "rollup": "^4.50.1", + "rollup": "^4.52.0", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-sourcemaps": "^0.6.3", - "ts-jest": "^29.4.1", + "ts-jest": "^29.4.4", "ts-node": "^10.9.2", "tslib": "^2.8.1", "typescript": "~5.9.2" @@ -849,9 +850,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.35.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@eslint/js/-/js-9.35.0.tgz", - "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", + "version": "9.36.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@eslint/js/-/js-9.36.0.tgz", + "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", "devOptional": true, "license": "MIT", "engines": { @@ -1029,9 +1030,9 @@ } }, "node_modules/@inquirer/checkbox/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1087,9 +1088,9 @@ } }, "node_modules/@inquirer/confirm/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1130,9 +1131,9 @@ } }, "node_modules/@inquirer/core/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1189,9 +1190,9 @@ } }, "node_modules/@inquirer/editor/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1248,9 +1249,9 @@ } }, "node_modules/@inquirer/expand/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1306,9 +1307,9 @@ } }, "node_modules/@inquirer/input/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1365,9 +1366,9 @@ } }, "node_modules/@inquirer/password/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1444,9 +1445,9 @@ } }, "node_modules/@inquirer/rawlist/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1504,9 +1505,9 @@ } }, "node_modules/@inquirer/select/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", + "version": "20.19.17", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-20.19.17.tgz", + "integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==", "license": "MIT", "optional": true, "dependencies": { @@ -1565,9 +1566,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://artifact.devsnc.com/repository/npm-all/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "devOptional": true, "license": "MIT", "engines": { @@ -1578,9 +1579,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://artifact.devsnc.com/repository/npm-all/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -2148,9 +2149,9 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.17.5", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@modelcontextprotocol/sdk/-/sdk-1.17.5.tgz", - "integrity": "sha512-QakrKIGniGuRVfWBdMsDea/dx1PNE739QJ7gCM41s9q+qaCYTHCdsIBXQVVXry3mfWAiaM9kT22Hyz53Uw8mfg==", + "version": "1.18.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@modelcontextprotocol/sdk/-/sdk-1.18.1.tgz", + "integrity": "sha512-d//GE8/Yh7aC3e7p+kZG8JqqEAwwDUmAfvH1quogtbk+ksS6E0RR6toKKESPYYZVre0meqkJb27zb+dhqE9Sgw==", "license": "MIT", "dependencies": { "ajv": "^6.12.6", @@ -3007,9 +3008,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz", - "integrity": "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.0.tgz", + "integrity": "sha512-VxDYCDqOaR7NXzAtvRx7G1u54d2kEHopb28YH/pKzY6y0qmogP3gG7CSiWsq9WvDFxOQMpNEyjVAHZFXfH3o/A==", "cpu": [ "arm" ], @@ -3021,9 +3022,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.1.tgz", - "integrity": "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.0.tgz", + "integrity": "sha512-pqDirm8koABIKvzL59YI9W9DWbRlTX7RWhN+auR8HXJxo89m4mjqbah7nJZjeKNTNYopqL+yGg+0mhCpf3xZtQ==", "cpu": [ "arm64" ], @@ -3035,9 +3036,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.1.tgz", - "integrity": "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.0.tgz", + "integrity": "sha512-YCdWlY/8ltN6H78HnMsRHYlPiKvqKagBP1r+D7SSylxX+HnsgXGCmLiV3Y4nSyY9hW8qr8U9LDUx/Lo7M6MfmQ==", "cpu": [ "arm64" ], @@ -3049,9 +3050,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.1.tgz", - "integrity": "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.0.tgz", + "integrity": "sha512-z4nw6y1j+OOSGzuVbSWdIp1IUks9qNw4dc7z7lWuWDKojY38VMWBlEN7F9jk5UXOkUcp97vA1N213DF+Lz8BRg==", "cpu": [ "x64" ], @@ -3063,9 +3064,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.1.tgz", - "integrity": "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.0.tgz", + "integrity": "sha512-Q/dv9Yvyr5rKlK8WQJZVrp5g2SOYeZUs9u/t2f9cQ2E0gJjYB/BWoedXfUT0EcDJefi2zzVfhcOj8drWCzTviw==", "cpu": [ "arm64" ], @@ -3077,9 +3078,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.1.tgz", - "integrity": "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.0.tgz", + "integrity": "sha512-kdBsLs4Uile/fbjZVvCRcKB4q64R+1mUq0Yd7oU1CMm1Av336ajIFqNFovByipciuUQjBCPMxwJhCgfG2re3rg==", "cpu": [ "x64" ], @@ -3091,9 +3092,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.1.tgz", - "integrity": "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.0.tgz", + "integrity": "sha512-aL6hRwu0k7MTUESgkg7QHY6CoqPgr6gdQXRJI1/VbFlUMwsSzPGSR7sG5d+MCbYnJmJwThc2ol3nixj1fvI/zQ==", "cpu": [ "arm" ], @@ -3105,9 +3106,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.1.tgz", - "integrity": "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.0.tgz", + "integrity": "sha512-BTs0M5s1EJejgIBJhCeiFo7GZZ2IXWkFGcyZhxX4+8usnIo5Mti57108vjXFIQmmJaRyDwmV59Tw64Ap1dkwMw==", "cpu": [ "arm" ], @@ -3119,9 +3120,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.1.tgz", - "integrity": "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.0.tgz", + "integrity": "sha512-uj672IVOU9m08DBGvoPKPi/J8jlVgjh12C9GmjjBxCTQc3XtVmRkRKyeHSmIKQpvJ7fIm1EJieBUcnGSzDVFyw==", "cpu": [ "arm64" ], @@ -3133,9 +3134,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.1.tgz", - "integrity": "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.0.tgz", + "integrity": "sha512-/+IVbeDMDCtB/HP/wiWsSzduD10SEGzIZX2945KSgZRNi4TSkjHqRJtNTVtVb8IRwhJ65ssI56krlLik+zFWkw==", "cpu": [ "arm64" ], @@ -3146,10 +3147,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.1.tgz", - "integrity": "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.0.tgz", + "integrity": "sha512-U1vVzvSWtSMWKKrGoROPBXMh3Vwn93TA9V35PldokHGqiUbF6erSzox/5qrSMKp6SzakvyjcPiVF8yB1xKr9Pg==", "cpu": [ "loong64" ], @@ -3160,6 +3161,19 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.43.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz", + "integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "version": "4.43.0", "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz", @@ -3174,9 +3188,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.1.tgz", - "integrity": "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.0.tgz", + "integrity": "sha512-X/4WfuBAdQRH8cK3DYl8zC00XEE6aM472W+QCycpQJeLWVnHfkv7RyBFVaTqNUMsTgIX8ihMjCvFF9OUgeABzw==", "cpu": [ "ppc64" ], @@ -3188,9 +3202,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.1.tgz", - "integrity": "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.0.tgz", + "integrity": "sha512-xIRYc58HfWDBZoLmWfWXg2Sq8VCa2iJ32B7mqfWnkx5mekekl0tMe7FHpY8I72RXEcUkaWawRvl3qA55og+cwQ==", "cpu": [ "riscv64" ], @@ -3202,9 +3216,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.1.tgz", - "integrity": "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.0.tgz", + "integrity": "sha512-mbsoUey05WJIOz8U1WzNdf+6UMYGwE3fZZnQqsM22FZ3wh1N887HT6jAOjXs6CNEK3Ntu2OBsyQDXfIjouI4dw==", "cpu": [ "riscv64" ], @@ -3216,9 +3230,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.1.tgz", - "integrity": "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.0.tgz", + "integrity": "sha512-qP6aP970bucEi5KKKR4AuPFd8aTx9EF6BvutvYxmZuWLJHmnq4LvBfp0U+yFDMGwJ+AIJEH5sIP+SNypauMWzg==", "cpu": [ "s390x" ], @@ -3230,9 +3244,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.1.tgz", - "integrity": "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.0.tgz", + "integrity": "sha512-nmSVN+F2i1yKZ7rJNKO3G7ZzmxJgoQBQZ/6c4MuS553Grmr7WqR7LLDcYG53Z2m9409z3JLt4sCOhLdbKQ3HmA==", "cpu": [ "x64" ], @@ -3244,9 +3258,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.1.tgz", - "integrity": "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.0.tgz", + "integrity": "sha512-2d0qRo33G6TfQVjaMR71P+yJVGODrt5V6+T0BDYH4EMfGgdC/2HWDVjSSFw888GSzAZUwuska3+zxNUCDco6rQ==", "cpu": [ "x64" ], @@ -3258,9 +3272,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.1.tgz", - "integrity": "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.0.tgz", + "integrity": "sha512-A1JalX4MOaFAAyGgpO7XP5khquv/7xKzLIyLmhNrbiCxWpMlnsTYr8dnsWM7sEeotNmxvSOEL7F65j0HXFcFsw==", "cpu": [ "arm64" ], @@ -3272,9 +3286,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.1.tgz", - "integrity": "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.0.tgz", + "integrity": "sha512-YQugafP/rH0eOOHGjmNgDURrpYHrIX0yuojOI8bwCyXwxC9ZdTd3vYkmddPX0oHONLXu9Rb1dDmT0VNpjkzGGw==", "cpu": [ "arm64" ], @@ -3286,9 +3300,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.1.tgz", - "integrity": "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.0.tgz", + "integrity": "sha512-zYdUYhi3Qe2fndujBqL5FjAFzvNeLxtIqfzNEVKD1I7C37/chv1VxhscWSQHTNfjPCrBFQMnynwA3kpZpZ8w4A==", "cpu": [ "ia32" ], @@ -3299,10 +3313,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.0.tgz", + "integrity": "sha512-fGk03kQylNaCOQ96HDMeT7E2n91EqvCDd3RwvT5k+xNdFCeMGnj5b5hEgTGrQuyidqSsD3zJDQ21QIaxXqTBJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.1.tgz", - "integrity": "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.0.tgz", + "integrity": "sha512-6iKDCVSIUQ8jPMoIV0OytRKniaYyy5EbY/RRydmLW8ZR3cEBhxbWl5ro0rkUNe0ef6sScvhbY79HrjRm8i3vDQ==", "cpu": [ "x64" ], @@ -3314,9 +3342,9 @@ ] }, "node_modules/@servicenow/eslint-plugin-sdk-app-plugin": { - "version": "4.0.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/eslint-plugin-sdk-app-plugin/-/eslint-plugin-sdk-app-plugin-4.0.0.tgz", - "integrity": "sha512-Me+fLAza+nyU59dpYg5FSIimP4X/V30qyZMrB4qhOfgO+tKr4TO8BiU+ctqyP18akZiGG1/c77JxVho3Hbiqew==", + "version": "4.0.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/eslint-plugin-sdk-app-plugin/-/eslint-plugin-sdk-app-plugin-4.0.1.tgz", + "integrity": "sha512-8g5HiYzLuEePToGngwvE+S+hvo5pyTtXTxgU9E/hvW67HSFRPynGSQGktYyEAAq+wiva/ah0IHLwIw44CMJImA==", "license": "MIT", "optional": true, "dependencies": { @@ -3550,9 +3578,9 @@ } }, "node_modules/@servicenow/isomorphic-rollup": { - "version": "1.2.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/isomorphic-rollup/-/isomorphic-rollup-1.2.1.tgz", - "integrity": "sha512-k4PRMF2Sub0gYoi2rVkOFkunFWiB1ELC2wGygS5lQWJqwEXIB4ZlO258381M5/Xf1CnQTtGOjZLgEWupznxNvA==", + "version": "1.2.2", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/isomorphic-rollup/-/isomorphic-rollup-1.2.2.tgz", + "integrity": "sha512-lzEa8jucfmBk17an6Eu5OrzU4lxzobKSLs2kr465kYNpXuiRb3mq7k0t2oC8QK7McUMyg31ZsdyljhKa2laRVw==", "license": "MIT", "optional": true, "dependencies": { @@ -3560,12 +3588,12 @@ } }, "node_modules/@servicenow/sdk": { - "version": "4.0.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk/-/sdk-4.0.0.tgz", - "integrity": "sha512-dhSnSmprrQO2cZJ/o5KajpOE3ifiQjdx2zhdG6KRWfOkHkpEXOJKoCkXLA2U+fZd5TWCzsvkEcAUAE2gHsa5tg==", + "version": "4.0.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk/-/sdk-4.0.1.tgz", + "integrity": "sha512-RJ356rYghMqxJ+EvWumjS3P0esQIGfvyI7suSzdBAbJkHPLMiYlAfP4PtDNj5mBURf4ZNQoL1mCPeG57/vA+3A==", "license": "MIT", "dependencies": { - "@servicenow/sdk-core": "4.0.0" + "@servicenow/sdk-core": "4.0.1" }, "bin": { "now-sdk": "bin/index.js", @@ -3578,20 +3606,20 @@ "pnpm": ">=10.8.0" }, "optionalDependencies": { - "@servicenow/sdk-api": "4.0.0", - "@servicenow/sdk-cli": "4.0.0", + "@servicenow/sdk-api": "4.0.1", + "@servicenow/sdk-cli": "4.0.1", "undici": "6.19.8" } }, "node_modules/@servicenow/sdk-api": { - "version": "4.0.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-api/-/sdk-api-4.0.0.tgz", - "integrity": "sha512-exoWB8LFdbI96ZeSmGISo8ihCp6j1iAlQh0CPXScTo3MNk6g8QWoX898o7DMDTbtGadBpfdR9L95zGp1THZSHQ==", + "version": "4.0.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-api/-/sdk-api-4.0.1.tgz", + "integrity": "sha512-aYzhyUQ5f39JgFqtKCOz0LEDELK0cuQpn+pmx8W3KcYxiW04jt7qvxEvnWqoyEu41o6mGAzjGzeupJPxmFbC8g==", "license": "MIT", "optional": true, "dependencies": { - "@servicenow/sdk-build-core": "4.0.0", - "@servicenow/sdk-build-plugins": "4.0.0", + "@servicenow/sdk-build-core": "4.0.1", + "@servicenow/sdk-build-plugins": "4.0.1", "crypto-js": "4.2.0", "fast-xml-parser": "4.4.1", "handlebars": "4.7.8", @@ -3614,13 +3642,13 @@ } }, "node_modules/@servicenow/sdk-build-core": { - "version": "4.0.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-build-core/-/sdk-build-core-4.0.0.tgz", - "integrity": "sha512-e7pPgiUlZRTz73ns0moAcA1W+3umck160p/xz75xgdqjIHSRHjw74a1J2d6oXvQ0exjeo3UV1ooUBfnP7F97gQ==", + "version": "4.0.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-build-core/-/sdk-build-core-4.0.1.tgz", + "integrity": "sha512-VF2fRNaddqXPE7UzMmGOPSJweUTDThsEyi2CJ1kcSNjz9eZaD75BEzsZuVvErl9vDj5DQSCr0XOs1lEs2SVesg==", "license": "MIT", "optional": true, "dependencies": { - "@servicenow/sdk-core": "4.0.0", + "@servicenow/sdk-core": "4.0.1", "fast-glob": "3.3.2", "fflate": "0.8.2", "json5": "2.2.3", @@ -3631,6 +3659,7 @@ "readable-stream": "4.5.2", "ts-morph": "23.0.0", "vscode-languageserver": "9.0.1", + "xml-js": "1.6.11", "xmlbuilder2": "3.1.1", "zod": "3.22.4" }, @@ -3650,18 +3679,18 @@ } }, "node_modules/@servicenow/sdk-build-plugins": { - "version": "4.0.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-build-plugins/-/sdk-build-plugins-4.0.0.tgz", - "integrity": "sha512-pF5Iu8SEtjlflltPMM8/k+3VDL48A4cf0O8x4kmrN+Aln7Qnpy8xwUdVk689TrYPH9fgtK6puSBSoctjxdYHlg==", + "version": "4.0.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-build-plugins/-/sdk-build-plugins-4.0.1.tgz", + "integrity": "sha512-BpGN4HRtGaBPYOJpqjr8aZnPOOc/DckR/iX5WpL0c8+lcOmkBKv6Cv+v+o0G+MaoSJqRPZX/5P7pfEswDfzs1g==", "license": "MIT", "optional": true, "dependencies": { "@cyclonedx/cyclonedx-library": "7.1.0", - "@servicenow/eslint-plugin-sdk-app-plugin": "4.0.0", + "@servicenow/eslint-plugin-sdk-app-plugin": "4.0.1", "@servicenow/glide": "26.0.1", - "@servicenow/sdk-build-core": "4.0.0", - "@servicenow/sdk-core": "4.0.0", - "@servicenow/sdk-repack": "4.0.0", + "@servicenow/sdk-build-core": "4.0.1", + "@servicenow/sdk-core": "4.0.1", + "@servicenow/sdk-repack": "4.0.1", "eslint": "8.50.0", "eslint-formatter-stylish": "8.40.0", "eslint-plugin-es-x": "7.2.0", @@ -3895,15 +3924,15 @@ } }, "node_modules/@servicenow/sdk-cli": { - "version": "4.0.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-cli/-/sdk-cli-4.0.0.tgz", - "integrity": "sha512-B1mY8EqNoNCSG6AZGjOeDc2c298J29iaMlh0O68o6hhRlNmTeiGfswWHqmZs/14G57U9bEB8hHbimvMr8oz4FQ==", + "version": "4.0.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-cli/-/sdk-cli-4.0.1.tgz", + "integrity": "sha512-OBQhHZgMVnyk1jdi5azAPGieQhld6WkVgbc8xjWcssf4YZa4UHmYX3/j2mX0n9NAObb2flEKbiVN7NkS+1OZEw==", "license": "MIT", "optional": true, "dependencies": { "@inquirer/prompts": "3.1.1", - "@servicenow/sdk-api": "4.0.0", - "@servicenow/sdk-build-core": "4.0.0", + "@servicenow/sdk-api": "4.0.1", + "@servicenow/sdk-build-core": "4.0.1", "chalk": "4.1.2", "ci-info": "4.1.0", "clipboardy": "4.0.0", @@ -3925,9 +3954,9 @@ } }, "node_modules/@servicenow/sdk-core": { - "version": "4.0.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-core/-/sdk-core-4.0.0.tgz", - "integrity": "sha512-vOW3+inEAG7dxVJn0yNxTVxBr5DVcI3NebhSbFifkPfiySRE+eZw6T0FslgKQ1M/9BSshEHuSXtXmFj1GDsT7A==", + "version": "4.0.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-core/-/sdk-core-4.0.1.tgz", + "integrity": "sha512-CADvN566g0YtW9eojZHRDRp16i7HRL0lqFwJe7yL4H5YHL91i2ZzhFGgzqFtGGququGpv9rcTiNzE/1etSvmXw==", "license": "MIT", "engines": { "node": ">=20.18.0", @@ -3935,14 +3964,14 @@ } }, "node_modules/@servicenow/sdk-repack": { - "version": "4.0.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-repack/-/sdk-repack-4.0.0.tgz", - "integrity": "sha512-NZpaDmYQ8la7KDK2L1N+s03LTbaOepUHP91ZF5fZ7Ryl8xgcwCx2Gy2VICWf2Ox182FWFK73lykdGBmZxvC6Yg==", + "version": "4.0.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@servicenow/sdk-repack/-/sdk-repack-4.0.1.tgz", + "integrity": "sha512-giiCdi0o6rddEHKSTdLhdDJIrFg7cl+ft5n0I6CWFjVP61jMbvlYI1Ki469/vtopYEVu4KzS1b6IoBZnaNd6Dg==", "license": "MIT", "optional": true, "dependencies": { - "@servicenow/isomorphic-rollup": "1.2.1", - "@servicenow/sdk-build-core": "4.0.0", + "@servicenow/isomorphic-rollup": "1.2.2", + "@servicenow/sdk-build-core": "4.0.1", "rollup": "4.43.0" } }, @@ -4076,19 +4105,6 @@ "linux" ] }, - "node_modules/@servicenow/sdk-repack/node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz", - "integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@servicenow/sdk-repack/node_modules/@rollup/rollup-linux-riscv64-gnu": { "version": "4.43.0", "resolved": "https://artifact.devsnc.com/repository/npm-all/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz", @@ -4443,13 +4459,13 @@ } }, "node_modules/@types/node": { - "version": "24.3.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-24.3.1.tgz", - "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "version": "24.5.2", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@types/node/-/node-24.5.2.tgz", + "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", "devOptional": true, "license": "MIT", "dependencies": { - "undici-types": "~7.10.0" + "undici-types": "~7.12.0" } }, "node_modules/@types/resolve": { @@ -4498,17 +4514,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.43.0.tgz", - "integrity": "sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.0.tgz", + "integrity": "sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.43.0", - "@typescript-eslint/type-utils": "8.43.0", - "@typescript-eslint/utils": "8.43.0", - "@typescript-eslint/visitor-keys": "8.43.0", + "@typescript-eslint/scope-manager": "8.44.0", + "@typescript-eslint/type-utils": "8.44.0", + "@typescript-eslint/utils": "8.44.0", + "@typescript-eslint/visitor-keys": "8.44.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -4522,22 +4538,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.43.0", + "@typescript-eslint/parser": "^8.44.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/parser/-/parser-8.43.0.tgz", - "integrity": "sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/parser/-/parser-8.44.0.tgz", + "integrity": "sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.43.0", - "@typescript-eslint/types": "8.43.0", - "@typescript-eslint/typescript-estree": "8.43.0", - "@typescript-eslint/visitor-keys": "8.43.0", + "@typescript-eslint/scope-manager": "8.44.0", + "@typescript-eslint/types": "8.44.0", + "@typescript-eslint/typescript-estree": "8.44.0", + "@typescript-eslint/visitor-keys": "8.44.0", "debug": "^4.3.4" }, "engines": { @@ -4553,14 +4569,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/project-service/-/project-service-8.43.0.tgz", - "integrity": "sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/project-service/-/project-service-8.44.0.tgz", + "integrity": "sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.43.0", - "@typescript-eslint/types": "^8.43.0", + "@typescript-eslint/tsconfig-utils": "^8.44.0", + "@typescript-eslint/types": "^8.44.0", "debug": "^4.3.4" }, "engines": { @@ -4575,14 +4591,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/scope-manager/-/scope-manager-8.43.0.tgz", - "integrity": "sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/scope-manager/-/scope-manager-8.44.0.tgz", + "integrity": "sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.43.0", - "@typescript-eslint/visitor-keys": "8.43.0" + "@typescript-eslint/types": "8.44.0", + "@typescript-eslint/visitor-keys": "8.44.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4593,9 +4609,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.43.0.tgz", - "integrity": "sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.0.tgz", + "integrity": "sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ==", "dev": true, "license": "MIT", "engines": { @@ -4610,15 +4626,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/type-utils/-/type-utils-8.43.0.tgz", - "integrity": "sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/type-utils/-/type-utils-8.44.0.tgz", + "integrity": "sha512-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.43.0", - "@typescript-eslint/typescript-estree": "8.43.0", - "@typescript-eslint/utils": "8.43.0", + "@typescript-eslint/types": "8.44.0", + "@typescript-eslint/typescript-estree": "8.44.0", + "@typescript-eslint/utils": "8.44.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -4635,9 +4651,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/types/-/types-8.43.0.tgz", - "integrity": "sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/types/-/types-8.44.0.tgz", + "integrity": "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA==", "dev": true, "license": "MIT", "engines": { @@ -4649,16 +4665,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/typescript-estree/-/typescript-estree-8.43.0.tgz", - "integrity": "sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.0.tgz", + "integrity": "sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.43.0", - "@typescript-eslint/tsconfig-utils": "8.43.0", - "@typescript-eslint/types": "8.43.0", - "@typescript-eslint/visitor-keys": "8.43.0", + "@typescript-eslint/project-service": "8.44.0", + "@typescript-eslint/tsconfig-utils": "8.44.0", + "@typescript-eslint/types": "8.44.0", + "@typescript-eslint/visitor-keys": "8.44.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -4691,16 +4707,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/utils/-/utils-8.43.0.tgz", - "integrity": "sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/utils/-/utils-8.44.0.tgz", + "integrity": "sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.43.0", - "@typescript-eslint/types": "8.43.0", - "@typescript-eslint/typescript-estree": "8.43.0" + "@typescript-eslint/scope-manager": "8.44.0", + "@typescript-eslint/types": "8.44.0", + "@typescript-eslint/typescript-estree": "8.44.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4734,13 +4750,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.43.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/visitor-keys/-/visitor-keys-8.43.0.tgz", - "integrity": "sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==", + "version": "8.44.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.0.tgz", + "integrity": "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.43.0", + "@typescript-eslint/types": "8.44.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -5518,6 +5534,16 @@ "license": "MIT", "optional": true }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.6", + "resolved": "https://artifact.devsnc.com/repository/npm-all/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz", + "integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://artifact.devsnc.com/repository/npm-all/bindings/-/bindings-1.5.0.tgz", @@ -5772,9 +5798,9 @@ "license": "MIT" }, "node_modules/browserslist": { - "version": "4.25.4", - "resolved": "https://artifact.devsnc.com/repository/npm-all/browserslist/-/browserslist-4.25.4.tgz", - "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", + "version": "4.26.2", + "resolved": "https://artifact.devsnc.com/repository/npm-all/browserslist/-/browserslist-4.26.2.tgz", + "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", "dev": true, "funding": [ { @@ -5792,9 +5818,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001737", - "electron-to-chromium": "^1.5.211", - "node-releases": "^2.0.19", + "baseline-browser-mapping": "^2.8.3", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, "bin": { @@ -6005,9 +6032,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001741", - "resolved": "https://artifact.devsnc.com/repository/npm-all/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", - "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", + "version": "1.0.30001743", + "resolved": "https://artifact.devsnc.com/repository/npm-all/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", + "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", "dev": true, "funding": [ { @@ -6593,9 +6620,9 @@ "optional": true }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://artifact.devsnc.com/repository/npm-all/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6737,9 +6764,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://artifact.devsnc.com/repository/npm-all/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "version": "2.1.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/detect-libc/-/detect-libc-2.1.0.tgz", + "integrity": "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==", "license": "Apache-2.0", "optional": true, "engines": { @@ -6846,9 +6873,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.217", - "resolved": "https://artifact.devsnc.com/repository/npm-all/electron-to-chromium/-/electron-to-chromium-1.5.217.tgz", - "integrity": "sha512-Pludfu5iBxp9XzNl0qq2G87hdD17ZV7h5T4n6rQXDi3nCyloBV3jreE9+8GC6g4X/5yxqVgXEURpcLtM0WS4jA==", + "version": "1.5.222", + "resolved": "https://artifact.devsnc.com/repository/npm-all/electron-to-chromium/-/electron-to-chromium-1.5.222.tgz", + "integrity": "sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==", "dev": true, "license": "ISC" }, @@ -6962,9 +6989,9 @@ } }, "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://artifact.devsnc.com/repository/npm-all/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "version": "1.3.4", + "resolved": "https://artifact.devsnc.com/repository/npm-all/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7031,9 +7058,9 @@ } }, "node_modules/eslint": { - "version": "9.35.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/eslint/-/eslint-9.35.0.tgz", - "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", + "version": "9.36.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/eslint/-/eslint-9.36.0.tgz", + "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "devOptional": true, "license": "MIT", "dependencies": { @@ -7043,7 +7070,7 @@ "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.35.0", + "@eslint/js": "9.36.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -10928,9 +10955,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.20", - "resolved": "https://artifact.devsnc.com/repository/npm-all/node-releases/-/node-releases-2.0.20.tgz", - "integrity": "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==", + "version": "2.0.21", + "resolved": "https://artifact.devsnc.com/repository/npm-all/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "dev": true, "license": "MIT" }, @@ -12181,9 +12208,9 @@ } }, "node_modules/rollup": { - "version": "4.50.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/rollup/-/rollup-4.50.1.tgz", - "integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==", + "version": "4.52.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/rollup/-/rollup-4.52.0.tgz", + "integrity": "sha512-+IuescNkTJQgX7AkIDtITipZdIGcWF0pnVvZTWStiazUmcGA2ag8dfg0urest2XlXUi9kuhfQ+qmdc5Stc3z7g==", "dev": true, "license": "MIT", "dependencies": { @@ -12197,27 +12224,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.50.1", - "@rollup/rollup-android-arm64": "4.50.1", - "@rollup/rollup-darwin-arm64": "4.50.1", - "@rollup/rollup-darwin-x64": "4.50.1", - "@rollup/rollup-freebsd-arm64": "4.50.1", - "@rollup/rollup-freebsd-x64": "4.50.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", - "@rollup/rollup-linux-arm-musleabihf": "4.50.1", - "@rollup/rollup-linux-arm64-gnu": "4.50.1", - "@rollup/rollup-linux-arm64-musl": "4.50.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", - "@rollup/rollup-linux-ppc64-gnu": "4.50.1", - "@rollup/rollup-linux-riscv64-gnu": "4.50.1", - "@rollup/rollup-linux-riscv64-musl": "4.50.1", - "@rollup/rollup-linux-s390x-gnu": "4.50.1", - "@rollup/rollup-linux-x64-gnu": "4.50.1", - "@rollup/rollup-linux-x64-musl": "4.50.1", - "@rollup/rollup-openharmony-arm64": "4.50.1", - "@rollup/rollup-win32-arm64-msvc": "4.50.1", - "@rollup/rollup-win32-ia32-msvc": "4.50.1", - "@rollup/rollup-win32-x64-msvc": "4.50.1", + "@rollup/rollup-android-arm-eabi": "4.52.0", + "@rollup/rollup-android-arm64": "4.52.0", + "@rollup/rollup-darwin-arm64": "4.52.0", + "@rollup/rollup-darwin-x64": "4.52.0", + "@rollup/rollup-freebsd-arm64": "4.52.0", + "@rollup/rollup-freebsd-x64": "4.52.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.0", + "@rollup/rollup-linux-arm-musleabihf": "4.52.0", + "@rollup/rollup-linux-arm64-gnu": "4.52.0", + "@rollup/rollup-linux-arm64-musl": "4.52.0", + "@rollup/rollup-linux-loong64-gnu": "4.52.0", + "@rollup/rollup-linux-ppc64-gnu": "4.52.0", + "@rollup/rollup-linux-riscv64-gnu": "4.52.0", + "@rollup/rollup-linux-riscv64-musl": "4.52.0", + "@rollup/rollup-linux-s390x-gnu": "4.52.0", + "@rollup/rollup-linux-x64-gnu": "4.52.0", + "@rollup/rollup-linux-x64-musl": "4.52.0", + "@rollup/rollup-openharmony-arm64": "4.52.0", + "@rollup/rollup-win32-arm64-msvc": "4.52.0", + "@rollup/rollup-win32-ia32-msvc": "4.52.0", + "@rollup/rollup-win32-x64-gnu": "4.52.0", + "@rollup/rollup-win32-x64-msvc": "4.52.0", "fsevents": "~2.3.2" } }, @@ -12409,6 +12437,13 @@ "@parcel/watcher": "^2.4.1" } }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://artifact.devsnc.com/repository/npm-all/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC", + "optional": true + }, "node_modules/schemes": { "version": "1.4.0", "resolved": "https://artifact.devsnc.com/repository/npm-all/schemes/-/schemes-1.4.0.tgz", @@ -12722,9 +12757,9 @@ } }, "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://artifact.devsnc.com/repository/npm-all/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "version": "0.2.4", + "resolved": "https://artifact.devsnc.com/repository/npm-all/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", "license": "MIT", "optional": true, "dependencies": { @@ -12732,9 +12767,9 @@ } }, "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://artifact.devsnc.com/repository/npm-all/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "version": "0.3.4", + "resolved": "https://artifact.devsnc.com/repository/npm-all/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", "license": "MIT", "optional": true }, @@ -13025,9 +13060,9 @@ } }, "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://artifact.devsnc.com/repository/npm-all/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -13190,9 +13225,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.3", - "resolved": "https://artifact.devsnc.com/repository/npm-all/tar-fs/-/tar-fs-2.1.3.tgz", - "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "version": "2.1.4", + "resolved": "https://artifact.devsnc.com/repository/npm-all/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", "optional": true, "dependencies": { @@ -13540,9 +13575,9 @@ } }, "node_modules/ts-jest": { - "version": "29.4.1", - "resolved": "https://artifact.devsnc.com/repository/npm-all/ts-jest/-/ts-jest-29.4.1.tgz", - "integrity": "sha512-SaeUtjfpg9Uqu8IbeDKtdaS0g8lS6FT6OzM3ezrDfErPJPHNDo/Ey+VFGP1bQIDfagYDLyRpd7O15XpG1Es2Uw==", + "version": "29.4.4", + "resolved": "https://artifact.devsnc.com/repository/npm-all/ts-jest/-/ts-jest-29.4.4.tgz", + "integrity": "sha512-ccVcRABct5ZELCT5U0+DZwkXMCcOCLi2doHRrKy1nK/s7J7bch6TzJMsrY09WxgUUIP/ITfmcDS8D2yl63rnXw==", "dev": true, "license": "MIT", "dependencies": { @@ -13832,9 +13867,9 @@ } }, "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://artifact.devsnc.com/repository/npm-all/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "version": "7.12.0", + "resolved": "https://artifact.devsnc.com/repository/npm-all/undici-types/-/undici-types-7.12.0.tgz", + "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", "devOptional": true, "license": "MIT" }, @@ -14270,6 +14305,19 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://artifact.devsnc.com/repository/npm-all/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "optional": true, + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, "node_modules/xmlbuilder2": { "version": "3.1.1", "resolved": "https://artifact.devsnc.com/repository/npm-all/xmlbuilder2/-/xmlbuilder2-3.1.1.tgz", diff --git a/package.json b/package.json index 615ee5f..2721166 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@modesty/fluent-mcp", - "version": "0.0.15", + "version": "0.0.16", "description": "MCP server for Fluent (ServiceNow SDK)", "keywords": [ "Servicenow SDK", @@ -49,12 +49,13 @@ } }, "dependencies": { - "@modelcontextprotocol/sdk": "1.17.5", - "@servicenow/sdk": "4.0.0", - "zod": "^3.25.76" + "@modelcontextprotocol/sdk": "1.18.1", + "@servicenow/sdk": "4.0.1", + "zod": "^3.25.76", + "zod-to-json-schema": "^3.24.6" }, "devDependencies": { - "@eslint/js": "^9.35.0", + "@eslint/js": "^9.36.0", "@rollup/plugin-commonjs": "^28.0.6", "@rollup/plugin-eslint": "^9.0.5", "@rollup/plugin-json": "^6.0.1", @@ -62,15 +63,15 @@ "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.4", "@types/jest": "^30.0.0", - "@types/node": "^24.3.1", - "@typescript-eslint/eslint-plugin": "^8.43.0", - "@typescript-eslint/parser": "^8.43.0", - "eslint": "^9.35.0", + "@types/node": "^24.5.2", + "@typescript-eslint/eslint-plugin": "^8.44.0", + "@typescript-eslint/parser": "^8.44.0", + "eslint": "^9.36.0", "jest": "^30.1.3", - "rollup": "^4.50.1", + "rollup": "^4.52.0", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-sourcemaps": "^0.6.3", - "ts-jest": "^29.4.1", + "ts-jest": "^29.4.4", "ts-node": "^10.9.2", "tslib": "^2.8.1", "typescript": "~5.9.2" diff --git a/src/server/fluentMCPServer.ts b/src/server/fluentMCPServer.ts index a6e636b..c2d325f 100644 --- a/src/server/fluentMCPServer.ts +++ b/src/server/fluentMCPServer.ts @@ -98,6 +98,52 @@ export class FluentMcpServer { // auto-auth code moved to fluentInstanceAuto.ts + /** + * Schedule a delayed initialization to ensure roots and auth are set up + * This provides a fallback if the client doesn't send proper notifications + */ + private scheduleDelayedInitialization(): void { + // Give the client some time to send notifications, then fallback + setTimeout(async () => { + try { + // Only initialize if roots haven't been set up yet + if (this.roots.length === 0) { + logger.info('No roots received from client after delay, using fallback initialization...'); + + // Try to request from client first, with short timeout + try { + await Promise.race([ + this.requestRootsFromClient(), + new Promise((_, reject) => + setTimeout(() => reject(new Error('Client roots request timeout')), 2000) + ) + ]); + } catch (error) { + // If client doesn't respond, use project root as fallback + logger.warn(`Client did not provide roots, using project root fallback: ${error}`); + const projectRoot = getProjectRootPath(); + await this.addRoot(`file://${projectRoot}`, 'Project Root (Fallback)'); + } + } + + // Trigger auth validation if not already triggered + if (!this.autoAuthTriggered) { + this.autoAuthTriggered = true; + logger.info('Triggering auto-auth validation...'); + autoValidateAuthIfConfigured(this.toolsManager).catch((error) => { + logger.warn('Auto-auth validation failed', { + error: error instanceof Error ? error.message : String(error), + }); + }); + } + } catch (error) { + logger.error('Error during delayed initialization', + error instanceof Error ? error : new Error(String(error)) + ); + } + }, 1000); // Wait 1 second for proper client notifications + } + /** * Request the list of roots from the client * This is called after the client sends the notifications/initialized notification @@ -125,11 +171,11 @@ export class FluentMcpServer { // Using the correct request format with schema const response = await this.mcpServer.server.request( { method: 'roots/list' }, - RootsResponseSchema + RootsResponseSchema as any ); - + // Since we provided a schema, response will be properly typed - const roots = response.roots; + const roots = (response as any).roots; if (Array.isArray(roots) && roots.length > 0) { logger.info('Received roots from client', { rootCount: roots.length }); @@ -169,9 +215,13 @@ export class FluentMcpServer { // Set up the tools/list handler server.setRequestHandler(ListToolsRequestSchema, async () => { - return { - tools: this.toolsManager.getMCPTools(), - }; + const tools = this.toolsManager.getMCPTools(); + + // Start a delayed initialization process to ensure roots and auth are set up + // even if the client doesn't send proper notifications + this.scheduleDelayedInitialization(); + + return { tools }; }); // Set up the resources/list handler diff --git a/src/tools/cliCommandTools.ts b/src/tools/cliCommandTools.ts index b21c834..564515a 100644 --- a/src/tools/cliCommandTools.ts +++ b/src/tools/cliCommandTools.ts @@ -10,8 +10,7 @@ import { } from '../utils/types.js'; import { getPrimaryRootPath as getRootContextPrimaryRootPath, getPrimaryRootPathFrom as getPrimaryRootPathFromArray } from '../utils/rootContext.js'; import { - VersionCommand, - HelpCommand, + SdkInfoCommand, // UpgradeCommand, // Commented out as it's not used AuthCommand, InitCommand, @@ -19,6 +18,9 @@ import { InstallCommand, TransformCommand, DependenciesCommand, + DownloadCommand, + CleanCommand, + PackCommand, } from './commands/index.js'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import logger from '../utils/logger.js'; @@ -368,15 +370,19 @@ export class CommandFactory { const textProcessor = writer || executor; return [ - new VersionCommand(executor), - new HelpCommand(executor), - // new UpgradeCommand(executor), // disable for now, it for globally installed now-sdk + // SDK Information Tool (using SDK flags, not commands) + new SdkInfoCommand(executor), + + // SDK Command Tools (actual SDK subcommands) new AuthCommand(textProcessor), // Uses writer to generate text instead of executing new InitCommand(textProcessor, mcpServer), // Uses writer to generate text instead of executing new BuildCommand(executor), new InstallCommand(executor), new TransformCommand(executor), new DependenciesCommand(textProcessor), // Uses writer to generate text instead of executing + new DownloadCommand(executor), + new CleanCommand(executor), + new PackCommand(executor), ]; } } diff --git a/src/tools/commands/cleanCommand.ts b/src/tools/commands/cleanCommand.ts new file mode 100644 index 0000000..0a0ee61 --- /dev/null +++ b/src/tools/commands/cleanCommand.ts @@ -0,0 +1,41 @@ +import { CommandArgument, CommandResult } from '../../utils/types.js'; +import { SessionAwareCLICommand } from './sessionAwareCommand.js'; + +/** + * Command to clean output directory of a Fluent (ServiceNow SDK) application + * Uses the session's working directory + */ +export class CleanCommand extends SessionAwareCLICommand { + name = 'clean_fluent_app'; + description = 'Clean up output directory of a Fluent (ServiceNow SDK) application'; + arguments: CommandArgument[] = [ + { + name: 'source', + type: 'string', + required: false, + description: 'Path to the directory that contains package.json configuration', + }, + { + name: 'debug', + type: 'boolean', + required: false, + description: 'Print debug output', + } + ]; + + async execute(args: Record): Promise { + const sdkArgs = ['now-sdk', 'clean']; + + // Add optional source directory if provided (overrides session working directory) + if (args.source) { + sdkArgs.push('--source', args.source as string); + } + + // Add debug flag if specified + if (args.debug) { + sdkArgs.push('--debug'); + } + + return this.executeWithSessionWorkingDirectory('npx', sdkArgs); + } +} diff --git a/src/tools/commands/downloadCommand.ts b/src/tools/commands/downloadCommand.ts new file mode 100644 index 0000000..d0f51cb --- /dev/null +++ b/src/tools/commands/downloadCommand.ts @@ -0,0 +1,57 @@ +import { CommandArgument, CommandResult } from '../../utils/types.js'; +import { SessionAwareCLICommand } from './sessionAwareCommand.js'; + +/** + * Command to download application metadata from a ServiceNow instance + * Uses the session's working directory + */ +export class DownloadCommand extends SessionAwareCLICommand { + name = 'download_fluent_app'; + description = 'Download application metadata from instance, including metadata that not exist in local but deployed to instance'; + arguments: CommandArgument[] = [ + { + name: 'directory', + type: 'string', + required: true, + description: 'Path to expand application', + }, + { + name: 'source', + type: 'string', + required: false, + description: 'Path to the directory that contains package.json configuration', + }, + { + name: 'incremental', + type: 'boolean', + required: false, + description: 'Download application metadata from the instance in incremental mode', + }, + { + name: 'debug', + type: 'boolean', + required: false, + description: 'Print debug output', + } + ]; + + async execute(args: Record): Promise { + const sdkArgs = ['now-sdk', 'download', args.directory as string]; + + // Add optional source directory if provided (overrides session working directory) + if (args.source) { + sdkArgs.push('--source', args.source as string); + } + + if (args.incremental) { + sdkArgs.push('--incremental'); + } + + // Add debug flag if specified + if (args.debug) { + sdkArgs.push('--debug'); + } + + return this.executeWithSessionWorkingDirectory('npx', sdkArgs); + } +} diff --git a/src/tools/commands/helpCommand.ts b/src/tools/commands/helpCommand.ts deleted file mode 100644 index c9be086..0000000 --- a/src/tools/commands/helpCommand.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { CommandArgument, CommandProcessor, CommandResult } from '../../utils/types'; - -import { SessionFallbackCommand } from './sessionFallbackCommand.js'; - -/** - * Command to get help information about Fluent (ServiceNow SDK) commands - */ -export class HelpCommand extends SessionFallbackCommand { - name = 'get_fluent_help'; - description = 'Provides help and usage information for any Fluent (ServiceNow SDK) command.'; - arguments: CommandArgument[] = [ - { - name: 'command', - type: 'string', - required: false, - description: 'The specific command to get help for', - }, - ]; - - constructor(commandProcessor: CommandProcessor) { - super(commandProcessor); - } - - async execute(args: Record): Promise { - this.validateArgs(args); - const command = args.command as string | undefined; - - if (command) { - return await this.executeWithFallback('npx', ['now-sdk', command, '--help']); - } else { - return await this.executeWithFallback('npx', ['now-sdk', '--help']); - } - } -} diff --git a/src/tools/commands/index.ts b/src/tools/commands/index.ts index c400a95..9dd1451 100644 --- a/src/tools/commands/index.ts +++ b/src/tools/commands/index.ts @@ -1,13 +1,14 @@ export * from './baseCommand.js'; export * from './sessionAwareCommand.js'; export * from './sessionFallbackCommand.js'; -export * from './versionCommand.js'; -export * from './helpCommand.js'; +export * from './sdkInfoCommand.js'; -export * from './upgradeCommand.js'; export * from './authCommand.js'; export * from './initCommand.js'; export * from './buildCommand.js'; export * from './installCommand.js'; export * from './transformCommand.js'; export * from './dependenciesCommand.js'; +export * from './downloadCommand.js'; +export * from './cleanCommand.js'; +export * from './packCommand.js'; diff --git a/src/tools/commands/initCommand.ts b/src/tools/commands/initCommand.ts index dd95f77..a5d4e00 100644 --- a/src/tools/commands/initCommand.ts +++ b/src/tools/commands/initCommand.ts @@ -87,7 +87,7 @@ export class InitCommand extends BaseCLICommand { name: 'workingDirectory', type: 'string', required: true, - description: "The directory where the Fluent (ServiceNow SDK) application will be created. Must be an empty local directory with no package.json or now.config.json files.", + description: 'The directory where the Fluent (ServiceNow SDK) application will be created. Must be an empty local directory with no package.json or now.config.json files.', }, { name: 'debug', @@ -451,7 +451,7 @@ export class InitCommand extends BaseCLICommand { * @param args Current arguments * @returns Promise resolving to the selected intent */ - private async elicitIntent(args: Record): Promise { + private async elicitIntent(_args: Record): Promise { if (!this.mcpServer) { throw new Error('Intent selection is required but MCP server not available for elicitation'); } diff --git a/src/tools/commands/packCommand.ts b/src/tools/commands/packCommand.ts new file mode 100644 index 0000000..3e7401b --- /dev/null +++ b/src/tools/commands/packCommand.ts @@ -0,0 +1,41 @@ +import { CommandArgument, CommandResult } from '../../utils/types.js'; +import { SessionAwareCLICommand } from './sessionAwareCommand.js'; + +/** + * Command to pack a Fluent (ServiceNow SDK) application into installable artifact + * Uses the session's working directory + */ +export class PackCommand extends SessionAwareCLICommand { + name = 'pack_fluent_app'; + description = 'Zip built Fluent (ServiceNow SDK) application into installable artifact'; + arguments: CommandArgument[] = [ + { + name: 'source', + type: 'string', + required: false, + description: 'Path to the directory that contains package.json configuration', + }, + { + name: 'debug', + type: 'boolean', + required: false, + description: 'Print debug output', + } + ]; + + async execute(args: Record): Promise { + const sdkArgs = ['now-sdk', 'pack']; + + // Add optional source directory if provided (overrides session working directory) + if (args.source) { + sdkArgs.push('--source', args.source as string); + } + + // Add debug flag if specified + if (args.debug) { + sdkArgs.push('--debug'); + } + + return this.executeWithSessionWorkingDirectory('npx', sdkArgs); + } +} diff --git a/src/tools/commands/sdkInfoCommand.ts b/src/tools/commands/sdkInfoCommand.ts new file mode 100644 index 0000000..b2d127c --- /dev/null +++ b/src/tools/commands/sdkInfoCommand.ts @@ -0,0 +1,138 @@ +import { CommandArgument, CommandProcessor, CommandResult } from '../../utils/types'; +import { BaseCLICommand } from './baseCommand.js'; +import { getProjectRootPath } from '../../config.js'; + +/** + * ServiceNow SDK information command that accepts SDK flags + * Handles -v/--version, -h/--help, -d/--debug flags as per SDK specification + */ +export class SdkInfoCommand extends BaseCLICommand { + name = 'sdk_info'; + description = 'Get Fluent (ServiceNow SDK) information using native SDK flags (-v, -h, -d)'; + arguments: CommandArgument[] = [ + { + name: 'flag', + type: 'string', + required: true, + description: 'SDK flag to execute (-v/--version, -h/--help, -d/--debug)', + }, + { + name: 'command', + type: 'string', + required: false, + description: 'Specific command to get help for (only used with -h/--help flag)', + }, + ]; + + constructor(commandProcessor: CommandProcessor) { + super(commandProcessor); + } + + /** + * Get command and working directory for ServiceNow SDK execution + */ + private getSdkCommand(): { command: string; baseArgs: string[]; workingDirectory: string } { + // Use the project root path where @servicenow/sdk is installed + const projectRoot = getProjectRootPath(); + + return { + command: 'npx', + baseArgs: ['now-sdk'], + workingDirectory: projectRoot + }; + } + + async execute(args: Record): Promise { + this.validateArgs(args); + + const flag = args.flag as string; + const command = args.command as string | undefined; + + // Validate flag + const validFlags = ['-v', '--version', '-h', '--help', '-d', '--debug']; + if (!validFlags.includes(flag)) { + return { + success: false, + output: '', + error: new Error(`Invalid flag '${flag}'. Valid flags: ${validFlags.join(', ')}`), + exitCode: 1 + }; + } + + // Build command arguments for SDK execution + const { command: sdkCommand, baseArgs, workingDirectory } = this.getSdkCommand(); + const sdkArgs: string[] = [...baseArgs]; + + if (flag === '-h' || flag === '--help') { + if (command) { + // Get help for specific command: npx now-sdk --help + sdkArgs.push(command, '--help'); + } else { + // Get general help: npx now-sdk --help + sdkArgs.push('--help'); + } + } else { + // For version and debug: npx now-sdk + sdkArgs.push(flag); + } + + try { + const result = await this.commandProcessor.process(sdkCommand, sdkArgs, false, workingDirectory); + + if (result.exitCode === 0) { + return { + success: true, + output: this.formatOutput(result.output, flag, command), + exitCode: result.exitCode + }; + } else { + return { + success: false, + output: result.output, + error: result.error || new Error(`SDK flag '${flag}' execution failed`), + exitCode: result.exitCode + }; + } + } catch (error) { + return { + success: false, + output: '', + error: error instanceof Error ? error : new Error('Unknown error occurred'), + exitCode: 1 + }; + } + } + + /** + * Format the output based on the flag used + */ + private formatOutput(output: string, flag: string, command?: string): string { + const trimmed = output.trim(); + + switch (flag) { + case '-v': + case '--version': { + // Extract version for cleaner presentation + const versionMatch = trimmed.match(/ServiceNow SDK v?(\d+\.\d+\.\d+[^\s]*)/i); + if (versionMatch) { + return `ServiceNow SDK Version: ${versionMatch[1]}\n\nFull output:\n${trimmed}`; + } + return `ServiceNow SDK Version Information:\n\n${trimmed}`; + } + + case '-h': + case '--help': + if (command) { + return `ServiceNow SDK Help for '${command}' command:\n\n${trimmed}\n\nNote: Retrieved using 'npx now-sdk ${command} --help'`; + } + return `ServiceNow SDK General Help:\n\n${trimmed}\n\nNote: Retrieved using 'npx now-sdk --help'`; + + case '-d': + case '--debug': + return `ServiceNow SDK Debug Information:\n\n${trimmed}\n\nNote: Retrieved using 'npx now-sdk --debug'`; + + default: + return trimmed; + } + } +} \ No newline at end of file diff --git a/src/tools/commands/sessionAwareCommand.ts b/src/tools/commands/sessionAwareCommand.ts index a583a5d..c115d2d 100644 --- a/src/tools/commands/sessionAwareCommand.ts +++ b/src/tools/commands/sessionAwareCommand.ts @@ -1,25 +1,32 @@ import { CommandResult } from '../../utils/types.js'; import { BaseCLICommand } from './baseCommand.js'; import { SessionManager } from '../../utils/sessionManager.js'; +import { getPrimaryRootPath } from '../../utils/rootContext.js'; import logger from '../../utils/logger.js'; /** - * Base class for commands that use the session working directory + * Base class for commands that use the session working directory with root context fallback * Extends BaseCLICommand and adds working directory handling */ export abstract class SessionAwareCLICommand extends BaseCLICommand { /** - * Get the working directory from the session, or use the current directory if not set + * Get the working directory from the session, or use the root context as fallback * @returns The working directory to use for the command */ protected getWorkingDirectory(): string | undefined { const sessionManager = SessionManager.getInstance(); - const workingDirectory = sessionManager.getWorkingDirectory(); + let workingDirectory = sessionManager.getWorkingDirectory(); if (workingDirectory) { logger.debug(`Using session working directory: ${workingDirectory}`); } else { - logger.debug('No working directory found in session'); + // Fallback to root context when no session working directory is set + try { + workingDirectory = getPrimaryRootPath(); + logger.debug(`No session working directory found, using root context: ${workingDirectory}`); + } catch (error) { + logger.debug(`No working directory found in session or root context: ${error}`); + } } return workingDirectory; @@ -45,7 +52,7 @@ export abstract class SessionAwareCLICommand extends BaseCLICommand { success: false, output: '', error: new Error( - 'No working directory found. Please run the init command first to set up a working directory.' + 'No working directory found. Please run the init command first to set up a working directory, or ensure MCP root context is configured.' ), }; } diff --git a/src/tools/commands/upgradeCommand.ts b/src/tools/commands/upgradeCommand.ts deleted file mode 100644 index 89d016f..0000000 --- a/src/tools/commands/upgradeCommand.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { CommandArgument, CommandProcessor, CommandResult } from '../../utils/types'; - -import { BaseCLICommand } from './baseCommand.js'; - -/** - * Command to upgrade Fluent (ServiceNow SDK) to the latest version - */ -export class UpgradeCommand extends BaseCLICommand { - name = 'upgrade_fluent'; - description = 'Upgrade globally installed Fluent (ServiceNow SDK) to the latest version. For a typical Fluent project, Fluent (ServiceNow SDK) is installed locally, not in global.'; - arguments: CommandArgument[] = [ - { - name: 'debug', - type: 'boolean', - required: false, - description: 'Enable debug mode for the upgrade process', - defaultValue: false, - }, - ]; - - constructor(commandProcessor: CommandProcessor) { - super(commandProcessor); - } - - async execute(args: Record): Promise { - this.validateArgs(args); - const debug = args.debug as boolean | undefined; - - const cmdArgs = ['now-sdk', 'upgrade']; - - if (debug) { - cmdArgs.push('--debug'); - } - - return await this.commandProcessor.process('npx', cmdArgs, true); - } -} diff --git a/src/tools/commands/versionCommand.ts b/src/tools/commands/versionCommand.ts deleted file mode 100644 index cdbbb66..0000000 --- a/src/tools/commands/versionCommand.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { CommandArgument, CommandProcessor, CommandResult } from '../../utils/types'; -import { SessionFallbackCommand } from './sessionFallbackCommand.js'; - -/** - * Command to retrieve Fluent (ServiceNow SDK) version information - */ -export class VersionCommand extends SessionFallbackCommand { - name = 'get_fluent_version'; - description = 'Retrieves the version number of the installed Fluent (ServiceNow SDK)'; - arguments: CommandArgument[] = []; - - constructor(commandProcessor: CommandProcessor) { - super(commandProcessor); - } - - async execute(args: Record): Promise { - this.validateArgs(args); - return await this.executeWithFallback('npx', ['now-sdk', '--version']); - } -} diff --git a/src/tools/toolsManager.ts b/src/tools/toolsManager.ts index 7300b90..763dc55 100644 --- a/src/tools/toolsManager.ts +++ b/src/tools/toolsManager.ts @@ -105,11 +105,11 @@ export class ToolsManager { // Convert command arguments to Zod schema const schema: Record = {}; - + // Build schema from command arguments for (const arg of command.arguments) { let zodType: z.ZodTypeAny; - + // Map command argument types to Zod types switch (arg.type) { case 'string': @@ -127,27 +127,35 @@ export class ToolsManager { default: zodType = z.any(); } - + // Make optional if not required if (!arg.required) { zodType = zodType.optional(); } - + schema[arg.name] = zodType; } + + // Create schema for MCP - use raw schema object, let MCP handle the z.object() wrapping + let inputSchema: any = undefined; + if (Object.keys(schema).length > 0) { + // Pass raw schema object, MCP will wrap it properly + inputSchema = schema; + } + // Register with MCP server this.mcpServer.registerTool( command.name, { title: command.name, description: command.description, - inputSchema: schema + inputSchema: inputSchema }, - async (params: Record) => { - const result = await command.execute(params); + async (args: { [x: string]: any }, _extra) => { + const result = await command.execute(args); return { - content: [{ type: 'text', text: result.output }], + content: [{ type: 'text' as const, text: result.output }], structuredContent: { success: result.success } }; } diff --git a/src/tools/types.ts b/src/tools/types.ts index 34ddd14..1264f40 100644 --- a/src/tools/types.ts +++ b/src/tools/types.ts @@ -9,7 +9,6 @@ export enum SdkCommandType { VERSION = 'version', HELP = 'help', DEBUG = 'debug', - UPGRADE = 'upgrade', AUTH = 'auth', INIT = 'init', BUILD = 'build', diff --git a/test/tools/newCommands.test.ts b/test/tools/newCommands.test.ts new file mode 100644 index 0000000..c5080ba --- /dev/null +++ b/test/tools/newCommands.test.ts @@ -0,0 +1,250 @@ +/** + * Tests for new SDK commands: Download, Clean, and Pack + */ +import { CommandFactory } from '../../src/tools/cliCommandTools.js'; +import { NodeProcessRunner } from '../../src/tools/cliCommandTools.js'; +import { DownloadCommand, CleanCommand, PackCommand } from '../../src/tools/commands/index.js'; + +// Mock the logger module +jest.mock('../../src/utils/logger.js', () => ({ + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + __esModule: true, + default: { + debug: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + } +})); + +// Mock the config module +jest.mock('../../src/config.js', () => ({ + getProjectRootPath: jest.fn().mockReturnValue('/mock/project/root') +})); + +// Mock the rootContext module +jest.mock('../../src/utils/rootContext.js', () => ({ + getPrimaryRootPath: jest.fn().mockReturnValue('/mock/root'), + getPrimaryRootPathFrom: jest.fn().mockReturnValue('/mock/root'), + setRoots: jest.fn(), +})); + +// Mock SessionManager +jest.mock('../../src/utils/sessionManager.js', () => ({ + SessionManager: { + getInstance: jest.fn().mockReturnValue({ + getWorkingDirectory: jest.fn().mockReturnValue('/mock/working/dir'), + setWorkingDirectory: jest.fn(), + }), + getWorkingDirectory: jest.fn().mockReturnValue('/mock/working/dir'), + setWorkingDirectory: jest.fn(), + } +})); + +describe('New SDK Commands', () => { + let mockProcessor: { process: jest.Mock }; + + beforeEach(() => { + jest.clearAllMocks(); + mockProcessor = { + process: jest.fn().mockResolvedValue({ + success: true, + output: 'Mock command output', + exitCode: 0 + }) + }; + }); + + describe('DownloadCommand', () => { + test('should create DownloadCommand with correct metadata', () => { + const command = new DownloadCommand(mockProcessor as any); + + expect(command.name).toBe('download_fluent_app'); + expect(command.description).toBe('Download application metadata from instance, including metadata that not exist in local but deployed to instance'); + expect(command.arguments).toHaveLength(4); + + // Check required directory argument + const directoryArg = command.arguments.find(arg => arg.name === 'directory'); + expect(directoryArg).toBeDefined(); + expect(directoryArg?.required).toBe(true); + expect(directoryArg?.type).toBe('string'); + expect(directoryArg?.description).toBe('Path to expand application'); + + // Check optional source argument + const sourceArg = command.arguments.find(arg => arg.name === 'source'); + expect(sourceArg).toBeDefined(); + expect(sourceArg?.required).toBe(false); + expect(sourceArg?.type).toBe('string'); + + // Check optional incremental argument + const incrementalArg = command.arguments.find(arg => arg.name === 'incremental'); + expect(incrementalArg).toBeDefined(); + expect(incrementalArg?.required).toBe(false); + expect(incrementalArg?.type).toBe('boolean'); + + // Check optional debug argument + const debugArg = command.arguments.find(arg => arg.name === 'debug'); + expect(debugArg).toBeDefined(); + expect(debugArg?.required).toBe(false); + expect(debugArg?.type).toBe('boolean'); + }); + + test('should execute download command with required directory', async () => { + const command = new DownloadCommand(mockProcessor as any); + + const result = await command.execute({ directory: 'my-app' }); + + expect(result.success).toBe(true); + expect(result.output).toContain('Mock command output'); + expect(mockProcessor.process).toHaveBeenCalledWith( + 'npx', + ['now-sdk', 'download', 'my-app'], + false, + '/mock/working/dir' + ); + }); + + test('should execute download command with all arguments', async () => { + const command = new DownloadCommand(mockProcessor as any); + + const result = await command.execute({ + directory: 'my-app', + source: './src', + incremental: true, + debug: true + }); + + expect(result.success).toBe(true); + expect(mockProcessor.process).toHaveBeenCalledWith( + 'npx', + ['now-sdk', 'download', 'my-app', '--source', './src', '--incremental', '--debug'], + false, + '/mock/working/dir' + ); + }); + }); + + describe('CleanCommand', () => { + test('should create CleanCommand with correct metadata', () => { + const command = new CleanCommand(mockProcessor as any); + + expect(command.name).toBe('clean_fluent_app'); + expect(command.description).toBe('Clean up output directory of a Fluent (ServiceNow SDK) application'); + expect(command.arguments).toHaveLength(2); + + // Check optional source argument + const sourceArg = command.arguments.find(arg => arg.name === 'source'); + expect(sourceArg).toBeDefined(); + expect(sourceArg?.required).toBe(false); + expect(sourceArg?.type).toBe('string'); + expect(sourceArg?.description).toBe('Path to the directory that contains package.json configuration'); + + // Check optional debug argument + const debugArg = command.arguments.find(arg => arg.name === 'debug'); + expect(debugArg).toBeDefined(); + expect(debugArg?.required).toBe(false); + expect(debugArg?.type).toBe('boolean'); + }); + + test('should execute clean command without arguments', async () => { + const command = new CleanCommand(mockProcessor as any); + + const result = await command.execute({}); + + expect(result.success).toBe(true); + expect(mockProcessor.process).toHaveBeenCalledWith( + 'npx', + ['now-sdk', 'clean'], + false, + '/mock/working/dir' + ); + }); + + test('should execute clean command with source and debug', async () => { + const command = new CleanCommand(mockProcessor as any); + + const result = await command.execute({ + source: 'src', + debug: true + }); + + expect(result.success).toBe(true); + expect(mockProcessor.process).toHaveBeenCalledWith( + 'npx', + ['now-sdk', 'clean', '--source', 'src', '--debug'], + false, + '/mock/working/dir' + ); + }); + }); + + describe('PackCommand', () => { + test('should create PackCommand with correct metadata', () => { + const command = new PackCommand(mockProcessor as any); + + expect(command.name).toBe('pack_fluent_app'); + expect(command.description).toBe('Zip built Fluent (ServiceNow SDK) application into installable artifact'); + expect(command.arguments).toHaveLength(2); + + // Check optional source argument + const sourceArg = command.arguments.find(arg => arg.name === 'source'); + expect(sourceArg).toBeDefined(); + expect(sourceArg?.required).toBe(false); + expect(sourceArg?.type).toBe('string'); + expect(sourceArg?.description).toBe('Path to the directory that contains package.json configuration'); + + // Check optional debug argument + const debugArg = command.arguments.find(arg => arg.name === 'debug'); + expect(debugArg).toBeDefined(); + expect(debugArg?.required).toBe(false); + expect(debugArg?.type).toBe('boolean'); + }); + + test('should execute pack command without arguments', async () => { + const command = new PackCommand(mockProcessor as any); + + const result = await command.execute({}); + + expect(result.success).toBe(true); + expect(mockProcessor.process).toHaveBeenCalledWith( + 'npx', + ['now-sdk', 'pack'], + false, + '/mock/working/dir' + ); + }); + + test('should execute pack command with source and debug', async () => { + const command = new PackCommand(mockProcessor as any); + + const result = await command.execute({ + source: './build', + debug: true + }); + + expect(result.success).toBe(true); + expect(mockProcessor.process).toHaveBeenCalledWith( + 'npx', + ['now-sdk', 'pack', '--source', './build', '--debug'], + false, + '/mock/working/dir' + ); + }); + }); + + describe('CommandFactory Integration', () => { + test('should include new commands in CommandFactory.createCommands', () => { + const mockExecutor = { process: jest.fn() }; + const commands = CommandFactory.createCommands(mockExecutor as any); + + const commandNames = commands.map(cmd => cmd.name); + + expect(commandNames).toContain('download_fluent_app'); + expect(commandNames).toContain('clean_fluent_app'); + expect(commandNames).toContain('pack_fluent_app'); + }); + }); +}); diff --git a/test/tools/sdkCommands.test.ts b/test/tools/sdkCommands.test.ts index 9c848a8..873579d 100644 --- a/test/tools/sdkCommands.test.ts +++ b/test/tools/sdkCommands.test.ts @@ -16,37 +16,24 @@ class MockProcessRunner extends NodeProcessRunner { async run(_command: string, args: string[] = []): Promise { // Return different mocked responses based on args - if (args.includes('--version')) { + if (args.includes('--version') || args.includes('-v')) { return { stdout: 'ServiceNow SDK v3.0.2', stderr: '', exitCode: 0 }; - } else if (args.includes('--help')) { + } else if (args.includes('--help') || args.includes('-h')) { return { stdout: 'ServiceNow SDK Help information', stderr: '', exitCode: 0 }; - } else if (args.includes('--debug')) { + } else if (args.includes('--debug') || args.includes('-d')) { return { stdout: 'Debug logs for ServiceNow SDK', stderr: '', exitCode: 0 }; - } else if (args.includes('upgrade')) { - let output = 'ServiceNow SDK upgraded to latest version'; - if (args.includes('--check')) { - output = 'ServiceNow SDK is up to date'; - } - if (args.includes('--debug')) { - output += '\nDebug information: Upgrade process details'; - } - return { - stdout: output, - stderr: '', - exitCode: 0 - }; } return this.mockResult; @@ -64,118 +51,144 @@ describe('SDK Command Tools', () => { commands = CommandFactory.createCommands(executor, executor); }); - test('VersionCommand should execute correctly', async () => { - const versionCommand = commands.find((cmd) => cmd.name === 'get_fluent_version'); - expect(versionCommand).toBeDefined(); + test('SdkInfoCommand should execute correctly with -v flag', async () => { + const sdkInfoCommand = commands.find((cmd) => cmd.name === 'sdk_info'); + expect(sdkInfoCommand).toBeDefined(); - const result = await versionCommand.execute({}); + const result = await sdkInfoCommand.execute({ flag: '-v' }); expect(result.success).toBe(true); - + // Basic presence check expect(result.output).toContain('ServiceNow SDK v'); - + // Extract version using regex and validate semantic versioning format const versionRegex = /ServiceNow SDK v(\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)/; const match = result.output.match(versionRegex); - + // Verify version string was found and extracted expect(match).not.toBeNull(); expect(match).toBeDefined(); - + // Extract the version without the prefix const versionString = match ? match[1] : ''; - + // Validate the format of the extracted version using semantic versioning regex const semverRegex = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/; expect(versionString).toMatch(semverRegex); - + // Validate version components are valid numbers const versionParts = versionString.split('.'); expect(Number(versionParts[0])).toBeGreaterThanOrEqual(0); // Major expect(Number(versionParts[1])).toBeGreaterThanOrEqual(0); // Minor - + // For patch, we need to handle potential pre-release/build metadata const patchPart = versionParts[2].split(/[-+]/)[0]; // Extract patch number before any pre-release/build metadata expect(Number(patchPart)).toBeGreaterThanOrEqual(0); // Patch }); - test('HelpCommand should execute correctly with no args', async () => { - const helpCommand = commands.find((cmd) => cmd.name === 'get_fluent_help'); - expect(helpCommand).toBeDefined(); + test('SdkInfoCommand should execute correctly with -h flag (general help)', async () => { + const sdkInfoCommand = commands.find((cmd) => cmd.name === 'sdk_info'); + expect(sdkInfoCommand).toBeDefined(); - const result = await helpCommand.execute({}); + const result = await sdkInfoCommand.execute({ flag: '-h' }); expect(result.success).toBe(true); expect(result.output).toContain('ServiceNow SDK Help information'); }); - test('HelpCommand should execute correctly with specific command', async () => { - const helpCommand = commands.find((cmd) => cmd.name === 'get_fluent_help'); - + test('SdkInfoCommand should execute correctly with -h flag and specific command', async () => { + const sdkInfoCommand = commands.find((cmd) => cmd.name === 'sdk_info'); + expect(sdkInfoCommand).toBeDefined(); + // Set up specific mock response - const mockStdout = 'Help for auth command'; - const mockStderr = ''; + const mockOutput = 'Help for auth command'; const mockExitCode = 0; - + // Override the run method directly for this test const originalRun = mockRunner.run; mockRunner.run = jest.fn().mockImplementation(async (_command, args) => { // Check if this is the specific auth help command we're testing if (args.includes('auth') && args.includes('--help')) { return { - stdout: mockStdout, - stderr: mockStderr, + stdout: mockOutput, + stderr: '', exitCode: mockExitCode }; } - + // Otherwise call the original implementation return originalRun.call(mockRunner, _command, args); }); // Execute the command - const result = await helpCommand.execute({ command: 'auth' }); - + const result = await sdkInfoCommand.execute({ flag: '-h', command: 'auth' }); + // Verify the command succeeded expect(result.success).toBe(true); - + // Verify the mock output is correctly returned in the result - expect(result.output).toContain(mockStdout); + expect(result.output).toContain(mockOutput); expect(result.exitCode).toBe(mockExitCode); expect(result.error).toBeUndefined(); - + // Verify the command was called with expected arguments expect(mockRunner.run).toHaveBeenCalledWith( - 'npx', - expect.arrayContaining(['now-sdk', 'auth', '--help']), - expect.any(String) // The working directory is passed as the third parameter + 'npx', // Should use npx + expect.arrayContaining(['now-sdk', 'auth', '--help']), // Args with 'now-sdk' prefix + expect.any(String) // Working directory should be provided (project root path) ); // Restore the original run method mockRunner.run = originalRun; }); - // test('UpgradeCommand should execute correctly with basic upgrade', async () => { - // const upgradeCommand = commands.find((cmd) => cmd.name === 'upgrade_fluent'); - // expect(upgradeCommand).toBeDefined(); + test('SdkInfoCommand should execute correctly with -d flag', async () => { + const sdkInfoCommand = commands.find((cmd) => cmd.name === 'sdk_info'); + expect(sdkInfoCommand).toBeDefined(); - // const result = await upgradeCommand.execute({}); - // expect(result.success).toBe(true); - // expect(result.output).toContain('upgraded to latest version'); - // }); + // Set up mock response for debug flag + const originalRun = mockRunner.run; + mockRunner.run = jest.fn().mockImplementation(async (_command, args) => { + if (args.includes('--debug')) { + return { + stdout: 'Debug logs for ServiceNow SDK', + stderr: '', + exitCode: 0 + }; + } + return originalRun.call(mockRunner, _command, args); + }); + const result = await sdkInfoCommand.execute({ flag: '-d' }); + expect(result.success).toBe(true); + expect(result.output).toContain('Debug logs for ServiceNow SDK'); - // test('UpgradeCommand should execute correctly with debug option', async () => { - // const upgradeCommand = commands.find((cmd) => cmd.name === 'upgrade_fluent'); + // Restore the original run method + mockRunner.run = originalRun; + }); - // const result = await upgradeCommand.execute({ debug: true }); - // expect(result.success).toBe(true); - // expect(result.output).toContain('Debug logs'); - // }); + test('SdkInfoCommand should handle invalid flags', async () => { + const sdkInfoCommand = commands.find((cmd) => cmd.name === 'sdk_info'); + expect(sdkInfoCommand).toBeDefined(); - test('Command should handle errors correctly', async () => { - const versionCommand = commands.find((cmd) => cmd.name === 'get_fluent_version'); + const result = await sdkInfoCommand.execute({ flag: '--invalid' }); + expect(result.success).toBe(false); + expect(result.error).toBeDefined(); + expect(result.error?.message).toContain('Invalid flag'); + }); + + test('SdkInfoCommand should handle missing required flag parameter', async () => { + const sdkInfoCommand = commands.find((cmd) => cmd.name === 'sdk_info'); + expect(sdkInfoCommand).toBeDefined(); + + await expect(sdkInfoCommand.execute({})).rejects.toThrow('Required argument \'flag\' is missing'); + }); + + test('SdkInfoCommand should handle errors correctly', async () => { + const sdkInfoCommand = commands.find((cmd) => cmd.name === 'sdk_info'); + expect(sdkInfoCommand).toBeDefined(); // Override the run method directly for this specific test + const originalRun = mockRunner.run; mockRunner.run = async () => { return { stdout: '', @@ -184,9 +197,12 @@ describe('SDK Command Tools', () => { }; }; - const result = await versionCommand.execute({}); + const result = await sdkInfoCommand.execute({ flag: '-v' }); expect(result.success).toBe(false); expect(result.exitCode).toBe(1); expect(result.error).toBeDefined(); + + // Restore the original run method + mockRunner.run = originalRun; }); }); diff --git a/test/tools/sessionAwareCommand.test.ts b/test/tools/sessionAwareCommand.test.ts index b73fa47..2d52bdd 100644 --- a/test/tools/sessionAwareCommand.test.ts +++ b/test/tools/sessionAwareCommand.test.ts @@ -13,6 +13,13 @@ jest.mock("../../src/utils/sessionManager.js", () => { }; }); +// Mock the rootContext +jest.mock("../../src/utils/rootContext.js", () => { + return { + getPrimaryRootPath: jest.fn().mockReturnValue("/test-root-context"), + }; +}); + // Create a concrete implementation of SessionAwareCLICommand for testing class TestSessionAwareCommand extends SessionAwareCLICommand { name = "test_command"; @@ -69,6 +76,11 @@ describe("SessionAwareCommand", () => { test("should return error when no working directory is available", async () => { // Override the mock to return undefined working directory (SessionManager.getInstance().getWorkingDirectory as jest.Mock).mockReturnValueOnce(undefined); + // Mock rootContext to throw error + const { getPrimaryRootPath } = require("../../src/utils/rootContext.js"); + (getPrimaryRootPath as jest.Mock).mockImplementationOnce(() => { + throw new Error("No root context available"); + }); const result = await sessionAwareCommand.execute({});