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

@progalaxyelabs/stonescriptphp-api-tester

v0.1.1

Published

API test infrastructure for StoneScriptPHP projects — coverage validation and test execution

Downloads

95

Readme

@progalaxyelabs/stonescriptphp-api-tester

API test infrastructure for StoneScriptPHP projects — coverage validation and test execution.

Zero npm dependencies. Uses only Node.js built-ins.

Installation

npm install @progalaxyelabs/stonescriptphp-api-tester

Or use directly via npx:

npx @progalaxyelabs/stonescriptphp-api-tester validate
npx @progalaxyelabs/stonescriptphp-api-tester run --flow=smoke

Commands

api-tester validate

Static analysis — cross-references your testplan.json against routes.php and the generated TypeScript api-client to find coverage gaps.

api-tester validate [options]

Options:

| Option | Default | Description | |--------|---------|-------------| | --testplan=<path> | ./api/tests/testplan.json | Path to testplan.json | | --client=<path> | ./api/client/src/index.ts | Path to api-client index.ts | | --routes=<path> | ./api/src/config/routes.php | Path to routes.php | | --verbose | | Show all matches, not just failures | | --json | | Output as JSON (for CI pipelines) |

Coverage checks performed:

  1. API Client -> Testplan (MUST be 100%): Every endpoint in the TypeScript client must appear in testplan.json
  2. Routes.php -> Testplan (MUST be 100%): Every route in routes.php must appear in testplan.json
  3. Testplan -> API Client (informational): Shows testplan endpoints not in api-client (expected for untyped routes)
  4. Graph Coverage (MUST be 100%): Every endpoint ID must appear in at least one graph edge
  5. Flow Coverage (SHOULD be 100%): Every endpoint ID should appear in at least one flow

Exit codes: 0 = all mandatory checks pass, 1 = coverage gaps found.

api-tester run

Runtime test execution — sends real HTTP requests following flows defined in testplan.json.

api-tester run [options]

Options:

| Option | Default | Description | |--------|---------|-------------| | --testplan=<path> | ./api/tests/testplan.json | Path to testplan.json | | --base-url=<url> | http://localhost:3000 | Base URL for API | | --flow=<name> | | Flow name to run, or all for all flows | | --endpoint=<id> | | Run a single endpoint by ID (for debugging) | | --dry-run | | Print what would happen without making HTTP calls | | --verbose | | Show request/response bodies | | --token=<token> | | Pre-obtained auth token (skip login) | | --email=<email> | | Email for login step | | --password=<pass> | | Password for login step | | --platform=<name> | | Platform name for auth login |

Examples:

# Run the smoke flow
api-tester run --flow=smoke --base-url=http://localhost:3011

# Run all flows with auth credentials
api-tester run --flow=all [email protected] --password=TestPass1 --platform=myapp

# Debug a single endpoint
api-tester run --endpoint=15 --verbose --base-url=http://localhost:3011

# Dry run — see what would execute without making requests
api-tester run --flow=mvp --dry-run

# Use a pre-obtained token
api-tester run --flow=smoke --token=eyJhbG...

testplan.json Format

The testplan is a JSON file that describes your API surface, how endpoints relate to each other, and how to test them.

{
  "meta": {
    "version": "1.0",
    "total_endpoints": 128,
    "api_base": "http://localhost:3011"
  },
  "endpoints": [
    {
      "id": 1,
      "method": "GET",
      "path": "/health",
      "name": "system.health",
      "group": "system",
      "auth_required": false,
      "in_api_client": false,
      "implementation_status": "implemented-untyped",
      "sample_request": null,
      "expected_status": 200,
      "response_shape": ["status", "service", "timestamp"]
    },
    {
      "id": 89,
      "method": "POST",
      "path": "/invoices",
      "name": "invoices.create",
      "group": "invoices",
      "auth_required": true,
      "in_api_client": true,
      "implementation_status": "implemented-typed",
      "sample_request": {
        "invoice_number": "INV-{{timestamp}}",
        "invoice_date": "2026-01-15",
        "distributor_id": "{{distributor_id}}",
        "items": []
      },
      "expected_status": 200,
      "response_shape": ["invoice_id"]
    }
  ],
  "graph": [
    {
      "from": 89,
      "to": 29,
      "carry": {
        "invoice_id": "response.data.invoice_id"
      },
      "note": "Create invoice, then fetch it by ID"
    }
  ],
  "flows": {
    "smoke": [1, 2, 3],
    "mvp": [14, 107, 105, 89, 91]
  }
}

Endpoint fields

| Field | Type | Description | |-------|------|-------------| | id | number | Unique endpoint identifier (referenced in graph/flows) | | method | string | HTTP method: GET, POST, PUT, DELETE | | path | string | URL path with :param placeholders | | name | string | Dot-notation name (e.g., invoices.create) | | group | string | Logical group for organization | | auth_required | boolean | Whether the endpoint requires a JWT | | in_api_client | boolean | Whether this endpoint is in the TypeScript api-client | | implementation_status | string | implemented-typed, implemented-untyped, or missing | | sample_request | object/null | Request body template with {{placeholder}} support | | expected_status | number | Expected HTTP status code | | response_shape | string[] | Array of field names expected in response data |

Graph edges

Graph edges define data dependencies between endpoints. When endpoint from succeeds, values are extracted from its response and carried to subsequent steps.

The carry object maps variable names to dot-notation paths into the response:

{
  "from": 89,
  "to": 29,
  "carry": {
    "invoice_id": "response.data.invoice_id"
  }
}

After step 89 (POST /invoices), the invoice_id is extracted from the response and used to resolve :id in step 29 (GET /invoices/:id).

Flows

Flows are named sequences of endpoint IDs executed in order. Each flow represents a business workflow (e.g., create distributor -> create item -> create invoice -> create bill).

Placeholders

sample_request fields support {{placeholder}} syntax:

| Placeholder | Resolves to | |-------------|-------------| | {{timestamp}} | Current Unix timestamp | | {{email}} | Generated test email | | {{any_carried_key}} | Value carried from a previous step |

Path parameters (:id, :slug) are resolved from carried data automatically.

StoneScriptPHP Awareness

The runner understands the StoneScriptPHP response format:

{"status": "ok", "message": "", "data": { ... }}

When validating response_shape, the runner checks body.data (not the wrapper) if the response has status: "ok". This matches how StoneScriptPHP wraps all responses via res_ok() and res_error().

Requirements

  • Node.js >= 18.0.0 (uses native fetch)
  • Zero npm dependencies

License

MIT