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

@looplay/types

v0.1.1

Published

Shared types for Looplay SDK and services

Readme

@looplay/types

Shared TypeScript types for the Looplay SDK and backend services.

This package provides shared types/interfaces used by both the Looplay SDK (client) and the Looplay platform API (server), ensuring end-to-end type safety across integrations.

  • 📦 Package name: @looplay/types
  • 🏷️ Version: 0.1.0
  • 🟦 Runtime: Zero dependencies (dev-only TypeScript)
  • 📜 License: UNLICENSED (private)

Installation

Published as a dual export package (ESM + CJS) with bundled .d.ts declaration files.

# npm
npm install @looplay/types

# pnpm
pnpm add @looplay/types

# yarn
yarn add @looplay/types

The package is private (UNLICENSED). Make sure you have access to the appropriate registry.


Integration Flow

To integrate Looplay into your game or service, follow these steps to ensure type-safe API communication.

1. Import the Types

Import the necessary types into your service or client code:

// ESM
import type {
  GameEventKey,
  TrackMatchEndRequest,
  EmitGameEventRequest,
  EmitGameEventResponse,
} from '@looplay/types';

// CJS
const types = require('@looplay/types');

2. Track Match Completions

When a player finishes a game session (win, lose, or abandon), construct the payload using TrackMatchEndRequest and send it to the platform.

const endMatchPayload: TrackMatchEndRequest = {
  matchId: 'unique-match-id-1234', // Ensure this is unique per match to avoid duplicates
  matchDurationSeconds: 120,
  isCompleted: true,
  isWin: true,
};

// Example using fetch
await fetch('https://api.looplay.io/games/your-game-id/end', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(endMatchPayload),
});

3. Emit Custom Game Events

For actions like claiming rewards or completing specific quests, use EmitGameEventRequest and expect an EmitGameEventResponse.

const eventPayload: EmitGameEventRequest = {
  actionCode: 'CLAIM_REWARD', // Can be a GameEventKey or a custom string
  value: 50,
  refId: 'quest-123',
  payload: { bonus: true, tier: 'gold' },
};

const res = await fetch('https://api.looplay.io/games/your-game-id/emit', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(eventPayload),
});

const data: EmitGameEventResponse = await res.json();

if (data.success) {
  console.log(`Event recorded: ${data.eventId}. Points earned: ${data.pointsEarned}`);
}

Exported Types Reference

| Name | Kind | Description | | --- | --- | --- | | GameEventKey | type | Platform-defined game event codes. Any string is also allowed for game-specific quests. | | TrackMatchEndRequest | interface | Body for POST /games/:id/end — track match/round completion. | | EmitGameEventRequest | interface | Body for POST /games/:id/emit — emit a custom action event. | | EmitGameEventResponse | interface | Response for POST /games/:id/emit. |

GameEventKey

export type GameEventKey =
  | 'PLAY_MATCH'
  | 'WIN_MATCH'
  | 'LOSE_MATCH'
  | 'COMPLETE_LEVEL'
  | 'CLAIM_REWARD'
  | 'CUSTOM_ACTION';
  • Enumerates the standard event codes defined by the platform.
  • Any custom string can be used for game/quest-specific events.

TrackMatchEndRequest

Body for POST /games/:id/end to report a match/round completion.

export interface TrackMatchEndRequest {
  /** Idempotency anchor — same matchId = same event, safe to dedup. */
  matchId: string;
  matchDurationSeconds: number;
  isCompleted?: boolean;
  isWin?: boolean;
}

| Field | Type | Required | Description | | --- | --- | --- | --- | | matchId | string | ✅ | Unique match identifier — used to deduplicate submissions. | | matchDurationSeconds | number | ✅ | Match duration in seconds. | | isCompleted | boolean | ❌ | Whether the match completed (vs. abandoned/cancelled). | | isWin | boolean | ❌ | Whether the player won the match. |

EmitGameEventRequest

Body for POST /games/:id/emit to emit a custom game event.

export interface EmitGameEventRequest {
  actionCode: GameEventKey | string;
  value?: number;
  refId?: string;
  payload?: Record<string, unknown>;
}

| Field | Type | Required | Description | | --- | --- | --- | --- | | actionCode | GameEventKey \| string | ✅ | Action code (standard key or custom string). | | value | number | ❌ | Numeric value associated with the event (e.g. points, count). | | refId | string | ❌ | External reference (e.g. quest id, item id). | | payload | Record<string, unknown> | ❌ | Arbitrary additional data. |

EmitGameEventResponse

export interface EmitGameEventResponse {
  success?: boolean;
  eventId?: string;
  pointsEarned?: number;
  [key: string]: unknown;
}

| Field | Type | Description | | --- | --- | --- | | success | boolean | Whether the event was successfully recorded. | | eventId | string | Server-side ID of the emitted event. | | pointsEarned | number | Points awarded by the event (if applicable). | | [key: string]: unknown | — | Allows the server to return additional custom fields. |


Development

Requirements

  • Node.js ≥ 18 (ES2022)
  • TypeScript ^5.6.3

Scripts

# Build into dist/ (with .d.ts, .d.ts.map, .js)
npm run build

# Type-check only, no emit
npm run typecheck

Notable TypeScript Settings

| Option | Value | Note | | --- | --- | --- | | target / lib | ES2022 | Modern runtime, top-level await, native Error cause. | | module / moduleResolution | ES2022 / Bundler | Designed for modern bundlers (Vite, esbuild, Webpack 5). | | declaration | true | Emits .d.ts files for consumers. | | strict | true | All strict checks enabled. | | outDir | dist | Output directory (gitignored). |

The dist/ and node_modules/ directories are gitignored. Only sources under src/ are committed.


Project Structure

looplay-types/
├── src/
│   └── index.ts        # All types are exported from here
├── dist/               # Build output (gitignored)
├── package.json
├── tsconfig.json
└── README.md

Contributing

  1. Add or modify types in src/index.ts.
  2. Run npm run typecheck to ensure no type errors.
  3. Run npm run build to regenerate dist/.
  4. Open a PR with a clear description of the change.

Any breaking type change must bump the major version and notify the SDK and services teams.


License

UNLICENSED — internal use only within the Looplay system.