URSYS Addons Framework - dsriseah/ursys GitHub Wiki

Concept

Addons live in the _ur_addons directory as "mini projects" that can import the @ursys/core library and build more specialized features. They're designed for both command line and browser use.

An addon directory is used for self-contained features that are built around "pure data" or "utility data transformation" that is written in platform-independent Typescript. This library can be imported directly on the server-side using an "entryfile" that lives in addon directory (see COMMAND LINE USE below) or exported as a package "@ursys/addons" library for both server and client platforms by adding it to @addon-client.ts or @addon-server.mts respectively.

Walkthrough

Let's add an addon directory to work in!

  1. open a VSCODE integrated terminal and cd _ur
  2. open another VSCODE integrated terminal and cd _ur_addons
  3. create an empty directory foo inside _ur_addons

In the _ur terminal, type ur by itself. You'll see that the 'foo' addon has been added. If you type ur foo, you will get an error because there is no "entryfile". Let's fix that!

  1. in the foo directory, create the file @foo-test.mts

Back in the _ur terminal, type ur foo and you will no longer see an error, though nothing interesting is happening. Let's add a console.log statement

  1. open @foo-test.mts and add console.log(process.argv)

Now when you type ur foo, you'll see the arguments that have been passed to @foo-test.mts when it was forked. Try adding more arguments to the command line:

ur foo this --flag=poop "Sally Johnson"

You'll see that all the arguments are passed from the command line to your @foo-test.mts script. You could parse these commands to do different things based on what you've passed.

Now let's create and import a typescript library.

  1. create a file inside foo called bar-lib.ts. Add the lines:
    • export function Bar() { console.log('barbar'); }
  2. in @foo-test.mts:
    • at the top add import pkg_bar from './bar-lib.ts'
    • add const {Bar} = pkg; next.
    • at the bottom, add Bar();

NOTE: if you're not familiar with Typescript, bear with this for now. Step 7's instructions are due to the imperfect meshing of Typescript with NodeJS at this time.

Now when you type ur foo, you'll see barbar also appear.

Finally, let's add a second entry point, which is useful for when you want to use the libraries in different ways, or perhaps want to include an entirely different utility inside your foo addon.

  1. In the foo directory, create the file @zoop.cjs (note the different extension).

When you type ur foo, the system will find the first alphabetically-listed file in the directory that begins with @. To run the new entry point, use this syntax:

ur foo@zoop

You'll see that nothing is really happening, because there is nothing in the @zoom.cjs file unless you added something yourself! Since this is a CommonJS file (evidenced by the .cjs extension), we can use the old-style NodeJS syntax for importing modules.

  1. In @zoom.cjs add these lines:
    • const { PR } = require('@ursys/core');
    • const TERM = PR('ZoopCJS','TagBlue');
    • TERM('Hello from @zoop.cjs');

Now when you type ur foo@zoop, you'll see some formatted text in the terminal.

A few things to note:

  • A .cjs file uses require module syntax (commonjs module)
  • A .mts file uses import module syntax (typescript module)

Tip

The various nuances of cross-compatibility between the four kinds of Node JS files, Typescript, and different platform contexts is extremely confusing. If you are also learning Typescript, it is even more confusing. It's not just you!

User Reference

COMMAND LINE USE

The ur command line utility executes from within the _ur directory. It scans the _ur_addons directory for addons; these are simply directories that don't have a leading underscore. For example. to run the command-line version of an addon in the _ur_addons/midi directory, you'd type:

ur midi

You can also just type ur by itself and it will list the directories it finds in _ur_addons.

The ur utility looks inside the addon subdirectory for directories, skipping ones that begin with an underscore. It then looks for the first matching file that begins with @; these are "entryfiles" that will be forked as an independent process. You can also specifiy which entryfile if you like. For example:

ur foo         
ur foo@entryfile

Currently we are using .mts (node typescript modules) for our entry files. You do not need to include the extension when designating the entryfile.

BUNDLING FOR LIBRARY USE

After you've written your pure Typescript implementation, you can include it in one of two files:

  • _ur_addons/@addon-client.ts - the client-side entry point for bundle generation
  • _ur_addons/@addon-server.mts - the server-side entry point for bundle generation

You would write a platform-specific library that wraps your pure typescript library for the specific needs of that platform, or choose to export it directly. The bundling operation is handled by the ur build command, creating files according to the _ur_addons/package.json exports and mainfiles properties. The libraries are exported in multiple formats for UMD, CommonJS, AMD, and ESM uses.

To use the library, you currently have to install it as a dependency using file: urls. For example, if you have the _ur and _ur_addons directories in your main app with its own package.json in the root, you would add the packages as follows:

npm i @ursys/core ../_ur
npm i @ursys/addons ../_ur_addons

After this, you should be able to require or import the @ursys/core and @ursys/addon libraries into your codebase. The method you use depends on what build system your main app uses. URSYS has its own self-contained build system that is independent of yours.

TROUBLESHOOTING

Q. Why are my import * as UR from '@ursys/core' statements showing red? It still runs! A. This might be because of Visual Studio's Typescript Language Server being confused. If you don't see any obvious path errors (missing .ts extension, wrong number of .., etc), try resaving the _ur_addons/tsconfig.json file to see if it goes away; this forces the internals to refresh...we think. Even opening the tsconfig.json file will invalidate all types...we think.

⚠️ **GitHub.com Fallback** ⚠️