reveclicat 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +186 -0
- package/dist/cli.js +1905 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +2255 -0
- package/dist/index.js +1940 -0
- package/dist/index.js.map +1 -0
- package/examples/express-handler.ts +90 -0
- package/examples/github-action.yml +57 -0
- package/examples/inbox/Caddyfile +5 -0
- package/examples/inbox/Dockerfile +24 -0
- package/package.json +74 -0
- package/scenarios/billing-issue-churns.yaml +18 -0
- package/scenarios/billing-issue-recovers.yaml +20 -0
- package/scenarios/cancel-then-uncancel.yaml +16 -0
- package/scenarios/happy-year.yaml +35 -0
- package/scenarios/trial-churns.yaml +15 -0
- package/scenarios/trial-converts.yaml +15 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/program.ts","../package.json","../src/core/colors.ts","../src/core/errors.ts","../src/core/config.ts","../src/schemas/common.ts","../src/core/clock.ts","../src/core/http.ts","../src/core/rng.ts","../src/core/set-path.ts","../src/core/state-machine.ts","../src/schemas/events.ts","../src/core/subscriber.ts","../src/core/engine.ts","../src/core/io.ts","../src/commands/send.ts","../src/commands/listen.ts","../src/core/output.ts","../src/core/scenario.ts","../src/commands/run.ts","../src/commands/init.ts","../src/commands/tail.ts","../src/commands/inbox.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { CommanderError } from \"commander\";\nimport { buildProgram } from \"./program.js\";\nimport { formatError, exitCodeFor } from \"./core/errors.js\";\n\nbuildProgram()\n .parseAsync(process.argv)\n .catch((err: unknown) => {\n if (err instanceof CommanderError) {\n // --help / --version exit 0; usage errors were already printed by the formatter.\n process.exitCode = err.exitCode;\n return;\n }\n process.stderr.write(formatError(err) + \"\\n\");\n process.exitCode = exitCodeFor(err);\n });\n","import { Command, type CommanderError } from \"commander\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { registerSend } from \"./commands/send.js\";\nimport { registerListen } from \"./commands/listen.js\";\nimport { registerRun } from \"./commands/run.js\";\nimport { registerInit } from \"./commands/init.js\";\nimport { registerTail } from \"./commands/tail.js\";\nimport { registerInbox } from \"./commands/inbox.js\";\nimport { RccError, formatError } from \"./core/errors.js\";\nimport { defaultIo, type Io } from \"./core/io.js\";\n\n/** Exit code for command-line usage errors (unknown command/option, missing argument). */\nexport const USAGE_EXIT_CODE = 2;\n\nexport function buildProgram(io: Io = defaultIo): Command {\n const program = new Command();\n program\n .name(\"rcc\")\n .description(\n \"Simulate RevenueCat subscription lifecycles and test webhooks locally and in CI.\\n\" +\n \"Unofficial project — not affiliated with RevenueCat, Inc.\",\n )\n .version(pkg.version, \"-v, --version\", \"print the version\")\n .exitOverride((err: CommanderError) => {\n if (err.exitCode !== 0) err.exitCode = USAGE_EXIT_CODE;\n throw err;\n });\n\n registerSend(program, io);\n registerListen(program, io);\n registerRun(program, io);\n registerInit(program, io);\n registerTail(program, io);\n registerInbox(program, io);\n\n // Route commander's own usage errors through the same formatter as every other error.\n for (const cmd of [program, ...program.commands]) {\n const label = cmd === program ? \"rcc\" : `rcc ${cmd.name()}`;\n cmd.configureOutput({\n writeOut: (s) => io.stdout.write(s),\n writeErr: (s) => io.stderr.write(s),\n outputError: (str, write) => {\n const message = str.trim().replace(/^error:\\s*/i, \"\");\n write(formatError(new RccError(message, { hint: `Run \\`${label} --help\\` for usage.`, exitCode: USAGE_EXIT_CODE })) + \"\\n\");\n },\n });\n }\n return program;\n}\n","{\n \"name\": \"reveclicat\",\n \"version\": \"0.1.0\",\n \"description\": \"Unofficial CLI to simulate RevenueCat subscription lifecycles and test webhooks locally and in CI. Not affiliated with RevenueCat, Inc.\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=20\"\n },\n \"bin\": {\n \"rcc\": \"dist/cli.js\",\n \"purr\": \"dist/cli.js\"\n },\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"scenarios\",\n \"examples\",\n \"README.md\",\n \"CHANGELOG.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsx src/cli.ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"lint\": \"eslint .\",\n \"typecheck\": \"tsc --noEmit\",\n \"check\": \"npm run typecheck && npm run lint && npm test\",\n \"prepublishOnly\": \"npm run check && npm run build\"\n },\n \"keywords\": [\n \"revenuecat\",\n \"webhooks\",\n \"cli\",\n \"subscriptions\",\n \"testing\",\n \"ci\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/RadW2020/ReveCliCat.git\"\n },\n \"dependencies\": {\n \"commander\": \"15.0.0\",\n \"yaml\": \"2.9.0\",\n \"zod\": \"4.5.1\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"10.0.1\",\n \"@types/express\": \"5.0.6\",\n \"@types/node\": \"26.4.0\",\n \"eslint\": \"10.9.1\",\n \"express\": \"5.2.1\",\n \"tsup\": \"8.5.1\",\n \"tsx\": \"4.23.12\",\n \"typescript\": \"6.0.3\",\n \"typescript-eslint\": \"8.68.0\",\n \"vitest\": \"4.1.11\"\n },\n \"homepage\": \"https://github.com/RadW2020/ReveCliCat#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/RadW2020/ReveCliCat/issues\"\n },\n \"author\": \"RadW2020\"\n}\n","/** Minimal ANSI colour helpers (no dependency). Disabled when NO_COLOR is set or stdout is not a TTY. */\nconst ESC = String.fromCharCode(27);\nconst enabled = (): boolean =>\n process.env[\"NO_COLOR\"] === undefined && process.env[\"FORCE_COLOR\"] !== \"0\" && (process.stdout.isTTY || process.env[\"FORCE_COLOR\"] !== undefined);\n\nconst wrap = (open: number, close = 39) => (s: string): string =>\n enabled() ? `${ESC}[${open}m${s}${ESC}[${close}m` : s;\n\nexport const red = wrap(31);\nexport const green = wrap(32);\nexport const yellow = wrap(33);\nexport const cyan = wrap(36);\nexport const magenta = wrap(35);\nexport const dim = wrap(2, 22);\nexport const bold = wrap(1, 22);\n","import { dim, red } from \"./colors.js\";\n\n/** User-facing error with an actionable hint. Rendered by formatError(). */\nexport class RccError extends Error {\n readonly hint: string | undefined;\n readonly exitCode: number;\n constructor(message: string, opts: { hint?: string; exitCode?: number; cause?: unknown } = {}) {\n super(message, opts.cause === undefined ? undefined : { cause: opts.cause });\n this.name = \"RccError\";\n this.hint = opts.hint;\n this.exitCode = opts.exitCode ?? 1;\n }\n}\n\nexport function formatError(err: unknown): string {\n const debug = process.env[\"RCC_DEBUG\"] === \"1\";\n const mark = red(\"✖\");\n if (err instanceof RccError) {\n let out = `${mark} ${err.message}`;\n if (err.hint) out += `\\n ${dim(\"→ \" + err.hint)}`;\n if (debug && err.stack) out += `\\n${dim(err.stack)}`;\n return out;\n }\n if (err instanceof Error) {\n return debug\n ? `${mark} ${err.stack ?? err.message}`\n : `${mark} ${err.message}\\n ${dim(\"→ Set RCC_DEBUG=1 for a stack trace.\")}`;\n }\n return `${mark} ${String(err)}`;\n}\n\nexport function exitCodeFor(err: unknown): number {\n return err instanceof RccError ? err.exitCode : 1;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { z } from \"zod\";\nimport { RccError } from \"./errors.js\";\nimport { CLI_STORES, ENVIRONMENTS } from \"../schemas/common.js\";\n\nexport const CONFIG_FILE = \"reveclicat.config.json\";\nexport const DEFAULT_TARGET = \"http://localhost:3000/webhook\";\n\nexport const ConfigSchema = z.strictObject({\n to: z.url({ error: \"`to` must be an absolute http(s) URL.\" }).optional(),\n authHeader: z.string().optional(),\n store: z.enum(CLI_STORES, { error: `\\`store\\` must be one of: ${CLI_STORES.join(\", \")}.` }).optional(),\n environment: z.enum(ENVIRONMENTS, { error: `\\`environment\\` must be one of: ${ENVIRONMENTS.join(\", \")}.` }).optional(),\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\n/** Read `reveclicat.config.json` from `dir` (default cwd). Missing file → {}. Invalid → RccError. */\nexport function loadConfig(dir: string = process.cwd()): Config {\n const file = join(dir, CONFIG_FILE);\n if (!existsSync(file)) return {};\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(file, \"utf8\"));\n } catch (cause) {\n throw new RccError(`${file} is not valid JSON.`, { hint: \"Fix the file or delete it and run `rcc init` again.\", cause });\n }\n const result = ConfigSchema.safeParse(raw);\n if (!result.success) {\n const issue = result.error.issues[0]!;\n const detail =\n issue.code === \"unrecognized_keys\"\n ? `unknown key ${issue.keys.map((k) => `\"${k}\"`).join(\", \")} (allowed: to, authHeader, store, environment)`\n : `${issue.path.join(\".\")}: ${issue.message}`;\n throw new RccError(`${file}: ${detail}`, { hint: \"See the config format in the README.\" });\n }\n return result.data;\n}\n\nexport interface ResolvedDefaults {\n to: string;\n authHeader: string | undefined;\n /** Not yet validated — the command validates against CLI_STORES / ENVIRONMENTS. */\n store: string;\n environment: string;\n}\n\n/** Precedence: explicit flag > config file > built-in default. Strings are validated later by the command. */\nexport function resolveDefaults(\n flags: { to?: string | undefined; authHeader?: string | undefined; store?: string | undefined; environment?: string | undefined },\n config: Config,\n): ResolvedDefaults {\n return {\n to: flags.to ?? config.to ?? DEFAULT_TARGET,\n authHeader: flags.authHeader ?? config.authHeader,\n store: flags.store ?? config.store ?? \"app_store\",\n environment: flags.environment ?? config.environment ?? \"SANDBOX\",\n };\n}\n\n/** Root of the installed `reveclicat` package (works from src/, dist/ and node_modules). */\nexport function packageRoot(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 6; i++) {\n const pkg = join(dir, \"package.json\");\n if (existsSync(pkg)) {\n try {\n if ((JSON.parse(readFileSync(pkg, \"utf8\")) as { name?: string }).name === \"reveclicat\") return dir;\n } catch {\n /* keep walking */\n }\n }\n dir = dirname(dir);\n }\n throw new RccError(\"Could not locate the reveclicat package root.\", { hint: \"Reinstall the package: npm i -g reveclicat\" });\n}\n","/**\n * Enumerations shared by schemas, the state machine and the CLI.\n * Values come from the official RevenueCat docs — see docs/payload-sources.md (S2, 2026-08-29).\n */\n\n/** The 7 event types supported in v0.1. */\nexport const EVENT_TYPES = [\n \"TEST\",\n \"INITIAL_PURCHASE\",\n \"RENEWAL\",\n \"CANCELLATION\",\n \"UNCANCELLATION\",\n \"BILLING_ISSUE\",\n \"EXPIRATION\",\n] as const;\nexport type EventType = (typeof EVENT_TYPES)[number];\n\nexport const ENVIRONMENTS = [\"SANDBOX\", \"PRODUCTION\"] as const;\nexport type Environment = (typeof ENVIRONMENTS)[number];\n\n/** `store` values as documented by RevenueCat. */\nexport const STORES = [\n \"AMAZON\",\n \"APP_STORE\",\n \"MAC_APP_STORE\",\n \"PADDLE\",\n \"PLAY_STORE\",\n \"PROMOTIONAL\",\n \"RC_BILLING\",\n \"ROKU\",\n \"STRIPE\",\n \"TEST_STORE\",\n] as const;\nexport type Store = (typeof STORES)[number];\n\nexport const PERIOD_TYPES = [\"TRIAL\", \"INTRO\", \"NORMAL\", \"PROMOTIONAL\", \"PREPAID\"] as const;\nexport type PeriodType = (typeof PERIOD_TYPES)[number];\n\nexport const CANCEL_REASONS = [\n \"UNSUBSCRIBE\",\n \"BILLING_ERROR\",\n \"DEVELOPER_INITIATED\",\n \"PRICE_INCREASE\",\n \"CUSTOMER_SUPPORT\",\n \"UNKNOWN\",\n] as const;\nexport type CancelReason = (typeof CANCEL_REASONS)[number];\n\nexport const EXPIRATION_REASONS = [...CANCEL_REASONS, \"SUBSCRIPTION_PAUSED\"] as const;\nexport type ExpirationReason = (typeof EXPIRATION_REASONS)[number];\n\n/** CLI-facing store names (lowercase) → RevenueCat `store` values. v0.1 supports app_store only (see Icebox). */\nexport const CLI_STORES = [\"app_store\"] as const;\nexport type CliStore = (typeof CLI_STORES)[number];\nexport const CLI_STORE_TO_STORE: Record<CliStore, Store> = { app_store: \"APP_STORE\" };\n","import { RccError } from \"./errors.js\";\n\nexport interface Duration {\n years: number;\n months: number;\n weeks: number;\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n}\n\nexport class InvalidDurationError extends RccError {\n constructor(input: string) {\n super(\n input === \"\" ? \"Duration is empty.\" : `Invalid ISO-8601 duration: \"${input}\".`,\n { hint: \"Use the form PnYnMnWnDTnHnMnS, e.g. P1M (one month), P1W (one week), P3D, PT12H.\" },\n );\n this.name = \"InvalidDurationError\";\n }\n}\n\nexport class ClockError extends RccError {\n constructor(message: string, hint?: string) {\n super(message, hint === undefined ? {} : { hint });\n this.name = \"ClockError\";\n }\n}\n\nconst DURATION_RE = /^P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?$/;\n\n/** Parse an ISO-8601 duration (`P1M`, `P1W`, `P1M2DT3H`, ...). Fractions are not supported. */\nexport function parseDuration(input: string): Duration {\n if (input === \"\") throw new InvalidDurationError(input);\n const m = DURATION_RE.exec(input);\n if (!m || input === \"P\" || input.endsWith(\"T\")) throw new InvalidDurationError(input);\n const n = (i: number): number => (m[i] === undefined ? 0 : Number(m[i]));\n return {\n years: n(1),\n months: n(2),\n weeks: n(3),\n days: n(4),\n hours: n(5),\n minutes: n(6),\n seconds: n(7),\n };\n}\n\nexport function formatDuration(d: Duration): string {\n let out = \"P\";\n if (d.years) out += `${d.years}Y`;\n if (d.months) out += `${d.months}M`;\n if (d.weeks) out += `${d.weeks}W`;\n if (d.days) out += `${d.days}D`;\n if (d.hours || d.minutes || d.seconds) {\n out += \"T\";\n if (d.hours) out += `${d.hours}H`;\n if (d.minutes) out += `${d.minutes}M`;\n if (d.seconds) out += `${d.seconds}S`;\n }\n return out === \"P\" ? \"PT0S\" : out;\n}\n\nexport function isZeroDuration(d: Duration): boolean {\n return Object.values(d).every((v) => v === 0);\n}\n\nconst MS = { second: 1_000, minute: 60_000, hour: 3_600_000, day: 86_400_000, week: 604_800_000 };\n\n/** Add a duration to a UTC instant (ms). Years/months are calendar-aware with day clamping. */\nexport function addDuration(ms: number, d: Duration): number {\n const date = new Date(ms);\n if (d.years || d.months) {\n const totalMonths = date.getUTCFullYear() * 12 + date.getUTCMonth() + d.years * 12 + d.months;\n const year = Math.floor(totalMonths / 12);\n const month = totalMonths % 12;\n const lastDay = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n const day = Math.min(date.getUTCDate(), lastDay);\n date.setUTCFullYear(year, month, day);\n }\n return (\n date.getTime() +\n d.weeks * MS.week +\n d.days * MS.day +\n d.hours * MS.hour +\n d.minutes * MS.minute +\n d.seconds * MS.second\n );\n}\n\n/** Fixed instant used as the start of every seeded simulation. */\nexport const SEEDED_EPOCH_MS = Date.UTC(2025, 0, 1);\n\n/** A clock that only moves forward, in simulated time. */\nexport class VirtualClock {\n private current: number;\n\n constructor(startMs: number) {\n this.current = startMs;\n }\n\n /** Seeded runs start at a fixed epoch so payloads are reproducible; unseeded runs start now. */\n static forSeed(seed: number | string | undefined, startAt?: number): VirtualClock {\n if (startAt !== undefined) return new VirtualClock(startAt);\n return new VirtualClock(seed === undefined ? Date.now() : SEEDED_EPOCH_MS);\n }\n\n now(): number {\n return this.current;\n }\n\n iso(): string {\n return new Date(this.current).toISOString();\n }\n\n /** Advance by a Duration or ISO-8601 string. Returns the new now(). */\n advance(duration: Duration | string): number {\n const d = typeof duration === \"string\" ? parseDuration(duration) : duration;\n if (isZeroDuration(d)) {\n throw new ClockError(\n `Cannot advance the clock by a zero-length duration (${formatDuration(d)}).`,\n \"The virtual clock only moves forward; use a positive duration such as P1D.\",\n );\n }\n const next = addDuration(this.current, d);\n if (next <= this.current) {\n throw new ClockError(\"The virtual clock cannot move backwards.\");\n }\n this.current = next;\n return next;\n }\n}\n","import { RccError } from \"./errors.js\";\nimport type { WebhookEnvelope } from \"../schemas/index.js\";\n\nexport interface PostResult {\n status: number;\n latencyMs: number;\n body: string;\n}\n\nexport interface PostOptions {\n authHeader?: string | undefined;\n /** Abort after this many ms (default 30 000). */\n timeoutMs?: number | undefined;\n}\n\nexport function unreachableError(url: string, cause: unknown): RccError {\n return new RccError(`Could not reach ${url}. Is your server running? Try \\`rcc listen\\` to test locally.`, {\n hint: `Then send events with: rcc send INITIAL_PURCHASE --to http://localhost:8787/webhook`,\n cause,\n });\n}\n\n/** POST an envelope as JSON. Network failures become an actionable RccError; HTTP status is returned as-is. */\nexport async function postEvent(url: string, envelope: WebhookEnvelope, opts: PostOptions = {}): Promise<PostResult> {\n const headers: Record<string, string> = { \"content-type\": \"application/json\", \"user-agent\": \"reveclicat\" };\n if (opts.authHeader !== undefined) headers[\"authorization\"] = opts.authHeader;\n const started = performance.now();\n let res: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(envelope),\n signal: AbortSignal.timeout(opts.timeoutMs ?? 30_000),\n });\n } catch (cause) {\n throw unreachableError(url, cause);\n }\n const body = await res.text().catch(() => \"\");\n return { status: res.status, latencyMs: Math.round(performance.now() - started), body };\n}\n\nexport function assertUrl(value: string, flag: string): string {\n try {\n const u = new URL(value);\n if (u.protocol !== \"http:\" && u.protocol !== \"https:\") throw new Error(\"protocol\");\n return value;\n } catch {\n throw new RccError(`Invalid URL for ${flag}: \"${value}\".`, { hint: \"Use an absolute http(s) URL, e.g. http://localhost:3000/webhook.\" });\n }\n}\n","import { randomUUID } from \"node:crypto\";\n\nexport interface Rng {\n /** Uniform float in [0, 1). */\n next(): number;\n /** Uniform integer in [0, maxExclusive). */\n int(maxExclusive: number): number;\n /** RFC-4122 v4-shaped UUID. */\n uuid(): string;\n /** n lowercase hex characters. */\n hex(n: number): string;\n}\n\n/** FNV-1a 32-bit hash, used to turn string seeds into numbers. */\nfunction fnv1a(str: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return h >>> 0;\n}\n\n/** mulberry32: tiny, fast, deterministic PRNG. Plenty for generating IDs. */\nfunction mulberry32(seed: number): () => number {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nconst HEX = \"0123456789abcdef\";\n\nexport function normalizeSeed(seed: number | string): number {\n return typeof seed === \"number\" ? seed >>> 0 : fnv1a(seed);\n}\n\n/** Create a random source. With a seed the sequence is fully deterministic. */\nexport function createRng(seed?: number | string): Rng {\n const seeded = seed !== undefined;\n const next = seeded ? mulberry32(normalizeSeed(seed)) : Math.random;\n const hex = (n: number): string => {\n let s = \"\";\n for (let i = 0; i < n; i++) s += HEX[Math.floor(next() * 16)];\n return s;\n };\n return {\n next,\n int: (max) => Math.floor(next() * max),\n hex,\n uuid: () => {\n if (!seeded) return randomUUID();\n const variant = HEX[8 + Math.floor(next() * 4)];\n return `${hex(8)}-${hex(4)}-4${hex(3)}-${variant}${hex(3)}-${hex(12)}`;\n },\n };\n}\n","/** Set `value` at a dot path (`a.b.c`) inside `target`, creating intermediate objects. Mutates and returns `target`. */\nexport function setPath(target: Record<string, unknown>, path: string, value: unknown): Record<string, unknown> {\n const keys = path.split(\".\");\n let cur: Record<string, unknown> = target;\n for (let i = 0; i < keys.length - 1; i++) {\n const k = keys[i]!;\n const next = cur[k];\n if (typeof next !== \"object\" || next === null || Array.isArray(next)) {\n const fresh: Record<string, unknown> = {};\n cur[k] = fresh;\n cur = fresh;\n } else {\n cur = next as Record<string, unknown>;\n }\n }\n cur[keys[keys.length - 1]!] = value;\n return target;\n}\n\n/** Apply a map of dot-path overrides. */\nexport function applyOverrides(target: Record<string, unknown>, overrides: Record<string, unknown>): Record<string, unknown> {\n for (const [k, v] of Object.entries(overrides)) setPath(target, k, v);\n return target;\n}\n","import { RccError } from \"./errors.js\";\nimport type { EventType } from \"../schemas/common.js\";\n\nexport const STATES = [\n \"none\",\n \"trial\",\n \"active\",\n \"cancelled_pending_expiration\",\n \"billing_issue\",\n \"expired\",\n] as const;\nexport type SubscriptionState = (typeof STATES)[number];\n\n/** Extra facts the pure transition needs. */\nexport interface TransitionContext {\n /** Does the product start with a free trial? (INITIAL_PURCHASE from `none`) */\n hasTrial: boolean;\n /** State to return to on UNCANCELLATION (the state before the CANCELLATION). */\n resumeState: \"trial\" | \"active\";\n}\n\nexport class IllegalTransitionError extends RccError {\n readonly state: SubscriptionState;\n readonly event: EventType;\n readonly legal: readonly EventType[];\n constructor(state: SubscriptionState, event: EventType) {\n const legal = legalEvents(state);\n super(\n `Illegal transition: cannot apply ${event} while the subscription is \"${state}\". ` +\n `Legal events from \"${state}\": ${legal.join(\", \")}.`,\n { hint: \"Check the order of the steps in your scenario (e.g. a RENEWAL needs an INITIAL_PURCHASE first).\" },\n );\n this.name = \"IllegalTransitionError\";\n this.state = state;\n this.event = event;\n this.legal = legal;\n }\n}\n\ntype Rule = (ctx: TransitionContext) => SubscriptionState;\n\n/** Transition table. Order of keys = order reported to the user. TEST is added to every state. */\nconst TABLE: Record<SubscriptionState, Partial<Record<EventType, Rule>>> = {\n none: { INITIAL_PURCHASE: (ctx) => (ctx.hasTrial ? \"trial\" : \"active\") },\n trial: {\n RENEWAL: () => \"active\",\n CANCELLATION: () => \"cancelled_pending_expiration\",\n BILLING_ISSUE: () => \"billing_issue\",\n EXPIRATION: () => \"expired\",\n },\n active: {\n RENEWAL: () => \"active\",\n CANCELLATION: () => \"cancelled_pending_expiration\",\n BILLING_ISSUE: () => \"billing_issue\",\n EXPIRATION: () => \"expired\",\n },\n cancelled_pending_expiration: {\n UNCANCELLATION: (ctx) => ctx.resumeState,\n EXPIRATION: () => \"expired\",\n },\n billing_issue: {\n RENEWAL: () => \"active\",\n EXPIRATION: () => \"expired\",\n CANCELLATION: () => \"cancelled_pending_expiration\",\n },\n expired: { INITIAL_PURCHASE: () => \"active\" },\n};\n\n/** Events that may legally follow `state`, in display order. */\nexport function legalEvents(state: SubscriptionState): EventType[] {\n return [...(Object.keys(TABLE[state]) as EventType[]), \"TEST\"];\n}\n\n/** Pure transition. Throws IllegalTransitionError; never returns an incoherent state. */\nexport function transition(state: SubscriptionState, event: EventType, ctx: TransitionContext): SubscriptionState {\n if (event === \"TEST\") return state;\n const rule = TABLE[state][event];\n if (!rule) throw new IllegalTransitionError(state, event);\n return rule(ctx);\n}\n","/**\n * Zod schemas for RevenueCat webhook events (v0.1: 7 event types).\n * Field names, types and inclusion rules follow docs/payload-sources.md (official docs, 2026-08-29).\n * Objects are non-strict: RevenueCat may add fields without bumping api_version.\n */\nimport { z } from \"zod\";\nimport { CANCEL_REASONS, ENVIRONMENTS, EVENT_TYPES, EXPIRATION_REASONS, PERIOD_TYPES, STORES } from \"./common.js\";\n\nconst ms = z.int();\n/** Doubles may be serialised as integers (e.g. `\"price\": 0`). */\nconst double = z.number();\n\nexport const SubscriberAttributeSchema = z.looseObject({\n value: z.string(),\n updated_at_ms: ms,\n});\n\nexport const ExperimentSchema = z.looseObject({\n experiment_id: z.string(),\n experiment_variant: z.string(),\n enrolled_at_ms: ms.nullable(),\n});\n\n/** Common fields — every event type. `app_id` is absent for PROMOTIONAL store events. */\nconst common = {\n id: z.string(),\n event_timestamp_ms: ms,\n app_id: z.string().optional(),\n};\n\n/** Subscriber identity fields. */\nconst identity = {\n app_user_id: z.string(),\n original_app_user_id: z.string(),\n aliases: z.array(z.string()),\n subscriber_attributes: z.record(z.string(), SubscriberAttributeSchema).optional(),\n experiments: z.array(ExperimentSchema).optional(),\n};\n\n/** Subscription lifecycle fields. \"Always\" → required (nullable where documented); \"Sometimes\" → optional. */\nconst lifecycle = {\n product_id: z.string(),\n period_type: z.enum(PERIOD_TYPES),\n purchased_at_ms: ms,\n expiration_at_ms: ms.nullable(),\n environment: z.enum(ENVIRONMENTS),\n entitlement_id: z.string().nullable(),\n entitlement_ids: z.array(z.string()).nullable(),\n presented_offering_id: z.string().nullable(),\n transaction_id: z.string(),\n original_transaction_id: z.string(),\n // Docs: \"Always\" = key present, value may be null. Real PROMOTIONAL events carry null here (T-064).\n is_family_share: z.boolean().nullable(),\n country_code: z.string().nullable(),\n store: z.enum(STORES).optional(),\n currency: z.string().nullable().optional(),\n price: double.nullable().optional(),\n price_in_purchased_currency: double.nullable().optional(),\n tax_percentage: double.nullable().optional(),\n commission_percentage: double.nullable().optional(),\n takehome_percentage: double.nullable().optional(),\n offer_code: z.string().nullable().optional(),\n renewal_number: z.int().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n discount_percentage: double.nullable().optional(),\n discount_amount: double.nullable().optional(),\n discount_identifier: z.string().nullable().optional(),\n};\n\nconst LifecycleEventBase = z.looseObject({ ...common, ...identity, ...lifecycle });\n\nexport const InitialPurchaseEventSchema = LifecycleEventBase.extend({ type: z.literal(\"INITIAL_PURCHASE\") });\n\nexport const RenewalEventSchema = LifecycleEventBase.extend({\n type: z.literal(\"RENEWAL\"),\n is_trial_conversion: z.boolean().optional(),\n});\n\nexport const CancellationEventSchema = LifecycleEventBase.extend({\n type: z.literal(\"CANCELLATION\"),\n cancel_reason: z.enum(CANCEL_REASONS),\n});\n\nexport const UncancellationEventSchema = LifecycleEventBase.extend({ type: z.literal(\"UNCANCELLATION\") });\n\nexport const BillingIssueEventSchema = LifecycleEventBase.extend({\n type: z.literal(\"BILLING_ISSUE\"),\n grace_period_expiration_at_ms: ms.nullable(),\n});\n\nexport const ExpirationEventSchema = LifecycleEventBase.extend({\n type: z.literal(\"EXPIRATION\"),\n expiration_reason: z.enum(EXPIRATION_REASONS),\n});\n\n/** Make every field of a shape `.nullable().optional()` while keeping the key types. */\nfunction nullableOptional<T extends Record<string, z.ZodType>>(shape: T): { [K in keyof T]: z.ZodOptional<z.ZodNullable<T[K]>> } {\n return Object.fromEntries(Object.entries(shape).map(([k, schema]) => [k, schema.nullable().optional()])) as {\n [K in keyof T]: z.ZodOptional<z.ZodNullable<T[K]>>;\n };\n}\n\n/**\n * VERIFIED against a real dashboard test event captured 2026-08-29 (test/fixtures/events/real/TEST.json).\n * RevenueCat publishes no sample; the real payload is \"purchase-like\" but every subscription-lifecycle\n * field may be null (transaction ids, prices, is_family_share, renewal_number, metadata...). Common and\n * subscriber-identity fields are always present.\n */\nexport const TestEventSchema = z.looseObject({\n type: z.literal(\"TEST\"),\n ...common,\n ...identity,\n ...nullableOptional(lifecycle),\n});\n\nexport const EVENT_SCHEMAS = {\n TEST: TestEventSchema,\n INITIAL_PURCHASE: InitialPurchaseEventSchema,\n RENEWAL: RenewalEventSchema,\n CANCELLATION: CancellationEventSchema,\n UNCANCELLATION: UncancellationEventSchema,\n BILLING_ISSUE: BillingIssueEventSchema,\n EXPIRATION: ExpirationEventSchema,\n} as const;\n\nexport const EventSchema = z.discriminatedUnion(\"type\", [\n TestEventSchema,\n InitialPurchaseEventSchema,\n RenewalEventSchema,\n CancellationEventSchema,\n UncancellationEventSchema,\n BillingIssueEventSchema,\n ExpirationEventSchema,\n]);\n\n/** `api_version` is a string (\"1.0\" today); newer versions must not hard-fail (docs: additive changes). */\nexport const WebhookEnvelopeSchema = z.looseObject({\n api_version: z.string(),\n event: EventSchema,\n});\n\n/**\n * Any well-formed RevenueCat event, whatever its `type`. RevenueCat adds event types without bumping\n * `api_version`, so receivers must accept these (T-065). Only the common + identity groups are required.\n */\nexport const UnknownEventSchema = z.looseObject({ type: z.string().min(1), ...common, ...identity });\nexport const UnknownWebhookEnvelopeSchema = z.looseObject({ api_version: z.string(), event: UnknownEventSchema });\nexport type UnknownEvent = z.infer<typeof UnknownEventSchema>;\n\nexport type EnvelopeClassification =\n | { kind: \"known\"; envelope: WebhookEnvelope }\n | { kind: \"unknown-type\"; type: string; envelope: z.infer<typeof UnknownWebhookEnvelopeSchema> }\n | { kind: \"invalid\"; issues: Array<{ path: string; message: string }> };\n\n/** Classify an incoming body: one of our 7 types, a well-formed event of another type, or invalid. */\nexport function classifyEnvelope(body: unknown): EnvelopeClassification {\n const known = WebhookEnvelopeSchema.safeParse(body);\n if (known.success) return { kind: \"known\", envelope: known.data };\n const loose = UnknownWebhookEnvelopeSchema.safeParse(body);\n const typeIsOurs = loose.success && (EVENT_TYPES as readonly string[]).includes(loose.data.event.type);\n if (loose.success && !typeIsOurs) return { kind: \"unknown-type\", type: loose.data.event.type, envelope: loose.data };\n const source = loose.success ? known : loose;\n return {\n kind: \"invalid\",\n issues: source.error.issues.map((i) => ({ path: i.path.join(\".\"), message: i.message })),\n };\n}\n\nexport type Event = z.infer<typeof EventSchema>;\nexport type WebhookEnvelope = z.infer<typeof WebhookEnvelopeSchema>;\nexport type InitialPurchaseEvent = z.infer<typeof InitialPurchaseEventSchema>;\nexport type RenewalEvent = z.infer<typeof RenewalEventSchema>;\nexport type CancellationEvent = z.infer<typeof CancellationEventSchema>;\nexport type UncancellationEvent = z.infer<typeof UncancellationEventSchema>;\nexport type BillingIssueEvent = z.infer<typeof BillingIssueEventSchema>;\nexport type ExpirationEvent = z.infer<typeof ExpirationEventSchema>;\nexport type TestEvent = z.infer<typeof TestEventSchema>;\nexport type LifecycleEvent = Exclude<Event, TestEvent>;\n","import { addDuration, formatDuration, parseDuration, type Duration, type VirtualClock } from \"./clock.js\";\nimport { RccError } from \"./errors.js\";\nimport type { Rng } from \"./rng.js\";\nimport { applyOverrides } from \"./set-path.js\";\nimport { transition, type SubscriptionState } from \"./state-machine.js\";\nimport {\n CLI_STORE_TO_STORE,\n EVENT_SCHEMAS,\n type CliStore,\n type Environment,\n type Event,\n type EventType,\n type PeriodType,\n} from \"../schemas/index.js\";\n\nexport interface SubscriberOptions {\n /** \"auto\" → `$RCAnonymousID:<32 hex>` from the RNG. */\n appUserId?: string | undefined;\n productId: string;\n period: string | Duration;\n /** Free-trial length; omit for no trial. */\n trial?: string | Duration | undefined;\n /** Billing-retry grace period (default P16D). */\n gracePeriod?: string | Duration | undefined;\n store?: CliStore | undefined;\n environment?: Environment | undefined;\n price?: number | undefined;\n currency?: string | undefined;\n countryCode?: string | undefined;\n entitlementIds?: string[] | undefined;\n appId?: string | undefined;\n}\n\nexport interface SubscriberDeps {\n clock: VirtualClock;\n rng: Rng;\n}\n\nexport class PrematureEventError extends RccError {\n constructor(event: EventType, nowMs: number, dueMs: number) {\n const remaining = msToDuration(dueMs - nowMs);\n super(\n `Cannot emit ${event} yet: the virtual clock is at ${new Date(nowMs).toISOString()} ` +\n `but the subscription runs until ${new Date(dueMs).toISOString()}. ` +\n `Add \\`advance: ${remaining}\\` (or more) before this step.`,\n { hint: \"The virtual clock must reach expiration_at_ms (or the end of the grace period) before EXPIRATION.\" },\n );\n this.name = \"PrematureEventError\";\n }\n}\n\nfunction msToDuration(ms: number): string {\n const days = Math.ceil(ms / 86_400_000);\n if (days >= 1) return `P${days}D`;\n return formatDuration({ ...parseDuration(\"PT1S\"), seconds: Math.max(1, Math.ceil(ms / 1000)) });\n}\n\nconst asDuration = (d: string | Duration): Duration => (typeof d === \"string\" ? parseDuration(d) : d);\n\n/**\n * Simulates one subscriber. Owns the state machine, the identity, and the current billing period,\n * and turns event types into schema-valid RevenueCat payloads.\n */\nexport class Subscriber {\n readonly history: Event[] = [];\n\n private _state: SubscriptionState = \"none\";\n private resumeState: \"trial\" | \"active\" = \"active\";\n\n private readonly period: Duration;\n private readonly trial: Duration | undefined;\n private readonly grace: Duration;\n private readonly store;\n private readonly environment: Environment;\n private readonly price: number;\n private readonly currency: string;\n private readonly countryCode: string;\n private readonly entitlementIds: string[];\n private readonly productId: string;\n\n private readonly appUserId: string;\n private readonly appId: string;\n private originalTransactionId: string | undefined;\n private transactionId: string | undefined;\n private purchasedAtMs: number | undefined;\n private expirationAtMs: number | undefined;\n private periodType: PeriodType = \"NORMAL\";\n private gracePeriodExpirationAtMs: number | null = null;\n\n constructor(\n opts: SubscriberOptions,\n private readonly deps: SubscriberDeps,\n ) {\n this.period = asDuration(opts.period);\n this.trial = opts.trial === undefined ? undefined : asDuration(opts.trial);\n this.grace = asDuration(opts.gracePeriod ?? \"P16D\");\n this.store = CLI_STORE_TO_STORE[opts.store ?? \"app_store\"];\n this.environment = opts.environment ?? \"SANDBOX\";\n this.price = opts.price ?? 9.99;\n this.currency = opts.currency ?? \"USD\";\n this.countryCode = opts.countryCode ?? \"US\";\n this.entitlementIds = opts.entitlementIds ?? [\"premium\"];\n this.productId = opts.productId;\n this.appUserId =\n opts.appUserId === undefined || opts.appUserId === \"auto\" ? `$RCAnonymousID:${deps.rng.hex(32)}` : opts.appUserId;\n this.appId = opts.appId ?? `app${deps.rng.hex(12)}`;\n }\n\n get state(): SubscriptionState {\n return this._state;\n }\n\n /** Current period end (ms) or undefined before the first purchase. */\n get expiresAt(): number | undefined {\n return this.expirationAtMs;\n }\n\n /** Emit an event: check legality, time guards, build + validate payload, commit state. */\n emit(type: EventType, overrides: Record<string, unknown> = {}): Event {\n const from = this._state;\n const next = transition(from, type, { hasTrial: this.trial !== undefined, resumeState: this.resumeState });\n const now = this.deps.clock.now();\n\n if (type === \"EXPIRATION\") {\n const due = Math.max(this.expirationAtMs ?? 0, from === \"billing_issue\" ? (this.gracePeriodExpirationAtMs ?? 0) : 0);\n if (now < due) throw new PrematureEventError(type, now, due);\n }\n\n // Work on a draft of the mutable period fields; commit only after validation.\n const draft = this.draftFor(type, from, now);\n const payload = applyOverrides(this.buildPayload(type, from, now, draft), overrides);\n const result = EVENT_SCHEMAS[type].safeParse(payload);\n if (!result.success) {\n const issue = result.error.issues[0]!;\n throw new RccError(`Generated ${type} payload is invalid at \"${issue.path.join(\".\")}\": ${issue.message}`, {\n hint: \"Check your --set / set: overrides against the RevenueCat field types (docs/payload-sources.md).\",\n });\n }\n\n if (type !== \"TEST\") {\n this.originalTransactionId = draft.originalTransactionId;\n this.transactionId = draft.transactionId;\n this.purchasedAtMs = draft.purchasedAtMs;\n this.expirationAtMs = draft.expirationAtMs;\n this.periodType = draft.periodType;\n this.gracePeriodExpirationAtMs = draft.gracePeriodExpirationAtMs;\n if (type === \"CANCELLATION\") this.resumeState = from === \"trial\" ? \"trial\" : \"active\";\n this._state = next;\n }\n const event = result.data;\n this.history.push(event);\n return event;\n }\n\n /* ----------------------------------------------------------- internals */\n\n private newTransactionId(): string {\n // App Store-like 16-digit numeric string.\n let s = String(1 + this.deps.rng.int(9));\n for (let i = 0; i < 15; i++) s += String(this.deps.rng.int(10));\n return s;\n }\n\n private draftFor(type: EventType, from: SubscriptionState, now: number): PeriodDraft {\n const d: PeriodDraft = {\n originalTransactionId: this.originalTransactionId,\n transactionId: this.transactionId,\n purchasedAtMs: this.purchasedAtMs,\n expirationAtMs: this.expirationAtMs,\n periodType: this.periodType,\n gracePeriodExpirationAtMs: this.gracePeriodExpirationAtMs,\n };\n switch (type) {\n case \"INITIAL_PURCHASE\": {\n const startsTrial = from === \"none\" && this.trial !== undefined;\n d.transactionId = this.newTransactionId();\n d.originalTransactionId ??= d.transactionId;\n d.purchasedAtMs = now;\n d.expirationAtMs = addDuration(now, startsTrial ? this.trial : this.period);\n d.periodType = startsTrial ? \"TRIAL\" : \"NORMAL\";\n d.gracePeriodExpirationAtMs = null;\n break;\n }\n case \"RENEWAL\": {\n const start = d.expirationAtMs ?? now;\n d.transactionId = this.newTransactionId();\n d.purchasedAtMs = start;\n d.expirationAtMs = addDuration(start, this.period);\n d.periodType = \"NORMAL\";\n d.gracePeriodExpirationAtMs = null;\n break;\n }\n case \"BILLING_ISSUE\":\n d.gracePeriodExpirationAtMs = addDuration(now, this.grace);\n break;\n case \"TEST\":\n if (from === \"none\") {\n d.transactionId = d.originalTransactionId = this.newTransactionId();\n d.purchasedAtMs = now;\n d.expirationAtMs = addDuration(now, this.period);\n d.periodType = \"NORMAL\";\n }\n break;\n default:\n break;\n }\n return d;\n }\n\n private buildPayload(type: EventType, from: SubscriptionState, now: number, d: PeriodDraft): Record<string, unknown> {\n const isPurchase = type === \"INITIAL_PURCHASE\" || type === \"RENEWAL\" || type === \"TEST\";\n const price = isPurchase && d.periodType !== \"TRIAL\" ? this.price : 0;\n const payload: Record<string, unknown> = {\n type,\n id: this.deps.rng.uuid(),\n event_timestamp_ms: now,\n app_id: this.appId,\n app_user_id: this.appUserId,\n original_app_user_id: this.appUserId,\n aliases: [this.appUserId],\n subscriber_attributes: {},\n product_id: this.productId,\n period_type: d.periodType,\n purchased_at_ms: d.purchasedAtMs,\n expiration_at_ms: d.expirationAtMs,\n environment: this.environment,\n entitlement_id: null,\n entitlement_ids: [...this.entitlementIds],\n presented_offering_id: null,\n transaction_id: d.transactionId,\n original_transaction_id: d.originalTransactionId,\n is_family_share: false,\n country_code: this.countryCode,\n store: this.store,\n currency: this.currency,\n price,\n price_in_purchased_currency: price,\n tax_percentage: 0,\n commission_percentage: 0.3,\n takehome_percentage: 0.7,\n offer_code: null,\n };\n switch (type) {\n case \"RENEWAL\":\n payload[\"is_trial_conversion\"] = from === \"trial\";\n break;\n case \"CANCELLATION\":\n payload[\"cancel_reason\"] = from === \"billing_issue\" ? \"BILLING_ERROR\" : \"UNSUBSCRIBE\";\n break;\n case \"BILLING_ISSUE\":\n payload[\"grace_period_expiration_at_ms\"] = d.gracePeriodExpirationAtMs;\n break;\n case \"EXPIRATION\":\n payload[\"expiration_reason\"] = from === \"billing_issue\" ? \"BILLING_ERROR\" : \"UNSUBSCRIBE\";\n break;\n default:\n break;\n }\n return payload;\n }\n}\n\ninterface PeriodDraft {\n originalTransactionId: string | undefined;\n transactionId: string | undefined;\n purchasedAtMs: number | undefined;\n expirationAtMs: number | undefined;\n periodType: PeriodType;\n gracePeriodExpirationAtMs: number | null;\n}\n","import { VirtualClock, addDuration, parseDuration } from \"./clock.js\";\nimport { RccError } from \"./errors.js\";\nimport { postEvent } from \"./http.js\";\nimport { createRng } from \"./rng.js\";\nimport type { LoadedScenario, Scenario, Step } from \"./scenario.js\";\nimport { Subscriber, type SubscriberOptions } from \"./subscriber.js\";\nimport type { Event, EventType, WebhookEnvelope } from \"../schemas/index.js\";\n\nexport interface Simulation {\n clock: VirtualClock;\n subscriber: Subscriber;\n}\n\n/** Create a clock + subscriber pair. Seeded → fixed epoch; unseeded → `startAt` (default now). */\nexport function createSimulation(opts: SubscriberOptions, seed: number | string | undefined, startAt?: number): Simulation {\n const clock = VirtualClock.forSeed(seed, startAt);\n const subscriber = new Subscriber(opts, { clock, rng: createRng(seed) });\n return { clock, subscriber };\n}\n\n/** Apply one step to a simulation. Returns the emitted event for `event` steps. */\nexport function applyStep(sim: Simulation, step: Step): Event | undefined {\n if (step.advance !== undefined) {\n sim.clock.advance(step.advance);\n return undefined;\n }\n return sim.subscriber.emit(step.event!, step.set ?? {});\n}\n\n/** Total virtual time a list of steps advances, starting from `fromMs` (calendar-aware). */\nexport function spanOf(steps: readonly Step[], fromMs: number): number {\n let t = fromMs;\n for (const s of steps) if (s.advance !== undefined) t = addDuration(t, parseDuration(s.advance));\n return t - fromMs;\n}\n\n/** Shortest legal history before a single event (see specs/F2-commands.md). */\nexport function preludeFor(type: EventType): Step[] {\n const ip: Step = { event: \"INITIAL_PURCHASE\" };\n switch (type) {\n case \"TEST\":\n case \"INITIAL_PURCHASE\":\n return [];\n case \"RENEWAL\":\n case \"BILLING_ISSUE\":\n return [ip, { advance: \"P1M\" }];\n case \"CANCELLATION\":\n return [ip, { advance: \"P10D\" }];\n case \"UNCANCELLATION\":\n return [ip, { advance: \"P10D\" }, { event: \"CANCELLATION\" }, { advance: \"P1D\" }];\n case \"EXPIRATION\":\n return [ip, { advance: \"P10D\" }, { event: \"CANCELLATION\" }, { advance: \"P21D\" }];\n }\n}\n\n/* ------------------------------------------------------------------ runScenario */\n\nexport interface EventResult {\n /** 0-based index of the step in `scenario.steps`. */\n step: number;\n type: EventType;\n virtualTime: string;\n status: number | null;\n latencyMs: number | null;\n event: Event;\n}\n\nexport interface ExpectationResult {\n scope: \"step\" | \"scenario\";\n step: number | null;\n rule: string;\n expected: string;\n actual: string;\n ok: boolean;\n}\n\nexport interface RunResult {\n scenario: string;\n seed: number | string | null;\n startedAt: string;\n endedAt: string;\n virtualSpanMs: number;\n events: EventResult[];\n expectations: ExpectationResult[];\n ok: boolean;\n}\n\nexport interface RunOptions {\n to: string;\n authHeader?: string | undefined;\n speed: \"instant\" | number;\n seed?: number | string | undefined;\n dryRun?: boolean | undefined;\n source?: Pick<LoadedScenario, \"file\" | \"stepPositions\"> | undefined;\n onEvent?: ((result: EventResult, envelope: WebhookEnvelope) => void) | undefined;\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));\n\nfunction subscriberOptions(scenario: Scenario): SubscriberOptions {\n const s = scenario.subscriber;\n return {\n appUserId: s.app_user_id,\n productId: s.product_id,\n period: s.period,\n trial: s.trial,\n gracePeriod: s.grace_period,\n store: s.store,\n environment: s.environment,\n };\n}\n\nfunction stepLabel(index: number, source: RunOptions[\"source\"]): string {\n const pos = source?.stepPositions[index];\n return pos ? `step ${index + 1} (${source.file}:${pos.line})` : `step ${index + 1}`;\n}\n\n/** Execute a scenario: advance the virtual clock, emit coherent events, deliver them, collect results. */\nexport async function runScenario(scenario: Scenario, opts: RunOptions): Promise<RunResult> {\n const sim = createSimulation(subscriberOptions(scenario), opts.seed);\n const startedMs = sim.clock.now();\n const events: EventResult[] = [];\n let delivered = 0;\n\n for (const [index, step] of scenario.steps.entries()) {\n if (step.advance !== undefined) {\n sim.clock.advance(step.advance);\n continue;\n }\n if (delivered > 0 && opts.speed !== \"instant\") await sleep(opts.speed);\n\n let event: Event;\n try {\n event = sim.subscriber.emit(step.event!, step.set ?? {});\n } catch (err) {\n if (err instanceof RccError) {\n throw new RccError(`${stepLabel(index, opts.source)}: ${err.message}`, {\n ...(err.hint === undefined ? {} : { hint: err.hint }),\n exitCode: err.exitCode,\n cause: err,\n });\n }\n throw err;\n }\n const envelope: WebhookEnvelope = { api_version: \"1.0\", event };\n let status: number | null = null;\n let latencyMs: number | null = null;\n if (!opts.dryRun) {\n const res = await postEvent(opts.to, envelope, { authHeader: opts.authHeader });\n status = res.status;\n latencyMs = res.latencyMs;\n }\n delivered++;\n const result: EventResult = { step: index, type: event.type, virtualTime: new Date(sim.clock.now()).toISOString(), status, latencyMs, event };\n events.push(result);\n opts.onEvent?.(result, envelope);\n }\n\n const endedMs = sim.clock.now();\n const expectations = evaluateExpectations(scenario, events);\n const allDelivered = events.every((e) => e.status === null || (e.status >= 200 && e.status < 300));\n return {\n scenario: scenario.name,\n seed: opts.seed ?? null,\n startedAt: new Date(startedMs).toISOString(),\n endedAt: new Date(endedMs).toISOString(),\n virtualSpanMs: endedMs - startedMs,\n events,\n expectations,\n ok: allDelivered && expectations.every((e) => e.ok),\n };\n}\n\n/* ------------------------------------------------------------------ expectations */\n\nconst SKIPPED = \"skipped\";\n\n/** Pure: evaluate step-level and scenario-level `expect:` blocks against the recorded results. */\nexport function evaluateExpectations(scenario: Scenario, events: readonly EventResult[]): ExpectationResult[] {\n const out: ExpectationResult[] = [];\n const label = (e: EventResult): string => `step ${e.step + 1} ${e.type}`;\n\n for (const e of events) {\n const want = scenario.steps[e.step]?.expect?.response_status;\n if (want === undefined) continue;\n const skipped = e.status === null;\n out.push({\n scope: \"step\",\n step: e.step,\n rule: \"response_status\",\n expected: String(want),\n actual: skipped ? SKIPPED : String(e.status),\n ok: skipped || e.status === want,\n });\n }\n\n const all = scenario.expect?.all_responses_status;\n if (all !== undefined) {\n const offenders = events.filter((e) => e.status !== null && e.status !== all);\n const skipped = events.every((e) => e.status === null);\n out.push({\n scope: \"scenario\",\n step: null,\n rule: \"all_responses_status\",\n expected: String(all),\n actual: skipped ? SKIPPED : offenders.length === 0 ? String(all) : offenders.map((e) => `${e.status} (${label(e)})`).join(\", \"),\n ok: skipped || offenders.length === 0,\n });\n }\n\n const max = scenario.expect?.max_response_ms;\n if (max !== undefined) {\n const measured = events.filter((e) => e.latencyMs !== null);\n const slowest = measured.reduce<EventResult | undefined>((acc, e) => (acc === undefined || e.latencyMs! > acc.latencyMs! ? e : acc), undefined);\n const skipped = slowest === undefined;\n out.push({\n scope: \"scenario\",\n step: null,\n rule: \"max_response_ms\",\n expected: `≤ ${max} ms`,\n actual: skipped ? SKIPPED : `${slowest.latencyMs} ms (${label(slowest)})`,\n ok: skipped || slowest.latencyMs! <= max,\n });\n }\n return out;\n}\n","export interface Writer {\n write(s: string): unknown;\n}\nexport interface Io {\n stdout: Writer;\n stderr: Writer;\n}\nexport const defaultIo: Io = { stdout: process.stdout, stderr: process.stderr };\nexport const println = (w: Writer, s = \"\"): void => {\n w.write(s + \"\\n\");\n};\n","import type { Command } from \"commander\";\nimport { RccError } from \"../core/errors.js\";\nimport { CONFIG_FILE, DEFAULT_TARGET, loadConfig, resolveDefaults } from \"../core/config.js\";\nimport { applyStep, createSimulation, preludeFor, spanOf } from \"../core/engine.js\";\nimport { assertUrl, postEvent } from \"../core/http.js\";\nimport { println, type Io } from \"../core/io.js\";\nimport { green, red, dim } from \"../core/colors.js\";\nimport { CLI_STORES, ENVIRONMENTS, EVENT_TYPES, type CliStore, type Environment, type EventType } from \"../schemas/common.js\";\nimport type { WebhookEnvelope } from \"../schemas/index.js\";\n\nexport { DEFAULT_TARGET };\n\nexport interface SendOptions {\n to?: string | undefined;\n store?: string | undefined;\n user?: string;\n product: string;\n authHeader?: string | undefined;\n environment?: string | undefined;\n set?: string[] | undefined;\n seed?: string;\n dryRun?: boolean | undefined;\n}\n\n/** Parse repeatable `--set key=value`. Values are JSON when they parse, otherwise strings. */\nexport function parseSetFlag(pairs: readonly string[]): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const pair of pairs) {\n const eq = pair.indexOf(\"=\");\n if (eq <= 0) {\n throw new RccError(`Invalid --set \"${pair}\": expected key=value.`, {\n hint: \"Example: --set price=4.99 --set subscriber_attributes.plan.value=pro\",\n });\n }\n const key = pair.slice(0, eq);\n const raw = pair.slice(eq + 1);\n let value: unknown = raw;\n try {\n value = JSON.parse(raw);\n } catch {\n /* plain string */\n }\n out[key] = value;\n }\n return out;\n}\n\nexport function parseEventType(input: string): EventType {\n const upper = input.toUpperCase();\n if ((EVENT_TYPES as readonly string[]).includes(upper)) return upper as EventType;\n throw new RccError(`Unknown event type \"${input}\". Valid types: ${EVENT_TYPES.join(\", \")}.`, {\n hint: \"Example: rcc send INITIAL_PURCHASE\",\n });\n}\n\nexport function parseEnvironment(input: string): Environment {\n if ((ENVIRONMENTS as readonly string[]).includes(input)) return input as Environment;\n throw new RccError(`Invalid --environment \"${input}\". Use one of: ${ENVIRONMENTS.join(\", \")}.`);\n}\n\nexport function parseStore(input: string): CliStore {\n if ((CLI_STORES as readonly string[]).includes(input)) return input as CliStore;\n throw new RccError(`Unsupported --store \"${input}\". v0.1 supports: ${CLI_STORES.join(\", \")}.`, {\n hint: \"Other stores are on the roadmap (see docs/BACKLOG.md → Icebox).\",\n });\n}\n\nexport function parseSeed(input: string | undefined): number | string | undefined {\n if (input === undefined) return undefined;\n return /^\\d+$/.test(input) ? Number(input) : input;\n}\n\n/** Build the single event (after its prelude) as an envelope. Exported for tests and `run`. */\nexport function buildSingleEvent(type: EventType, opts: SendOptions): WebhookEnvelope {\n const seed = parseSeed(opts.seed);\n const prelude = preludeFor(type);\n const subscriberOpts = {\n appUserId: opts.user ?? \"auto\",\n productId: opts.product,\n period: \"P1M\",\n store: parseStore(opts.store ?? \"app_store\"),\n environment: parseEnvironment(opts.environment ?? \"SANDBOX\"),\n };\n // Unseeded: start in the past so the final event lands at ≈ now.\n const startAt = seed === undefined ? Date.now() - spanOf(prelude, Date.now()) : undefined;\n const sim = createSimulation(subscriberOpts, seed, startAt);\n for (const step of prelude) applyStep(sim, step);\n const event = sim.subscriber.emit(type, parseSetFlag(opts.set ?? []));\n return { api_version: \"1.0\", event };\n}\n\nexport function registerSend(program: Command, io: Io): void {\n program\n .command(\"send\")\n .argument(\"<EVENT_TYPE>\", `event to send: ${EVENT_TYPES.join(\" | \")}`)\n .description(\"Send a single, schema-valid RevenueCat webhook event to your endpoint.\")\n .option(\"--to <url>\", `target URL (default: ${DEFAULT_TARGET}, or \"to\" in ${CONFIG_FILE})`)\n .option(\"--store <store>\", `store: ${CLI_STORES.join(\" | \")} (default: app_store, or \"store\" in ${CONFIG_FILE})`)\n .option(\"--user <app_user_id>\", \"app_user_id (default: generated $RCAnonymousID)\")\n .option(\"--product <product_id>\", \"product_id\", \"com.example.premium.monthly\")\n .option(\"--auth-header <value>\", `value sent as the Authorization header (default: \"authHeader\" in ${CONFIG_FILE})`)\n .option(\"--environment <env>\", `${ENVIRONMENTS.join(\" | \")} (default: SANDBOX, or \"environment\" in ${CONFIG_FILE})`)\n .option(\"--set <key=value>\", \"override a payload field (repeatable, dot paths allowed)\", (v: string, acc: string[] | undefined) => [...(acc ?? []), v])\n .option(\"--seed <seed>\", \"deterministic ids and timestamps\")\n .option(\"--dry-run\", \"print the payload instead of sending it\")\n .addHelpText(\"after\", `\nExamples:\n $ rcc send INITIAL_PURCHASE\n $ rcc send RENEWAL --to http://localhost:8787/webhook --auth-header \"Bearer dev\"\n $ rcc send CANCELLATION --set cancel_reason=BILLING_ERROR --dry-run | jq .event.type`)\n .action(async (eventType: string, opts: SendOptions) => {\n const type = parseEventType(eventType);\n const d = resolveDefaults(opts, loadConfig());\n const to = assertUrl(d.to, \"--to\");\n const envelope = buildSingleEvent(type, { ...opts, to, store: d.store, environment: d.environment, authHeader: d.authHeader });\n if (opts.dryRun) {\n println(io.stdout, JSON.stringify(envelope, null, 2));\n return;\n }\n const res = await postEvent(to, envelope, { authHeader: d.authHeader });\n const ok = res.status >= 200 && res.status < 300;\n const mark = ok ? green(\"✔\") : red(\"✖\");\n println(io.stdout, `${mark} ${type.padEnd(16)} → ${to} ${res.status} ${dim(`(${res.latencyMs} ms)`)}`);\n if (!ok) {\n throw new RccError(`Endpoint answered ${res.status} for ${type}.`, {\n hint: \"RevenueCat treats anything other than 200 as a failure and retries. Check your handler logs.\",\n });\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport { RccError } from \"../core/errors.js\";\nimport { assertUrl } from \"../core/http.js\";\nimport { println, type Io } from \"../core/io.js\";\nimport { bold, cyan, dim, green, red, yellow } from \"../core/colors.js\";\nimport { classifyEnvelope } from \"../schemas/index.js\";\n\nexport const DEFAULT_PORT = 8787;\n\nexport interface ListenOptions {\n port: number;\n forward?: string | undefined;\n authHeader?: string | undefined;\n verbose?: boolean | undefined;\n io: Io;\n}\n\nexport interface Listener {\n url: string;\n port: number;\n close(): Promise<void>;\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let raw = \"\";\n req.on(\"data\", (c: Buffer) => (raw += c.toString(\"utf8\")));\n req.on(\"end\", () => resolve(raw));\n req.on(\"error\", reject);\n });\n}\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { \"content-type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n\nconst clock = (): string => new Date().toISOString().slice(11, 19);\n\n/** Start the local webhook receiver. Resolves once listening. */\nexport async function startListener(opts: ListenOptions): Promise<Listener> {\n const { io } = opts;\n const log = (s: string): void => println(io.stdout, s);\n\n const server = createServer((req, res) => {\n void handle(req, res);\n });\n\n async function handle(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (req.method !== \"POST\") {\n json(res, 404, { error: `Use POST to deliver webhook events (got ${req.method ?? \"?\"} ${req.url ?? \"\"}).` });\n return;\n }\n const raw = await readBody(req);\n const time = dim(clock());\n\n if (opts.authHeader !== undefined && req.headers[\"authorization\"] !== opts.authHeader) {\n log(`${time} ${red(bold(\"AUTH MISMATCH\"))} Authorization header ${req.headers[\"authorization\"] === undefined ? \"missing\" : \"does not match --auth-header\"} → 401`);\n json(res, 401, { error: \"Authorization header mismatch\" });\n return;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n log(`${time} ${red(bold(\"INVALID\"))} body is not JSON → 400`);\n json(res, 400, { error: \"Body is not valid JSON\" });\n return;\n }\n const classified = classifyEnvelope(parsed);\n if (classified.kind === \"invalid\") {\n const issues = classified.issues.map((i) => ({ path: i.path || \"(root)\", message: i.message }));\n const shown = issues.slice(0, 3).map((i) => `${i.path}: ${i.message}`).join(\"; \");\n const more = issues.length > 3 ? ` (+${issues.length - 3} more)` : \"\";\n log(`${time} ${red(bold(\"INVALID\"))} ${shown}${more} → 400`);\n if (opts.verbose) log(dim(JSON.stringify(parsed, null, 2)));\n json(res, 400, { error: \"Invalid RevenueCat webhook envelope\", issues });\n return;\n }\n\n const ev = classified.envelope.event;\n const typeLabel =\n classified.kind === \"known\"\n ? cyan(bold(ev.type.padEnd(16)))\n : `${yellow(bold(\"UNSUPPORTED\"))} ${yellow(ev.type)}`;\n let status = 200;\n let suffix = \"\";\n if (opts.forward !== undefined) {\n try {\n const headers: Record<string, string> = { \"content-type\": \"application/json\" };\n const auth = req.headers[\"authorization\"];\n if (auth !== undefined) headers[\"authorization\"] = auth;\n const started = performance.now();\n const upstream = await fetch(opts.forward, { method: \"POST\", headers, body: raw, signal: AbortSignal.timeout(30_000) });\n status = upstream.status;\n suffix = ` ${dim(\"→ forwarded\")} ${opts.forward} ${status < 300 ? green(String(status)) : red(String(status))} ${dim(`(${Math.round(performance.now() - started)} ms)`)}`;\n } catch (err) {\n status = 502;\n suffix = ` ${red(\"forward failed\")}: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n const statusText = status < 300 ? green(String(status)) : red(String(status));\n const productId = typeof ev[\"product_id\"] === \"string\" ? ev[\"product_id\"] : \"\";\n log(`${time} ${typeLabel} ${yellow(ev.app_user_id)} ${productId} → ${statusText}${suffix}`);\n if (opts.verbose) log(dim(JSON.stringify(classified.envelope, null, 2)));\n json(res, status, { ok: status < 300 });\n }\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n reject(\n err.code === \"EADDRINUSE\"\n ? new RccError(`Port ${opts.port} is already in use.`, { hint: `Pick another one: rcc listen --port ${opts.port + 1}` })\n : new RccError(`Could not start the listener: ${err.message}`, { cause: err }),\n );\n });\n server.listen(opts.port, () => resolve());\n });\n\n const port = (server.address() as AddressInfo).port;\n const url = `http://localhost:${port}/webhook`;\n log(`${green(\"●\")} Listening on ${bold(url)}`);\n if (opts.authHeader !== undefined) log(dim(` expecting Authorization: ${opts.authHeader}`));\n if (opts.forward !== undefined) log(dim(` forwarding to ${opts.forward}`));\n log(dim(` try: rcc send INITIAL_PURCHASE --to ${url}`));\n\n return {\n url,\n port,\n close: () =>\n new Promise((resolve, reject) => {\n server.closeAllConnections();\n server.close((err) => (err ? reject(err) : resolve()));\n }),\n };\n}\n\nexport function registerListen(program: Command, io: Io): void {\n program\n .command(\"listen\")\n .description(\"Start a local HTTP server that receives, validates and pretty-prints webhook events.\")\n .option(\"--port <n>\", \"port to listen on\", String(DEFAULT_PORT))\n .option(\"--forward <url>\", \"forward each request (body + Authorization) to this URL and relay its status\")\n .option(\"--auth-header <value>\", \"expected Authorization header; mismatches are flagged and answered 401\")\n .option(\"--verbose\", \"print the full JSON payload of each event\")\n .addHelpText(\"after\", `\nExamples:\n $ rcc listen\n $ rcc listen --port 9000 --auth-header \"Bearer dev\" --verbose\n $ rcc listen --forward http://localhost:3000/webhook`)\n .action(async (opts: { port: string; forward?: string; authHeader?: string; verbose?: boolean }) => {\n if (!/^\\d{1,5}$/.test(opts.port) || Number(opts.port) > 65535) {\n throw new RccError(`Invalid --port \"${opts.port}\".`, { hint: \"Use an integer between 1 and 65535.\" });\n }\n if (opts.forward !== undefined) assertUrl(opts.forward, \"--forward\");\n const listener = await startListener({ ...opts, port: Number(opts.port), io });\n const stop = (): void => {\n void listener.close().finally(() => process.exit(0));\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n await new Promise<void>(() => {\n /* run until killed */\n });\n });\n}\n","import { bold, dim, green, red } from \"./colors.js\";\nimport type { EventResult, RunResult } from \"./engine.js\";\nimport type { Scenario } from \"./scenario.js\";\n\n/** Render rows as a padded text table. Colour helpers must not affect widths, so cells are coloured after padding. */\nexport function table(headers: string[], rows: string[][], colour?: (cell: string, col: number, row: number) => string): string {\n const widths = headers.map((h, i) => Math.max(h.length, ...rows.map((r) => (r[i] ?? \"\").length)));\n const pad = (cells: string[], row: number): string =>\n cells\n .map((c, i) => {\n const padded = i === 0 ? c.padStart(widths[i]!) : c.padEnd(widths[i]!);\n return colour && row >= 0 ? colour(padded, i, row) : padded;\n })\n .join(\" \")\n .trimEnd();\n return [dim(pad(headers, -1)), ...rows.map((r, i) => pad(r, i))].join(\"\\n\");\n}\n\nexport function humanDays(ms: number): string {\n return `${Math.round(ms / 86_400_000)}d`;\n}\n\nconst RUN_HEADERS = [\"#\", \"event\", \"virtual time\", \"status\", \"latency\"] as const;\n\n/**\n * Table renderer whose column widths are known up front (from the scenario), so rows can be\n * printed one by one as events are delivered and still line up with the header.\n */\nexport interface LiveTable {\n header(): string;\n row(e: EventResult, index: number): string;\n}\n\nexport function createRunTable(scenario: Pick<Scenario, \"steps\">): LiveTable {\n const eventCount = scenario.steps.filter((s) => s.event !== undefined).length;\n const eventTypes = scenario.steps.map((s) => s.event ?? \"\");\n const widths = [\n Math.max(RUN_HEADERS[0].length, String(eventCount).length),\n Math.max(RUN_HEADERS[1].length, ...eventTypes.map((t) => t.length)),\n Math.max(RUN_HEADERS[2].length, \"2025-01-01T00:00:00.000Z\".length),\n RUN_HEADERS[3].length,\n Math.max(RUN_HEADERS[4].length, \"99999 ms\".length),\n ];\n const pad = (cells: readonly string[], colour?: (cell: string, col: number) => string): string =>\n cells\n .map((c, i) => {\n const padded = i === 0 ? c.padStart(widths[i]!) : c.padEnd(widths[i]!);\n return colour ? colour(padded, i) : padded;\n })\n .join(\" \")\n .trimEnd();\n return {\n header: () => dim(pad(RUN_HEADERS)),\n row: (e, index) =>\n pad(\n [String(index + 1), e.type, e.virtualTime, e.status === null ? \"—\" : String(e.status), e.latencyMs === null ? \"—\" : `${e.latencyMs} ms`],\n (cell, col) => {\n if (col !== 3) return cell;\n if (e.status === null) return dim(cell);\n return e.status >= 200 && e.status < 300 ? green(cell) : red(cell);\n },\n ),\n };\n}\n\n/** Whole table at once (same layout as the live version). */\nexport function renderRunTable(result: RunResult, scenario?: Pick<Scenario, \"steps\">): string {\n const t = createRunTable(scenario ?? { steps: result.events.map((e) => ({ event: e.type })) });\n return [t.header(), ...result.events.map((e, i) => t.row(e, i))].join(\"\\n\");\n}\n\nexport function renderRunSummary(result: RunResult): string {\n const total = result.events.length;\n const okCount = result.events.filter((e) => e.status !== null && e.status >= 200 && e.status < 300).length;\n const failed = result.events.filter((e) => e.status !== null && !(e.status >= 200 && e.status < 300)).length;\n const span = `${humanDays(result.virtualSpanMs)} (${result.startedAt.slice(0, 10)} → ${result.endedAt.slice(0, 10)})`;\n const counts = result.events.some((e) => e.status === null)\n ? `${total} events · dry run`\n : `${total} events · ${okCount} ok · ${failed} failed`;\n const exps = result.expectations;\n const expText = exps.length ? ` · ${exps.filter((e) => e.ok).length}/${exps.length} expectations passed` : \"\";\n const mark = result.ok ? green(\"✔\") : red(\"✖\");\n return `${mark} ${bold(counts)} · virtual span ${span}${expText}`;\n}\n\nexport function renderFailedExpectations(result: RunResult): string[] {\n return result.expectations\n .filter((e) => !e.ok)\n .map((e) => {\n const where = e.scope === \"step\" ? `step ${e.step! + 1} ${result.events.find((ev) => ev.step === e.step)?.type ?? \"\"}` : \"scenario\";\n return `${red(\"✖\")} expectation failed · ${where} · ${e.rule}: expected ${e.expected}, got ${e.actual}`;\n });\n}\n","import { readFileSync } from \"node:fs\";\nimport { LineCounter, isMap, isNode, parseDocument, type Document, type Node } from \"yaml\";\nimport { z } from \"zod\";\nimport { parseDuration } from \"./clock.js\";\nimport { RccError } from \"./errors.js\";\nimport { CLI_STORES, ENVIRONMENTS, EVENT_TYPES } from \"../schemas/common.js\";\n\n/* ------------------------------------------------------------------ schema */\n\nconst duration = z.string().superRefine((val, ctx) => {\n try {\n parseDuration(val);\n } catch {\n ctx.addIssue({ code: \"custom\", message: `Invalid ISO-8601 duration: \"${val}\". Examples: P1M, P1W, P3D, PT12H.` });\n }\n});\n\nconst list = (values: readonly string[]): string => values.join(\", \");\n\nconst eventType = z.enum(EVENT_TYPES, {\n error: (iss) => `Unknown event type \"${String(iss.input)}\". Valid types: ${list(EVENT_TYPES)}.`,\n});\n\nconst httpStatus = z.int({ error: \"response_status must be an integer HTTP status (e.g. 200).\" }).min(100).max(599);\n\nexport const SubscriberConfigSchema = z.strictObject({\n app_user_id: z.string().min(1).default(\"auto\"),\n product_id: z.string().min(1).default(\"com.example.premium.monthly\"),\n period: duration.default(\"P1M\"),\n trial: duration.optional(),\n grace_period: duration.default(\"P16D\"),\n store: z.enum(CLI_STORES, {\n error: (iss) => `Unsupported store \"${String(iss.input)}\". v0.1 supports: ${list(CLI_STORES)}.`,\n }).default(\"app_store\"),\n environment: z.enum(ENVIRONMENTS, {\n error: (iss) => `Invalid environment \"${String(iss.input)}\". Use one of: ${list(ENVIRONMENTS)}.`,\n }).default(\"SANDBOX\"),\n});\n\nconst StepExpectSchema = z.strictObject({ response_status: httpStatus });\n\n/** Overrides applied to a payload; keys may be dot paths (`subscriber_attributes.plan.value`). */\nconst SetSchema = z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()]));\n\nconst RawStepSchema = z.strictObject({\n event: eventType.optional(),\n advance: duration.optional(),\n set: SetSchema.optional(),\n expect: StepExpectSchema.optional(),\n});\n\nconst StepSchema = RawStepSchema.superRefine((step, ctx) => {\n const hasEvent = step.event !== undefined;\n const hasAdvance = step.advance !== undefined;\n if (hasEvent === hasAdvance) {\n ctx.addIssue({\n code: \"custom\",\n message: \"A step must have exactly one of `event: <TYPE>` or `advance: <duration>`.\",\n });\n return;\n }\n if (hasAdvance && (step.set !== undefined || step.expect !== undefined)) {\n ctx.addIssue({ code: \"custom\", message: \"`set` and `expect` are only allowed on `event` steps.\" });\n }\n});\n\nexport const ScenarioExpectSchema = z.strictObject({\n all_responses_status: httpStatus.optional(),\n max_response_ms: z.int().positive({ error: \"max_response_ms must be a positive integer (milliseconds).\" }).optional(),\n});\n\nexport const ScenarioSchema = z.strictObject({\n name: z\n .string({ error: \"`name` is required.\" })\n .regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/, \"name may only contain letters, digits, '.', '_' and '-'.\"),\n description: z.string().optional(),\n subscriber: SubscriberConfigSchema.default({\n app_user_id: \"auto\",\n product_id: \"com.example.premium.monthly\",\n period: \"P1M\",\n grace_period: \"P16D\",\n store: \"app_store\",\n environment: \"SANDBOX\",\n }),\n steps: z.array(StepSchema).min(1, \"`steps` must contain at least one step.\"),\n expect: ScenarioExpectSchema.optional(),\n});\n\nexport type Scenario = z.infer<typeof ScenarioSchema>;\nexport type SubscriberConfig = z.infer<typeof SubscriberConfigSchema>;\nexport type Step = z.infer<typeof StepSchema>;\nexport type EventStep = Step & { event: NonNullable<Step[\"event\"]> };\nexport type AdvanceStep = Step & { advance: string };\n\nexport function isEventStep(step: Step): step is EventStep {\n return step.event !== undefined;\n}\n\n/* ------------------------------------------------------------------ errors */\n\nexport class ScenarioValidationError extends RccError {\n readonly file: string;\n readonly line: number;\n readonly column: number;\n readonly path: string;\n constructor(opts: { file: string; line: number; column: number; path: string; detail: string; hint?: string }) {\n const where = opts.path === \"\" ? \"\" : `${opts.path}: `;\n super(`${opts.file}:${opts.line}:${opts.column} — ${where}${opts.detail}`, {\n hint: opts.hint ?? \"See the scenario format in the README or run `rcc init` for working examples.\",\n });\n this.name = \"ScenarioValidationError\";\n this.file = opts.file;\n this.line = opts.line;\n this.column = opts.column;\n this.path = opts.path;\n }\n}\n\nfunction dotted(path: readonly PropertyKey[]): string {\n return path.reduce<string>((acc, seg) => {\n if (typeof seg === \"number\") return `${acc}[${seg}]`;\n return acc === \"\" ? String(seg) : `${acc}.${String(seg)}`;\n }, \"\");\n}\n\ninterface Pos {\n line: number;\n column: number;\n}\n\n/** Find the best YAML node for a zod path (walking up when the node is missing) and return its 1-based position. */\nfunction locate(doc: Document, counter: LineCounter, path: readonly PropertyKey[], keyName?: string): Pos {\n const segs = path.filter((s): s is string | number => typeof s !== \"symbol\");\n for (let depth = segs.length; depth >= 0; depth--) {\n const sub = segs.slice(0, depth);\n const node: unknown = sub.length === 0 ? doc.contents : doc.getIn(sub, true);\n if (!isNode(node)) continue;\n if (keyName !== undefined && depth === segs.length && isMap(node)) {\n const pair = node.items.find((p) => isNode(p.key) && String(p.key.toJSON()) === keyName);\n const keyNode = pair?.key;\n if (isNode(keyNode) && keyNode.range) return toPos(counter, keyNode.range[0]);\n }\n if ((node as Node).range) return toPos(counter, (node as Node).range![0]);\n }\n return { line: 1, column: 1 };\n}\n\nfunction toPos(counter: LineCounter, offset: number): Pos {\n const { line, col } = counter.linePos(offset);\n return { line, column: col };\n}\n\n/* ------------------------------------------------------------------ loading */\n\nexport interface StepPosition {\n line: number;\n column: number;\n}\n\nexport interface LoadedScenario {\n scenario: Scenario;\n file: string;\n /** 1-based position of every step node, for mid-run error messages. */\n stepPositions: StepPosition[];\n}\n\n/** Parse scenario YAML text and keep the position of every step. `file` is used only for messages. */\nexport function parseScenarioWithSource(text: string, file = \"<inline>\"): LoadedScenario {\n const counter = new LineCounter();\n const doc = parseDocument(text, { lineCounter: counter, keepSourceTokens: true });\n\n const syntax = doc.errors[0];\n if (syntax) {\n const pos = syntax.linePos?.[0];\n throw new ScenarioValidationError({\n file,\n line: pos?.line ?? 1,\n column: pos?.col ?? 1,\n path: \"\",\n detail: `YAML syntax error: ${syntax.message.split(\"\\n\")[0] ?? syntax.code}`,\n });\n }\n\n const result = ScenarioSchema.safeParse(doc.toJS() ?? {});\n if (result.success) {\n const stepPositions = result.data.steps.map((_, i) => locate(doc, counter, [\"steps\", i]));\n return { scenario: result.data, file, stepPositions };\n }\n\n // Report the first (most specific) issue. Custom \"exactly one of\" issues are the most useful for steps.\n const issue = result.error.issues[0]!;\n const keyName = issue.code === \"unrecognized_keys\" ? issue.keys[0] : undefined;\n const pos = locate(doc, counter, issue.path, keyName);\n const detail =\n issue.code === \"unrecognized_keys\"\n ? `Unknown key${issue.keys.length > 1 ? \"s\" : \"\"} ${issue.keys.map((k) => `\"${k}\"`).join(\", \")}.`\n : issue.code === \"invalid_type\" && issue.input === undefined\n ? `Missing required field \\`${String(issue.path.at(-1) ?? \"\")}\\`.`\n : issue.message;\n throw new ScenarioValidationError({ file, line: pos.line, column: pos.column, path: dotted(issue.path), detail });\n}\n\n/** Parse scenario YAML text. */\nexport function parseScenario(text: string, file = \"<inline>\"): Scenario {\n return parseScenarioWithSource(text, file).scenario;\n}\n\n/** Read and validate a scenario file from disk, keeping step positions. */\nexport function loadScenarioWithSource(file: string): LoadedScenario {\n let text: string;\n try {\n text = readFileSync(file, \"utf8\");\n } catch (cause) {\n throw new RccError(`Scenario file not found: ${file}`, {\n hint: \"Check the path, or run `rcc init` to create a scenarios/ folder with examples.\",\n cause,\n });\n }\n return parseScenarioWithSource(text, file);\n}\n\n/** Read and validate a scenario file from disk. */\nexport function loadScenario(file: string): Scenario {\n return loadScenarioWithSource(file).scenario;\n}\n","import type { Command } from \"commander\";\nimport { RccError } from \"../core/errors.js\";\nimport { runScenario } from \"../core/engine.js\";\nimport { assertUrl } from \"../core/http.js\";\nimport { println, type Io } from \"../core/io.js\";\nimport { createRunTable, renderFailedExpectations, renderRunSummary } from \"../core/output.js\";\nimport { loadScenarioWithSource } from \"../core/scenario.js\";\nimport { bold, dim } from \"../core/colors.js\";\nimport { parseSeed } from \"./send.js\";\nimport { CONFIG_FILE, DEFAULT_TARGET, loadConfig, resolveDefaults } from \"../core/config.js\";\n\nexport interface RunCommandOptions {\n to?: string | undefined;\n authHeader?: string | undefined;\n speed: string;\n seed?: string;\n dryRun?: boolean | undefined;\n json?: boolean | undefined;\n}\n\nexport function parseSpeed(input: string): \"instant\" | number {\n if (input === \"instant\") return \"instant\";\n const n = Number(input);\n if (Number.isInteger(n) && n >= 0) return n;\n throw new RccError(`Invalid --speed \"${input}\": use \\`instant\\` or a number of milliseconds between events (e.g. --speed 500).`);\n}\n\nexport function registerRun(program: Command, io: Io): void {\n program\n .command(\"run\")\n .argument(\"<scenario.yaml>\", \"scenario file to execute\")\n .description(\"Run a scenario: advance a virtual clock, emit a coherent event sequence and deliver it over HTTP.\")\n .option(\"--to <url>\", `target URL (default: ${DEFAULT_TARGET}, or \"to\" in ${CONFIG_FILE})`)\n .option(\"--auth-header <value>\", `value sent as the Authorization header (default: \"authHeader\" in ${CONFIG_FILE})`)\n .option(\"--speed <instant|ms>\", \"wall-clock pause between events\", \"instant\")\n .option(\"--seed <seed>\", \"deterministic ids and timestamps\")\n .option(\"--dry-run\", \"print each envelope as JSON (one per line) instead of sending\")\n .option(\"--json\", \"print the full run result as one JSON document on stdout (human output goes to stderr)\")\n .addHelpText(\"after\", `\nExamples:\n $ rcc run scenarios/trial-churns.yaml\n $ rcc run scenarios/happy-year.yaml --to http://localhost:8787/webhook --speed 250\n $ rcc run scenarios/billing-issue-recovers.yaml --dry-run --seed 42 | jq .event.type\n $ rcc run scenarios/happy-year.yaml --json > result.json # CI: exit 1 on any failed expectation`)\n .action(async (file: string, opts: RunCommandOptions) => {\n const d = resolveDefaults(opts, loadConfig());\n const to = assertUrl(d.to, \"--to\");\n const speed = parseSpeed(opts.speed);\n const loaded = loadScenarioWithSource(file);\n const human = opts.dryRun || opts.json ? io.stderr : io.stdout;\n const desc = loaded.scenario.description ? ` — ${loaded.scenario.description}` : \"\";\n println(human, `▶ ${bold(loaded.scenario.name)}${dim(desc)}`);\n const live = createRunTable(loaded.scenario);\n println(human, live.header());\n let index = 0;\n\n const result = await runScenario(loaded.scenario, {\n to,\n authHeader: d.authHeader,\n speed,\n seed: parseSeed(opts.seed),\n dryRun: opts.dryRun ?? false,\n source: loaded,\n onEvent: (r, envelope) => {\n println(human, live.row(r, index++));\n if (opts.dryRun && !opts.json) println(io.stdout, JSON.stringify(envelope));\n },\n });\n\n for (const line of renderFailedExpectations(result)) println(human, line);\n println(human, renderRunSummary(result));\n if (opts.json) println(io.stdout, JSON.stringify(result, null, 2));\n if (!result.ok) {\n const failedExp = result.expectations.filter((e) => !e.ok).length;\n throw new RccError(\n failedExp > 0\n ? `Scenario finished with ${failedExp} failed expectation${failedExp === 1 ? \"\" : \"s\"}.`\n : \"Scenario finished with failed deliveries.\",\n { hint: \"Every event must be answered with a 2xx status and every expect: block must hold. Check your handler logs, or run with --dry-run to inspect payloads.\" },\n );\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { copyFileSync, existsSync, mkdirSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { CONFIG_FILE, DEFAULT_TARGET, packageRoot } from \"../core/config.js\";\nimport { RccError } from \"../core/errors.js\";\nimport { println, type Io } from \"../core/io.js\";\nimport { bold, dim, green } from \"../core/colors.js\";\n\nexport interface InitOptions {\n force?: boolean | undefined;\n}\n\n/** Create the config file and example scenarios in `cwd`. Returns the files written. */\nexport function initProject(cwd: string, opts: InitOptions): string[] {\n const scenariosSrc = join(packageRoot(), \"scenarios\");\n const examples = readdirSync(scenariosSrc).filter((f) => f.endsWith(\".yaml\")).sort();\n const targets = [CONFIG_FILE, ...examples.map((f) => join(\"scenarios\", f))];\n\n const existing = targets.filter((t) => existsSync(join(cwd, t)));\n if (existing.length > 0 && !opts.force) {\n throw new RccError(`Refusing to overwrite existing file${existing.length === 1 ? \"\" : \"s\"}: ${existing.join(\", \")}`, {\n hint: \"Run `rcc init --force` to overwrite, or delete them first.\",\n });\n }\n\n const written: string[] = [];\n const config = { to: DEFAULT_TARGET, store: \"app_store\", environment: \"SANDBOX\" };\n writeFileSync(join(cwd, CONFIG_FILE), JSON.stringify(config, null, 2) + \"\\n\");\n written.push(CONFIG_FILE);\n mkdirSync(join(cwd, \"scenarios\"), { recursive: true });\n for (const f of examples) {\n copyFileSync(join(scenariosSrc, f), join(cwd, \"scenarios\", f));\n written.push(join(\"scenarios\", f));\n }\n return written;\n}\n\nexport function registerInit(program: Command, io: Io): void {\n program\n .command(\"init\")\n .description(`Create ${CONFIG_FILE} and a scenarios/ folder with the six example scenarios in the current directory.`)\n .option(\"--force\", \"overwrite existing files\")\n .addHelpText(\"after\", `\nExamples:\n $ rcc init\n $ rcc init --force`)\n .action((opts: InitOptions) => {\n const cwd = process.cwd();\n const written = initProject(cwd, opts);\n println(io.stdout, `${green(\"✔\")} Created ${written.length} files in ${bold(relative(process.cwd(), cwd) || \".\")}:`);\n for (const f of written) println(io.stdout, ` ${dim(\"+\")} ${f}`);\n println(io.stdout, \"\");\n println(io.stdout, `Next: start your webhook handler (or \\`rcc listen\\`), then run`);\n println(io.stdout, ` ${bold(\"rcc run scenarios/trial-churns.yaml\")}`);\n println(io.stdout, dim(`Defaults (target URL, auth header, store, environment) live in ${CONFIG_FILE}.`));\n });\n}\n","import type { Command } from \"commander\";\nimport { RccError } from \"../core/errors.js\";\nimport { assertUrl } from \"../core/http.js\";\nimport { println, type Io } from \"../core/io.js\";\nimport { bold, cyan, dim, green, magenta, red, yellow } from \"../core/colors.js\";\nimport { classifyEnvelope } from \"../schemas/index.js\";\n\nexport const SMEE_ORIGIN = \"https://smee.io\";\n\n/* ------------------------------------------------------------------ SSE */\n\nexport interface SseFrame {\n id?: string;\n event?: string;\n data: string;\n}\n\n/** Parse a text/event-stream byte stream into frames. Comments (`: ping`) and empty frames are dropped. */\nexport async function* parseSseStream(source: AsyncIterable<Uint8Array>): AsyncGenerator<SseFrame> {\n const decoder = new TextDecoder();\n let buffer = \"\";\n let cur: { id?: string; event?: string; data: string[] } = { data: [] };\n const flush = (): SseFrame | undefined => {\n if (cur.data.length === 0) {\n cur = { data: [] };\n return undefined;\n }\n const frame: SseFrame = { data: cur.data.join(\"\\n\") };\n if (cur.id !== undefined) frame.id = cur.id;\n if (cur.event !== undefined) frame.event = cur.event;\n cur = { data: [] };\n return frame;\n };\n for await (const chunk of source) {\n buffer += decoder.decode(chunk, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) !== -1) {\n const line = buffer.slice(0, nl).replace(/\\r$/, \"\");\n buffer = buffer.slice(nl + 1);\n if (line === \"\") {\n const f = flush();\n if (f) yield f;\n continue;\n }\n if (line.startsWith(\":\")) continue;\n const colon = line.indexOf(\":\");\n const field = colon === -1 ? line : line.slice(0, colon);\n const value = colon === -1 ? \"\" : line.slice(colon + 1).replace(/^ /, \"\");\n if (field === \"data\") cur.data.push(value);\n else if (field === \"id\") cur.id = value;\n else if (field === \"event\") cur.event = value;\n }\n }\n const last = flush();\n if (last) yield last;\n}\n\n/* ------------------------------------------------------------------ smee */\n\n/** GET <origin>/new and return the channel URL from the redirect. */\nexport async function createSmeeChannel(origin = SMEE_ORIGIN): Promise<string> {\n let res: Response;\n try {\n res = await fetch(`${origin}/new`, { redirect: \"manual\", signal: AbortSignal.timeout(15_000) });\n } catch (cause) {\n throw new RccError(`Could not reach ${origin} to create a channel.`, {\n hint: \"Check your connection, or pass an existing channel: rcc tail --smee https://smee.io/<channel>\",\n cause,\n });\n }\n const location = res.headers.get(\"location\");\n if (!location) throw new RccError(`${origin}/new did not return a channel URL (HTTP ${res.status}).`);\n return new URL(location, origin).toString();\n}\n\n/* ------------------------------------------------------------------ tail */\n\nexport type TailSource =\n | { kind: \"smee\"; url: string }\n | { kind: \"inbox\"; url: string; token: string; since?: number | undefined };\n\nexport interface TailOptions {\n source: TailSource;\n forward?: string | undefined;\n verbose?: boolean | undefined;\n io: Io;\n /** Reconnect delays in ms (last one repeats). */\n backoffMs?: number[] | undefined;\n}\n\nexport interface TailHandle {\n close(): Promise<void>;\n /** Resolves when the loop exits (after close()). */\n done: Promise<void>;\n}\n\ninterface RelayedRequest {\n headers: Record<string, string>;\n /** Parsed body (smee) — used for validation and printing. */\n body: unknown;\n /** Raw body when the source preserves it (inbox); forwarded verbatim. */\n raw?: string | undefined;\n timestamp: number | undefined;\n}\n\n/** `rcc inbox` records: `{ seq, receivedAt, headers, body: <raw string>, ... }`. */\nfunction fromInbox(data: string): RelayedRequest | undefined {\n let rec: { headers?: Record<string, string>; body?: string; receivedAt?: string };\n try {\n rec = JSON.parse(data) as typeof rec;\n } catch {\n return undefined;\n }\n if (typeof rec.body !== \"string\") return undefined;\n let body: unknown = rec.body;\n try {\n body = JSON.parse(rec.body);\n } catch {\n /* keep raw */\n }\n return { headers: rec.headers ?? {}, body, raw: rec.body, timestamp: rec.receivedAt ? Date.parse(rec.receivedAt) : undefined };\n}\n\n/** smee delivers `{ ...lower-cased request headers, body, query, timestamp }`. */\nfunction fromSmee(data: string): RelayedRequest | undefined {\n let obj: unknown;\n try {\n obj = JSON.parse(data);\n } catch {\n return undefined;\n }\n if (typeof obj !== \"object\" || obj === null) return undefined;\n const { body, query: _q, timestamp, ...rest } = obj as Record<string, unknown>;\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(rest)) if (typeof v === \"string\") headers[k.toLowerCase()] = v;\n return { headers, body, timestamp: typeof timestamp === \"number\" ? timestamp : undefined };\n}\n\nconst clock = (ms?: number): string => new Date(ms ?? Date.now()).toISOString().slice(11, 19);\nconst sleep = (ms: number, signal: AbortSignal): Promise<void> =>\n new Promise((resolve) => {\n if (signal.aborted) return resolve();\n const t = setTimeout(resolve, ms);\n signal.addEventListener(\"abort\", () => (clearTimeout(t), resolve()), { once: true });\n });\n\n/** Follow a relay's SSE stream, print each real webhook, optionally forward it to a local URL. */\nexport function startTail(opts: TailOptions): TailHandle {\n const { io } = opts;\n const log = (s: string): void => println(io.stdout, s);\n const controller = new AbortController();\n const backoff = opts.backoffMs ?? [1000, 2000, 5000, 10_000, 30_000];\n\n const src = opts.source;\n const streamUrl = (): string => {\n if (src.kind === \"smee\") return src.url;\n const u = new URL(\"/events/stream\", src.url.endsWith(\"/\") ? src.url : src.url + \"/\");\n if (src.since !== undefined) u.searchParams.set(\"since\", String(src.since));\n return u.toString();\n };\n const streamHeaders = (): Record<string, string> =>\n src.kind === \"inbox\" ? { accept: \"text/event-stream\", authorization: `Bearer ${src.token}` } : { accept: \"text/event-stream\" };\n\n log(`${green(\"●\")} Tailing ${bold(opts.source.url)}`);\n if (opts.source.kind === \"smee\") {\n log(` Paste this URL in RevenueCat → Integrations → Webhooks: ${cyan(opts.source.url)}`);\n log(dim(\" smee.io is a public relay with no persistence: events only arrive while this command is running.\"));\n }\n if (opts.forward) log(dim(` forwarding each event to ${opts.forward}`));\n\n async function handle(req: RelayedRequest): Promise<void> {\n const time = dim(clock(req.timestamp));\n const classified = classifyEnvelope(req.body);\n let label: string;\n if (classified.kind === \"invalid\") {\n const issues = classified.issues.slice(0, 3).map((i) => `${i.path}: ${i.message}`).join(\"; \");\n label = `${red(bold(\"INVALID\"))} ${issues}`;\n } else {\n const ev = classified.envelope.event;\n const productId = typeof ev[\"product_id\"] === \"string\" ? ev[\"product_id\"] : \"\";\n const typeLabel = classified.kind === \"known\" ? cyan(bold(ev.type.padEnd(16))) : `${yellow(bold(\"UNSUPPORTED\"))} ${yellow(ev.type)}`;\n label = `${typeLabel} ${yellow(ev.app_user_id)} ${productId}`;\n }\n let suffix = \"\";\n if (opts.forward) {\n try {\n const headers: Record<string, string> = { \"content-type\": \"application/json\" };\n const auth = req.headers[\"authorization\"];\n if (auth !== undefined) headers[\"authorization\"] = auth;\n const started = performance.now();\n const res = await fetch(opts.forward, {\n method: \"POST\",\n headers,\n body: req.raw ?? JSON.stringify(req.body),\n signal: AbortSignal.timeout(30_000),\n });\n const status = res.status < 300 ? green(String(res.status)) : red(String(res.status));\n suffix = ` → ${status} ${dim(`(${Math.round(performance.now() - started)} ms)`)}`;\n } catch (err) {\n suffix = ` ${red(\"forward failed\")}: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n log(`${time} ${magenta(\"real\")} ${label}${suffix}`);\n if (opts.verbose) log(dim(JSON.stringify(req.body, null, 2)));\n }\n\n async function loop(): Promise<void> {\n let attempt = 0;\n while (!controller.signal.aborted) {\n try {\n const res = await fetch(streamUrl(), { headers: streamHeaders(), signal: controller.signal });\n if (res.status === 401) {\n throw new RccError(`The inbox at ${src.url} rejected the token (401).`, { hint: \"Check --token against the inbox's --token / INBOX_TOKEN.\" });\n }\n if (!res.ok || !res.body) throw new Error(`HTTP ${res.status}`);\n attempt = 0;\n for await (const frame of parseSseStream(res.body)) {\n if (frame.event === \"ready\" || frame.data === \"{}\") continue;\n const req = src.kind === \"inbox\" ? fromInbox(frame.data) : fromSmee(frame.data);\n if (req) await handle(req);\n }\n if (controller.signal.aborted) return;\n throw new Error(\"stream ended\");\n } catch (err) {\n if (controller.signal.aborted) return;\n const delay = backoff[Math.min(attempt, backoff.length - 1)]!;\n attempt++;\n const reason = err instanceof RccError ? `${err.message} ${err.hint ?? \"\"}` : err instanceof Error ? err.message : String(err);\n log(`${dim(clock())} ${yellow(\"reconnecting\")} in ${delay} ms ${dim(`(${reason.trim()})`)}`);\n await sleep(delay, controller.signal);\n }\n }\n }\n\n const done = loop();\n return {\n done,\n close: async () => {\n controller.abort();\n await done.catch(() => undefined);\n },\n };\n}\n\n/* ------------------------------------------------------------------ command */\n\nexport function registerTail(program: Command, io: Io): void {\n program\n .command(\"tail\")\n .description(\"Receive real RevenueCat webhooks on your machine through a relay, print them, and optionally forward them to a local URL.\")\n .option(\"--smee [channel-url]\", \"use the public smee.io relay; creates a channel when no URL is given\")\n .option(\"--inbox <url>\", \"use a self-hosted `rcc inbox` at this URL (requires --token)\")\n .option(\"--token <secret>\", \"read token of the inbox\")\n .option(\"--since <seq>\", \"inbox only: replay stored events after this sequence number (0 = everything)\")\n .option(\"--all\", \"inbox only: replay the whole history (same as --since 0)\")\n .option(\"--forward <url>\", \"re-POST each event (body + Authorization) to this local URL\")\n .option(\"--verbose\", \"print the full JSON payload of each event\")\n .addHelpText(\"after\", `\nExamples:\n $ rcc tail --smee # prints a URL to paste in RevenueCat → Integrations → Webhooks\n $ rcc tail --smee https://smee.io/abc123 --forward http://localhost:3000/webhook\n $ rcc tail --smee --verbose\n $ rcc tail --inbox https://hooks.example.com --token s3cret --all --forward http://localhost:3000/webhook`)\n .action(async (opts: { smee?: string | boolean; inbox?: string; token?: string; since?: string; all?: boolean; forward?: string; verbose?: boolean }) => {\n if (opts.smee !== undefined && opts.inbox !== undefined) {\n throw new RccError(\"Use either --smee or --inbox, not both.\");\n }\n if (opts.smee === undefined && opts.inbox === undefined) {\n throw new RccError(\"rcc tail needs a source.\", {\n hint: \"Use --smee to receive events through smee.io (zero setup), or --inbox <url> --token <t> for a self-hosted inbox.\",\n });\n }\n if (opts.forward !== undefined) assertUrl(opts.forward, \"--forward\");\n let source: TailSource;\n if (opts.inbox !== undefined) {\n if (!opts.token) throw new RccError(\"--inbox requires --token.\", { hint: \"The token is the inbox's --token / INBOX_TOKEN.\" });\n const since = opts.all ? 0 : opts.since !== undefined ? Number(opts.since) : undefined;\n if (since !== undefined && (!Number.isInteger(since) || since < 0)) throw new RccError(`Invalid --since \"${opts.since ?? \"\"}\".`);\n source = { kind: \"inbox\", url: assertUrl(opts.inbox, \"--inbox\"), token: opts.token, since };\n } else {\n const url = typeof opts.smee === \"string\" ? assertUrl(opts.smee, \"--smee\") : await createSmeeChannel();\n source = { kind: \"smee\", url };\n }\n const handle = startTail({ source, forward: opts.forward, verbose: opts.verbose, io });\n const stop = (): void => {\n void handle.close().finally(() => process.exit(0));\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n await handle.done;\n });\n}\n","import type { Command } from \"commander\";\nimport { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport { join } from \"node:path\";\nimport { RccError } from \"../core/errors.js\";\nimport { println, type Io } from \"../core/io.js\";\nimport { bold, cyan, dim, green, red, yellow } from \"../core/colors.js\";\nimport { classifyEnvelope } from \"../schemas/index.js\";\n\nexport const DEFAULT_INBOX_PORT = 8788;\nconst EVENTS_FILE = \"events.jsonl\";\nconst KEPT_HEADERS = [\"authorization\", \"content-type\", \"user-agent\", \"x-revenuecat-webhook-signature\"];\n\n/** One stored delivery. `body` is the raw request text so nothing is lost. */\nexport interface InboxRecord {\n seq: number;\n receivedAt: string;\n headers: Record<string, string>;\n body: string;\n valid: boolean;\n authOk: boolean;\n issues?: Array<{ path: string; message: string }>;\n eventId?: string;\n eventType?: string;\n /** Well-formed event whose `type` is not one of the 7 rcc generates (forward compatibility). */\n unsupportedType?: boolean;\n duplicateOf?: number;\n}\n\nexport interface InboxOptions {\n port: number;\n token: string;\n authHeader?: string | undefined;\n dataDir: string;\n maxEvents?: number | undefined;\n io: Io;\n}\n\nexport interface Inbox {\n url: string;\n port: number;\n subscribers: number;\n close(): Promise<void>;\n}\n\n/* ------------------------------------------------------------------ storage */\n\nclass Store {\n private records: InboxRecord[] = [];\n private lastSeq = 0;\n private readonly file: string;\n\n constructor(\n private readonly dir: string,\n private readonly maxEvents: number,\n ) {\n mkdirSync(dir, { recursive: true });\n this.file = join(dir, EVENTS_FILE);\n if (existsSync(this.file)) {\n for (const line of readFileSync(this.file, \"utf8\").split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n this.records.push(JSON.parse(line) as InboxRecord);\n } catch {\n /* skip corrupt line */\n }\n }\n this.lastSeq = this.records.at(-1)?.seq ?? 0;\n if (this.records.length > this.maxEvents) this.compact();\n }\n }\n\n nextSeq(): number {\n return ++this.lastSeq;\n }\n\n add(rec: InboxRecord): void {\n this.records.push(rec);\n appendFileSync(this.file, JSON.stringify(rec) + \"\\n\");\n if (this.records.length > this.maxEvents) this.compact();\n }\n\n private compact(): void {\n this.records = this.records.slice(-this.maxEvents);\n writeFileSync(this.file, this.records.map((r) => JSON.stringify(r)).join(\"\\n\") + \"\\n\");\n }\n\n since(seq: number, limit: number): InboxRecord[] {\n return this.records.filter((r) => r.seq > seq).slice(0, limit);\n }\n\n findByEventId(id: string): InboxRecord | undefined {\n return this.records.find((r) => r.eventId === id);\n }\n\n get count(): number {\n return this.records.length;\n }\n}\n\n/* ------------------------------------------------------------------ server */\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let raw = \"\";\n req.on(\"data\", (c: Buffer) => (raw += c.toString(\"utf8\")));\n req.on(\"end\", () => resolve(raw));\n req.on(\"error\", reject);\n });\n}\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { \"content-type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n\nconst clock = (): string => new Date().toISOString().slice(11, 19);\n\n/** Start the self-hosted inbox. Resolves once listening. */\nexport async function startInbox(opts: InboxOptions): Promise<Inbox> {\n if (!opts.token) {\n throw new RccError(\"rcc inbox needs a read token.\", {\n hint: \"Pass --token <secret> (or set INBOX_TOKEN). Clients read events with `rcc tail --inbox <url> --token <secret>`.\",\n });\n }\n const { io } = opts;\n const log = (s: string): void => println(io.stdout, s);\n const store = new Store(opts.dataDir, opts.maxEvents ?? 10_000);\n const streams = new Set<ServerResponse>();\n\n const authorized = (req: IncomingMessage, url: URL): boolean =>\n req.headers[\"authorization\"] === `Bearer ${opts.token}` || url.searchParams.get(\"token\") === opts.token;\n\n const server = createServer((req, res) => {\n void handle(req, res);\n });\n\n async function handle(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = new URL(req.url ?? \"/\", \"http://inbox\");\n const path = url.pathname;\n\n if (req.method === \"GET\" && path === \"/health\") {\n json(res, 200, { ok: true, events: store.count });\n return;\n }\n if (req.method === \"POST\" && path === \"/webhook\") {\n await receive(req, res);\n return;\n }\n if (req.method === \"GET\" && (path === \"/events\" || path === \"/events/stream\")) {\n if (!authorized(req, url)) {\n json(res, 401, { error: \"Missing or invalid token. Use `Authorization: Bearer <token>` or ?token=.\" });\n return;\n }\n const since = Number(url.searchParams.get(\"since\") ?? (path === \"/events\" ? \"0\" : String(store.count === 0 ? 0 : store.since(0, Infinity).at(-1)!.seq)));\n if (path === \"/events\") {\n const limit = Math.min(Number(url.searchParams.get(\"limit\") ?? \"100\"), 1000);\n const events = store.since(since, limit);\n json(res, 200, { events, next: events.at(-1)?.seq ?? since });\n return;\n }\n res.writeHead(200, { \"content-type\": \"text/event-stream\", \"cache-control\": \"no-cache\", connection: \"keep-alive\" });\n res.write(`event: ready\\ndata: {}\\n\\n`);\n for (const rec of store.since(since, Infinity)) res.write(`id: ${rec.seq}\\nevent: webhook\\ndata: ${JSON.stringify(rec)}\\n\\n`);\n streams.add(res);\n const ping = setInterval(() => res.write(\": ping\\n\\n\"), 25_000);\n res.on(\"close\", () => {\n clearInterval(ping);\n streams.delete(res);\n });\n return;\n }\n json(res, 404, { error: `Not found. Endpoints: POST /webhook, GET /events, GET /events/stream, GET /health.` });\n }\n\n async function receive(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const raw = await readBody(req);\n const headers: Record<string, string> = {};\n for (const h of KEPT_HEADERS) {\n const v = req.headers[h];\n if (typeof v === \"string\") headers[h] = v;\n }\n const authOk = opts.authHeader === undefined || headers[\"authorization\"] === opts.authHeader;\n\n let parsed: unknown;\n let isJson = true;\n try {\n parsed = JSON.parse(raw);\n } catch {\n isJson = false;\n }\n const rec: InboxRecord = { seq: store.nextSeq(), receivedAt: new Date().toISOString(), headers, body: raw, valid: false, authOk };\n let status: number;\n let label: string;\n if (!isJson) {\n status = 400;\n label = `${red(bold(\"INVALID\"))} body is not JSON`;\n } else {\n const classified = classifyEnvelope(parsed);\n if (classified.kind !== \"invalid\") {\n const ev = classified.envelope.event;\n rec.valid = true;\n rec.eventId = ev.id;\n rec.eventType = ev.type;\n if (classified.kind === \"unknown-type\") rec.unsupportedType = true;\n const dup = store.findByEventId(rec.eventId);\n if (dup) rec.duplicateOf = dup.seq;\n const typeLabel = classified.kind === \"known\" ? cyan(bold(ev.type.padEnd(16))) : `${yellow(bold(\"UNSUPPORTED\"))} ${yellow(ev.type)}`;\n label = `${typeLabel} ${yellow(ev.app_user_id)}${dup ? dim(` (retry of #${dup.seq})`) : \"\"}`;\n } else {\n rec.issues = classified.issues;\n label = `${red(bold(\"INVALID\"))} ${rec.issues.slice(0, 3).map((i) => `${i.path}: ${i.message}`).join(\"; \")}`;\n }\n status = authOk ? 200 : 401;\n }\n if (!authOk) label = `${red(bold(\"AUTH MISMATCH\"))} ${label}`;\n\n store.add(rec);\n for (const s of streams) s.write(`id: ${rec.seq}\\nevent: webhook\\ndata: ${JSON.stringify(rec)}\\n\\n`);\n log(`${dim(clock())} #${rec.seq} ${label} → ${status < 300 ? green(String(status)) : red(String(status))}`);\n json(res, status, status === 400 ? { error: \"Body is not valid JSON\" } : status === 401 ? { error: \"Authorization header mismatch\" } : { ok: true, seq: rec.seq });\n }\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n reject(\n err.code === \"EADDRINUSE\"\n ? new RccError(`Port ${opts.port} is already in use.`, { hint: `Pick another one: rcc inbox --port ${opts.port + 1}` })\n : new RccError(`Could not start the inbox: ${err.message}`, { cause: err }),\n );\n });\n server.listen(opts.port, () => resolve());\n });\n const port = (server.address() as AddressInfo).port;\n const url = `http://localhost:${port}`;\n log(`${green(\"●\")} Inbox listening on ${bold(url)} — ${store.count} stored event${store.count === 1 ? \"\" : \"s\"} in ${opts.dataDir}`);\n log(dim(` RevenueCat → POST ${url}/webhook${opts.authHeader === undefined ? \" (no --auth-header: accepting any Authorization)\" : \"\"}`));\n log(dim(` you → rcc tail --inbox <public-url> --token <token>`));\n\n return {\n url,\n port,\n get subscribers() {\n return streams.size;\n },\n close: () =>\n new Promise((resolve, reject) => {\n for (const s of streams) s.destroy();\n server.closeAllConnections();\n server.close((err) => (err ? reject(err) : resolve()));\n }),\n };\n}\n\nexport function registerInbox(program: Command, io: Io): void {\n program\n .command(\"inbox\")\n .description(\"Run a self-hosted webhook inbox: stores every delivery (JSONL) and streams it to `rcc tail --inbox`. Put HTTPS in front.\")\n .option(\"--port <n>\", \"port to listen on (env PORT)\", process.env[\"PORT\"] ?? String(DEFAULT_INBOX_PORT))\n .option(\"--token <secret>\", \"bearer token clients need to read events (env INBOX_TOKEN)\", process.env[\"INBOX_TOKEN\"])\n .option(\"--auth-header <value>\", \"Authorization value RevenueCat must send; mismatches stored and answered 401 (env RC_WEBHOOK_AUTH)\", process.env[\"RC_WEBHOOK_AUTH\"])\n .option(\"--data-dir <dir>\", \"where events.jsonl lives (env INBOX_DATA_DIR)\", process.env[\"INBOX_DATA_DIR\"] ?? \"./inbox-data\")\n .option(\"--max-events <n>\", \"keep only the newest N events\", \"10000\")\n .addHelpText(\"after\", `\nExamples:\n $ rcc inbox --token s3cret --auth-header \"Bearer from-dashboard\"\n $ INBOX_TOKEN=s3cret PORT=8080 rcc inbox --data-dir /data`)\n .action(async (opts: { port: string; token?: string; authHeader?: string; dataDir: string; maxEvents: string }) => {\n if (!/^\\d{1,5}$/.test(opts.port) || Number(opts.port) > 65535) {\n throw new RccError(`Invalid --port \"${opts.port}\".`, { hint: \"Use an integer between 1 and 65535.\" });\n }\n const maxEvents = Number(opts.maxEvents);\n if (!Number.isInteger(maxEvents) || maxEvents < 1) throw new RccError(`Invalid --max-events \"${opts.maxEvents}\".`);\n const box = await startInbox({ port: Number(opts.port), token: opts.token ?? \"\", authHeader: opts.authHeader, dataDir: opts.dataDir, maxEvents, io });\n const stop = (): void => {\n void box.close().finally(() => process.exit(0));\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n await new Promise<void>(() => {\n /* run until killed */\n });\n });\n}\n"],"mappings":"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","names":["ms","duration","z","z","ms","clock","ms","eventType","ms","readFileSync","z","z","pos","readFileSync","existsSync","join","join","existsSync","clock","ms","sleep","existsSync","mkdirSync","readFileSync","writeFileSync","createServer","join","mkdirSync","join","existsSync","readFileSync","writeFileSync","readBody","json","clock","url","createServer"]}
|