{"id":21505362,"url":"https://github.com/ibm-messaging/mq-mqi-nodejs","last_synced_at":"2025-05-16T09:03:40.336Z","repository":{"id":40213480,"uuid":"109041327","full_name":"ibm-messaging/mq-mqi-nodejs","owner":"ibm-messaging","description":"Calling IBM MQ from Node.js - a JavaScript MQI wrapper","archived":false,"fork":false,"pushed_at":"2025-04-15T11:01:26.000Z","size":1756,"stargazers_count":79,"open_issues_count":14,"forks_count":43,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-04-15T12:22:04.499Z","etag":null,"topics":["ibm-mq","javascript","nodejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ibm-messaging.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-31T19:11:18.000Z","updated_at":"2025-04-15T11:01:30.000Z","dependencies_parsed_at":"2024-02-29T19:29:00.510Z","dependency_job_id":"1fd5ae2d-6a4e-4325-97d7-b8456d2cc816","html_url":"https://github.com/ibm-messaging/mq-mqi-nodejs","commit_stats":{"total_commits":137,"total_committers":13,"mean_commits":"10.538461538461538","dds":"0.43065693430656937","last_synced_commit":"a3384e80b919e8e5604bbc28b7eaa4b2ede21e51"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-messaging%2Fmq-mqi-nodejs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-messaging%2Fmq-mqi-nodejs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-messaging%2Fmq-mqi-nodejs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-messaging%2Fmq-mqi-nodejs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ibm-messaging","download_url":"https://codeload.github.com/ibm-messaging/mq-mqi-nodejs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254422789,"owners_count":22068682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ibm-mq","javascript","nodejs"],"created_at":"2024-11-23T19:02:27.818Z","updated_at":"2025-05-16T09:03:40.312Z","avatar_url":"https://github.com/ibm-messaging.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mq-mqi-nodejs\nThis repository demonstrates a way to call IBM MQ from applications running in a Node.js environment.\n\n## N-API REWRITE for V2 (Jun 2023)\nThis version of the package has been heavily rewritten, to remove some of the outdated/unmaintained dependencies. There\nare other potential benefits to the rewrite, including improved performance and the opportunity to port to platforms\nthat the dependencies could not support.\n\nSee the [BREAKING_CHANGES](BREAKING_CHANGES_V2.md) file for changes you might need to make to your application.\n\n## MQI Description\nThe package exposes the IBM MQ programming interface via a wrapper layer implemented in JavaScript. This should make it\neasy for a Node.js developer to send and receive messages via MQ, and interact with other MQ-enabled applications in the\norganisation.\n\nThe package is based on the full MQI. It uses essentially the same verbs and structures as the C or COBOL interface, but\nwith a more appropriate style for this environment. It removes the need for a developer to worry about how to map\nelements to the underlying C libraries and instead enables a focus on the business application code. For example,\nJavaScript strings are used instead of fixed-length, spaced-padded fields.\n\nMost MQI verbs and parameters are implemented here. Where there are missing details within the verbs, these are shown by\nTODO markers in the source files.\n\nIt is assumed that someone using this package does have a basic understanding of the procedural MQI, as that is needed\nto decide which options and fields may need to be set for each verb.\n\nThe implemented verbs follow the JavaScript style, invoking user-supplied callback functions on completion. In all\ncases, the callbacks are presented with an MQError object as the first parameter when an error or warning occurs (null\notherwise), followed by other relevant objects and data. If the callback is not provided by the application, then either\nan exception is thrown, or the verb returns.\n\n###  Synchrony\nThe main verbs - `Conn(x)`, `Disc`, `Open`, `Close`, `Sub`, `Put`, `Put1` and `Get` - have true synchronous and\nasynchronous variations. The default is that these verbs are asynchronous, to be more natural in a Node.js environment.\nWhen given a `...Sync` suffix (eg `OpenSync`) then the verb is synchronous. Callback functions are required for the\nOpenSync and SubSync verbs to obtain the object handles; these are not returned explicitly from the function calls.\n\nThe remaining verbs (including `Cmit` and `Back`) internally make synchronous calls to the underlying MQI\nservices. Callback functions can still be used to indicate completion of the operation, with function return values and\nexceptions being available if you want to treat them more synchronously rather than pseudo-async.\n\nFor the asynchronous functions, a callback function is mandatory.\n\nNote that MQ also has a concept of Asynchronous Put (an MQPMO option) usable from client applications. That can be used\nin conjunction with a later call to the `Stat` function to determine the success of the Put calls, but it is not related\nto asynchronous notification of the operation completion in JavaScript terms.\n\n#### Synchronous compatibility option\nThe SyncMQICompat tuning parameter (among other tuning options) has been removed with the V2 implementation.\n\n### Promises\nMost of the core MQI verbs (excluding the GET variants) have Promise-based alternatives named with a `...Promise` suffix\n(eg `ConnxPromise`). This can help with removal of much of the typical callback nesting. See the amqsputp.js sample for\na demonstration of how these can be used. There is no Get-based Promise because the async Get operation invokes\ncallbacks multiple times as messages appear.\n\n### Message Retrieval\nThis implementation includes two mechanisms for retrieving messages from a queue:\n* *GetSync()* is the call that does an MQGET(wait) synchronously. In a Node environment, it blocks the execution thread\n  until it completes. That may be OK for an immediate retrieval where the wait time is set to zero, but it is not\n  recommended for any times where you want to wait a while for a message to arrive. Some of the samples use this\n  function for simplicity, where the Get() is not the interesting aspect being demonstrated.\n* *Get()* is the call that works asynchronously. The callback given as a parameter to this function is invoked\n  asynchronously. The function remains active after delivering a message to permit receipt of multiple messages. To stop\n  the callback being called for further messages, use the *GetDone()* function. This behaviour is similar to how the MQI\n  *MQCB* callback invocation works.\n\nThis package uses MQCB/MQCTL-managed callbacks for true asynchronous processing. As such, some of the TuningParameter\nvalues that were available in the 1.x versions of the code have been removed. You will get an exception if you try to\nuse those parameters.\n\nFor more advanced handling of inbound messages, there is a *Ctl()* verb. This is an analogue of `MQCTL` and requires you\nto explicitly start message consumption. It is the default behaviour. You should always use this if you are going to\nopen multiple queues simultaneously for reading. The `tuningParameter.useCtl` or `MQIJS_NOUSECTL` environment variable\ncontrol whether or not to require use of the new verb. Older applications can use `useCtl=false` or the environment\nvariable for backwards compatibility; newer applications should use *Ctl()* going forward.\n\nSample programs **amqsget**, **amqsgeta**, and **amqsgetac** demonstrate the different techniques.\n\n### Calling the MQI from the message delivery callback\n\nThe callback function invoked as part of *Get()* processing has to be scheduled to run on a different OS thread than the\nMQI thinks it has called. The default strategy for how this is managed internally allows you to call the MQI from your\ncallback function. You can, for example, call *Cmit()* from the callback function, safely knowing which message\noperations will be committed.\n\n#### Alternative callback strategy\n\nThere is an alternative callback strategy that a tuning parameter option configures.\n```\n  mq.setTuningParameters({callbackStrategy: \"READAHEAD\"});\n```\n\nSetting this option MIGHT make retrieval of large numbers of messages run faster. But it can also cause operations to\noverlap. So you might not know which messages have actually been removed from the queue. It is therefore definitely not\nrecommended if you care about transactionality. And if you want to call the MQI from within your callback in this mode,\nyou will have to manually suspend callbacks temporarily. Otherwise you will probably get an `MQRC_HCONN_ASYNC_ACTIVE`\n(2500) error returned.\n\nInstead, you can temporarily disable the asynchronous delivery, call the MQI, and then resume. For example, if you want\nto *Inq()* on some aspect of the queue, then doing something like this works inside the Node.js callback.\n\n```\n  mq.Ctl(connectionHandle, MQC.MQOP_SUSPEND, function (err) {\n    if (err) console.log(formatErr(err));\n  });\n  var selectors = [ new mq.MQAttr(MQC.MQIA_CURRENT_Q_DEPTH)];\n  mq.Inq(queueHandle,selectors, function (err) {\n    if (err) console.log(formatErr(err));\n  });\n  mq.Ctl(connectionHandle, MQC.MQOP_RESUME, function (err) {\n    if (err) console.log(formatErr(err));\n  });\n```\nThe *Ctl()* and *Inq()* calls in this fragment are synchronous operations, so do not need to be nested inside callbacks.\n\n## Message body\nWhen putting messages, JavaScript Buffers and strings can be used; string values automatically set the MQMD Format field\nto \"MQSTR\". When getting messages, data is always returned in a Buffer.\n\n## Alternative JavaScript routes into MQ\nThere are already some other ways to access MQ from Node.js:\n* MQ supports connections via AMQP channels. There are a number of AMQP 1.0 client implementations available for Node.js.\n* The MQTT protocol has an implementation [here](https://www.npmjs.com/package/mqtt). MQ supports connections from MQTT\n  clients via the XR service and Telemetry channels.\n* MQ has a simple REST API for messaging that is accessible from any environment. See\n  [here](https://www.ibm.com/docs/en/ibm-mq/latest?topic=api-getting-started-messaging-rest) for more information.\n\nThese interfaces may be suitable for many messaging applications, even though they do not give access to the full\nservices available from MQ such as transactions.\n\n## Unimplemented capabilities\nAll the application-level MQI verbs are implemented. Structures and verbs that are only used in other environments - for\nexample in exits - are not provided as only C is a supported language for those operations.\n\nThere are no structure definitions for most MQ header elements in message contents such as the MQCIH structure.\n\nHowever there is a definition and sample program to manipulate the Dead Letter Header (MQDLH). There is also a\ndefinition for the MQRFH2 structure header, though not for the individual folders and properties that may be added to\nthat structure. Instead of explicitly using an MQRFH2, it is recommended you use the message property APIs.\n\nThe **amqsget** sample shows ways to process the returned message, including extracting details from the MQDLH and MQRFH2\nstructures if they are part of the message.\n\n## Local queue manager connectivity\n\nThe C MQ library is dynamically loaded at runtime. By default, this package will try to load the library from the\n`node_modules` directory associated with the application.\n\nFor platforms where the MQ Redistributable Client exists and has been installed, this means that local bindings\nconnections will not work to connect to a queue manager, even if there is also a full MQ installation on the machine.\nOnly client connections can be used by the Redistributable Client libraries. Trying to connect to a local queue manager\nwill likely result in an **MQRC_Q_MGR_NAME_ERROR** (2058) error.\n\nTo override this default behaviour and to permit use of local bindings connections, the full MQ installation libraries\nmust be used instead. There are two mechanisms to do this:\n* Set the `MQIJS_NOREDIST` environment variable during `npm install` so that the Redist Client package is not downloaded\n  and installed in the `node_modules` directory.\n* Set the `MQIJS_PREFER_INSTALLED_LIBRARY` environment variable at runtime\n\nThe use of the Redist Client libraries is preferred wherever possible, so that new function can be introduced regardless\nof the version of MQ that has been \"properly\" installed on a machine.\n\n## Client connectivity\n\nClient connections work in the usual way.\n* Definitions can be set up externally via CCDT or the MQSERVER environment variable\n* Definitions can be set up programmatically via the MQCD and MQSCO structures passed to *Connx()*\n\nTo force client connections, even when there is a full MQ server set of libraries installed and loaded:\n* The program can set the `MQCNO_CLIENT_BINDING` flag in the MQCNO options during *Connx()*\n* You can set the `MQ_CONNECT_TYPE` environment variable to \"CLIENT\".\n\n## Extra operations\nThe package includes a couple of verbs that are not standard in the MQI.\n* *GetDone()* is used to end asynchronous retrieval of messages.\n* *GetSync()* is equivalent of the traditional MQGET operation.\n* *Lookup()* extracts strings corresponding to MQI numbers, similar to the *MQConstants.lookup()* method in Java.\n\n## Requirements\n* node version 16 or greater.\n* On platforms other than Windows and Linux x64, you must also install the MQ client package\n* I have run it on Windows, where the NPM 'windows-build-tools' package also needed to be installed first. See\n  [this document](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#environment-setup-and-configuration)\n  for more information on Windows.\n\n## Installation:\nTo install this package, you can pull it straight from the NPM repository. You can also refer to it in a package.json\nfile for automatic installation.\n\n~~~\nmkdir \u003csomething\u003e\ncd \u003csomething\u003e\nnpm install ibmmq\n~~~\n\n### Prerequisite components\n\nInstallation of the package will automatically install any prerequisite packages downloadable from the npm repository.\nBy default, it will pull in packages listed in both the `dependencies` and the `devDependencies` sections. For\nenvironments where you only want to run a program, then adding an option `npm install --only=prod` or setting the\n`NODE_ENV` environment variable to `production` will cause downloads of only the runtime dependencies.\n\n### The MQ C Client libraries\n\nThe package requires the MQ C client libraries to be installed/available.\n\nFor Windows and Linux x64, the npm installation process tries to access the Redistributable Client packages and unpack\nthem automatically.\n\nNote: IBM removes older levels of the Redistributable Client packages when they become unsupported. If you want to\ncontinue to use older versions of this package (which will reference those unsupported MQ versions) then you will have\nto keep a local copy of the tar/zip files and unpack it as part of your build process, using the MQIJS_* environment\nvariables to control installation and runtime.\n\n#### Controlling the download location\n\nThe download of the Redistributable Client packages will, by default, try to go to the `public.dhe.ibm.com` site. If\nthat is not reachable - perhaps you are installing into a machine that does not have access to the public internet -\nthen you can override the location that the install process tries to use. Set the environment variable\n`MQIJS_LOCAL_URL` to something like `https://myserver.example.com:8080/MQClients`.\n\nYou might also considering copying the Redistributable Client package to one of your own servers, and pointing at that,\nas a way of handling any unavailability of the `dhe.ibm.com` site.\n\nIf you do not want the automatic installation of the MQ runtime at all, then set the environment variable\n`MQIJS_NOREDIST` to any value before running npm install. The MQ libraries are then be found at runtime using mechanisms\nsuch as searching `LD_LIBRARY_PATH` (Linux) or `PATH` (Windows).\n\n## Controlling the downloaded version\n\nThe post-installation program will usually be pointing at the most recent Continuous Delivery version of MQ (for example\n9.1.4.0). These versions of MQ do not have fixpacks released, though they may have updates available specifically aimed\nat security vulnerabilities (CSU packages). You can override both the version (VRM) and fixpack to be installed,\nassuming that full VRMF level is still available for download. Setting the environment variables `MQIJS_VRM` and\n`MQIJS_FIXPACK` will select a specific Redistributable Client package to be installed. Note that installing an older VRM\nthan the default in the current version of this package may not work, if newer options have been introduced to the MQI.\nAt the time of writing this paragraph, the latest version of MQ was 9.2.0 (with no later CD releases), but there was\nalso a 9.2.0.1 fixpack. If you want to pick that up instead of the base 9.2.0.0 referred to in postinstall.js, then set\n`MQIJS_FIXPACK=1` before running `npm install`. Once newer CD levels are available, then the postinstall script will\npoint at those instead by default. If you want to select a CSU level (very similar to a fixpack, but with a more limited\nscope) then the same environment variable can be used.\n\n### Setting environment variables for the installation process\n\nThe MQIJS_* environment variables used during  `npm install` can also be set in an *.npmrc* file.  These are more commonly\nwritten in lowercase, so `export MQIJS_VRM=9.3.4` would become `mqijs_vrm=9.3.4` in the NPM configuration file. But\nthe package does attempt to reference a variety of case options. The real environment variable takes precedence over the\n*.npmrc* setting.\n\n### Downloading behind a proxy\n\nDownloading the Redistributable C Client libraries behind a proxy is supported. Use the environment variables\n`https_proxy` and `no_proxy` to control proxy behaviour.\n\nFor example, the following command will use a proxy server at `http://localhost:8080` to download the redistributable\nlibraries:\n\n```\n% HTTPS_PROXY=http://localhost:8080 npm install\n```\n\nYou can disable this behaviour by adding `public.dhe.ibm.com` to the `NO_PROXY` environment variable. The following\ncommand will not use the proxy to download the redistributable libraries:\n\n```\n% NO_PROXY=\"public.dhe.ibm.com\" HTTPS_PROXY=http://localhost:8080 npm install\n```\n\nAlternatively, you can simply `unset HTTPS_PROXY`.\n\n### MacOS\nThe MQ client package for MacOS can be found at\n[this site](https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqdev/mactoolkit). Download a\nsuitable version and install it in a local directory. The package is signed, and is not a simple tar/zip format. The\nenvironment variable `DYLD_LIBRARY_PATH` then should be set to the lib64 directory within that tree before running the\nprogram.\n\nFor example\n\n`export DYLD_LIBRARY_PATH=/opt/mqm/lib64`\n\nThe MacOS client is also now available via the `brew` command. See [here](https://github.com/ibm-messaging/homebrew-ibmmq)\nfor instructions on configuring your system for downloads using this mechanism.\n\n#### Errors and warnings during build\nIf you get an error message such as \"gyp: No Xcode or CLT version detected\" while running `npm install` you may need to\ninstall the developer tools. Usually the command `xcode-select --install` will deal with this.\n\n### Other platforms\nFor other MQ-supported platforms and environments, the C runtime can be installed from your MQ installation media, or\nfrom the full Client downloads at [this site](https://www.ibm.com/support/fixcentral/swg/selectFixes?parent=ibm~WebSphere\u0026product=ibm/WebSphere/WebSphere+MQ\u0026platform=All\u0026function=fixid\u0026fixids=*-IBM-MQC-*).\n\nThe Redistributable Client packages for Windows and Linux x64 are also available directly from\n[this site](https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqdev/redist).\n\nThis package cannot currently run on z/OS as the prerequisite MQ libraries are not available there in the same way as\nother platforms. However, it might be possible in future to add that platform as there are no dependencies on 3rd party\nnon-core components (eg lib-ffi) that would never be available on z/OS.\n\n## Sample applications\nSee the samples [README](samples/README.md) file for more information about the sample programs.\n\n## Containers\n\nThe samples directory includes a Dockerfile that can be used as the basis of generating an independent container to run\nMQ programs. The **run.docker** script builds and executes the container. Environment variables are used in the\nDockerfile and the script to control connection to the queue manager.\n\n## Documentation\n\nThe package contains JSDoc comments that can be formatted using the **makedoc** script in the root directory. The\ngenerated documentation is then accessible via a web browser.\n\n## TypeScript\n\nThe package includes a set of type definitions, suitable for use with TypeScript programs. Some of the sample programs\nhave also been converted to use types. See the `samples/typescript` directory. These definitions have been tested with\nthe `tsc` compiler, the `ts-node` front-end, and inside the VSCode IDE.\n\n\n### Bitwise vs Array Options fields\n\nTo help with syntax checking, many of the fields in the MQI that are normally set with bitwise operations (for example,\n`pmo.Options = MQPMO_SYNCPOINT|MQPMO_NEW_CORREL_ID`) can also be set using an array syntax such as\n`pmo.Options = [MQPMO_SYNCPOINT, MQPMO_NEW_CORREL_ID]`. Once you make a choice in your application on which style to\nuse, you should stay consistent throughout the program. If input to an MQI function uses arrays, then the field will\nstill be an array on return from the function. It doesn't change shape within the MQI call. But sometimes you may still\nneed an explicit definition as the fields are defined as having either a number or an array type and the compiler may\nnot know which it is set to at some places when it needs to validate the code.\n\nIf you are using the array format, then any elements with the real value 0 will not show up in the array after an MQI\ncall. For example, `MQPMO_NONE` would not be in the array following an MQPUT call even if you had set it in the original\narray.\n\n\nInterrogating and modifying the options fields has to be done by being explicit about how the field is being used. For\nexample,\n\n```\n  pmo.Options = [MQC.MQPMO_NO_SYNCPOINT, MQC.MQPMO_NEW_MSG_ID, MQC.MQPMO_NEW_CORREL_ID];\n  mq.PutSync( ... )\n\n  var opts = pmo.Options as mq.MQC_MQPMO[]; // Be explicit\n  if (opts.includes(MQC.MQPMO_SYNCPOINT)) {\n    console.log(\"Array includes value SYNCPOINT\");\n  } else {\n    console.log(\"Array does not include value SYNCPOINT\");\n  }\n```\n\nand an example from the `amqsbra.ts`example where we use the bitwise operations to modify a field:\n\n```\n  gmo!.Options = ((gmo!.Options as number) \u0026 ~MQC.MQGMO_BROWSE_FIRST);\n  gmo!.Options = (gmo!.Options | MQC.MQGMO_BROWSE_NEXT);\n```\n\n## Support for OpenTelemetry Tracing\nIf your application is using OTel tracing, then context for traces/spans can be propagated through MQ messages as work\nmoves between applications. There should be no need for applications to change for this MQ transfer to happen; available\nOTel libraries are automatically recognised and used. See comments in `lib/mqiotel.js` for more information.\n\nThe only MQI extension is the optional use of an `OtelOpts.RemoveRFH2` flag on the MQGMO structure.\n\n## History\n\nSee [CHANGES](CHANGES.md).\n\n## Health Warning\n\nThis package is provided as-is with no guarantees of support or updates. You cannot use IBM formal support channels\n(Cases/PMRs) for assistance with material in this repository.\n\nbased on any feedback. Versioned releases are made in this repository to assist with using stable APIs. Future versions\nThere are also no guarantees of compatibility with any future versions of the package; the API is subject to change\nwill follow semver guidance so that breaking changes will only be done with a new major version number.\n\n## Issues and Contributions\n\nFor feedback and issues relating specifically to this package, please use the\n[GitHub issue tracker](https://github.com/ibm-messaging/mq-mqi-nodejs/issues).\n\nContributions to this package can be accepted under the terms of the Developer's Certificate of Origin, found in the\n[DCO file](DCO1.1.txt) of this repository. When submitting a pull request, you must include a statement stating you\naccept the terms in the DCO.\n\n\n## Acknowledgements\nThanks to the IBM App Connect team for the initial implementation of the asynchronous MQI variations. Their work has\nbeen adopted and adapted into this library.\n\nThanks to Andre Asselin for the TypeScript definitions and sample program conversions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibm-messaging%2Fmq-mqi-nodejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fibm-messaging%2Fmq-mqi-nodejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibm-messaging%2Fmq-mqi-nodejs/lists"}