|
| 1 | +# Extending Zowe Explorer for IBM CICS Transaction Server |
| 2 | + |
| 3 | +A set of APIs is exposed from the Zowe Explorer for IBM CICS TS VS Code extension to allow extenders to interact with, and add functionality to, the set of supported CICS resources. |
| 4 | + |
| 5 | +## Context Menu Contribution |
| 6 | + |
| 7 | +A straight forward way for extenders to contribute actions to CICS Resources would be to add context menu items to the resources in the CICS tree inside Zowe Explorer. |
| 8 | + |
| 9 | +VS Code uses the [contributes section of the package.json](https://code.visualstudio.com/api/references/contribution-points#contributes.menus) to specify when actions should be visible on a tree item. |
| 10 | + |
| 11 | +Inside `contributes.menus.view/item/context`, a block can be added to add your existing command to a CICS tree item using the `viewItem =~` pattern. |
| 12 | + |
| 13 | +### Example Context Menu |
| 14 | + |
| 15 | +1. Below is an example that adds a command to CICS Program tree items. |
| 16 | + |
| 17 | +```json |
| 18 | +"contributes": { |
| 19 | + "commands": [ |
| 20 | + { |
| 21 | + "command": "my-extension-id.extensionDoesThingsToACICSProgram", |
| 22 | + "title": "Make Changes to my CICS Program", |
| 23 | + "category": "My Custom Extension" |
| 24 | + }, |
| 25 | + ], |
| 26 | + "menus": { |
| 27 | + "view/item/context": [ |
| 28 | + { |
| 29 | + "when": "view == cics-view && viewItem =~ /^CICSResourceNode.CICSProgram.*/ && !listMultiSelection", |
| 30 | + "command": "my-extension-id.extensionDoesThingsToACICSProgram", |
| 31 | + "group": "Extenders" |
| 32 | + }, |
| 33 | + ] |
| 34 | + } |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +2. This is an example that adds a command to CICS Local File tree items representing ENABLED Local Files. |
| 39 | + |
| 40 | +```json |
| 41 | +"contributes": { |
| 42 | + "commands": [ |
| 43 | + { |
| 44 | + "command": "my-extension-id.actionOnEnabledLocalFile", |
| 45 | + "title": "Perform action on Enabled Local File", |
| 46 | + "category": "My Custom Extension" |
| 47 | + }, |
| 48 | + ], |
| 49 | + "menus": { |
| 50 | + "view/item/context": [ |
| 51 | + { |
| 52 | + "when": "view == cics-view && viewItem =~ /^CICSResourceNode.CICSLocalFile.ENABLED.*/", |
| 53 | + "command": "my-extension-id.actionOnEnabledLocalFile", |
| 54 | + "group": "Extenders" |
| 55 | + } |
| 56 | + ] |
| 57 | + } |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +## Obtaining the Extender API |
| 62 | + |
| 63 | +An independent NPM package is available containing all the interfaces relevant to an extender, alongside a helper method to conveniently import them. |
| 64 | + |
| 65 | +To install the API package, run |
| 66 | + |
| 67 | +```sh |
| 68 | +npm install @zowe/cics-for-zowe-explorer-api |
| 69 | +``` |
| 70 | + |
| 71 | +Then to use the APIs, import the utilities and run the getter. |
| 72 | + |
| 73 | +```typescript |
| 74 | +import { getCICSForZoweExplorerAPI, IExtensionAPI } from "@zowe/cics-for-zowe-explorer-api"; |
| 75 | + |
| 76 | +export async function activate(ctx) { |
| 77 | + ... |
| 78 | + const cicsAPI: IExtensionAPI | undefined = await getCICSForZoweExplorerAPI("3.13.0"); |
| 79 | + ... |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +The `getCICSForZoweExplorerAPI` method takes an optional minimum version parameter that you can provide if a certain level of the Zowe Explorer for IBM CICS TS extension is required for your extension. |
| 84 | + |
| 85 | +If the specified version requirement is met, and the APIs exist, an object implementing the `IExtensionAPI` interface is returned. |
| 86 | + |
| 87 | +## Available Actions |
| 88 | + |
| 89 | +### Extending a Resource |
| 90 | + |
| 91 | +A Resource Extender class is available in the API to register actions that will be available on the specified resource type. |
| 92 | + |
| 93 | +Here, we'll create an action using the `ResourceAction` class, and register it using the API's `resources.resourceExtender.registerAction` method. |
| 94 | + |
| 95 | +```typescript |
| 96 | +import { getCICSForZoweExplorerAPI, IExtensionAPI, IResourceAction, ResourceTypes } from "@zowe/cics-for-zowe-explorer-api"; |
| 97 | + |
| 98 | +const cicsAPI: IExtensionAPI | undefined = await getCICSForZoweExplorerAPI("3.13.0"); |
| 99 | + |
| 100 | +const myCustomResourceAction = new ResourceAction({ |
| 101 | + id: "MY.UNIQUE.ACTION.ID", |
| 102 | + name: "Name to appear in action menus", |
| 103 | + resourceType: ResourceTypes.CICSLocalFile, |
| 104 | + action: "command.available.to.vscode", |
| 105 | +}); |
| 106 | + |
| 107 | +cicsAPI.resources.resourceExtender.registerAction(myCustomResourceAction); |
| 108 | +``` |
| 109 | + |
| 110 | +Mandatory fields that must be supplied when creating an action are: |
| 111 | + |
| 112 | +- `id`: A unique ID for this action, used for registering and removing it. |
| 113 | +- `name`: The human-readible name for the action that appears in any action menus. |
| 114 | +- `resourceType`: Specifies which CICS resources it should be available to run against. |
| 115 | +- `action`: The action to perform. This can take either of the following forms, but the same data about the resource is provided to both: |
| 116 | + - String - a command ID already registered with VS Code. |
| 117 | + - Function - a function that is called with data passed to it about the resource. |
| 118 | + |
| 119 | +Optional fields available to adapt the behaviour of the action: |
| 120 | + |
| 121 | +- `visibleWhen` - A function that takes the resource and context as arguments, that determines if the action is applicable and should show. |
| 122 | + |
| 123 | +There are two inputs to the `visibleWhen` and `action` methods. |
| 124 | + |
| 125 | +1. The resource itself, containing attributes of the CICS resource - an example being `IProgram` for a CICS Program resource. |
| 126 | +2. The resource context, containing information about where the resource is installed, including a CICSplex name if applicable, CICS region name, and the Zowe profile used to retrieve it. |
| 127 | + |
| 128 | +Note: The type of the resource parameter is dictated by the `resourceType` paramter of your `ResourceAction`. This means creating an action with `resourceType: ResourceTypes.CICSLocalFile` will result in the resource passed to your `action` and `visibleWhen` methods being of type `ILocalFile`. View the examples below to see how these paramters can be used by your action. |
| 129 | + |
| 130 | +### Examples |
| 131 | + |
| 132 | +1. Extending a CICS Local File |
| 133 | + |
| 134 | +```typescript |
| 135 | +import { getCICSForZoweExplorerAPI, IExtensionAPI, IResourceAction, ResourceTypes } from "@zowe/cics-for-zowe-explorer-api"; |
| 136 | + |
| 137 | +export async function activate(ctx) { |
| 138 | + const cicsAPI: IExtensionAPI | undefined = await getCICSForZoweExplorerAPI("3.13.0"); |
| 139 | + |
| 140 | + const myCustomResourceAction = new ResourceAction({ |
| 141 | + id: "MY.UNIQUE.ACTION.ID", |
| 142 | + name: "Name to appear in action menus", |
| 143 | + resourceType: ResourceTypes.CICSLocalFile, |
| 144 | + action: "command.available.to.vscode", |
| 145 | + }); |
| 146 | + |
| 147 | + cicsAPI.resources.resourceExtender.registerAction(myCustomResourceAction); |
| 148 | +} |
| 149 | +``` |
| 150 | + |
| 151 | +2. Run a custom function when a CICS Program is enabled |
| 152 | + |
| 153 | +This examples utilises the `visibleWhen` field to only show the action when the CICS Program is enabled, as well as passing a custom function to `action` to log information about the resource and it's context. |
| 154 | + |
| 155 | +```typescript |
| 156 | +import { |
| 157 | + getCICSForZoweExplorerAPI, |
| 158 | + IExtensionAPI, |
| 159 | + IProgram, |
| 160 | + IResourceAction, |
| 161 | + IResourceContext, |
| 162 | + ResourceTypes, |
| 163 | +} from "@zowe/cics-for-zowe-explorer-api"; |
| 164 | + |
| 165 | +export async function activate(ctx) { |
| 166 | + const cicsAPI: IExtensionAPI | undefined = await getCICSForZoweExplorerAPI("3.13.0"); |
| 167 | + |
| 168 | + const myResourceLoggingAction = new ResourceAction({ |
| 169 | + id: "CUSTOM.ENABLED.PROGRAM.FUNCTIOn", |
| 170 | + name: "Log resource and resource context information", |
| 171 | + |
| 172 | + resourceType: ResourceTypes.CICSProgram, |
| 173 | + |
| 174 | + visibleWhen: (resource: IProgram, context: IResourceContext) => { |
| 175 | + return resource.status === "ENABLED"; |
| 176 | + }, |
| 177 | + |
| 178 | + action: (resource: IProgram, context: IResourceContext) => { |
| 179 | + console.log(resource.program); |
| 180 | + console.log(context.cicsplexName, context.regionName); |
| 181 | + }, |
| 182 | + }); |
| 183 | + |
| 184 | + cicsAPI.resources.resourceExtender.registerAction(myResourceLoggingAction); |
| 185 | +} |
| 186 | +``` |
| 187 | + |
| 188 | +Note: the `resource` paramter of the `action` method is strongly typed as `IProgram` because the `resourceType` attribute is set to `ResourceTypes.CICSProgram`. |
| 189 | + |
| 190 | +3. Run a VS Code command registered elsewhere with some additional arguments from the CICS resource. |
| 191 | + |
| 192 | +This example shows the flexibility that comes with writing your own action functions. You have access to the resource and resource context information, but can process it or manipulate it in some way before passing it to an existing VS Code command. This use case is useful for extenders that have existing functionality that they wish to trigger from Zowe Explorer for IBM CICS TS. |
| 193 | + |
| 194 | +```typescript |
| 195 | +import { getCICSForZoweExplorerAPI, IExtensionAPI, ITask, ResourceAction, IResourceContext, ResourceTypes } from "@zowe/cics-for-zowe-explorer-api"; |
| 196 | +import * as vscode from "vscode"; |
| 197 | + |
| 198 | +export async function activate(ctx) { |
| 199 | + vscode.commands.registerCommand("MY.CICSTASK.COMMAND", (cicsTaskId: string, cicsTranId: string, cicsRegionName: string, val: number) => { |
| 200 | + console.log(`${val}: Transaction ${cicsTranId} running with task ID ${cicsTaskId} in region ${cicsRegionName}`); |
| 201 | + }); |
| 202 | + |
| 203 | + const cicsAPI: IExtensionAPI | undefined = await getCICSForZoweExplorerAPI("3.13.0"); |
| 204 | + |
| 205 | + if (cicsAPI) { |
| 206 | + const myResourceLoggingAction = new ResourceAction({ |
| 207 | + id: "MY.CICSTASK.CUSTOM.ACTION", |
| 208 | + name: "Run my own builtin command for my tasks", |
| 209 | + resourceType: ResourceTypes.CICSTask, |
| 210 | + |
| 211 | + action: async (resource: ITask, context: IResourceContext) => { |
| 212 | + const val = Math.round(Math.random() * 100); |
| 213 | + const taskID = resource.task; |
| 214 | + const tranID = resource.tranid; |
| 215 | + const regionName = context.regionName; |
| 216 | + |
| 217 | + await vscode.commands.executeCommand("MY.CICSTASK.COMMAND", taskID, tranID, regionName, val); |
| 218 | + }, |
| 219 | + }); |
| 220 | + |
| 221 | + cicsAPI.resources.resourceExtender.registerAction(myResourceLoggingAction); |
| 222 | + } |
| 223 | +} |
| 224 | +``` |
0 commit comments