Sequence Development Guide for TypeScript and JavaScript


Scramjet's Sequences are usually the user's source code with all its required dependencies packed and ready to be uploaded and executed on the Scramjet Cloud Platform. With this set of algorithmic steps, a Sequence can produce, consume and transform data by enhancing its abilities through the Scramjet Framework. Scramjet's Sequences iterate over data on demand asynchronously. The following sections will ensure a proper buildup of a Sequence with all its requirements ready to be executed on Scramjet's Cloud Platform. In this section, You as a user will be guided through a series of steps to ensure the execution of your Typescript/JavaScript Sequence successfully on the Scramjet Cloud Platform.

For demonstrational purposes, Scramjet's audio2text typescript sample found on GitHub demonstrates the integration of AssemblyAI code for speech recognition in a Scramjet Sequence which can be run by a user through the below command. A user must include their AssemblyAI token once executing the start Sequence command. As a reminder escaping the quotation marks is a must for this command. For more information on si command-lines check CLI reference section.

si sequence start <Sequence-id> --args [\"<AssemblyAI-token>\"]

And for retrieving the transcribed text of the audio file a user can use either si output command or output API endpoint. For more information on API endpoints check API reference section.

si instance output <Instance-id>

Handler

Scramjet Cloud Platform using the following method to process the context argument in order to return a response which can be also used by other sequences. keeping in mind that Events can be triggered while a Sequence is running and Topics can be produced and consumed as part of a Sequence.

const { PassThrough } = require("stream"); module.exports = async function(input) { const output = new PassThrough(); // your code here, you can also process an input stream return output; // return stream value };

AppContext

By running the asynchronous function on SCP, the object of this interface is passed through to the Application context which allows it to communicate with Scramjet Cloud Platform to ensure that it's in operation and should be kept alive without interruption. Methods of the class AppContext will be invoked only once the Sequence is uploaded and run on SCP. AppContext methods will not work properly if the Sequence is run on your local machine unless being run though STH. Available methods of this class can be found on Scramjet's GitHub repository.

Packaging

For a Sequence to be deployed on Scramjet Cloud Platform (SCP), the script and all its dependencies must be packed in a tar.gz file before being uploaded to SCP. One or multiple files must be included in the same directory in order for a Sequence to be packed. the following points are the basic structural components required for a Sequence to be run on SCP. In the case of TypeScript running npm run Build is mandatory to transpile .ts files to .js before packing a Sequence. Samples and Templates are found under the Example section.

  • index.js - The main file with the user's logic

  • Files - In case the user's Sequence requires any additional files it is mandatory to add those files to the same directory alongside the rest of requirements.

  • Dependencies - All dependencies that are needed to execute the Sequence. Dependencies must be in the same directory alongside the rest of required files which will be packed as a Sequence.

  • package.json - The manifest file that describes this particular Sequence.

    To create a package.json file with the values that you supply, use the following command-line
    npm init - creates a new package.json file with elementary properties. Contains prompts about the project , such as the name, version, etc. for more information on package.json. A brief illustration is shown in the below section.

    { "name": "SequenceName", "version": "0.23.0", "main": "./index", "author": "USER", "license": "GPL-3.0", "description": "what is it about", "keywords": [ "streaming", "data transformation", "Data Transformer" ], "repository": { "type": "git", "url": "https://github.com/" }, "engines": { "node": "^18.0.0" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "tsc -p tsconfig.json", "postbuild": "cp -r package.json dist/ && (cd dist && npm i --only=production) && cp src/utils/song.wav dist/utils && cp src/utils/config.json dist/utils ", "pack": "si seq pack ./dist/", "clean": "rm -rf ./dist ./*.tar.gz" }, "assets": [ "song.wav" ], "dependencies": { "@scramjet/utility": "^0.33.5", "@types/node": "^18.16.2", "axios": "^1.3.6", "date-and-time": "^2.4.3", "typescript": "^5.0.4" } }
  • tsconfig.json - The indicator file for TypeScript.

    It is a crucial file for managing your project, it creates itself after running tsc --init command, which initializes the TypeScript project. This file is where you can set the compiler options. Basically this is an indicator for TypeScript, which says that the project in which this file lies and all the other sub folders should be managed by TypeScript and it also tells Typescript how to compile all the *.ts files in the project

    { "compilerOptions": { "lib": [ "ESNext" ], "target": "ESNext", "module": "CommonJS", "outDir": "./dist", "esModuleInterop": true, "skipLibCheck": true, "resolveJsonModule": true, } }

Deploy

A user can manually pack a Sequence in the form of a tar.gz file by using
si sequence pack <path/to/folder/dist> command and then send a Sequence to the Scramjet Cloud Platform by using
si sequence send <path/to/filename.tar.gz> command. Or a user can deploy a Sequence on SCP by using the deploy command
si sequence deploy|run [options] <path/to/folder> which will pack, send and start the Sequence in one go and return both Sequence and Instance ids. In case for TypeScript after transpiling deploy command should point out to the ./dist folder
si sequence deploy|run [options] <path/to/folder/dist>
More information is found under the CLI reference section.

Logs

Scramjet Cloud Platform is constantly monitoring the user's Sequence, and producing log output for a Sequence which can be accessible. Details of each invoked Sequence can be viewed through different methods. More information on Scramjet's object-logger .

  • SCP Console Panel > Space > Show logs > Download

  • Returns the log through calling the logger method inside the index.js file. In order to be retrieved use
    /instance/<Instance-id>/log API endpoint. The below example will provide a brief illustration.

    import { ReadableApp } from "@scramjet/types"; const app: ReadableApp<string> = async function(_stream) { // Write to a instance logger. first parameter could be any on the following list: // Logger has the following log levels: // - **debug** // - **error** // - **fatal** // - **info** // - **trace** // - **warn** this.logger.write("INFO", "this is info log"); return Promise.resolve("end"); }; export default app;
  • Returns the log through calling the Error class inside the index.js file. In order to be retrieved through
    /instance/<Instance-id>/stderr API endpoint, or through CLI as si instance stderr <Instance-id>. The below example will provide a brief illustration.

    import { ReadableApp } from "@scramjet/types"; const app: ReadableApp<string> = async function(_stream) { // This will write an error message to stderr const err = new Error("The Sequence was not completed"); console.error(err); return Promise.resolve("end"); }; export default app;
  • For displaying the content through console.log a user can use /instance/<Instance-id>/stdout API endpoint, or through CLI as
    si instance stdout <Instance-id>. The below example will provide a brief illustration.

    import { ReadableApp } from "@scramjet/types"; ​ const app: ReadableApp<string> = async function(_stream) { // This will write to a stdout const random = Math.random(); ​ console.log(random); ​ return Promise.resolve("end"); }; ​ export default app;

Events

Scramjet facilitates the communication between Instances through an asynchronous way of handling and responding to events. Scramjet's Runner uses EventEmitter to propagate Event messages between Scramjet's API and a Sequence. An event follows a publish-subscribe pattern, where the object emitting the event is known as the publisher, and the objects listening for the event are known as subscribers or listeners. When an event occurs, the listener will execute a callback function within an Instance or trigger further actions based on the event, whether it is a communication with other Instances or passing a payload to an event callback function.
Overall, Scramjet's Sequences are designed to be event-driven, communicating with each other if necessary, to enhance flexibility and extensibility. The below example will provide a brief illustration on how events are triggered. The two event methods that can be used in the Sequence are:

  • emit is used to trigger an event in an Instance. The emitted event can be accessed by using /instance/<Instance-id>/event API endpoint or through SDK InstanceClient.

  • on is used to add a callback function that will to be executed in an Instance when the event is received. This method can be executed by sending a named Event with the required payload to the Instance using /instance/<Instance-id>/_event API endpoint or through SDK InstanceClient.

import { InertApp } from "@scramjet/types"; const mod = async function(_stream) { this.on("test-event", async (message) => { this.emit("emitted-event", `reply to ${message}`) }); await new Promise(res => setTimeout(res, 60000)); } as InertApp; export default mod;

Was it helpful?

Didn't find information needed?

Join our Scramjet Community on Discord, where you can get help from our engineers directly.