This skill generates new POS or payment adapter implementations following the adapter pattern.
-
Gather Requirements
Ask user:
- Adapter Type: POS or Payment?
- Vendor Name: Square, Toast, Clover, Stripe, PayPal, etc.
Example:
Creating new adapter. Please provide:
1. Adapter type (POS or Payment):
2. Vendor name (e.g., Square, Toast, Stripe):
-
Read Adapter Interface
For POS Adapters:
cat packages/pos-adapters/src/types.ts
Interface includes:
testConnection(config) - Verify credentials and API access
pullMenu(config) - Fetch menu from POS system
pushOrder(config, order) - Send order to POS
parseWebhook(body, headers) - Parse webhook events
parseStockUpdate(webhookData) - Parse inventory updates
For Payment Adapters:
cat packages/payment-adapters/src/types.ts
Interface includes:
createPayment(config, amount, metadata) - Create payment intent
parseWebhook(body, headers) - Parse webhook events
refund(config, paymentId, amount) - Process refunds
-
Read Example Implementation
For POS:
cat packages/pos-adapters/src/square.ts
For Payment:
cat packages/payment-adapters/src/stripe.ts
-
Generate Adapter File
Create new file at:
- POS:
packages/pos-adapters/src/{vendor}.ts
- Payment:
packages/payment-adapters/src/{vendor}.ts
Template Structure:
import { IPosAdapter, PosConfig, PosMenu, PosOrder, PosWebhookEvent } from './types';
export class {Vendor}Adapter implements IPosAdapter {
async testConnection(config: PosConfig): Promise<boolean> {
throw new Error('Not implemented');
}
async pullMenu(config: PosConfig): Promise<PosMenu> {
throw new Error('Not implemented');
}
async pushOrder(config: PosConfig, order: PosOrder): Promise<string> {
throw new Error('Not implemented');
}
parseWebhook(body: any, headers: Record<string, string>): PosWebhookEvent | null {
throw new Error('Not implemented');
}
parseStockUpdate(webhookData: any): { itemId: string; available: boolean } | null {
throw new Error('Not implemented');
}
}
-
Update Package Exports
Add to packages/{pos|payment}-adapters/src/index.ts:
export * from './{vendor}';
-
Generate Test Stub
Create packages/{pos|payment}-adapters/src/{vendor}.test.ts:
import { describe, it, expect } from 'vitest';
import { {Vendor}Adapter } from './{vendor}';
describe('{Vendor}Adapter', () => {
const adapter = new {Vendor}Adapter();
describe('testConnection', () => {
it('should validate API credentials', async () => {
});
});
describe('pullMenu', () => {
it('should fetch and transform menu data', async () => {
});
});
describe('pushOrder', () => {
it('should create order in {Vendor} system', async () => {
});
});
describe('parseWebhook', () => {
it('should verify webhook signature', () => {
});
it('should parse order status updates', () => {
});
});
});
-
Provide Implementation Guidance
Critical Security Requirements:
-
Webhook Signature Verification:
const signature = headers['x-{vendor}-signature'];
const expectedSignature = crypto
.createHmac('sha256', config.webhookSecret)
.update(JSON.stringify(body))
.digest('hex');
if (signature !== expectedSignature) {
return null;
}
-
Encrypted Config Storage:
interface {Vendor}Config extends PosConfig {
apiKey: string;
apiSecret: string;
locationId: string;
}
-
Error Handling:
try {
const response = await fetch('{vendor-api-url}', {
headers: { Authorization: `Bearer ${config.apiKey}` }
});
if (!response.ok) {
throw new Error(`{Vendor} API error: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('[{Vendor}Adapter] API call failed', error);
throw new Error('Failed to connect to {Vendor}');
}
Vendor-Specific Considerations:
- Square: Requires OAuth, supports catalog sync
- Toast: Requires partner approval, limited API access
- Clover: Multiple authentication methods, complex modifier structure
- Stripe: Webhooks require endpoint registration, idempotency keys
Data Transformation:
Each vendor has different schemas - normalize to OpenOrder format:
const posMenu: PosMenu = {
categories: vendorCategories.map(cat => ({
id: cat.vendorId,
name: cat.displayName,
items: cat.products.map(item => ({
id: item.sku,
name: item.title,
description: item.desc,
price: Math.round(item.priceInDollars * 100),
available: item.inStock
}))
}))
};
-
Remind About Next Steps
After scaffolding:
- Read vendor API documentation
- Set up test account with vendor
- Implement each method incrementally
- Add integration tests with real API (use test mode)
- Update
apps/api/src/services/pos-service.ts to register new adapter
- Add vendor to dashboard settings UI
- Document required config fields in
docs/