or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

alfred-integration.mdconfiguration-storage.mderror-handling.mdhttp-client.mdindex.mdinput-output.mdstring-matching.md
tile.json

tessl/npm-alfy

Create Alfred workflows with ease

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/alfy@2.1.x

To install, run

npx @tessl/cli install tessl/npm-alfy@2.1.0

index.mddocs/

Alfy

Alfy is a comprehensive Node.js toolkit for creating Alfred workflows with ease. It provides a simplified API for handling input/output operations, automatic configuration and caching management, built-in HTTP request handling with optional caching, seamless integration with Alfred's Script Filter JSON format, automatic update notifications, extensive debugging capabilities, and utilities for string matching, error handling, and system icon access.

Package Information

  • Package Name: alfy
  • Package Type: npm
  • Language: JavaScript (ESM)
  • Installation: npm install alfy
  • Node.js Requirement: >=18

Core Imports

import alfy from "alfy";

Note: Alfy is an ESM module and requires Node.js >=18. CommonJS require() is not supported.

Workflow Configuration

Optional configuration in package.json to control Alfy behavior:

{
  "alfy": {
    "updateNotification": false
  }
}
  • updateNotification: Set to false to disable automatic update notifications (default: true)

Basic Usage

import alfy from "alfy";

// Fetch data with automatic caching
const data = await alfy.fetch('https://jsonplaceholder.typicode.com/posts');

// Filter based on user input
const items = alfy
  .inputMatches(data, 'title')
  .map(element => ({
    title: element.title,
    subtitle: element.body,
    arg: element.id
  }));

// Output results to Alfred
alfy.output(items);

Architecture

Alfy is designed around several key components:

  • Input/Output System: Direct integration with Alfred's Script Filter format for seamless data exchange
  • HTTP Client: Built-in HTTP client with intelligent caching and error handling
  • String Matching Engine: Flexible matching system supporting objects, nested properties, and custom functions
  • Configuration Management: Persistent storage for both workflow configuration and user preferences
  • Alfred Integration: Deep integration with Alfred's environment variables and system features
  • Error Handling: Automatic exception handling and user-friendly error display

Capabilities

CLI Tools

Command-line utilities for workflow development and management.

// Binaries provided by the package
run-node: "./run-node.sh";
"alfy-init": "./init.js";
"alfy-cleanup": "./cleanup.js";

Available CLI tools:

  • run-node: Bash wrapper script that ensures Node.js is available in Alfred's environment by inheriting the user's PATH
  • alfy-init: Runs alfred-link and alfred-config to set up workflow linking and configuration
  • alfy-cleanup: Runs alfred-unlink to remove workflow symlinks and clean up

Input and Output

Core functionality for handling Alfred input and presenting results to users. Includes input parsing, result formatting, and Alfred Script Filter JSON generation.

// User input from Alfred
input: string;

// Return results to Alfred
function output(items: ScriptFilterItem[], options?: OutputOptions): void;

Input and Output

HTTP Client

Built-in HTTP client with automatic caching, transformation support, and error handling for fetching remote data.

function fetch(url: string, options?: FetchOptions): Promise<unknown>;

HTTP Client

String Matching

Flexible string matching utilities for filtering data based on user input, with support for object properties and custom matching functions.

function matches<T>(input: string, list: T[], target?: string | MatchFunction<T>): T[];
function inputMatches<T>(list: T[], target?: string | MatchFunction<T>): T[];

String Matching

Configuration and Storage

Persistent configuration and caching system with automatic cleanup and workflow-specific data management.

// Workflow configuration
config: Conf;

// User workflow configuration
userConfig: Map<string, string>;

// Cached data with TTL support
cache: CacheConf;

Configuration and Storage

Alfred Integration

Direct integration with Alfred's environment, including metadata access, system icons, and debugging support.

// Workflow metadata
meta: WorkflowMeta;

// Alfred environment data
alfred: AlfredEnvironment;

// System icons
icon: IconUtilities;

// Debug mode detection
debug: boolean;

Alfred Integration

Error Handling and Logging

Built-in error handling with user-friendly display and debugging utilities for workflow development.

function log(text: string): void;
function error(error: Error | string): void;

Error Handling and Logging

Types

interface OutputOptions {
  rerunInterval?: number;
}

interface FetchOptions extends Partial<GotOptions> {
  maxAge?: number;
  transform?: (body: unknown) => unknown;
  json?: boolean;
  resolveBodyOnly?: boolean;
}

interface ScriptFilterItem {
  uid?: string;
  title: string;
  subtitle?: string;
  arg?: string;
  icon?: IconElement | string;
  valid?: boolean;
  match?: string;
  autocomplete?: string;
  type?: 'default' | 'file' | 'file:skipcheck';
  mods?: Partial<Record<ModifierKey, ModifierKeyItem>>;
  text?: TextElement;
  quicklookurl?: string;
  variables?: Record<string, string>;
}

interface IconElement {
  path?: string;
  type?: 'fileicon' | 'filetype';
}

interface TextElement {
  copy?: string;
  largetype?: string;
}

interface ModifierKeyItem {
  valid?: boolean;
  title?: string;
  subtitle?: string;
  arg?: string;
  icon?: string;
  variables?: Record<string, string>;
}

type ModifierKey = 'fn' | 'ctrl' | 'opt' | 'cmd' | 'shift';
type MatchFunction<T> = (item: T, input: string) => boolean;

interface ActionElement {
  /** Forward text to Alfred */
  text?: string | string[];
  /** Forward URL to Alfred */
  url?: string | string[];
  /** Forward file path to Alfred */
  file?: string | string[];
  /** Forward some value and let the value type be inferred from Alfred */
  auto?: string | string[];
}

interface WorkflowMeta {
  name: string;
  version: string;
  uid: string;
  bundleId: string;
}

interface AlfredEnvironment {
  version: string;
  theme: string;
  themeBackground: string;
  themeSelectionBackground: string;
  themeSubtext: string;
  data: string;
  cache: string;
  preferences: string;
  preferencesLocalHash: string;
}

interface IconUtilities {
  get(iconName: string): string;
  info: string;
  warning: string;
  error: string;
  alert: string;
  like: string;
  delete: string;
}

interface CacheConf<T extends Record<string, any> = Record<string, unknown>> extends Conf<T> {
  isExpired(key: keyof T): boolean;
  get<Key extends keyof T>(key: Key, options?: CacheGetOptions): T[Key];
  get<Key extends keyof T>(key: Key, defaultValue: Required<T>[Key], options?: CacheGetOptions): Required<T>[Key];
  get<Key extends string, Value = unknown>(key: Exclude<Key, keyof T>, defaultValue?: Value, options?: CacheGetOptions): Value;
  get(key: string, defaultValue?: unknown, options?: CacheGetOptions): unknown;
  set<Key extends keyof T>(key: Key, value?: T[Key], options?: CacheSetOptions): void;
  set(key: string, value: unknown, options: CacheSetOptions): void;
  set(object: Partial<T>, options: CacheSetOptions): void;
  set<Key extends keyof T>(key: Partial<T> | Key | string, value?: T[Key] | unknown, options?: CacheSetOptions): void;
}

interface CacheGetOptions {
  ignoreMaxAge?: boolean;
}

interface CacheSetOptions {
  maxAge?: number;
}

// External types from dependencies
interface Conf<T = Record<string, unknown>> {
  get<K extends keyof T>(key: K): T[K];
  get<K extends keyof T>(key: K, defaultValue: T[K]): T[K];
  get(key: string): unknown;
  get(key: string, defaultValue: unknown): unknown;
  set<K extends keyof T>(key: K, value: T[K]): void;
  set(key: string, value: unknown): void;
  has(key: string): boolean;
  delete(key: string): void;
  clear(): void;
  size: number;
  [Symbol.iterator](): IterableIterator<[string, unknown]>;
  keys(): IterableIterator<string>;
}

interface GotOptions {
  headers?: Record<string, string>;
  timeout?: { request?: number };
  retry?: { limit?: number };
  method?: string;
  json?: unknown;
  responseType?: string;
  resolveBodyOnly?: boolean;
  // ... other got options from the got library
}