@thewhateverapp/shared

v0.2.1

Published

Shared types, schemas, and utilities for The Whatever App platform. Provides Zod schemas for validation and TypeScript types for type safety across all packages.

Readme

@thewhateverapp/shared

Shared types, schemas, and utilities for The Whatever App platform. Provides Zod schemas for validation and TypeScript types for type safety across all packages.

Features

  • 🔍 Type Safety: Comprehensive TypeScript definitions
  • ✅ Validation: Zod schemas for runtime validation
  • 📦 Zero Dependencies: Only depends on Zod
  • 🎯 Domain Models: Tiles, apps, bidding, points, users
  • ⚙️ Configuration: Platform config and feature flags

Installation

npm install @thewhateverapp/shared

Usage

Import Types

import type {
  AppManifest,
  TilePosition,
  TileBid,
  UserPoints,
  FeatureFlags
} from '@thewhateverapp/shared';

Import Zod Schemas

import {
  AppManifest,
  TilePosition,
  AppGenerationRequest
} from '@thewhateverapp/shared';

// Validate data
const result = AppManifest.safeParse(data);

if (result.success) {
  console.log('Valid manifest:', result.data);
} else {
  console.error('Validation errors:', result.error);
}

Core Types

App & Manifest

import type { AppManifest, AppComponent, AppVersion } from '@thewhateverapp/shared';

const manifest: AppManifest = {
  id: 'uuid-here',
  name: 'My App',
  description: 'A cool app',
  version: '1.0.0',
  owner: 'user_123',
  createdAt: '2025-01-01T00:00:00Z',
  updatedAt: '2025-01-01T00:00:00Z',
  components: {
    tile: {
      entrypoint: '/tile/page.tsx',
      assets: ['tile.css', 'tile.js']
    },
    page: {
      entrypoint: '/page/page.tsx',
      assets: ['page.css', 'page.js']
    },
    worker: {
      entrypoint: '/worker/index.ts',
      routes: ['/api/*']
    }
  },
  metadata: {
    icon: 'https://cdn.example.com/icon.png',
    color: '#FF6B6B',
    tags: ['game', 'fun']
  }
};

Tiles & Positions

import type { Tile, TilePosition, TileStatus } from '@thewhateverapp/shared';

const position: TilePosition = {
  row: 0,
  col: 5
};

const tile: Tile = {
  id: 'tile-uuid',
  position: { row: 0, col: 5 },
  ownerId: 'user_123',
  tileId: 'app-uuid',
  status: 'owned',
  isElite: true,
  metadata: {
    name: 'My Tile',
    description: 'Elite tile',
    color: '#FF6B6B',
    tags: ['featured']
  },
  visibility: 'public',
  createdAt: '2025-01-01T00:00:00Z',
  updatedAt: '2025-01-01T00:00:00Z'
};

Bidding System

import type { TileBid, TileBidExtended, BiddingRound } from '@thewhateverapp/shared';

const bid: TileBid = {
  tileId: 'tile-123',
  position: { row: 0, col: 0 },
  bidder: 'user_456',
  amount: 10.5,
  tileId: 'app-uuid',
  timestamp: '2025-01-01T10:00:00Z',
  status: 'pending'
};

const extendedBid: TileBidExtended = {
  ...bid,
  pointsAmount: 1000,
  currentHighBid: 950,
  rotationWeek: '2025-W01',
  expiresAt: '2025-01-07T23:59:59Z'
};

WhateverPoints

import type {
  UserPoints,
  PointsTransaction,
  PointsPackage
} from '@thewhateverapp/shared';

const userPoints: UserPoints = {
  userId: 'user_123',
  balance: 1500,
  totalEarned: 2000,
  totalSpent: 500,
  lastUpdated: '2025-01-01T00:00:00Z'
};

const transaction: PointsTransaction = {
  id: 'txn-uuid',
  userId: 'user_123',
  amount: 100,
  type: 'purchase',
  description: 'Bought 100 points',
  stripePaymentIntentId: 'pi_xxx',
  createdAt: '2025-01-01T00:00:00Z'
};

const package: PointsPackage = {
  id: 'pkg_starter',
  name: 'Starter Pack',
  points: 100,
  priceUsd: 9.99,
  stripePriceId: 'price_xxx',
  bonusPoints: 10,
  popular: false,
  enabled: true
};

Agent Service

import type {
  AppGenerationRequest,
  FileOperation,
  AgentAction,
  DomainTool
} from '@thewhateverapp/shared';

const request: AppGenerationRequest = {
  prompt: 'Create a counter app',
  userId: 'user_123',
  preferences: {
    style: 'modern',
    primaryColor: '#FF6B6B',
    features: ['animations', 'dark-mode']
  }
};

const fileOp: FileOperation = {
  type: 'create',
  path: 'src/components/Counter.tsx',
  content: 'export const Counter = () => { ... }',
  encoding: 'utf8'
};

const action: AgentAction = {
  id: 'action-123',
  timestamp: '2025-01-01T00:00:00Z',
  type: 'file_operation',
  details: fileOp,
  result: {
    success: true,
    message: 'File created successfully'
  }
};

Platform Configuration

import type { PlatformConfig, FeatureFlags } from '@thewhateverapp/shared';

const config: PlatformConfig = {
  maxTilesPerRow: 10,
  maxRows: 100,
  tileSize: 512,
  minimumBid: 1,
  bidIncrement: 0.1,
  maxAppsPerUser: 10,
  allowedDomains: ['thewhatever.app']
};

const features: FeatureFlags = {
  eliteTileBidding: true,
  whateverPoints: true,
  tileMarketplace: false,
  userDashboard: true,
  stripePayments: true,
  weeklyRotation: true
};

Validation with Zod

Validate User Input

import { AppGenerationRequest, TilePosition } from '@thewhateverapp/shared';

// Validate generation request
const requestResult = AppGenerationRequest.safeParse({
  prompt: 'Create a game',
  userId: 'user_123',
  preferences: {
    style: 'playful'
  }
});

if (requestResult.success) {
  // Type-safe data
  const { prompt, userId, preferences } = requestResult.data;
} else {
  // Handle validation errors
  console.error(requestResult.error.format());
}

// Validate position
const positionResult = TilePosition.safeParse({ row: 0, col: 5 });

Validate API Responses

import { AppManifest } from '@thewhateverapp/shared';

async function fetchManifest(tileId: string) {
  const response = await fetch(`/api/apps/${tileId}`);
  const data = await response.json();

  // Validate response matches schema
  const result = AppManifest.safeParse(data);

  if (!result.success) {
    throw new Error('Invalid manifest data');
  }

  return result.data; // Type-safe manifest
}

Parse with Defaults

import { PlatformConfig } from '@thewhateverapp/shared';

// Parse with default values
const config = PlatformConfig.parse({
  tileSize: 512
  // Other fields will use defaults
});

console.log(config.maxTilesPerRow); // 10 (default)
console.log(config.minimumBid); // 1 (default)

All Available Types

Tiles

  • TilePosition - Row and column position
  • TileDimensions - Fixed 256×554 dimensions
  • TileStatus - empty, owned, elite, bidding
  • Tile - Complete tile object
  • TileUpdateRequest - Update tile metadata
  • EliteTilePosition - Elite tile position (row 0)

Apps

  • AppComponent - tile, page, worker
  • AppManifest - Complete app manifest
  • AppVersion - Versioned app snapshot
  • AppGenerationRequest - AI generation request

Bidding

  • TileBid - Basic bid
  • TileBidExtended - Bid with points and rotation
  • BiddingRound - Weekly bidding round

Points

  • UserPoints - User's point balance
  • PointsTransaction - Point transaction record
  • PointsPackage - Points purchase package
  • StripePaymentIntent - Stripe payment record

Agent Service

  • FileOperation - File CRUD operations
  • AgentAction - Agent action log
  • DomainTool - Domain-specific tool definition

Platform

  • PlatformConfig - Platform configuration
  • FeatureFlags - Feature toggle flags

Constants

import { TILE_SIZE, MAX_TILES_PER_ROW } from '@thewhateverapp/shared';

console.log(TILE_SIZE); // 512
console.log(MAX_TILES_PER_ROW); // 10

Utilities

import { generateId, formatDate, validateEmail } from '@thewhateverapp/shared';

const id = generateId(); // Generate UUID
const formatted = formatDate(new Date()); // ISO datetime string
const isValid = validateEmail('[email protected]'); // true

TypeScript Support

All types are fully typed with TypeScript. Import types using the type keyword:

import type {
  AppManifest,
  Tile,
  TileBid,
  UserPoints
} from '@thewhateverapp/shared';

Import Zod schemas for validation:

import {
  AppManifest,
  Tile,
  TileBid,
  UserPoints
} from '@thewhateverapp/shared';

Best Practices

1. Always Validate External Data

import { AppManifest } from '@thewhateverapp/shared';

// ❌ Don't trust external data
const manifest = await response.json();

// ✅ Always validate
const result = AppManifest.safeParse(await response.json());
if (result.success) {
  // Now type-safe
  const manifest = result.data;
}

2. Use Discriminated Unions

import type { TileStatus } from '@thewhateverapp/shared';

function handleTile(status: TileStatus) {
  switch (status) {
    case 'empty':
      // Handle empty tile
      break;
    case 'owned':
      // Handle owned tile
      break;
    case 'elite':
      // Handle elite tile
      break;
    case 'bidding':
      // Handle bidding
      break;
  }
}

3. Leverage Zod Transformations

import { z } from 'zod';
import { AppManifest } from '@thewhateverapp/shared';

// Extend schemas with transformations
const AppManifestWithDefaults = AppManifest.transform(data => ({
  ...data,
  metadata: {
    ...data.metadata,
    color: data.metadata?.color || '#000000'
  }
}));

Development

# Install dependencies
npm install

# Run type checking
npm run typecheck

# Lint code
npm run lint

Related Packages

License

Proprietary - All rights reserved