Skip to main content

Actions

Actions are simple input/output functionality performed as tasks in a scaffold. They are the building blocks of a scaffold and are used to perform a variety of operations, such as copying files, installing npm packages, and more.

More information on how to use actions as part of a scaffold can be found in the Scaffold Tasks documentation.

Philosophy

Actions are fancy functions. You feed it data and it performs an operation. The difference is that actions are wrapped up with convenience methods and have an order of events that are performed.

  • Can be synchronous or asynchronous
  • Base data can be provided upon instantiation, or passed in as an argument on execution

Default Actions

The following actions are available by default when using a scaffold:

NameDescription
contextDetermine if the context of the scaffold is valid
customRun custom logic
file:copyCopy a file
file:modifyModify a file
npm:installInstall npm packages
npm:uninstallUninstall npm packages
path:ensureEnsure a path exists

Usage

Actions are defined in the tasks property of the scaffold. Each action is an object with a type property that defines which action to run.

{
tasks: [
{
type: 'file:copy',
source: 'src/index.js',
target: 'dist/index.js'
}
]
}

Templating

Actions can be templated using the {{ }} syntax. This allows for dynamic values to be passed into the action.

{
tasks: [
{
type: 'file:copy',
source: 'src/{{ name }}.js',
target: 'dist/{{ name }}.js'
}
]
}

Additionally, there is $$ syntax that allows for the swapping of values. This is useful for when you want to replace a value with another value that is part of the data object and retain its type (e.g. boolean, number, array, object, etc.).

{
tasks: [
{
type: 'file:copy',
source: 'src/index.js',
target: '$$name'
}
]
}

Included in the $$ syntax is the ability to set a default value if the value is not found in the data object.

{
tasks: [
{
type: 'file:copy',
source: 'src/index.js',
target: '$$name|default'
}
]
}

To apply a type to the default value, preface it with a type setter.

{
tasks: [
{
type: 'file:copy',
source: 'src/index.js',
target: '$$name',
options: {
overwrite: '$$force|bool:false'
}
}
]
}

The available type setters are:

  • bool
  • int
  • float

Custom Actions

Custom actions can be created by the scaffold author and are added to a scaffold via the actionTypes property.

Custom Action Properties

  • name - The name of the action (required)
  • description - A description of the action
  • startMessage - A message to display when the action starts
  • successMessage - A message to display when the action is successful
  • failureMessage - A message to display when the action fails
  • run - The method that performs the action

Custom Action Usage

Custom actions are defined as classes that extend the ScaffoldAction class. The class must have a run method that performs the action.

import { ScaffoldAction } from '@panda/scaffold'

export class MyScaffoldAction extends ScaffoldAction {
static name = 'my-action'
static description = 'My action'

startMessage = 'Running my action'
successMessage = 'My action ran successfully'
failureMessage = 'My action failed'

async run({
handler,
data = {}
}: {
handler: (data: any, ctx: any) => any
data?: { [key: string]: any }
}, ctx: any) {
if (!handler) throw new Error('No handler() method provided')
return await handler(data, ctx)
}
}

The custom action can then be used in the scaffold.

import { Scaffold } from '@panda/scaffold'
import { MyScaffoldAction } from './my-scaffold-action'

new Scaffold({
actionTypes: {
'my-action': MyScaffoldAction
},
actions: [
{
type: 'my-action',
handler: async (data) => {
// Custom logic
}
}
]
})

Examples

Copy a single file

import { Scaffold } from '@panda/scaffold'

new Scaffold({
tasks: [
{
type: 'file:copy',
source: 'src/index.js',
target: 'dist/index.js'
}
]
})