# Serenji - Getting Started

Serenji from George James Software (GJS) is an extension for Visual Studio Code (VSCode), allowing you to edit and debug InterSystems ObjectScript code directly in the namespaces where that code executes. No exporting and importing of files is necessary.

Serenji includes an embedded edition of the Deltanji source code management product from GJS. A separate VSCode extension integrates Deltanji with VSCode as a source control provider that you can interact with from the Source Control viewlet. Contact GJS for more information about that extension. You can also access Serenji's embedded Deltanji through its web browser UI.

# Installation

Use the Extensions viewlet in VSCode (Ctrl/⌘+Shift+X) to search for Serenji and install it.

Alternatively, download it as a VSIX file from https://georgejames.com/files/vscode-serenji-3.0.2.vsix and use the "..." menubutton in upper right corner of the Extensions viewlet to choose "Install from VSIX..."

To edit and debug code on an InterSystems environment you must first prepare it. Eligible environments must be running InterSystems IRIS Data Platform (herafter abbreviated as 'IRIS'), or Cache, Ensemble or HealthShare. The minimum InterSystems version supported by the standard extension kit is 2009.1. If you need support for earlier versions, email support@georgejames.com for advice.

## Install the Serenji software

The following instructions apply to all supported environments. They should also be followed to upgrade Serenji software on environments previously set up for use with an earlier version of this extension.

References to IRIS apply equally to Caché, Ensemble and HealthShare environments.

Proceed as follows:

2. Unzip it. The zip contains a filetree rooted in a directory called Serenji.

3. Move the unzipped Serenji directory to where you want the software to be located long-term. On a Windows host this could be C:\Serenji. We recommend you avoid putting it under C:\Program Files\ as, depending on your exact configuration, that location may cause permission issues during the installation.

4. Open a Terminal session in IRIS, authenticating as a user with maximum privileges (e.g. holding the %All role), such as SuperUser. This level of permission is necessary so that the install script can add a namespace, a database and a web application to your IRIS configuration.

5. Optionally, enable terminal logging in case you have installation problems and need advice from GJS. If you are using InterSystems Terminal use the Logging... option on Terminal's File menu.

The next step imports and compiles a class called Serenji.Installer. This contains a classmethod that you will later run to create a database for the Serenji code and the embedded Deltanji source control repository. The Serenji.Installer class can be loaded into any existing namespace. We suggest you use the USER namespace if it is available.

1. Switch to the USER namespace. Load and compile the class from the Serenji.Installer.xml file in the directory of your unpacked Serenji kit, e.g.

%SYS>zn "USER"

USER>d $system.OBJ.Load("C:\Serenji\Serenji.Installer.xml","c") 2. Now invoke its RunInstall method, passing as a parameter the path to the root of your Serenji kit, e.g. USER>d ##class(Serenji.Installer).RunInstall("C:\Serenji\") 3. When this completes, turn off terminal logging if you previously enabled it. 4. Review the output for any error messages. If you are unsure whether the installation succeeded, contact support@georgejames.com 5. You may now tidy up by deleting the Serenji.Installer class from the namespace you imported and ran it in, e.g. USER>d$system.OBJ.Delete("Serenji.Installer.cls")

6. If your target environment is a failover member of an InterSystems mirroring configuration you will probably want to add the SERENJI database, namespace and other settings to the other failover member so that it can host your editing and debugging whenever it takes over as master.

## Start the Serenji Service

The Serenji Service is an ObjectScript process (%Serenj830) that must be running before the Serenji extension can connect VSCode to that InterSystems environment.

Start it in the SERENJI namespace which was created when you installed the Serenji software on the environment. An interactive startup asks what port it should listen on (default is 43211) and what port range to use for the inbound data connection (default is the single port 43212):

USER>zn "serenji"

SERENJI>d Service^%Serenji

Tips:

• For a silent start on the previously-chosen ports: do ServiceStart^%Serenji or job ServiceStart^%Serenji
• To stop the service: do ServiceStop^%Serenji
• To test whether it is running: Write ServiceStatus^%Serenji
• If you intend to use Serenji's debug features then the $USERNAME that the service process runs as must hold WRITE permission on the resource protecting the CACHESYS / IRISSYS database. This permission allows it to call$SYSTEM.Security.Login(user) without a password after getting user from the client-side keyfile.
• The service process usually appears in your system status display as the routine %Serenj830.

# Configure your Visual Studio Code client for editing

## Add a User Setting to define a connection

Add a section of JSON to User Settings. One way to access this is:

• Open the VSCode Command Palette, e.g. by typing F1 or Ctrl/⌘+Shift+P
• Locate the command Preferences: Open Settings (JSON) and execute it

Below is an example of a connection definition for a local InterSystems environment running the Serenji Service on port 43211:

    "serenji.servers": {
"tin.iris181": {
"host": "127.0.0.1",
"port": 43211,
},
},


Highlight the above block. Copy it using Ctrl/⌘+C. Position the cursor at the end of line 1 of your settings.json file. Press Enter to add a new line. Paste using Ctrl/⌘+V.

• In the above example the connection name is tin.iris181 which is a lowercase variant of the $SYSTEM variable of the target environment, with . substituted for :. This is our recommended naming convention. You can name your connections other ways if you prefer, but connection names must consist only of lowercase a to z, digits, underscore, minus and dot characters. • username and password will be used to negotiate InterSystems security (equivalent to authenticating from Portal, Studio, Atelier etc). On a target environment installed with the Minimal Security option, default valid credentials suitable for use here are SuperUser and SYS as shown. • If the username element is omitted or set to "" you will be prompted to enter one upon first connection to the target in a VSCode session. • The user account must hold the SerenjiUser role or the %All role. • Omit the password element if you don't want to store it in plaintext in your VSCode Settings file. You will then be prompted for your password the first time it is needed in a VSCode session. Remember to save the modified settings.json file (Ctrl/⌘+S). ## Create a VSCode workspace A workspace specifies which server(s) you will work on, and which namespace(s). 1. Start with no workspace open (i.e. close any currently open one via 'File\Close Workspace' or Ctrl/⌘+K followed by F). 2. Open the VSCode Command Palette, e.g. by typing F1 or Ctrl/⌘+Shift+P 3. Run Serenji: Add Folder to Workspace 4. Choose the server you previously added to User Settings, e.g. tin.iris181 5. If the server definition doesn't specify a namespace, optionally enter one when prompted. Or leave that field empty if you want the workspace to access all namespaces on the server. 6. If prompted for your password (because you omitted it from User Settings), enter it. 7. Save the workspace (File\Save Workspace As...), then close and reopen it. A quirk of VSCode means that unless you do this the set of workspace-specific settings received from the InterSystems environment will not be correctly activated. ## Explore and edit code In the VSCode Explorer viewlet (Ctrl/⌘+Shift+E) expand the workspace tree. If you didn't restrict your folder to a single namespace, expand one of the listed namespaces to find routines and classes that you can open. Any changes you make to them here will be written to the namespace as soon as you save them within VSCode. Compilation happens immediately after saving, and compilation errors appear in the Problems panel. The tree does not show generated code (e.g. INTs generated from CLS or MAC definitions), or code that is not stored in the namespace's default database (mapped code). Consider enabling VSCode breadcrumbs via the View menu so you can easily jump to methods, properties and line labels in your code. The Outline section of VSCode Explorer also lets you do this, and the '...' button on the Outline header gives you extra control of the order in which the items appear. To create a new class or routine, right-click at the appropriate place in the tree (e.g. on the desired namespace if your folder is giving you a multi-namespace view of your server), then choose 'New File'. Enter the required name, which must include the appropriate suffix (.cls, .mac, .inc or .int). The initial contents of a new file come from one of the template files that are located in the .serenji subfolder of your workspace root. You can edit these templates. You can also create copies of these in the XXX\.serenji subfolder of your XXX namespace if you need namespace-specific templates for new files. To help with class editing Serenji provides default snippets which add properties and methods. Access these as usual in VSCode by typing Ctrl/⌘+space, then start typing method or property. After selecting a snippet, use the Tab key to move between fields within it. A class or routine can be deleted from within VSCode. Be aware that this action will immediately delete the item from the namespace on your server. CAUTION: VSCode might misleadingly advise you that it is going to move the document to the Trash / Recycle Bin and that you will be able to restore it from there. This is cause by a VSCode bug. In fact the deletion will be permanent, with no way of undoing it. One way of protecting your server code is to register it for management by the Deltanji source control bundled with Serenji. You can launch the Deltanji UI from the Command Palette using Serenji: Open Deltanji in Web Browser. # Configure your Visual Studio Code client for debugging To use the debug features of Serenji you will need a keyfile issued by George James Software. Each keyfile unlocks debugging for a named user on a specific InterSystems environment. Without a keyfile you can only use Serenji to view and edit code. Keyfiles are only issued for identifiable individuals. They are not available for generic usernames such as 'Admin', 'SuperUser', '_SYSTEM' etc. ## Obtain a debug key 1. Connect Serenji to the target environment using the username you want to debug as. This user will require the %Development:Use privilege. This typically comes from the user having been assigned the %Developer role. 2. Expand the workspace root, e.g 'Serenji: tin.iris181' 3. Expand the .serenji folder. 4. Open the file named registrationData.txt (the contents are generated dynamically when opened). 5. Copy the contents of this file into an email to admin@georgejames.com requesting a Serenji key. Please give your email the subject line Serenji License Key request. An example of the contents:  Version: 3.0.0 Username: me HostKey: lYOmLEHkf8DTsC3CxoUKpJR5ums System: TIN:IRIS181 Platform: IRIS for Windows (x86-64) 2018.1.2 (Build 609U) Now: 2019-03-05T16:58:49+00:00  If your registration data indicated that your InterSystems environment is mirrored, also include in your email the Serenji registration data from the failover member (if you have one) by logging into Terminal with the same username and then running the following command in the SERENJI namespace of the failover environment: Do ^%Serenji 6. Wait for an email response telling you how to collect your keyfile. Please note that the response is manually created by GJS personnel during UK business hours. 7. Follow the instructions in that email to download your keyfile and save it. ## Tell VSCode where to find your keyfile Add a license object property to the entry you previously defined in serenji.servers in your User Settings (JSON view). For example, if you named your Serenji connection tin.iris181 and you saved your keyfile as C:\Users\me\Documents\SerenjiKeys\me-TIN-IRIS181.p12 your augmented serenji.servers setting should look something like this: "serenji.servers": { "tin.iris181": { "host": "127.0.0.1", "port": 43211, "username": "me", "password": "secret", "license": { "keyfile": "C:\\Users\\me\\Documents\\SerenjiKeys\\me-TIN-IRIS181.p12" } }, },  Note how backslashes must be doubled in JSON string values. # Debugging Serenji uses native InterSystems debug facilities, and these require INT code to exist. In view of this, when you edit and save a class or a routine with Serenji the post-save compile retains INT code by default. However if you want to debug code that hasn't been changed through Serenji you may first need to recompile it and specify the "k" flag for the compilation. ## Launch a routine for debugging 1. In the Debug viewlet (Ctrl/⌘+Shift+D) use the configuration selector dropdown to choose a 'Routine' entry. Then click the adjacent green 'go' button. 2. If prompted for a namespace, enter one e.g. USER (this can also be entered in lowercase). 3. When prompted for an execution startpoint, enter a simple one for your initial testing, e.g. INT^%T 4. The target code will load and execution will suspend at the startpoint you specified. 5. Use VSCode's standard debug facilities. ## Debug a classmethod 1. In the Debug viewlet (Ctrl/⌘+Shift+D) use the configuration selector dropdown to choose a 'ClassMethod' entry. Then click the adjacent green 'go' button. 2. If prompted for a namespace, enter one e.g. USER (this can also be entered in lowercase). 3. When prompted for an execution startpoint, enter a string in the format Package.Class.ClassMethod() e.g. %Library.PopulateUtils.City(). This format is more concise than the conventional ##class format. 4. The target code will load and execution will suspend at the startpoint you specified. 5. Use VSCode's standard debug facilities. ## Debug a running process 1. In the Debug viewlet (Ctrl/⌘+Shift+D) use the configuration selector dropdown to choose an 'Existing Process' entry. Then click the adjacent green 'go' button. 2. When prompted, enter the PID ($JOB number) of the process you want to debug.
3. When that process executes its next command Serenji will attempt to start debugging it.
4. Use VSCode's standard debug facilities.

# Troubleshooting

• VSCode must be able to connect to the ports the Serenji Service listens on. By default these are 43211 and 43212. Make sure no firewalls are blocking these for incoming connections.
• If your IRIS target is running in a Docker container you must publish the Serenji Service ports to the same ports on the Docker host, for example by adding --publish 43211-43212:43211-43212 to your docker run command. You must also set the global node ^%Serenjvc("ftpServer","serverAddress") so it contains the IPv4 address at which VSCode can reach your Docker host. In the simple case where you are running VSCode on the Docker host, the following command in the SERENJI namespace is suitable: set ^%Serenjvc("ftpServer","serverAddress")="127.0.0.1"
• During server-side installation, if you aren't able to fetch the zipfile from the George James Software website, you can find an alternative copy in the targets subdirectory of the directory where the Serenji extension was installed by VSCode. On Windows the user named me would typically find it in C:\Users\me\.vscode\extensions\georgejames.vscode-serenji-x.y.z\targets\ and on Linux and macOS it will typically be in ~/.vscode/extensions/georgejames.vscode-serenji-x.y.z/targets/

# Next Steps

You may wish to take some of the following extra steps.

## Autostart the Serenji Service

Add code to your InterSystems environment that will autostart the Serenji Service process on startup. We recommend using the SYSTEM^%ZSTART entrypoint on non-mirrored environments and NotifyBecomePrimary^ZMIRROR (in %SYS) on mirrored ones.

Suggested code fragments:

%ZSTART    ; Custom startup logic suitable for non-mirrored environments
; See https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GSTU_customize#GSTU_customize_startstop
q
;
SYSTEM	;This subroutine is called during system startup
; Start the Serenji Service
try {
j ServiceStart^%Serenji|"SERENJI"|
}
catch e {
d ##class(%SYS.System).WriteToConsoleLog("SYSTEM^%ZSTART error: "_e.AsSystemError(),,1)
}
q


or

ZMIRROR    ; Custom logic for specific mirroring events
; See https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GHA_mirror#GHA_mirror_set_tunable_params_zmirror_routine
q
;
NotifyBecomePrimary() PUBLIC {
; This procedure is called as a notification when this system becomes Primary
; It does not return any value

; Start the Serenji Service on the primary system
try {
j ServiceStart^%Serenji|"SERENJI"|
}
catch e {
d ##class(%SYS.System).WriteToConsoleLog("NotifyBecomePrimary^ZMIRROR error: "_e.AsSystemError(),,1)
}
q
}


When you used the Command Picker to add a folder to your workspace, your workspace settings file was given an entry like this:

"folders": [
{
"uri": "serenji://tin.iris181/",
"name": "Serenji: tin.iris181"
}
],


By editing the workspace JSON directly you can change the display name of the root folder.

You can suffix a folder URI with a namespace name in order to constrain the folder to a single namespace. This happens automatically if you enter a namespace name when running the Serenji: Add Folder to Workspace command, in which case the name property is also suffixed with the namespace name.

You can also use the serenji-readonly scheme in a folder URI instead of the serenji scheme, resulting in readonly access to everything under that folder. In addition the serenji-readonly scheme doesn't filter out generated or mapped files (e.g. INTs generated from CLS and MAC files, or code mapped from another database).

Examples of these techniques are shown below:

"folders": [
{
"uri": "serenji://tin.iris181/SAMPLES",
"name": "Serenji: tin.iris181 SAMPLES"
},
{
"name": "Readonly view of SAMPLES on IRIS181 (generated or mapped code not filtered out)"
},
{
"uri": "serenji://tin.iris181/",
"name": "Serenji: tin.iris181"
}
],


Notice how you can amend the root name, and can dedicate a root to a single namespace if you want.

## Install your own server certificate

When debugging, communication with the Serenji Service is always done over a secure socket connection. When you installed Serenji on your InterSystems environment an SSL/TLS configuration entry named 'Serenji' was created, using a generic self-signed certificate file and unpassworded private key file that is bundled with the Serenji kit. This is done for convenience, since the arrangement is sufficient to enable VSCode to connect for debugging. However the use of a publicly-shared private key leaves the network trafic vulnerable to decryption by anyone in possession of that key. It also means the the VSCode client does not verify the identity of the server it connects to.

To protect debug network traffic against decryption by third parties, go to 'System Administration > Security > SSL/TLS Configurations' in Portal. Edit the 'Serenji' entry, changing the fields in the section titled "This server's credentials" so as to make it use your own certificate and private key.

# Uninstalling

To remove Serenji's components from an InterSystems server, deleting any information recorded by the embedded Deltanji, do the following:

1. Stop the Serenji Service process: do ServiceStop^%Serenji

2. Note what directory the embedded Deltanji was installed in. You can find this in the global node ^%Serenjvc("programFiles") in the SERENJI namespace:

SERENJI>write ^%Serenjvc("programFiles")

3. In Portal use System Administration > Configuration > Additional Settings > Source Control to reset to NONE the source control class of each namespace you previously put under the control of this Deltanji instance. The old setting for these namespaces will be SerenjiStudio.SourceControl or SerenjiStudio.SourceControl.Ensemble.

4. For each namespace you put under Deltanji's control, plus for the %SYS namespace, use System Administration > Configuration > System Configuration > Namespaces to review mappings defined on the %ALL pseudo-namespace for globals, rountes and packages. Remove all mappings directed to the SERENJI database. Remember to save the changes.

5. Use System Administration > Configuration > System Configuration > Local Databases to delete the SERENJI database. Review the confirmation page to make sure that your action will only affect the SERENJI namespace. If any other namespaces are listed here, stop and consult support@georgejames.com. Provided only the SERENJI namespace is listed on the delete dialog, check the box alongside it and also check the box to allow deletion of the database file. Click the "Finish" button to proceed with the deletion.

6. If local databases SERENJIENSTEMP and SERENJISECONDARY exist, delete these as well.

7. Use System Administration > Security > Roles to delete the %DB_SERENJI and SerenjiUser roles, plus the %DB_SERENJISECONDARY role if it exists.

8. Use System Administration > Security > Resources to delete the %DB_SERENJI resource, plus the %DB_SERENJISECONDARY resource if it exists.

9. Use System Administration > Security > Web Applications to delete the /serenji/deltanji application if it remains.

10. In each namespace Serenji's Deltanji was controlling, delete the ^Serenjvp global.

11. If you previously added code into the %ZSTART routine in the %SYS namespace to autostart the Serenji Service process, remove that code.

12. Verify that a restart of your InterSystems environment works correctly.

13. Delete the Serenji parent directory of the Deltanji installation directory that you identified in step #1.