Publishing Packages

1. Licensing

1.1. https://tatin.dev

If you want to publish packages to the Principal Tatin server (https://tatin.dev) then your package must carry a property license, and its value must be one of the licenses listed on the web page. All licenses that will be accepted offer a great deal of freedom to a user of a package: there are almost no restrictions.

Note that the same holds true for the test server (https://test.tatin.dev)

1.2. Your own server

If you want to run your own server then you can do whatever you like, of course. The document “Server — Tips and Tricks” offers details.

2. Groups, names and version numbers

A package ID consists of at least three parts:

Optionally such an ID may also comprehend a build number that is separated from the version number by a plus (+).

2.1. The Group

A group can be anything really:

Once you have chosen a group name, and published a package with that group name to the principal Tatin Registry, you are advised to create a “home page” for that group. Use that for anything useful like background, motivation, contact details, whatever.

When a group is listed in a browser, the name of a group is converted into a link to that home page.

Of course, group-related home pages do not always make sense, therefore by default they are not active; see GroupHomePages in the INI file.

2.2. The name

The name should give the user an idea of what a package might do. Group+name must be unique, but you might well use a name that is already used under a different group name, though this is not recommended.

2.3. The version number

The version number must consist of three parts separated by dots:

Optionally additional information might be added. Examples are:

There is one restriction: a + cannot be part of the name of a beta version. The reason for that is that finally a build number might be added to a version number, and a build number is separated from the rest of the version number by a plus (+) character. Examples:

Build numbers are mostly not shown by Tatin.

3. Precondition: API key

Whether you want to publish to the principal Tatin server at https://tatin.dev or your own Tatin Server or a Tatin Server that someone in your company runs, first you need an API key. “API key” is just a fancy expression for a password that is used by an application.

API keys are required for publishing — and possibly deleting — packages, but not for consuming them.

They are saved in the user settings — for details see the document “Tatin User Settings”.

3.1. The Server

3.1.1. The principal Tatin Server

If you want to publish on https://tatin.dev you need to ask info@tatin.dev for an API key.

You must provide these pieces of information:

First step after receiving an API key


After having received an API key you must first create a home page for your group name on the server. Only then can you start publishing packages.

3.1.2. Credentials for the Tatin Test Server

The Tatin Test Server publishes an API key on its website; it's “Tatin-Test-API-Key”. It allows you to publish anything you want, including any group name except a few reserved group names: “aplteam” and “dyalog”.

Notes:

3.1.3. Where are API keys saved?

3.1.3.1. Client

API keys are saved in the user settings file. The quickest and yet safe way to edit that file is via the user command:

      ]TatIN.UserSettings -edit
3.1.3.2. Server

Credentials are saved in the file “Credentials.csv” in the Registry's home folder.

3.1.4. Credentials for your own Tatin Server

If you run your own Tatin Server, we suggest that you create a UUID and use that as an API key.

For an API key to be accepted by a Tatin Server, it must be added to a file Credentials.txt in the Registry's root directory.

Make sure that you specify it as either

<group-name>,<api-key>

or

*,<api-key>

If the server finds such a file it will perform the following actions:

The format of the file Credentials.csv is:

<group-name>,<api-key-hash>,<salt>
*,<api-key-hash>,<salt>
*

The different scenarios can be mixed:

group1,<hash1,<salt1>
group2,<hash2,<salt2>
*,{hash3>,<salt3>

This means that one can only publish packages with the group name…

and anything else by using the API key “hash3” was created from.

Note that * or*, or *= all mean that no API key is required. On its own, it's the same as having no credentials file, but it can be useful together with other group names:

<group1>,<hash1>
<group2>,<hash2>
*

This is interpreted as “require API keys for the groups <group1> and <group2> but allow anything else without an API key”.

Finally, you can allow anybody to publish packages under a particular group name without providing an API key:

<group1>,<hash1>,<email-address>
<group2>,
*,<hash3>

This means:

3.1.4.1. Editing the file “Credentials.csv”

There is one reason why you might need to change the file Credentials.csv: when a group name must be deleted for some reason.

If a new group needs to be added, or a new API key needs to be assigned to an existing group, you must create a file Credentials.txt, see above.

3.1.4.2. Comments

The files Credentials.txt as well as Credentials.csv both allow comment lines: any line that has a ; as the very first character is regarded a comment.

4. Publishing

4.1. Preparing

4.1.1. How to structure a package

A Tatin package requires all source code (functions, operators, classes, interfaces and namespace scripts) to be separated from other files (like CSS files, EXEs, DLLs etc.).

Tatin calls the former “source” and the latter “assets”.

4.1.2. The package configuration file

The file apl-package.json must exist in order to make a folder a package.

What is required and how to create and change a package configuration file is discussed in the document PackageConfiguration.

4.1.3. The dependency file

The file apl-dependencies.txt is only required when a package depends on other packages.

Dependencies may by installed in a package project in different ways:

Information

In case you specify a dependency that has not (yet) been published, then this has no consequences: the server will not reject such a package.

That might come as a surprise, but there is a reason for this: when a bunch of packages is published then there might well be mutual or worse circular dependencies. Insisting on dependencies already being published would not work then.

Usually, you will specify just a full package ID as a dependency. If you wish you may also specify either a URL following the http[s]:// protocol or a zip file following the file:// protocol. The latter is always a temporary solution, however.

Notes:

4.2. Final step

Once the preparation is done the final step is easy. Specify the folder hosting the package:

]TATIN.PublishPackage /path2package [tatin]

The folder may or may not carry a trailing slash (/).

This would attempt to publish the package found in path2package/ to the principal Tatin Server.

You can also build a new version by calling ]TATIN.BuildPackage (or its aquivalent, the API-function BuildPackage) and specify the resulting ZIP file as an argument to PublishPackage:

]TATIN.PublishPackage /path2package/group-name-1.2.3.zip [tatin]

When a path to a package project is provided rather than a ZIP file then ]PublishProject would create the ZIP file itself.

Note that both ]PublishPackage as well as ]BuildPackage assume that if the package about to be published depends on other packages these packages will be installed in a subfolder packages/.

However, if the project is managed by Cider then Tatin investigates the Cider config file. Cider has two properties dependencies.tatin and dependencies_dev.tatin designed to hold the folder with package dependencies, and if one of them is not empty then Tatin would use it, or question the user if both are set and not empty.

If you do not use Cider but want to establish a non-default subfolder (read: not named packages/) as the one holding package dependencies then you must specify the subfolder with the -dependencies= flag.

4.3. User command packages

Packages that are user commands are a special case. Here is why:

User commands must have a user command script — that's what makes them a user command. They can simply be installed as Tatin packages and the job is done. But there is a problem.

The package might look like this:

MyUserCommand/
    APLSource/
        MyUserCommand/        ⍝ Contains the code
        TestData/
        TestCases/
        MyUserCommand.dyalog  ⍝ The user command script
    packages/
        ...
    packages_dev/
        ...
    apl-package.json
    cider.config
    LICENSE
    README

The package configuration parameter source will then read APLSource/MyUserCommand because we don't want TestData/ and TestCases/ to be part of the installed package.

But that would mean that the script MyUserCommand.dyalog would not be installed either, so there is a problem: the script would not make it when the packages are installed. Also, the user command script should live in the root of the package's installation folder, not in a sub folder.

That's why Tatin needs to know that the package is a user command, and where to find its script. This does the trick:

userCommandScript: "APLSource/MyUserCommand.dyalog",

The fact that the parameter exists and is not empty tells Tatin that it is a user command, and the path allows Tatin to first install everything as usual and then move the script to the root of the package installation folder.

The installed package will then consist of:

Note that by definition a package must contain some code. If a user command is implemented as a single script file, which is possible and perfectly fine with simple user commands, this would not be the case. For this reason, it is advisable to separate the user command as such (with the necessary Run, List and Help functions) from the “business logic” that does the real work.

The latter one would remain in the package, fulfilling the requirement.

5. Deleting packages

Whether you can delete a package once it was published depends on the policy the server operates:

Note that anything that carries something that is not a digit after the second dot in the version number and before the build separator “+” qualifies as a beta version.

Examples:

apltree-Foo-1.0.0                 ⍝ Not a beta
apltree-Foo-1.0.0+123             ⍝ Not a beta
apltree-Foo-1.0.0-alpha-1         ⍝ A beta
apltree-Foo-1.0.0-alpha-1+123     ⍝ A beta

You can find out which policy the server operates in two ways:

Or visit its website, for example, https://tatin.dev: at the bottom of the home page the server mentions the “delete” policy it operates.

6. Development strategies

Let's imagine that you are supposed to develop Tatin packages for your employer, the company “XYZ”.

You can now develop a package Foo and publish it on [my], probably several times until it is stable.

You would then publish it on [my-team]. At the same time, you would either delete the package from [my] or, if you want the Registry [my] to be ignored altogether, set its priority to zero.

When all is good the beta is promoted to an official release and published to the Tatin company server. At the same time, the package will most likely be deleted from the Team server.