Skip to content

03. IPM Manifest (Module.xml)

isc-kiyer edited this page Nov 12, 2024 · 10 revisions

Module.xml example

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
  <Document name="demo-module.ZPM">
    <Module>
      <Name>demo-module</Name>
      <Version>1.0.0</Version>
      <Description>description</Description>
      <Keywords>keywords</Keywords>
      <Author>
        <Person>your name</Person>
        <Organization>your organization</Organization>
        <CopyrightDate>2020</CopyrightDate>
        <License>MIT</License>
        <Notes>notes</Notes>
      </Author>
      <Packaging>module</Packaging>
      <Dependencies>
        <ModuleReference>
          <Name>MDX2JSON</Name>
          <Version>2.2.*</Version>
        </ModuleReference>
      </Dependencies>
      <Default Name="count" Value="7" />       
      <SystemRequirements Version=">=2020.1" Interoperability="enabled" />
      <SourcesRoot>src</SourcesRoot>
      <Resource Name="Demo.PKG"/>
      <Resource Name="REST.Dispatch.CLS"/>
      <Resource Name="Demo.test.GBL"/>
      <Resource Name="Myapp.MAC" Directory="newmac"/>
      <FileCopy Name="lib/" Target="${libdir}my-lib/"/>
      <FileCopy Name="somefile.jar" Target="${libdir}my-lib/"/>
      <UnitTest Name="/tests/unit_tests/" Package="Test.Unit" Phase="test"/>
      <SystemSetting Name="CSP.DefaultFileCharset" Value="UTF-8"/>
      <Invoke Class="Demo.First" Method="Populate"></Invoke>
      <Invoke Class="Demo.First" Method="Populate">
        <Arg>${count}</Arg>
        <Arg>test string</Arg>
      </Invoke>
      <Invoke Class="%EnsembleMgr" Method="EnableNamespace" Phase="Compile" When="Before" CheckStatus="true">
         <Arg>${namespace}</Arg>
         <Arg>${verbose}</Arg>
      </Invoke>

      <CSPApplication
        Url="/hello"
        SourcePath="/src/csp"
        DeployPath="${cspdir}rest-test"
        ServeFiles="1"
        Recurse="1"
        CookiePath="/hello"
        UseCookies="2"
        MatchRoles=":${dbrole}"
        PasswordAuthEnabled="1"
        UnauthenticatedEnabled="0"
       />

       <CSPApplication 
        Url="/rest-test"
        Recurse="1"
        MatchRoles=":${dbrole}"
        PasswordAuthEnabled="1"
        UnauthenticatedEnabled="0"
        DispatchClass="REST.Dispatch"
        ServeFiles="1"
        CookiePath="/rest-test"
        UseCookies="2"
       />
    <AfterInstallMessage>Module installed successfully! To start call USER>Do ##class(Package.Class).Run()</AfterInstallMessage>     
    </Module>    
  </Document>
</Export>


Elements

<Export generator="Cache" version="25">

The root element

<Document>

In name attribute specify your module name with .ZPM suffix
<Document name="demo-module.ZPM">

<Module>

contains all module metadata elements

<Name>

Module name, avoid whitespace characters
<Name>demo-module</Name>

<Version>

Module version
<Version>1.0.0</Version>

<Dependencies>

Module dependencies; specify each dependent module in <ModuleReference> element.
In dependant module Version element you can specify an exact version (1.2.36) or use asterisk.
<Version>2.2.*</Version> - means the latest version grater than 2.2.0 and less then 2.3.0
<Version>*</Version> - means the latest version

<Default>

Custom parameter with its default values
You can use these parameters to transfer data to the module installer during installation. If you define a parameter
<Default Name="count" Value="7" />
you can pass a parameter value in install or load command zpm: USER>install demo-module -Dzpm.count=12

<SystemRequirements>

Use Version attribute to specify IRIS versions, supported by your module.
Use Interoperability attribute to indicate that your module requires Interoperability.
<SystemRequirements Version=">=2020.1" Interoperability="enabled" />

<SourcesRoot>

Specify the directory where code of the module is placed
This element is required
<SourcesRoot>src</SourcesRoot>

<Resource>

Use the following suffixes for different types of resources:

  • .PKG - Package
  • .CLS - Class
  • .INC - Include
  • .MAC - Routine
  • .LOC - LocalizedErrorMessages
  • .GBL - Global
  • .DFI - DeepSee Item
  • <nosuffix> - document

Attributes

  • Deploy
    • If set to true, this resource is not shipped in application packaging.
  • Directory
    • Directory the resource is located in. If not specified, uses the default folders in /src.
      • /cls - for Classes (.PKG, CLS)
      • /mac - for Routines
      • /inc - for Include
    • Example:
        <SourcesRoot>src</SourcesRoot>
        <Resource Name="REST.Dispatch.CLS" />
        <Resource Name="Myapp.MAC" Directory="newmac"/>
    
  • Flags
    • Compile flags (see documentation here)
    • Example: <Resource Name="MyPackage.PKG" Flags="cku"/>
  • Generated
    • Specify if this resource is generated. A generated resource will not be loaded nor exported by lifecycle methods.
  • Name
    • Name of the resource (required)
    • Examples:
      • <Resource Name="MyPackage.objectscript.PKG"/>
      • <Resource Name="MyPackage.MyFile.INC"/>
      • <Resource Name="/doc/README.txt"/>
  • Preload
    • Specify if this resource is in the preload directory to be loaded before other resources. Useful for installers.
    • Example:
      • <Resource Name="MyPackage.Installer.CLS" Preload="true"/>
  • ProcessorClass
    • Specifies a class that handles lifecycle events for this resource.
    • Typically only applicable to directory/file resources.
    • See here for options
  • Scope
    • Restricts the scope in which this resource is included. Default is all scopes.
    • Options:
      • test
      • verify

Custom Attributes

If additional/custom name-value pairs are required, they can be specified as attributes of the resource, e.g.

  <Resource Name="MyPackage.PKG">
    <Attribute Name="CustomAttribute">SomeValue</Attribute>
    <Attribute Name="SomeBoolean">1</Attribute>
    <Attribute Name="AnotherSetting">25</Attribute>
  </Resource>

<Invoke>

Each <Invoke> indicates which Class Method should be called at a specified phase (e.g. during installation)
Specify method arguments with <Arg> if necessary. Values in <Arg> can be either primitives or system expressions.

<Invoke Class="%EnsembleMgr" Method="EnableNamespace" Phase="Compile" When="Before" CheckStatus="true">
     <Arg>${namespace}</Arg>
     <Arg>${verbose}</Arg>
</Invoke>

Invoke attributes:

  • Class (required): Class for which method is to be run.
  • Method (required): Name of class method to run.
  • CheckStatus (Default: false): expects that invoked method returns %Status, and use it to check the status of installation.
  • Phase (Default: Configure): the phase during which it should be executed.
  • CustomPhase (as of v1): If provided, the Phase property will be ignored. This CustomPhase will be used and no corresponding lifecycle is required. This can be used to run a custom phase of a module that does not run during any regular OOTB IPM command (e.g. if you want to run your custom phase my-phase, you can do so using the command - zpm "MyModule my-phase").
  • When (Default: After), values: Before and After: To execute before or after the main execution for the phase.

<AfterInstallMessage>

AfterInstallMessage tag is intended to message package users next steps after successful installation. This message will appear in terminal after all the package's resources processing. It should be placed insude <Module> tag. Example: <AfterInstallMessage>Module installed successfully! To start call USER>Do ##class(Package.Class).Run()</AfterInstallMessage>

Custom Localized Strings Example

The ^IRIS.msg global can be automatically populated using .LOC resources. (See here for more information on usage of the global within IRIS.)

module.xml

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
  <Document name="loc-example.ZPM">
    <Module>
      <Name>loc-example</Name>
      <Version>1.0.0</Version>
      <Packaging>module</Packaging>
      <SourcesRoot>src</SourcesRoot>
      <Resource Name="My.Errors.LOC"/>
      <Resource Name="en.loc"/>
    </Module>
  </Document>
</Export>

src\localize\en.xml

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="IRIS" version="26">
  <Document name="demo.LOC">
    <MsgFile Language="en">
      <MsgDomain Domain="myapp">
        <Message Id="Information">Some Information</Message>
        <Message Id="Description">Some Description</Message>
      </MsgDomain>
    </MsgFile>
  </Document>
</Export>

src\localize\My\Errors.xml

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="IRIS" version="26">
  <Document name="My.Errors.LOC">
    <MsgFile Language="en">
      <MsgDomain Domain="MyErr">
        <Message Id="CustomError">Value %1 is invalid</Message>
      </MsgDomain>
    </MsgFile>
  </Document>
</Export>

Result After Installing

^IRIS.Msg("MyErr","en","CustomError")="Value %1 is invalid"
^IRIS.Msg("myapp","en","Description")="Some Description"
^IRIS.Msg("myapp","en","Information")="Some Information"

Globals Resource Example

Globals can be added to a package using a .GBL resource in module.xml and adding an appropriate .xml file in the src/gbl directory.

module.xml

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
  <Document name="globals-test.ZPM">
    <Module>
      <Name>globals-test</Name>
      <Version>1.0.0</Version>
      <Packaging>module</Packaging>
      <SourcesRoot>src</SourcesRoot>
      <Resource Name="My.Settings.GBL"/>
    </Module>
  </Document>
</Export>

src/gbl/My.Settings.xml

<?xml version="1.0" encoding="UTF-8"?>
<Export generator="IRIS" version="26">
<Global>
<Node><Sub>^My.Settings</Sub>
    <Node><Sub>Mode</Sub>
        <Data>Example</Data>
    </Node>
    <Node><Sub>Parameter</Sub>
        <Data>42</Data>
    </Node>
</Node>
</Global>
</Export>

Result After Installing

^My.Settings("Mode")="Example"
^My.Settings("Parameter")=42

System Expressions

Case-insensitive expressions that can be used in strings. Note that the $ symbol in the expression can be located either inside or outside the curly braces, e.g. {$ns} is equivalent to ${ns}.

  • {name} - the name of the current resource. Notice that it doesn't have a $ sign.

  • ${ns} - the current namespace.

  • ${namespace} - the current namespace.

  • ${namespaceLower} - the current namespace in lower case.

  • ${namespaceRoutineDB} - the default routines database for the current namespace.

  • ${namespaceGlobalsDB} - the default globals database for the current namespace.

  • ${installDir} - the instance's install directory (i.e. $System.Util.InstallDirectory())

  • ${dataDir} - the instance's data directory (i.e. $System.Util.DataDirectory())

  • ${mgrDir} - the instance's mgr directory (i.e. ##class(%Library.File).ManagerDirectory())

  • ${cspDir} - the instance's root CSP directory (i.e. $System.Util.InstallDirectory()_"csp")

  • ${binDir} - the instance's bin directory (i.e. $System.Util.BinaryDirectory())

  • ${libDir} - the instance's lib directory (i.e. $System.Util.InstallDirectory()_"lib")

  • ${webroot} - the instance's constructed url with host and port (e.g. http://123.45.678.90:52773/)

  • ${dbrole} - (deprecated in favor of ${globalsDbRole}) the current namespace's globals database role

  • ${globalsDbRole} - the current namespace's globals database role, functionally equivalent to ${dbrole} in legacy packages.

  • ${root} - the resource module's root directory

  • ${packagename} - the name of the package

  • ${version} - the version string of the package

  • In particular, you can also $$$macros will be expanded. But the macro cannot contain any arguments. For example, $$$OK will be expanded to 1, while $$$ThrowOnError(##class(xxx).yyy()) won't be correctly handled.

Examples:

  • If the install directory is C:\InterSystems\IRIS\, then ${installDir} evaluates to C:\InterSystems\IRIS\, ${cspDir} evaluates to C:\InterSystems\IRIS\CSP, and ${libDir} evaluates to C:\InterSystems\IRIS\lib
  • Resource attributes can make use of these expressions like this:
<Resource Name="MyResource">
  <Attribute Name="Directory">${cspdir}${namespace}/my-directory</Attribute>
</Resource>

Resource Processors

Resource processors can always be specified using the <Resource name=MyName ProcessorClass=MyProcessorClass> syntax, but default resource processors (listed below) can be specified using the <<processor-class>> syntax, e.g. <UnitTest> and <CSPApplication>.

Copy

  • Copies the specified resource from the (Source) database to the target namespace (respecting mappings configured for that namespace) during the Reload phase.
  • Attributes
    • Source - name of the namespace to be copied from (required)
    • Overwrite - if set to false (default is true), resources that already exist in the current/target namespace will not be overwritten

CSPApplication

Each <CSPApplication> defines a web application.

For CSP/ZEN applications required attributes:

  • Url - application name
  • Path - source folder with .csp files
  • Directory - destination directory (to which files will be copied during installation)

For REST applications required attributes:

  • Url - application name
  • DispatchClass - class name

Use attributes as they are described for <CSPApplication> tag here

Grant attribute is replaced by MatchRoles.

Mapping of Match Roles to added Target Roles.
MatchRoles are in the format:
MatchRole:TargetRole1:TargetRole2
To specify a role to always be granted to an application, set MatchRole="", i.e. (:TargetRole1)

Additional attributes that can be used instead of AuthenticationMethods:

  • PasswordAuthEnabled
  • UnauthenticatedEnabled
  • DelegatedAuthEnabled
  • KerberosAuthEnabled

Additional attributes

  • Enabled
  • DeepSeeEnabled
  • iKnowEnabled

FileCopy

  • Copies the specified directory or file (the resource name) to a specific target location (InstallDirectory) during the Activate phase.
  • Attributes:
    • InstallDirectory (or Target or Dest) - Path to which the directory or file (a full filename, in that case) should be copied upon installation; may contain expressions
    • Overlay - If true, the files should be added to the target location (rather than fully replacing it, causing other files there to be deleted). Relevant for directories only.
    • CSPApplication - Optional hint to source control class: which CSP application path do these files map to? For use cases where the CSPApplication resource processor is too heavy-handed - e.g., /csp/xslt. Of course, this is only relevant for files that need to be copied to a CSP application. Note that this may be a full CSP file path, not only the name of a CSP application.
    • Defer - If true, the files will be copied at the end of the Activate phase rather than at the beginning. The default is to copy the files at the beginning of the Activate phase. Use this for build artifacts.
  • Examples
    • <FileCopy Name="lib/" Target="${libdir}my-lib/"/>
      Copies content of lib folder to Target

    • <FileCopy Name="somefile.jar" Target="${libdir}my-lib/"/>
      Copies just desired file to Target

    • You can use ${libdir} or ${bindir} for installdir/lib and installdir/bin respectively. See the System Expressions section for more details.

    • If the Name ends with a slash, it will be copied as a folder. During uninstall, the Target folder will be deleted
      <FileCopy Name="dsw/" Target="${cspdir}dsw/configs/"/>

LegacyLocalizedMessages

  • Processes a message dictionary export of error message names, generating an include file with macros to represent them.
  • Alternative to Default.LocalizedMessages, which is automatically used for .LOC files.
  • Attributes
    • includeFiles - Acceptable Formats:
      • <include file name>
      • <domain>:<include file name>[,<domain>:<include file name>[,<domain>:<include file name>...]]
    • merge - Set to 1 to merge the domain (i.e., in ^IRIS.Msg(domain)/^IRIS.MsgNames(domain)) with contents loaded from other error message XML files. Additional work will likely be required to make the domain available for localization in such cases, likely using the LocalizationExport resource processor.

LocalizationExport

  • Resource processor to automatically export messages in given list of domains to a particular file after compilation
  • This works with a resource like /localize/MessageFileName.xml (Domains attribute required; resource name used as export target), or MyPackage.Errors.LOC (Filename attribute required; Domains populated automatically from the message file)
  • For .LOC resources, the default resource processor class (%IPM.ResourceProcessor.Default.LocalizedMessages) should be used instead.

ModuleExport

  • In the Activate phase, exports the in-database code resources of this module (classes, routines, include files) as a Studio project in a single XML file.
  • Attributes
    • TargetFile - file to which the module should be exported (required)

<UnitTest> or <Test>

Specifies the unit tests to be loaded and run. In development mode modules, unit tests are always loaded and not deleted after they are run.

  • Package - the package containing the unit tests
  • Class - the class containing the unit tests (note: either Package or Class must be defined)
  • Name - the directory that the package or class is located in
    • e.g. for <UnitTest Name="/tests/unit_tests/" Package="Test.Unit" Phase="test"/>, the unit tests will in /test/unit_tests/Test/Unit/
  • Phase - the phase the tests will run in
    • test: development namespace
    • verify: new, separate, clean namespace
    • test,verify: run in both cases

Different unit tests can be specified for different phases:

<UnitTest Name="/tests/unit_tests/" Package="Test.Unit" Phase="test"/>
<UnitTest Name="/tests/integration_tests/" Package="Test.Integration" Phase="verify"/>

These tests can be run using test <module> for test phase tests and verify <module> for verify phase tests.