npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@action-class/core

v1.0.0

Published

Framework to write object oriented GitHub Actions

Downloads

6

Readme

@action-class/core

A library for creating GitHub Actions with a class-based approach.
This library simplifies the process of defining inputs, outputs, and other action properties, as well as handling the pre, main, and post steps of the action.

Installation

npm install @action-class/core

Usage

Create a new GitHub Action class by extending the constructor returned by the action call from '@action-class/core'. Define action properties, inputs, and outputs in the action call argument. To complete a runnable action you need to implement at least a main and optionally a pre, and a post method.

import { action, runAction } from '@action-class/core';

export class ExampleAction extends action({
  name: 'name',
  description: 'description',
  author: 'author',
  branding: {
    color: 'orange',
    icon: 'sunset',
  },
  inputs: {
    // Define your inputs here
  },
  outputs: {
    // Define your outputs here
  },
}) {
  // Define your class properties and constructor here

  async pre(): Promise<void> {
    // Define the pre step logic here
  }

  async main(): Promise<void> {
    // Define the main step logic here
  }

  async post(): Promise<void> {
    // Define the post step logic here
  }
}

// Execute the action with the constructor arguments
runAction(TestAction, 'test');

API

action(options: ActionOptions): constructor

The action function is a higher-order function that takes an ActionOptions object as an argument and returns a class constructor. The ActionOptions object defines the properties, inputs, outputs, and branding for the action.

runAction(ActionClass: Class, ...args: any[]): Promise<void>

The runAction function takes a GitHub Action class and its constructor arguments, then executes the action. This async function needs to be called at the end of the action file and not being awaited.

ActionOptions

  • name (optional): The name of the action. Defaults to the name from the package.json.
  • description (optional): A short description of the action. Defaults to the description from the package.json.
  • author (optional): The author of the action. Defaults to the author from the package.json if present.
  • branding (optional): An object with branding properties for the action. See GitHub branding guidelines for valid values.
  • inputs (optional): An object with the action inputs. See Inputs for more information.
  • outputs (optional): An object with the action outputs. See Outputs for more information.

Inputs and Outputs

The inputs and outputs properties of the ActionOptions object define the inputs and outputs of your GitHub Action. Inputs and outputs are defined using key-value pairs, where the key is the name of the input or output, and the value is an object with specific properties.

Inputs

Inputs are defined in the inputs property of the ActionOptions object. Each input is represented by an object with the following properties:

  • description: A string describing the input.
  • required (optional): A boolean indicating whether the input is required. Defaults to false.
  • defaultValue (optional): The default value for the input if it's not provided.
  • trimWhitespace (optional): A boolean indicating whether to trim whitespace from the input value. Defaults to true.
  • validate (optional): A validation function for the input value. It takes the input value as an argument and returns either true if the value is valid or an error message string if it's not.

As well as maximum of one of the following mutually exclusive properties:

  • type: The data type of the input. Can be one of 'string', 'number', 'boolean', or 'string[]'.
  • converter: An object with fromInput and toInput methods for converting the input value from a string to a custom type and vice versa.
Outputs

Outputs are defined in the outputs property of the ActionOptions object. Each output is represented by an object with the following properties:

  • description: A string describing the output.
  • type (optional): The data type of the output. Can be one of 'string', 'number', 'boolean', or 'string[]'. Defaults to 'string'
  • initValue (optional): The initial value for the output.
  • converter (optional): A conversion function for the output value. It takes the output value as an argument and returns the converted value.
Example
export class ExampleAction extends action({
  inputs: {
    a: { description: 'description a', required: true },
    b: { description: 'description b', trimWhitespace: false, type: 'string[]' },
    c: { description: 'description c', defaultValue: true, type: 'boolean' },
    d: {
      description: 'description d',
      defaultValue: 123,
      validate: (value?: number) => (!!value && value > 0 ? true : 'Value must be greater than 0'),
    },
    e: { description: 'description e', type: 'number', deprecationMessage: 'e is deprecated' },
    f: {
      description: 'description f',
      required: true,
      converter: {
        fromInput: (value: string) => JSON.parse(value) as Repo,
        toInput: (value: Repo) => JSON.stringify(value),
      },
    },
    g: {
      description: 'description g',
      required: true,
      converter: {
        fromInput: (value: string) => new Date(value),
        toInput: (value: Date) => value.toISOString(),
      },
    },
  },
  outputs: {
    a: { description: 'description a' },
    b: { description: 'description b', type: 'boolean' },
    c: { description: 'description c', type: 'number' },
    d: { description: 'description d', converter: (value: Repo) => JSON.stringify(value) },
    e: { description: 'description e', type: 'number', initValue: 123 },
  },
}) {
  /// rest of the action class
}

All input values are evaluated before the main method is called and stored in a readonly inputs property of the action class. The inputs property is an object with the same keys as the inputs property of the ActionOptions. All validations for required inputs and input values are performed during this initialization and error messages are produced if any of the validations fail. If an input marked as deprecated, but a value is supplied by the user, a warning message will be produced.

All output values are stored in a readonly outputs property of the action class. The outputs property is an object with the same keys as the outputs property of the ActionOptions. The outputs property is initialized with the initValue property of each output, if present. When a value is assigned to an output property, the value is converted to a string using the converter property of the output, if present, and automatically send to back to the workflow as the actions output.

export class ExampleAction {
  async main(): Promise<void> {
    console.log(this.inputs);

    this.outputs.a = this.inputs.a;
    this.outputs.b = this.inputs.c;
    this.outputs.c = this.inputs.d;
    this.outputs.d = this.inputs.f;

    console.log(JSON.stringify(this.outputs));
  }
}

Fluent API

Alternatively, you can use the ActionBuilder class to define your action. This class provides a fluent API for defining the action properties, inputs, and outputs.

actionBuilder(): ActionBuilder

The actionBuilder function returns a new ActionBuilder instance.

ActionBuilder

The ActionBuilder class provides a fluent API for defining the action properties, inputs, and outputs.

name(name: string): ActionBuilder

Sets the name of the action.

description(description: string): ActionBuilder

Sets the description of the action.

author(author: string, email?: string): ActionBuilder

Sets the author of the action. If the email argument is provided, it will be added to the author string using the format author <email>.

branding(color: ActionYmlBranding['color'], icon: ActionYmlBranding['icon']): ActionBuilder

Sets the branding properties of the action. The color and icon arguments are restricted to the values defined in GitHub branding guidelines.

input(name: string, description: string, options?: ActionInputOptions): ActionBuilder

Adds an input to the action. The options argument recognizes the same properties as described in Inputs except for description. If the options argument is not provided, the input will be defined as an optional string input.

inputs(inputs: { [name]: ActionInputOptions }): ActionBuilder

Adds multiple inputs to the action. The inputs argument is an object with the input names as keys and the input options as values. This structure is equivalent to the inputs property of the ActionOptions object as described in Inputs.

output(name: string, description: string, options?: ActionOutputOptions): ActionBuilder

Adds an output to the action. The options argument recognizes the same properties as described in Outputs except for description. If the options argument is not provided, the output will be of type string.

outputs(outputs: { [name]: ActionOutputOptions }): ActionBuilder

Adds multiple outputs to the action. The outputs argument is an object with the output names as keys and the output options as values. This structure is equivalent to the outputs property of the ActionOptions object as described in Outputs.

build(): ActionConstructor

Builds the action class and returns it.

Fluent Example

import { actionBuilder } from '@action-class/core';

export class ExampleAction extends actionBuilder()
  .name('name')
  .description('description')
  .author('author')
  .branding('orange', 'sunset')
  .input('a', 'description a', { required: true })
  .input('b', 'description b', { trimWhitespace: false, type: 'string[]' })
  .input('c', 'description c')
  .output('a', 'description a')
  .output('b', 'description b', { type: 'boolean' })
  .build() {
  // Define your class properties and constructor here

  async pre(): Promise<void> {
    // Define the pre step logic here
  }

  async main(): Promise<void> {
    // Define the main step logic here
  }

  async post(): Promise<void> {
    // Define the post step logic here
  }
}

Generating the action.yml with generate-action-yml tool

generate-action-yml is a utility script provided by the '@action-class/action-yml' package. It helps you automatically generate an action.yml file from your action class definition. This ensures that your action's metadata stays in sync with the actual code, reducing the chance of errors and inconsistencies.

To integrate the generate-action-yml tool into your action project, follow these steps:

  1. Add a script to your package.json file that calls the generate-action-yml tool. You'll need to provide the action class name and, optionally, the paths to your package.json and main JavaScript file.

    In your package.json, add the following line under the scripts section:

    {
      "scripts": {
        "action-yml": "generate-action-yml ExampleAction"
      }
    }

    Replace ExampleAction with the name of your action class.

    In this example, the generate-action-yml tool will automatically locate your package.json and main JavaScript file (using the main field in your package.json). If you need to specify custom paths, you can do so using the --package-json | -p and --action-js | -a options:

    {
      "scripts": {
        "action-yml": "generate-action-yml -p <path-to-package-json> -a <path-to-action-js> ExampleAction"
      }
    }

    Replace <path-to-package-json> with the path to your package.json file and <path-to-action-js> with the path to your main JavaScript file relative to the location of the package.json.

  2. Run the script to generate the action.yml file:

    npm run action-yml

    This command will execute the generate-action-yml script and create an action.yml file in the directory of your package.json file. The generated action.yml file will contain the metadata from your action class, such as the name, description, inputs, and outputs.

With the generate-action-yml tool integrated into your action project, you can easily keep your action.yml file up-to-date with your action class definition. Make sure to run the script every time you make changes to your action class to ensure that the action.yml file remains consistent with your code.

License

This library is published under the MIT license.