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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@instantlycreative/pulse

v0.4.3

Published

# Initializing

Readme

Pulse

Initializing

npm add @instantlycreative/pulse

Importing in browser

import { PulseClient } from '@instantlycreative/pulse'

const client = new PulseClient()

Importing in node

import { PulseClient } from '@instantlycreative/pulse'
import crossFetch from 'cross-fetch'
import WebSocket from 'ws'

const client = new PulseClient({
  fetch: crossFetch,
  ws: WebSocket,
})

Usage

Before running any command, you must login:

const { token } = await client.login({ email: '[email protected]', password: 'mypasswd' })
if (token) {
  fs.writeFileSync('~/.pulse.token', token)
}

Alternatively, you can just pass a saved token.

const token = fs.readFileSync('~/.pulse.token', 'utf8')
await client.login({ token })

API

Runtime:

  • docker
  • node14.x
  • node16.x
  • node18.x
  • node20.x
  • python3.8
  • python3.9
  • python3.10
  • python3.11
  • python3.12
  • ruby3.2
  • ruby3.3

login

async login({
  email: string,
  password: string
}): Promise<{
  success: boolean;
  token?: string;
  error?: string
}>

async login({
  token: string
}): Promise<{
  success: boolean;
  token?: string;
  error?: string
}>

get

async get({
  pulseId
}: {
  pulseId: string
}): Promise<{
  success: boolean
  team?: Team
  pulse?: Pulse
  statuses?: Status[]
  error?: string
}>
interface Team {
  id: string
  name: string
  createdByUser: string
  createdAt: Date
  updatedAt: Date
}
interface Pulse {
  id: string
  name: string
  teamId: string
  controllerId: string
  createdAt: Date
  updatedAt: Date
  deletedAt: Date | null
}
interface Status {
  id: string
  pulseId: string
  sequence: number
  status: PulseStatus
  isPaused: boolean
  data: any
  createdAt: Date
  updatedAt: Date
}
export enum PulseStatus {
  CREATED = 'created',
  INITIALIZING = 'initializing',
  INITIALIZED = 'initialized',
  UPDATING = 'updating',
  UPDATED = 'updated',
  WARMING = 'warming',
  READY = 'ready',
  EXECUTING = 'executing',
  STOPPING = 'stopping',
  STOPPED = 'stopped',
  DELETED = 'deleted',
}

create

async create({
  pulseId,      // if not provided, a random id will be generated
  name,
  teamId,
  runtime,
}: {
  pulseId?: string
  name?: string
  teamId: string
  runtime: string
}): Promise<{
  success: boolean;
  pulseId?: string;
  error?: string
}>

fork

async fork({
  pulseId,
  newPulseId,   // if not provided, a random id will be generated
}: {
  pulseId: string
  newPulseId?: string
}): Promise<{
  success: boolean;
  pulseId?: string
  error?: string;
}>

update

async update({
  pulseId,
  name,
  buildOptions, // if runtime supports it, i.e, docker build step args
  execOptions,  // runtime exec options, e.g., "--param" in "node --param /app/script.js"
  execPath,     // entry point, e.g., "/script.js" in "node /script.js", or "/Dockerfile" for "docker" runtime.
  files,        // files to be uploaded to the app directory. cannot be used with "zipFile"
  zipFile,      // zip with the app. will be extracted to /app/ directory. cannot be used with "files"
  initFile,     // initialization script
  envFile,      // .env file
  stdinFile,    // a file that will be used as stdin for the app
  vcpu,         // number of virtual CPUs
  memory,       // memory in MB
  balloon,      // initial balloon size in MB
  autoPause,    // pause the app after it's done executing the user app
  autoShutdown, // shutdown the app after it's done executing the user app
  autoDelete,   // delete the app on shutdown
}: {
  pulseId: string
  name?: string
  buildOptions?: string
  execOptions?: string
  execPath: string
  files?: { [path: string]: string | Buffer | File }
  zipFile?: string | Buffer | File
  initFile?: string | Buffer | File
  envFile?: string | Buffer | File
  stdinFile?: string | Buffer | File
  vcpu?: string
  memory?: string
  balloon?: string
  autoPause?: boolean
  autoShutdown?: boolean
  autoDelete?: boolean
}): Promise<{
  success: boolean;
  accessToken?: string;
  error?: string
}>
export interface File {
  source?: string // path on disk
  content?: string | Buffer
  mode?: number // like 0o755
}

Use accessToken to stream the output using client.stream().

Notes on build and exec options:

  • buildOptions is only used for the docker runtime.
  • execOptions is used for all runtimes.
const { accessToken } = await client.update({
  pulseId,
  execPath: '/script.js',
  files: {
    '/script.js': 'console.log("Hello, world!")',
  },
  execOptions: '--max-old-space-size=4096', // node param to set memory to 4GB
})

This is will result in executing "node --max-old-space-size=4096 /script.js".

const { accessToken } = await client.update({
  pulseId,
  execPath: '/script.js',
  files: {
    '/script.js': 'console.log("Hello, world!")',
  },
  buildOptions: '--build-arg=HELLO=WORLD --build-arg=ANOTHER=ARG', // docker build arg
})

This is will result in adding "--build-arg=HELLO=WORLD" and "--build-arg=ANOTHER=ARG" params to the "docker build" command.

Notes on files:

  • files is an object where the key is the path and the value is the content. The path must start with a slash, but the resulting file will be created in the app directory, which is /run/app.
  • zipFile is a zip file that will be extracted to the app directory (/run/app).
  • initFile is a script that will be executed before the user script.
  • envFile is a .env file that will be used to set environment variables.
  • stdinFile is a file that will be used as stdin for the app.

When any file is a string, it will be treated as utf-8 encoded content:

const { accessToken } = await client.update({
  pulseId,
  execPath: '/script.js',
  files: {
    '/script.js': 'console.log("Hello, world!")',
  },
})

When any file is a buffer, it will be treated as binary content:

import fs from 'fs'

const { accessToken } = await client.update({
  pulseId,
  execPath: '/script.js',
  zipFile: fs.readFileSync('/some/path/to/local/script.zip'), // returns Buffer
})

Otherwise, you can use the File interface:

Note:

  • "source" is the path to the file on disk.
  • "content" is the content of the file.
  • "mode" is the file mode.
  • "source" and "content" are mutually exclusive.
const { accessToken } = await client.update({
  pulseId,
  execPath: '/script.js',
  files: {
    '/script.js': {
      source: '/some/path/to/local/script.js',
      mode: 0o755,
    },
    '/other/script.js': {
      content: 'console.log("Hello, world!")',
      mode: 0o644,
    },
    '/another/script.js': {
      content: Buffer.from('console.log("Hello, world!")'),
      mode: 0o644,
    },
  },
})

Optional initFile is a bash script that will be executed before the user script:

const { accessToken } = await client.update({
  pulseId,
  execPath: '/script.js',
  zipFile: fs.readFileSync('/some/path/to/local/script.zip'),
  initFile: `#!/bin/bash
echo "Hello, world!"
echo "Goodbye, world!"
`,
})

Optional envFile is a .env file that will be used to set environment variables:

const { accessToken } = await client.update({
  pulseId,
  execPath: '/script.js',
  zipFile: fs.readFileSync('/some/path/to/local/script.zip'),
  envFile: `VAR1="value 1"
VAR2="value 2"
ANOTHER_VAR="another value"
# ... you get the idea
`,
})

Optional stdinFile is a file that will be used as stdin for the app:

const { accessToken } = await client.update({
  pulseId,
  execPath: '/script.js',
  zipFile: fs.readFileSync('/some/path/to/local/script.zip'),
  stdinFile: fs.readFileSync('/some/path/to/local/stdin.txt'),
})

If the app reads STDIN, it will read from that file.

warmUp

async warmUp({ pulseId }: { pulseId: string }): Promise<{ success: boolean; error?: string }>

run

async run({ pulseId }: { pulseId: string }): Promise<{ success: boolean; accessToken?: string; error?: string }>

pause

async pause({ pulseId }: { pulseId: string }): Promise<{ success: boolean; error?: string }>

resume

async resume({ pulseId }: { pulseId: string }): Promise<{ success: boolean; error?: string }>

shutdown

async shutdown({ pulseId }: { pulseId: string }): Promise<{ success: boolean; error?: string }>

delete

async delete({ pulseId }: { pulseId: string }): Promise<{ success: boolean; error?: string }>

balloon

async balloon({
  pulseId,
  balloon, // change balloon size to this (in MB)
}: {
  pulseId: string
  balloon: number
}): Promise<{
  success: boolean;
  error?: string
}>

history

async history({
  pulseId,
}: {
  pulseId: string
}): Promise<{
  success: boolean;
  outputs?: Output[];
  problems?: Problem[];
  code?: number | null;
  error?: string
}>
interface Output {
  pulseId: string
  time: Date
  source: string // "manager", "controller", "vm", "agent", "app"
  stream: string // "stdout" or "stderr"
  data: string
}
interface Problem {
  pulseId: string
  time: Date
  source: string // "manager", "controller", "vm", "agent", "app"
  message: string
  stack?: string
}

stats

async stats({
  pulseId,
}: {
  pulseId: string
}): Promise<{
  success: boolean;
  stats?: AgentStats | null;
  error?: string
}>
interface AgentStats {
  time: number
  cpuAverage: number
  memAverage: number
  memTotal: number
  memFree: number
  memAvailable: number
  vsz: number
  rss: number
  user: number
  system: number
  guest: number
}

teamList

async teamList(): Promise<{ success: boolean; teams?: Team[]; error?: string }>
interface Team {
  id: string
  name: string
  createdByUser: string
  createdAt: number
  updatedAt: number
}

teamGet

async teamGet({ teamId }: { teamId: string }): Promise<{ success: boolean; team?: Team; error?: string }>
interface Team {
  id: string
  name: string
  createdByUser: string
  createdAt: number
  updatedAt: number
}

teamCreate

async teamCreate({ name }: { name: string }): Promise<{ success: boolean; team?: Team; error?: string }>
interface Team {
  id: string
  name: string
  createdByUser: string
  createdAt: number
  updatedAt: number
}

teamUpdate

async teamUpdate({ teamId, name }: { teamId: string; name: string }): Promise<{ success: boolean; team?: Team; error?: string }>
interface Team {
  id: string
  name: string
  createdByUser: string
  createdAt: number
  updatedAt: number
}

teamDelete

async teamDelete({ teamId }: { teamId: string }): Promise<{ success: boolean; team?: Team; error?: string }>
interface Team {
  id: string
  name: string
  createdByUser: string
  createdAt: number
  updatedAt: number
}

teamUserList

async teamUserList({ teamId }: { teamId: string }): Promise<{ success: boolean; users?: User[]; error?: string }>
interface User {
  id: string
  email: string
  name: string
  createdAt: number
  updatedAt: number
}

teamUserAdd

async teamUserAdd({ teamId, userId }: { teamId: string; userId: string }): Promise<{ success: boolean; error?: string }>
interface User {
  id: string
  email: string
  name: string
  createdAt: number
  updatedAt: number
}

teamUserRemove

async teamUserRemove({ teamId, userId }: { teamId: string; userId: string }): Promise<{ success: boolean; error?: string }>

run

This is a do-all method that will:

  • create
  • update
  • warmUp
  • run
  • delete
async run(({
  pulseId,
  name,
  buildOptions, // if runtime supports it, i.e, docker build step args
  execOptions,  // runtime exec options, e.g., "--param" in "node --param /app/script.js"
  execPath,     // entry point, e.g., "/script.js" in "node /script.js", or "/Dockerfile" for "docker" runtime.
  files,        // files to be uploaded to the app directory. cannot be used with "zipFile"
  zipFile,      // zip with the app. will be extracted to /app/ directory. cannot be used with "files"
  initFile,     // initialization script
  envFile,      // .env file
  stdinFile,    // a file that will be used as stdin for the app
  vcpu,         // number of virtual CPUs
  memory,       // memory in MB
  balloon,      // initial balloon size in MB
  autoPause,    // pause the app after it's done executing the user app
  autoShutdown, // shutdown the app after it's done executing the user app
  autoDelete,   // delete the app on shutdown
}: {
  pulseId: string
  name?: string
  buildOptions?: string
  execOptions?: string
  execPath: string
  files?: { [path: string]: string | Buffer | File }
  zipFile?: string | Buffer | File
  initFile?: string | Buffer | File
  envFile?: string | Buffer | File
  stdinFile?: string | Buffer | File
  vcpu?: string
  memory?: string
  balloon?: string
  autoPause?: boolean
  autoShutdown?: boolean
  autoDelete?: boolean
}): Promise<{
  success: boolean;
  accessToken?: string;
  error?: string
}>

Use accessToken to stream the output using client.stream().

stream

async stream({
  accessToken,
  onOutput,
  onProblem,
  onFinish,
}: {
  accessToken: string
  onOutput?: (data: Output) => void
  onProblem?: (data: Problem) => void
  onFinish?: (data: Finished) => void
}): Promise<void>
type ManagerMsgOutput = {
  type: 'OUTPUT'
  pulseId: string
  output: Output
}
interface Output {
  pulseId: string
  time: Date
  source: string // "manager", "controller", "vm", "agent", "app"
  stream: string // "stdout" or "stderr"
  data: string
}
interface Problem {
  pulseId: string
  time: Date
  source: string // "manager", "controller", "vm", "agent", "app"
  message: string
  stack?: string
}
export interface Finished {
  pulseId: string
  code: number | null
  stats: AgentStats | null
}
interface AgentStats {
  time: number
  cpuAverage: number
  memAverage: number
  memTotal: number
  memFree: number
  memAvailable: number
  vsz: number
  rss: number
  user: number
  system: number
  guest: number
}

An example:

await manager.stream({
  accessToken,
  onOutput: (data) => {
    process.stdout.write(data.output.data)
  },
  onProblem: (data) => {
    console.error(data.error.message)
  },
  onFinish: (data) => {
    console.log('--------------------')
    console.log(`Exit code: ${data.code}`)
    if (data.stats) {
      console.log(`Time: ${stats.time}ms`)
      console.log(`CPU average: ${stats.cpuAverage.toFixed(2)}%`)
      console.log(`Memory average: ${stats.memAverage.toFixed(2)}%`)
      console.log(`Memory total: ${(stats.memTotal / 1024).toFixed(2)}MB`)
      console.log(`Memory free: ${(stats.memFree / 1024).toFixed(2)}MB`)
      console.log(`Memory available: ${(stats.memAvailable / 1024).toFixed(2)}MB`)
      console.log(`VSZ: ${stats.vsz}`)
      console.log(`RSS: ${stats.rss}`)
      console.log(`User: ${stats.user.toFixed(2)}%`)
      console.log(`System: ${stats.system.toFixed(2)}%`)
      console.log(`Guest: ${stats.guest.toFixed(2)}%`)
    }
  },
})