Claude-code-plugins-plus-skills maintainx-local-dev-loop
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/maintainx-pack/skills/maintainx-local-dev-loop" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-maintainx-local-dev-loop && rm -rf "$T"
manifest:
plugins/saas-packs/maintainx-pack/skills/maintainx-local-dev-loop/SKILL.mdsource content
MaintainX Local Dev Loop
Overview
Set up an efficient local development workflow for building and testing MaintainX integrations with hot reload, mock servers, and automated testing.
Prerequisites
- Completed
setupmaintainx-install-auth - Node.js 18+ installed
environment variable setMAINTAINX_API_KEY
Instructions
Step 1: Initialize TypeScript Project
mkdir maintainx-integration && cd maintainx-integration npm init -y npm install axios dotenv npm install -D typescript tsx vitest @types/node npx tsc --init --target ES2022 --module NodeNext --moduleResolution nodenext --outDir dist
Create
tsconfig.json paths:
{ "compilerOptions": { "target": "ES2022", "module": "NodeNext", "moduleResolution": "nodenext", "outDir": "dist", "strict": true, "esModuleInterop": true }, "include": ["src/**/*"] }
Step 2: Project Structure
maintainx-integration/ ├── src/ │ ├── client.ts # MaintainX API client (from install-auth) │ ├── work-orders.ts # Work order service layer │ └── sync.ts # Data sync logic ├── tests/ │ ├── client.test.ts # Unit tests with mocks │ └── integration.test.ts # Live API tests ├── .env # MAINTAINX_API_KEY=... ├── .env.example # MAINTAINX_API_KEY=your-key-here ├── package.json └── tsconfig.json
Step 3: Dev Scripts in package.json
{ "scripts": { "dev": "tsx watch src/index.ts", "test": "vitest run", "test:watch": "vitest", "test:integration": "INTEGRATION=true vitest run tests/integration.test.ts", "build": "tsc", "repl": "tsx src/repl.ts" } }
Step 4: Write Unit Tests with Mocked API
// tests/client.test.ts import { describe, it, expect, vi, beforeEach } from 'vitest'; import axios from 'axios'; vi.mock('axios'); describe('MaintainXClient', () => { beforeEach(() => { vi.resetAllMocks(); process.env.MAINTAINX_API_KEY = 'test-key-123'; }); it('creates a work order', async () => { const mockResponse = { data: { id: 1, title: 'Test WO', status: 'OPEN' }, }; vi.mocked(axios.create).mockReturnValue({ post: vi.fn().mockResolvedValue(mockResponse), interceptors: { response: { use: vi.fn() } }, } as any); const { MaintainXClient } = await import('../src/client'); const client = new MaintainXClient(); const result = await client.createWorkOrder({ title: 'Test WO' }); expect(result.data.title).toBe('Test WO'); expect(result.data.status).toBe('OPEN'); }); it('paginates work orders', async () => { const page1 = { data: { workOrders: [{ id: 1 }], cursor: 'abc' } }; const page2 = { data: { workOrders: [{ id: 2 }], cursor: null } }; const getMock = vi.fn() .mockResolvedValueOnce(page1) .mockResolvedValueOnce(page2); vi.mocked(axios.create).mockReturnValue({ get: getMock, interceptors: { response: { use: vi.fn() } }, } as any); const { MaintainXClient } = await import('../src/client'); const client = new MaintainXClient(); const all = []; let cursor: string | undefined; do { const { data } = await client.getWorkOrders({ cursor }); all.push(...data.workOrders); cursor = data.cursor; } while (cursor); expect(all).toHaveLength(2); }); });
Step 5: Interactive REPL
// src/repl.ts import * as repl from 'node:repl'; import 'dotenv/config'; import { MaintainXClient } from './client'; const client = new MaintainXClient(); console.log('MaintainX REPL ready. `client` is available.'); console.log('Try: await client.getWorkOrders({ limit: 3 })'); const r = repl.start({ prompt: 'maintainx> ' }); r.context.client = client;
# Start REPL npm run repl # maintainx> const { data } = await client.getWorkOrders({ limit: 3 }) # maintainx> data.workOrders.map(wo => wo.title)
Output
- TypeScript project configured with
for hot reloadtsx watch - Vitest unit tests with mocked MaintainX API responses
- Interactive REPL for exploring the API
template for team onboarding.env.example- Dev/test/build scripts in
package.json
Error Handling
| Issue | Solution |
|---|---|
undefined | Copy to and fill in your key |
| 429 Rate Limited during dev | Add delays between calls, use mocks for unit tests |
| TypeScript import errors | Ensure in tsconfig |
not found | Install with |
Resources
Next Steps
For SDK patterns and best practices, see
maintainx-sdk-patterns.
Examples
Docker-based dev environment:
# Dockerfile.dev FROM node:20-slim WORKDIR /app COPY package*.json ./ RUN npm install COPY . . CMD ["npm", "run", "dev"]
# docker-compose.dev.yml services: app: build: { dockerfile: Dockerfile.dev } env_file: .env volumes: ["./src:/app/src"]
Run integration tests against live API:
INTEGRATION=true npm run test:integration