SPB Git

Repository Public

PLAYGROUND.md 7.6 KB 105 lines markdown

1# Playground — catalog, deep links, how to extend23The playground (`/playground`, also embedded in `/dashboard/playground`) is a single reusable component:45```jsx6import Playground from './src/playground/Playground.jsx'7<Playground apiKey={sessionKey} embedded />   // apiKey optional → keyless mode8```910`apiKey` is sent as `Authorization: Bearer …` on every run and on the WebSocket URL (`?api_key=`). It lives in React state only — never localStorage, sessionStorage, cookies or the address bar. Code exports always print `$HFMD_API_KEY`.1112## Files1314| File | Role |15|---|---|16| `src/playground/catalog.js` | The request types (data only) + resolution/validation helpers |17| `src/playground/Playground.jsx` | The component: catalog nav, form, URL preview, run, result views, quota panel, code export, presets |18| `src/playground/RequestForm.jsx` | Form generated from `entry.params` |19| `src/playground/SymbolInput.jsx` | Debounced autocomplete (`/v1/{asset}/tickers?search=`, `/v1/futures/roots`, `/v1/options/tickers`) |20| `src/playground/views/{JsonView,TableView,ChartView}.jsx` | Collapsible JSON · virtualised sortable table (50 000 rows) · lightweight-charts (candles / line, roll markers) |21| `src/playground/RateLimitPanel.jsx` | `X-RateLimit-*` bars, reset countdown, 429 `Retry-After` countdown |22| `src/playground/WebSocketTab.jsx` | `/v1/stream` client (disabled without key) |23| `src/playground/codegen.js` | curl / Python (requests + pandas) / JavaScript (fetch) generators |24| `src/playground/presets.js` | One-click examples |25| `src/components/Pg{Tabs,CodeBlock,Callout,CopyButton}.jsx` | Local UI primitives (swap for web-core's shared ones when available) |2627## Catalog schema2829```js30{31  id: 'futures-continuous',            // stable, URL-safe — used in deep links and tests32  group: 'Futures',                    // one of GROUPS: Bars · Futures · Options · Fundamentals · Symbols · Stream33  title: 'Futures continuous (v2)',34  method: 'GET',                       // or 'WS' for the stream tab35  path: '/v1/futures/{root}/continuous',36  operationIds: ['futures_continuous_v1_futures__root__continuous_get'],  // OpenAPI ids that map here37  description: 'Markdown-free one-liner shown above the form',38  fixed: { asset: 'crypto' },          // optional: values injected in the path/query but hidden from the form39  requiresKey: false,                  // stream only40  params: [41    { name: 'root', in: 'path', type: 'symbol', required: true, source: 'futures_root', default: 'ES', placeholder: 'ES', help: '…' },42    { name: 'roll', in: 'query', type: 'enum', enum: ['', 'volume', 'open_interest', 'calendar'], default: 'volume' },43    { name: 'depth', in: 'query', type: 'number', default: 1, min: 1, max: 12 },44    { name: 'from', in: 'query', type: 'date' },                   // native <input type=date>45    { name: 'start', in: 'query', type: 'datetime' },              // native datetime-local, sent as "YYYY-MM-DD HH:MM:SS"46    { name: 'adjustment', in: 'query', type: 'enum', enumBy: { asset: { stock: [...], futures: [...] } }, enum: [''] },  // dependent enum47    { name: 'symbol', in: 'path', type: 'text', pattern: '^[A-Z]{1,3}[FGHJKMNQUVXZ]\\d{2}$' },48  ],49  result: {50    kind: 'bars' | 'series' | 'table' | 'list' | 'object' | 'ws' | 'auto',51    timeKey: 'datetime',               // x axis hint for the chart52    valueKeys: ['close', 'settle'],    // preferred y column(s) for line charts53    listKey: 'tickers',                // for `list` kinds: JSON key holding a flat array54    envelope: 'v2',                    // rows live in `data`, extras in `meta` (roll_dates → chart markers)55  },56}57```5859Param types → controls: `symbol` (autocomplete), `enum` (select; `''` = server default), `number`, `date`, `datetime`, `text` (optional `pattern`), `bool`. Validation (`validate()`) enforces required, numeric bounds, date formats, patterns and enum membership; Run is disabled until the form is valid.6061Result routing after a run: `bars`/`series` with a detectable time column → Chart tab first; any rows → Table; otherwise JSON. `format=csv` parses the CSV for the table and offers a download; `format=parquet` offers the download only.6263## Deep-link contract6465```66/playground?ep=<ref>&<param>=<value>&…67```6869- `ref` is either a **catalog id** (`stock-bars`, `futures-chain`, …) or an **OpenAPI `operationId`** (`bars_v1_bars__asset___ticker__get`, `opt_chain_v1_options_chain__ticker__get`, …). FastAPI's default naming is `<function>_<path with / and {} → _>_<method>`.70- Every other query parameter is a form value (path or query param of the entry). Unknown names are ignored for curated entries and kept for spec-generated ones.71- Resolution order (`resolveEntry()` in `Playground.jsx`):72  1. catalog `id` match;73  2. entry whose `operationIds` contains `ref` — when several entries share an operation (e.g. `bars_v1_bars__asset___ticker__get` → Stock/ETF, Crypto, FX, Index, legacy futures) the one whose `fixed` values match the supplied params wins (`asset=crypto` → Crypto bars);74  3. otherwise `/openapi.json` is fetched, `ref` is looked up, and the entry with the same **method + path template** is used;75  4. otherwise a **generic form is generated from the spec** (path/query parameters, enums from `schema.enum` or `^(a|b)$` patterns, defaults, descriptions) — a notice says so;76  5. otherwise a warning is shown and the default entry (`stock-bars`) is loaded.77- The address bar is rewritten (`history.replace`) to `?ep=<catalog id>&<non-default values>` so links copied from the browser are short and stable. Spec-generated entries keep `ep=<operationId>`.78- Docs "Try it" buttons should therefore link to `/playground?ep=${operation.operationId}&${exampleParams}`. No coordination with the catalog is needed: unknown operations still get a working form.79- The dashboard mounts the same component under `/dashboard/playground` — the same query contract applies there.8081## Presets (`presets.js`)8283| Label | Entry | Values |84|---|---|---|85| AAPL 1-min today | `stock-bars` | `ticker=AAPL timeframe=1min start=<today>` |86| CL chain | `futures-chain` | `root=CL` |87| ES continuous back-adjusted 2015-2025 | `futures-continuous` | `root=ES roll=volume adjust=back_adjusted depth=1 interval=1d from=2015-01-01 to=2025-12-31` |88| NG term structure | `futures-term-structure` | `root=NG` |89| AAPL income statements (quarterly) | `fundamentals-statements` | `ticker=AAPL statement=income period=quarterly` |90| Screener: PE<15 & ROE>15% | `fundamentals-screener` | `filter=pe<15,roe>0.15 sort=-market_cap` |9192## Adding a request type93941. Append an entry to `CATALOG` in `catalog.js` (copy the closest one). Put the FastAPI `operationId` in `operationIds` — check it in `/openapi.json` once the route exists.952. If it belongs to a new area, add the group name to `GROUPS` (ordering of the left column).963. Set `result` so the right view opens first (`bars` for OHLC, `series` + `timeKey`/`valueKeys` for one line, `list` + `listKey` for flat arrays).974. Optional: a preset in `presets.js`, a symbol `source` in `SymbolInput.jsx` if a new autocomplete endpoint is needed.985. Add an assertion in `e2e/playground.spec.js` (deep link → URL preview) and run `npm run test:e2e`.99100Errors: any non-2xx JSON envelope `{"error":{code,message,docs}}` is displayed with a Docs button; a bare FastAPI `{"detail":"Not Found"}` 404 is rendered as "Endpoint not available yet — coming soon" (the v2 modules are deployed independently).101102## Tests103104`npm run test:e2e` (Playwright, Chromium). The config builds the site and serves `vite preview` on `:4173`; specs mock every `/v1/*` and `/openapi.json` call with `page.route`, so the suite runs offline.105
Files main
Menu

Theme