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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@ollie-shop/cli

v0.3.4

Published

Ollie Shop CLI for building custom checkouts

Readme

@ollie-shop/cli

Internal CLI for managing Ollie Shop components, functions, store versions, and projects.

Quick Start

# Run CLI from monorepo root
pnpm --filter @ollie-shop/cli cli

# Or from the CLI package directory
cd packages/cli
npm run cli

# With arguments
npm run cli -- component create --name my-component
npm run cli -- store-version create --store 123e4567-e89b-12d3-a456-426614174000 --name "Holiday Theme"

# Enable debug output
DEBUG=ollie:* npm run cli -- login

Features Overview

🏪 Store Version Management

  • Create, manage, and deploy different store configurations
  • A/B testing and gradual rollouts
  • Template-based version creation

🧩 Component System

  • Create React components for checkout customization
  • Build, validate, and deploy components
  • Slot-based component architecture (header, main, sidebar, footer)
  • NEW: Interactive component creation wizard
  • NEW: Rich deployment progress visualization

⚡ Function Management

  • Create serverless functions for checkout logic
  • Event-driven architecture (cart, customer, shipping, payment, order)
  • Local testing and cloud deployment

📋 Template System

  • Pre-built checkout templates
  • Apply templates to store versions
  • Preview before applying

🚀 Enhanced Developer Experience (Phase 1)

  • Smart Error Recovery: Actionable suggestions for common errors
  • Context-Aware Commands: Shows relevant commands based on current directory
  • Interactive Mode: Step-by-step wizards for complex operations
  • Rich Progress Visualization: Detailed deployment progress with stats

Architecture Overview

Command Flow

User Input
    │
    ▼
CLI Entry (src/index.ts)
    │
    ├─> Command Parser (Commander.js)
    │   └─> Global Options (--verbose, --quiet, etc.)
    │
    ├─> Command Registration (src/commands/*.ts)
    │   └─> Option Schemas (Zod validation)
    │
    ├─> Action Execution (src/actions/*.ts)
    │   ├─> Console Output (utils/cliConsole.ts)
    │   ├─> Spinner Management
    │   └─> Lazy Load @ollie-shop/core
    │
    └─> Error Handling
        └─> Recovery Suggestions

Core Files

src/index.ts - CLI Entry Point

export class OllieShopCLI {
  private program: Command;
  
  constructor() {
    // Sets up Commander instance
    // Registers global options
    // Configures error handling
  }
  
  async run(argv: string[]): Promise<void> {
    // Parses arguments
    // Validates global options
    // Executes command
  }
}

src/commands/ - Command Registration

Each command file exports a function that:

  1. Creates a Commander command
  2. Defines options with Zod schemas
  3. Binds to action handler
// Example: component.ts
export function registerComponentCommands(program: Command) {
  const cmd = program.command('component');
  
  cmd.command('create')
     .option('--name <name>', 'Component name')
     .option('--slot <slot>', 'Component slot')
     .action(async (options) => {
       const validated = componentOptionsSchema.parse(options);
       await componentActions.createComponent(validated, cliConsole);
     });
}

src/actions/ - Business Logic Delegation

Actions handle:

  • User feedback (spinners, messages)
  • Core service delegation
  • Error transformation
// Example: component.actions.ts
export async function createComponent(options: ComponentOptions, cliConsole: CliConsole) {
  const spinner = cliConsole.spinner('Creating component...');
  try {
    // Lazy load core service
    const { createComponent: createComponentService } = await import('@ollie-shop/core');
    
    const result = await createComponentService(options);
    spinner.succeed('Component created');
    
    // Show next steps
    cliConsole.nextSteps('Next steps', [
      { description: 'Navigate to directory', command: `cd ${result}` },
      { description: 'Install dependencies', command: 'npm install' },
      { description: 'Start development', command: 'npm run dev' }
    ]);
  } catch (error) {
    spinner.fail('Failed to create component');
    throw error;
  }
}

CLI Console Utility

The cliConsole utility (src/utils/cliConsole.ts) provides consistent output formatting:

interface CliConsole {
  // Basic output
  log(message: string): void;
  error(message: string): void;
  warn(message: string): void;
  info(message: string): void;
  success(message: string): void;
  
  // Formatting
  dim(message: string): void;
  bold(message: string): void;
  
  // Complex output
  list(items: string[]): void;
  table(data: any[]): void;
  json(data: any): void;
  
  // Interactive
  spinner(message: string): Ora;
  confirm(message: string): Promise<boolean>;
  prompt(questions: any[]): Promise<any>;
}

Usage patterns:

// Simple messages
cliConsole.success('✓ Build completed');
cliConsole.error('✗ Validation failed');

// Formatted lists
cliConsole.info('Available templates:');
cliConsole.list(['default', 'grocery', 'sales']);

// Spinners for async operations
const spinner = cliConsole.spinner('Building...');
await longOperation();
spinner.succeed('Build complete');

// Interactive prompts
const confirm = await cliConsole.confirm('Deploy to production?');

Authentication Flow

// src/actions/auth.actions.ts
1. Start local server on port 7777
2. Open browser to auth endpoint
3. Wait for callback with credentials
4. Save to ~/.ollie-shop/credentials.json
5. Return user info (currently mocked)

Error Handling

Custom error class with recovery suggestions:

class OllieShopCLIError extends Error {
  constructor(
    message: string,
    public context?: Record<string, any>,
    public suggestions?: string[]
  ) {
    super(message);
  }
}

// Usage
throw new OllieShopCLIError(
  'Component not found',
  { path: './src/components' },
  [
    'Run "ollieshop component create" to create a new component',
    'Check that you are in the correct directory'
  ]
);

Input Validation & DX Enhancements

All CLI commands now feature enhanced validation with helpful error messages:

Component Name Validation

# ❌ Invalid: uppercase letters
$ ollieshop component create --name TestComponent
Error: Invalid component name: Must be lowercase with hyphens only
Examples: header-nav, shopping-cart, product-list

# ✅ Valid: kebab-case
$ ollieshop component create --name test-component

Function Validation

# ❌ Invalid: wrong invocation type
$ ollieshop function create --name test --invocation invalid
Error: Invalid function invocation type
Valid invocations: request, response

# ✅ Valid: proper invocation
$ ollieshop function create --name validate-order --invocation request

UUID Validation (Store Versions)

# ❌ Invalid: not a UUID
$ ollieshop store-version create --store abc123 --name v2
Error: Invalid store ID: Must be a valid store ID
Example: 123e4567-e89b-12d3-a456-426614174000

# ✅ Valid: proper UUID format
$ ollieshop store-version create --store 123e4567-e89b-12d3-a456-426614174000 --name v2

Validation Features

  • Early validation: Errors caught at parse time, not after processing
  • Helpful examples: Error messages include valid examples
  • Format hints: Shows expected formats (kebab-case, UUID, etc.)
  • Enum suggestions: Lists all valid options for enums
  • Required fields: Clear indication when fields are missing
  • Help integration: --help shows examples for each command

Component Validation

The component validate command checks for:

  • Required files: index.tsx, package.json, meta.json
  • Valid TypeScript/JavaScript: Source files compile without errors
  • Component metadata: Valid meta.json structure
  • Package dependencies: All required dependencies present
# Validate a component (components are created in ./components/<name>/)
$ ollieshop component validate --path ./components/my-component

# Or validate from within component directory (automatic path detection)
$ cd components/my-component
$ ollieshop component validate

Automatic Path Detection

The CLI now automatically detects when you're inside a component or function directory:

# Navigate to component directory
$ cd components/header-nav

# These commands automatically use the current directory
$ ollieshop component validate   # No --path needed
$ ollieshop component build      # No --path needed
$ ollieshop component deploy     # No --path needed

# Same works for functions
$ cd functions/validate-order
$ ollieshop function validate    # No --path needed
$ ollieshop function build       # No --path needed
$ ollieshop function test        # No --path needed
$ ollieshop function deploy      # No --path needed

The CLI detects the project type by looking for:

  • Components: meta.json with type "component" or presence of index.tsx/index.jsx
  • Functions: meta.json with type "function" or presence of index.ts/index.js

If you're not in the right directory type, you'll get helpful error messages:

# In a function directory trying to run component command
$ ollieshop component validate
Error: Current directory appears to be a function, not a component.
Please navigate to a component directory or specify --path

# In project root
$ ollieshop component validate
Error: No component found in current directory.
Try navigating to a component directory:
  cd components/<component-name>
Or specify the path:
  --path ./components/<component-name>

🚀 Enhanced Developer Experience Features

Smart Error Recovery

When errors occur, the CLI now provides actionable suggestions:

$ ollieshop component create --name MyComponent

❌ Component name validation failed

💡 Possible solutions:
  1. Use lowercase letters and hyphens only (e.g., header-nav)
  2. Examples: shopping-cart, product-list

📍 Context:
  Current directory: /Users/dev/project

Context-Aware Command Suggestions

Running ollieshop without arguments shows context-aware suggestions:

$ ollieshop

📍 Current location:
  You're in a component directory: header-nav

Common commands for this component:
  validate   Check component validity
  build      Build for production
  dev        Start development server
  deploy     Deploy to cloud

Recent commands:
  ollieshop validate --fix (2 min ago)
  ollieshop build --watch (1 hour ago)

💡 Tip: Run 'ollieshop dev' to start developing this component

Interactive Mode

Use --interactive flag for step-by-step guidance:

$ ollieshop component create --interactive

🎨 Component Creation Wizard

? Component name: shopping-cart
? Component slot: › 
❯ Header
  Main (default)
  Sidebar  
  Footer

? Language: › 
❯ TypeScript (recommended)
  JavaScript

? Include test files? (Y/n)

[Preview] This will run: ollieshop component create --name shopping-cart --slot header

? Create this component? (Y/n)

Rich Progress Visualization

Deployment now shows detailed progress:

$ ollieshop component deploy --wait

🚀 Starting deployment...

🔍 Validating      ████████████████████ 100% | 0.3s ✓
🔨 Building        ███████████░░░░░░░░░  60% | 1.2s | Bundling dependencies...
⚡ Optimizing      ░░░░░░░░░░░░░░░░░░░░   0% | Queued
🚀 Deploying       ░░░░░░░░░░░░░░░░░░░░   0% | Queued
✅ Verifying       ░░░░░░░░░░░░░░░░░░░░   0% | Queued

📊 Build Stats:
  • Bundle size: 127KB (gzipped: 42KB)
  • Tree shaking: Removed 18 unused exports
  • Dependencies: 12 (3 updated)

✅ Deployment completed successfully!

Deployment URL: https://cdn.ollie.shop/components/header-nav-v1.2.0.js
Total time: 3.4s

Function Validation

The function validate command checks for:

  • Required files: index.ts or index.js, package.json, meta.json
  • Valid exports: Handler function properly exported
  • Function metadata: Valid meta.json structure
  • Package dependencies: All required dependencies present
# Validate a function (functions are created in ./functions/<name>/)
$ ollieshop function validate --path ./functions/my-function

# Or validate from within function directory
$ cd functions/my-function
$ ollieshop function validate

Command Implementation Status

✅ Fully Implemented & Delegated to Core

These commands are fully functional and delegate to @ollie-shop/core:

Store Version Management

  • store-version create - Create new store version
  • store-version list - List all versions for a store
  • store-version get - Get version details
  • store-version activate/deactivate - Toggle version status
  • store-version set-default - Set default version
  • store-version clone - Clone existing version
  • store-version delete - Delete version

Component Management

  • component create - Create new component
  • component build - Build component
  • component validate - Validate component structure
  • component deploy - Deploy component with build status polling
  • component deploy-status - Check deployment status

Function Management

  • function create - Create new function
  • function build - Build function
  • function validate - Validate function structure
  • function test - Test function locally
  • function deploy - Deploy function with build status polling
  • function deploy-status - Check deployment status

Template Management

  • template list - List available templates
  • template apply - Apply template to version
  • template preview - Preview template

Project Management

  • project init - Initialize new project
  • project info - Show project information
  • project link - Link to existing project

🔄 Partially Implemented

These commands have basic functionality but need database integration:

  • component list - Shows empty list (needs Supabase)
  • function list - Shows empty list (needs Supabase)

🔧 CLI-Only Features

  • login - OAuth flow with local server
  • whoami - Shows current user (mocked)
  • docs - Opens documentation
  • help - Shows command help
  • version - Shows CLI version

Testing the CLI Locally

Manual Testing Checklist

# 1. Test authentication
npm run cli -- login
npm run cli -- whoami

# 2. Test store version commands
npm run cli -- store-version create --store 123e4567-e89b-12d3-a456-426614174000 --name "Test Version"
npm run cli -- store-version list --store 123e4567-e89b-12d3-a456-426614174000
npm run cli -- store-version get <version-id>
npm run cli -- store-version activate <version-id>
npm run cli -- store-version set-default <version-id>

# 3. Test component commands
npm run cli -- component create --name test-component --slot header
# Note: Components are created in ./components/<name>/ directory
npm run cli -- component validate --path ./components/test-component
npm run cli -- component build --path ./components/test-component
npm run cli -- component deploy --path ./components/test-component
npm run cli -- component deploy-status <build-id>
npm run cli -- component list

# 4. Test function commands
npm run cli -- function create --name test-function --event cart --timing before
# Note: Functions are created in ./functions/<name>/ directory
npm run cli -- function validate --path ./functions/test-function
npm run cli -- function build --path ./functions/test-function
npm run cli -- function test --path ./functions/test-function
npm run cli -- function deploy --path ./functions/test-function
npm run cli -- function deploy-status <build-id>
npm run cli -- function list

# 5. Test template commands
npm run cli -- template list
npm run cli -- template preview default
npm run cli -- template apply minimal --version <version-id>

# 6. Test project commands
npm run cli -- project init test-project --template default
npm run cli -- project info
npm run cli -- project link <project-id>

# 7. Test error handling
npm run cli -- component create  # Missing required --name
npm run cli -- invalid-command   # Unknown command

# 8. Test global options
npm run cli -- --verbose component create --name test-component
npm run cli -- --quiet component build
npm run cli -- --no-color component list

Debugging

# Enable debug output
DEBUG=ollie:* npm run cli -- component create --name Test

# Use Node debugger
node --inspect-brk ./dist/bin/cli.js component create --name Test

# Check generated files
ls -la ~/.ollie-shop/
cat ~/.ollie-shop/credentials.json

Adding New Commands

  1. Create command file in src/commands/:
// src/commands/newfeature.command.ts
export const newFeatureCommand = (program: Command) => {
  const cmd = program
    .command('newfeature')
    .description('New feature description');
    
  // Add subcommands
  cmd.command('action')
     .option('--param <value>', 'Parameter description')
     .action(newFeatureActions.action);
};
  1. Create action file in src/actions/:
// src/actions/newfeature.actions.ts
export const action = async (options: NewFeatureOptions) => {
  const spinner = cliConsole.spinner('Processing...');
  
  try {
    // Delegate to core
    const { NewFeatureService } = await import('@ollie-shop/core');
    const service = new NewFeatureService();
    await service.process(options);
    
    spinner.succeed('Complete');
  } catch (error) {
    spinner.fail('Failed');
    throw error;
  }
};
  1. Register in main CLI:
// src/commands/index.ts
export * from './newfeature.command';

Core Integration Pattern

The CLI follows a strict delegation pattern:

// CLI Layer - User interaction only
async function createComponent(options) {
  // 1. Show spinner
  const spinner = cliConsole.spinner('Creating...');
  
  try {
    // 2. Lazy load core service
    const { ComponentService } = await import('@ollie-shop/core');
    
    // 3. Delegate all logic to core
    const service = new ComponentService();
    const result = await service.create(options);
    
    // 4. Show success and next steps
    spinner.succeed('Created');
    showNextSteps(result);
    
  } catch (error) {
    // 5. Handle errors with context
    spinner.fail('Failed');
    handleError(error);
  }
}

Configuration Files

ollie.json Structure

{
  "storeId": "uuid",
  "versionId": "uuid", 
  "platform": "vtex",
  "platformStoreId": "string",
  "sessionId": "uuid",
  "props": {},
  "theme": {}
}

Credentials Storage

// ~/.ollie-shop/credentials.json
{
  "accessToken": "jwt-token",
  "refreshToken": "refresh-token",
  "expiresAt": "2024-01-01T00:00:00Z"
}

Development Workflow

# 1. Make changes to CLI
cd packages/cli
vim src/commands/component.command.ts

# 2. Build and test
pnpm build
npm run cli -- component create --name Test

# 3. Test with core changes
cd ../core
pnpm build
cd ../cli
npm run cli -- component create --name Test

# 4. Run tests (when implemented)
pnpm test

Known Issues & TODOs

High Priority

  1. Implement real authentication (currently returns mock user)
  2. Add Supabase integration for list commands
  3. Connect to AWS Builder service
  4. Implement dev server with Vite

Medium Priority

  1. Add comprehensive test suite
  2. Implement progress bars for long operations
  3. Add command aliases (e.g., oc for ollieshop component)
  4. Cache command results where appropriate

Low Priority

  1. Add shell completion
  2. Implement update notifications
  3. Add telemetry (with opt-out)
  4. Create interactive mode

Debugging Tips

  1. Check core delegation: Most issues are in @ollie-shop/core, not CLI
  2. Validate schemas: Zod errors show what's missing
  3. Use verbose mode: --verbose shows additional output
  4. Check credentials: cat ~/.ollie-shop/credentials.json
  5. Clear state: rm -rf ~/.ollie-shop to start fresh